V4L/DVB (13505): uvcvideo: Refactor chain scan

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>
This commit is contained in:
Laurent Pinchart 2009-11-25 12:00:29 -03:00 committed by Mauro Carvalho Chehab
parent fd3e921739
commit 4057ac6ca9

View 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;