All terminals and units are now added to a single linked list of entities per chain. This makes terminals and units handling code more generic. Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> Index: v4l-dvb-mc/linux/drivers/media/video/uvc/uvc_ctrl.c =================================================================== --- v4l-dvb-mc.orig/linux/drivers/media/video/uvc/uvc_ctrl.c +++ v4l-dvb-mc/linux/drivers/media/video/uvc/uvc_ctrl.c @@ -744,17 +744,7 @@ struct uvc_control *uvc_find_control(str v4l2_id &= V4L2_CTRL_ID_MASK; /* Find the control. */ - __uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next); - if (ctrl && !next) - return ctrl; - - list_for_each_entry(entity, &chain->iterms, chain) { - __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); - if (ctrl && !next) - return ctrl; - } - - list_for_each_entry(entity, &chain->extensions, chain) { + list_for_each_entry(entity, &chain->entities, chain) { __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); if (ctrl && !next) return ctrl; @@ -946,17 +936,7 @@ int __uvc_ctrl_commit(struct uvc_video_c int ret = 0; /* Find the control. */ - ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback); - if (ret < 0) - goto done; - - list_for_each_entry(entity, &chain->iterms, chain) { - ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); - if (ret < 0) - goto done; - } - - list_for_each_entry(entity, &chain->extensions, chain) { + list_for_each_entry(entity, &chain->entities, chain) { ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback); if (ret < 0) goto done; @@ -1070,8 +1050,9 @@ int uvc_xu_ctrl_query(struct uvc_video_c int ret; /* Find the extension unit. */ - list_for_each_entry(entity, &chain->extensions, chain) { - if (entity->id == xctrl->unit) + list_for_each_entry(entity, &chain->entities, chain) { + if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT && + entity->id == xctrl->unit) break; } Index: v4l-dvb-mc/linux/drivers/media/video/uvc/uvc_driver.c =================================================================== --- v4l-dvb-mc.orig/linux/drivers/media/video/uvc/uvc_driver.c +++ v4l-dvb-mc/linux/drivers/media/video/uvc/uvc_driver.c @@ -1215,7 +1215,6 @@ static int uvc_scan_chain_entity(struct return -1; } - list_add_tail(&entity->chain, &chain->extensions); break; case UVC_VC_PROCESSING_UNIT: @@ -1254,7 +1253,6 @@ static int uvc_scan_chain_entity(struct if (uvc_trace_param & UVC_TRACE_PROBE) printk(" <- IT %d\n", entity->id); - list_add_tail(&entity->chain, &chain->iterms); break; case UVC_TT_STREAMING: @@ -1267,7 +1265,6 @@ static int uvc_scan_chain_entity(struct return -1; } - list_add_tail(&entity->chain, &chain->iterms); break; default: @@ -1276,6 +1273,7 @@ static int uvc_scan_chain_entity(struct return -1; } + list_add_tail(&entity->chain, &chain->entities); return 0; } @@ -1306,7 +1304,7 @@ static int uvc_scan_chain_forward(struct return -EINVAL; } - list_add_tail(&forward->chain, &chain->extensions); + list_add_tail(&forward->chain, &chain->entities); if (uvc_trace_param & UVC_TRACE_PROBE) { if (!found) printk(" (->"); @@ -1326,7 +1324,7 @@ static int uvc_scan_chain_forward(struct return -EINVAL; } - list_add_tail(&forward->chain, &chain->oterms); + list_add_tail(&forward->chain, &chain->entities); if (uvc_trace_param & UVC_TRACE_PROBE) { if (!found) printk(" (->"); @@ -1382,7 +1380,7 @@ static int uvc_scan_chain_backward(struc if (uvc_trace_param & UVC_TRACE_PROBE) printk(" %d", term->id); - list_add_tail(&term->chain, &chain->iterms); + list_add_tail(&term->chain, &chain->entities); uvc_scan_chain_forward(chain, term, entity); } @@ -1403,7 +1401,7 @@ static int uvc_scan_chain(struct uvc_vid int id; entity = oterm; - list_add_tail(&entity->chain, &chain->oterms); + list_add_tail(&entity->chain, &chain->entities); uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); id = entity->output.bSourceID; @@ -1443,21 +1441,25 @@ static int uvc_scan_chain(struct uvc_vid return 0; } -static unsigned int uvc_print_terms(struct list_head *terms, char *buffer) +static unsigned int uvc_print_terms(struct list_head *terms, u16 dir, + char *buffer) { struct uvc_entity *term; unsigned int nterms = 0; char *p = buffer; list_for_each_entry(term, terms, chain) { - p += sprintf(p, "%u", term->id); - if (term->chain.next != terms) { + if (!UVC_ENTITY_IS_TERM(term) || + UVC_TERM_DIRECTION(term) != dir) + continue; + + if (nterms) p += sprintf(p, ","); - if (++nterms >= 4) { - p += sprintf(p, "..."); - break; - } + if (++nterms >= 4) { + p += sprintf(p, "..."); + break; } + p += sprintf(p, "%u", term->id); } return p - buffer; @@ -1468,9 +1470,9 @@ static const char *uvc_print_chain(struc static char buffer[43]; char *p = buffer; - p += uvc_print_terms(&chain->iterms, p); + p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p); p += sprintf(p, " -> "); - uvc_print_terms(&chain->oterms, p); + uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p); return buffer; } @@ -1501,9 +1503,7 @@ static int uvc_scan_device(struct uvc_de if (chain == NULL) return -ENOMEM; - INIT_LIST_HEAD(&chain->iterms); - INIT_LIST_HEAD(&chain->oterms); - INIT_LIST_HEAD(&chain->extensions); + INIT_LIST_HEAD(&chain->entities); mutex_init(&chain->ctrl_mutex); chain->dev = dev; @@ -1676,13 +1676,13 @@ static int uvc_register_video(struct uvc * Register all video devices in all chains. */ static int uvc_register_terms(struct uvc_device *dev, - struct uvc_video_chain *chain, struct list_head *terms) + struct uvc_video_chain *chain) { struct uvc_streaming *stream; struct uvc_entity *term; int ret; - list_for_each_entry(term, terms, chain) { + list_for_each_entry(term, &chain->entities, chain) { if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING) continue; @@ -1708,11 +1708,7 @@ static int uvc_register_chains(struct uv int ret; list_for_each_entry(chain, &dev->chains, list) { - ret = uvc_register_terms(dev, chain, &chain->iterms); - if (ret < 0) - return ret; - - ret = uvc_register_terms(dev, chain, &chain->oterms); + ret = uvc_register_terms(dev, chain); if (ret < 0) return ret; } Index: v4l-dvb-mc/linux/drivers/media/video/uvc/uvcvideo.h =================================================================== --- v4l-dvb-mc.orig/linux/drivers/media/video/uvc/uvcvideo.h +++ v4l-dvb-mc/linux/drivers/media/video/uvc/uvcvideo.h @@ -76,6 +76,7 @@ struct uvc_xu_control { #define UVC_TERM_INPUT 0x0000 #define UVC_TERM_OUTPUT 0x8000 +#define UVC_TERM_DIRECTION(term) ((term)->type & 0x8000) #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) @@ -409,11 +410,9 @@ struct uvc_video_chain { struct uvc_device *dev; struct list_head list; - struct list_head iterms; /* Input terminals */ - struct list_head oterms; /* Output terminals */ + struct list_head entities; /* All entities */ struct uvc_entity *processing; /* Processing unit */ struct uvc_entity *selector; /* Selector unit */ - struct list_head extensions; /* Extension units */ struct mutex ctrl_mutex; }; Index: v4l-dvb-mc/linux/drivers/media/video/uvc/uvc_v4l2.c =================================================================== --- v4l-dvb-mc.orig/linux/drivers/media/video/uvc/uvc_v4l2.c +++ v4l-dvb-mc/linux/drivers/media/video/uvc/uvc_v4l2.c @@ -628,12 +628,16 @@ static long uvc_v4l2_do_ioctl(struct fil (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { if (index != 0) return -EINVAL; - iterm = list_first_entry(&chain->iterms, - struct uvc_entity, chain); + list_for_each_entry(iterm, &chain->entities, chain) { + if (UVC_ENTITY_IS_ITERM(iterm)) + break; + } pin = iterm->id; } else if (pin < selector->selector.bNrInPins) { pin = selector->selector.baSourceID[index]; - list_for_each_entry(iterm, chain->iterms.next, chain) { + list_for_each_entry(iterm, &chain->entities, chain) { + if (!UVC_ENTITY_IS_ITERM(iterm)) + continue; if (iterm->id == pin) break; } -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html