V4L/DVB (13505): uvcvideo: Refactor chain scan
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Wed, 25 Nov 2009 15:00:29 +0000 (12:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 5 Dec 2009 20:42:12 +0000 (18:42 -0200)
Don't handle the first output terminal in a chain in a special way. Use
uvc_scan_chain_entity() like for all other entities, making the chain
scan code more generic.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/uvc/uvc_driver.c

index 8d51a6a130b0417feedd74a2a62a5e4f845c3af9..e7ce898ad7065fea7c1a6cdbfec480c071dabdc1 100644 (file)
@@ -1265,13 +1265,12 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
                break;
 
        case UVC_TT_STREAMING:
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk(" <- IT %d\n", entity->id);
-
-               if (!UVC_ENTITY_IS_ITERM(entity)) {
-                       uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
-                               "terminal %u.\n", entity->id);
-                       return -1;
+               if (UVC_ENTITY_IS_ITERM(entity)) {
+                       if (uvc_trace_param & UVC_TRACE_PROBE)
+                               printk(" <- IT %d\n", entity->id);
+               } else {
+                       if (uvc_trace_param & UVC_TRACE_PROBE)
+                               printk(" OT %d", entity->id);
                }
 
                break;
@@ -1351,10 +1350,11 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
 }
 
 static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
-       struct uvc_entity *entity)
+       struct uvc_entity **_entity)
 {
+       struct uvc_entity *entity = *_entity;
        struct uvc_entity *term;
-       int id = -1, i;
+       int id = -EINVAL, i;
 
        switch (UVC_ENTITY_TYPE(entity)) {
        case UVC_VC_EXTENSION_UNIT:
@@ -1398,34 +1398,49 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
 
                id = 0;
                break;
+
+       case UVC_ITT_VENDOR_SPECIFIC:
+       case UVC_ITT_CAMERA:
+       case UVC_ITT_MEDIA_TRANSPORT_INPUT:
+       case UVC_OTT_VENDOR_SPECIFIC:
+       case UVC_OTT_DISPLAY:
+       case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+       case UVC_TT_STREAMING:
+               id = UVC_ENTITY_IS_OTERM(entity) ? entity->output.bSourceID : 0;
+               break;
        }
 
-       return id;
+       if (id <= 0) {
+               *_entity = NULL;
+               return id;
+       }
+
+       entity = uvc_entity_by_id(chain->dev, id);
+       if (entity == NULL) {
+               uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+                       "unknown entity %d.\n", id);
+               return -EINVAL;
+       }
+
+       *_entity = entity;
+       return 0;
 }
 
 static int uvc_scan_chain(struct uvc_video_chain *chain,
-                         struct uvc_entity *oterm)
+                         struct uvc_entity *term)
 {
        struct uvc_entity *entity, *prev;
-       int id;
 
-       entity = oterm;
-       list_add_tail(&entity->chain, &chain->entities);
-       uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
+       uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
 
-       id = entity->output.bSourceID;
-       while (id != 0) {
-               prev = entity;
-               entity = uvc_entity_by_id(chain->dev, id);
-               if (entity == NULL) {
-                       uvc_trace(UVC_TRACE_DESCR, "Found reference to "
-                               "unknown entity %d.\n", id);
-                       return -EINVAL;
-               }
+       entity = term;
+       prev = NULL;
 
+       while (entity != NULL) {
+               /* Entity must not be part of an existing chain */
                if (entity->chain.next || entity->chain.prev) {
                        uvc_trace(UVC_TRACE_DESCR, "Found reference to "
-                               "entity %d already in chain.\n", id);
+                               "entity %d already in chain.\n", entity->id);
                        return -EINVAL;
                }
 
@@ -1437,14 +1452,10 @@ static int uvc_scan_chain(struct uvc_video_chain *chain,
                if (uvc_scan_chain_forward(chain, entity, prev) < 0)
                        return -EINVAL;
 
-               /* Stop when a terminal is found. */
-               if (UVC_ENTITY_IS_TERM(entity))
-                       break;
-
                /* Backward scan */
-               id = uvc_scan_chain_backward(chain, entity);
-               if (id < 0)
-                       return id;
+               prev = entity;
+               if (uvc_scan_chain_backward(chain, &entity) < 0)
+                       return -EINVAL;
        }
 
        return 0;