[PATCH 3.18 108/124] [media] uvcvideo: uvc_scan_fallback() for webcams with broken chain

2017-04-20 Thread Greg Kroah-Hartman
3.18-stable review patch.  If anyone has any objections, please let me know.

--

From: Henrik Ingo 

commit e950267ab802c8558f1100eafd4087fd039ad634 upstream.

Some devices have invalid baSourceID references, causing uvc_scan_chain()
to fail, but if we just take the entities we can find and put them
together in the most sensible chain we can think of, turns out they do
work anyway. Note: This heuristic assumes there is a single chain.

At the time of writing, devices known to have such a broken chain are
  - Acer Integrated Camera (5986:055a)
  - Realtek rtl157a7 (0bda:57a7)

Signed-off-by: Henrik Ingo 
Signed-off-by: Laurent Pinchart 
Signed-off-by: Mauro Carvalho Chehab 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/media/usb/uvc/uvc_driver.c |  118 +++--
 1 file changed, 112 insertions(+), 6 deletions(-)

--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1553,6 +1553,114 @@ static const char *uvc_print_chain(struc
return buffer;
 }
 
+static struct uvc_video_chain *uvc_alloc_chain(struct uvc_device *dev)
+{
+   struct uvc_video_chain *chain;
+
+   chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+   if (chain == NULL)
+   return NULL;
+
+   INIT_LIST_HEAD(>entities);
+   mutex_init(>ctrl_mutex);
+   chain->dev = dev;
+   v4l2_prio_init(>prio);
+
+   return chain;
+}
+
+/*
+ * Fallback heuristic for devices that don't connect units and terminals in a
+ * valid chain.
+ *
+ * Some devices have invalid baSourceID references, causing uvc_scan_chain()
+ * to fail, but if we just take the entities we can find and put them together
+ * in the most sensible chain we can think of, turns out they do work anyway.
+ * Note: This heuristic assumes there is a single chain.
+ *
+ * At the time of writing, devices known to have such a broken chain are
+ *  - Acer Integrated Camera (5986:055a)
+ *  - Realtek rtl157a7 (0bda:57a7)
+ */
+static int uvc_scan_fallback(struct uvc_device *dev)
+{
+   struct uvc_video_chain *chain;
+   struct uvc_entity *iterm = NULL;
+   struct uvc_entity *oterm = NULL;
+   struct uvc_entity *entity;
+   struct uvc_entity *prev;
+
+   /*
+* Start by locating the input and output terminals. We only support
+* devices with exactly one of each for now.
+*/
+   list_for_each_entry(entity, >entities, list) {
+   if (UVC_ENTITY_IS_ITERM(entity)) {
+   if (iterm)
+   return -EINVAL;
+   iterm = entity;
+   }
+
+   if (UVC_ENTITY_IS_OTERM(entity)) {
+   if (oterm)
+   return -EINVAL;
+   oterm = entity;
+   }
+   }
+
+   if (iterm == NULL || oterm == NULL)
+   return -EINVAL;
+
+   /* Allocate the chain and fill it. */
+   chain = uvc_alloc_chain(dev);
+   if (chain == NULL)
+   return -ENOMEM;
+
+   if (uvc_scan_chain_entity(chain, oterm) < 0)
+   goto error;
+
+   prev = oterm;
+
+   /*
+* Add all Processing and Extension Units with two pads. The order
+* doesn't matter much, use reverse list traversal to connect units in
+* UVC descriptor order as we build the chain from output to input. This
+* leads to units appearing in the order meant by the manufacturer for
+* the cameras known to require this heuristic.
+*/
+   list_for_each_entry_reverse(entity, >entities, list) {
+   if (entity->type != UVC_VC_PROCESSING_UNIT &&
+   entity->type != UVC_VC_EXTENSION_UNIT)
+   continue;
+
+   if (entity->num_pads != 2)
+   continue;
+
+   if (uvc_scan_chain_entity(chain, entity) < 0)
+   goto error;
+
+   prev->baSourceID[0] = entity->id;
+   prev = entity;
+   }
+
+   if (uvc_scan_chain_entity(chain, iterm) < 0)
+   goto error;
+
+   prev->baSourceID[0] = iterm->id;
+
+   list_add_tail(>list, >chains);
+
+   uvc_trace(UVC_TRACE_PROBE,
+ "Found a video chain by fallback heuristic (%s).\n",
+ uvc_print_chain(chain));
+
+   return 0;
+
+error:
+   kfree(chain);
+   return -EINVAL;
+}
+
 /*
  * Scan the device for video chains and register video devices.
  *
@@ -1575,15 +1683,10 @@ static int uvc_scan_device(struct uvc_de
if (term->chain.next || term->chain.prev)
continue;
 
-   chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+   chain = uvc_alloc_chain(dev);
if (chain == NULL)

[PATCH 3.18 108/124] [media] uvcvideo: uvc_scan_fallback() for webcams with broken chain

2017-04-20 Thread Greg Kroah-Hartman
3.18-stable review patch.  If anyone has any objections, please let me know.

--

From: Henrik Ingo 

commit e950267ab802c8558f1100eafd4087fd039ad634 upstream.

Some devices have invalid baSourceID references, causing uvc_scan_chain()
to fail, but if we just take the entities we can find and put them
together in the most sensible chain we can think of, turns out they do
work anyway. Note: This heuristic assumes there is a single chain.

At the time of writing, devices known to have such a broken chain are
  - Acer Integrated Camera (5986:055a)
  - Realtek rtl157a7 (0bda:57a7)

Signed-off-by: Henrik Ingo 
Signed-off-by: Laurent Pinchart 
Signed-off-by: Mauro Carvalho Chehab 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/media/usb/uvc/uvc_driver.c |  118 +++--
 1 file changed, 112 insertions(+), 6 deletions(-)

--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1553,6 +1553,114 @@ static const char *uvc_print_chain(struc
return buffer;
 }
 
+static struct uvc_video_chain *uvc_alloc_chain(struct uvc_device *dev)
+{
+   struct uvc_video_chain *chain;
+
+   chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+   if (chain == NULL)
+   return NULL;
+
+   INIT_LIST_HEAD(>entities);
+   mutex_init(>ctrl_mutex);
+   chain->dev = dev;
+   v4l2_prio_init(>prio);
+
+   return chain;
+}
+
+/*
+ * Fallback heuristic for devices that don't connect units and terminals in a
+ * valid chain.
+ *
+ * Some devices have invalid baSourceID references, causing uvc_scan_chain()
+ * to fail, but if we just take the entities we can find and put them together
+ * in the most sensible chain we can think of, turns out they do work anyway.
+ * Note: This heuristic assumes there is a single chain.
+ *
+ * At the time of writing, devices known to have such a broken chain are
+ *  - Acer Integrated Camera (5986:055a)
+ *  - Realtek rtl157a7 (0bda:57a7)
+ */
+static int uvc_scan_fallback(struct uvc_device *dev)
+{
+   struct uvc_video_chain *chain;
+   struct uvc_entity *iterm = NULL;
+   struct uvc_entity *oterm = NULL;
+   struct uvc_entity *entity;
+   struct uvc_entity *prev;
+
+   /*
+* Start by locating the input and output terminals. We only support
+* devices with exactly one of each for now.
+*/
+   list_for_each_entry(entity, >entities, list) {
+   if (UVC_ENTITY_IS_ITERM(entity)) {
+   if (iterm)
+   return -EINVAL;
+   iterm = entity;
+   }
+
+   if (UVC_ENTITY_IS_OTERM(entity)) {
+   if (oterm)
+   return -EINVAL;
+   oterm = entity;
+   }
+   }
+
+   if (iterm == NULL || oterm == NULL)
+   return -EINVAL;
+
+   /* Allocate the chain and fill it. */
+   chain = uvc_alloc_chain(dev);
+   if (chain == NULL)
+   return -ENOMEM;
+
+   if (uvc_scan_chain_entity(chain, oterm) < 0)
+   goto error;
+
+   prev = oterm;
+
+   /*
+* Add all Processing and Extension Units with two pads. The order
+* doesn't matter much, use reverse list traversal to connect units in
+* UVC descriptor order as we build the chain from output to input. This
+* leads to units appearing in the order meant by the manufacturer for
+* the cameras known to require this heuristic.
+*/
+   list_for_each_entry_reverse(entity, >entities, list) {
+   if (entity->type != UVC_VC_PROCESSING_UNIT &&
+   entity->type != UVC_VC_EXTENSION_UNIT)
+   continue;
+
+   if (entity->num_pads != 2)
+   continue;
+
+   if (uvc_scan_chain_entity(chain, entity) < 0)
+   goto error;
+
+   prev->baSourceID[0] = entity->id;
+   prev = entity;
+   }
+
+   if (uvc_scan_chain_entity(chain, iterm) < 0)
+   goto error;
+
+   prev->baSourceID[0] = iterm->id;
+
+   list_add_tail(>list, >chains);
+
+   uvc_trace(UVC_TRACE_PROBE,
+ "Found a video chain by fallback heuristic (%s).\n",
+ uvc_print_chain(chain));
+
+   return 0;
+
+error:
+   kfree(chain);
+   return -EINVAL;
+}
+
 /*
  * Scan the device for video chains and register video devices.
  *
@@ -1575,15 +1683,10 @@ static int uvc_scan_device(struct uvc_de
if (term->chain.next || term->chain.prev)
continue;
 
-   chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+   chain = uvc_alloc_chain(dev);
if (chain == NULL)
return -ENOMEM;
 
-   INIT_LIST_HEAD(>entities);
-   mutex_init(>ctrl_mutex);
-   chain->dev = dev;
-