10.扫描视频设备链和注册视频设备
[cpp] ?
struct uvc_video_chain { ? ?//uvc视频链 ?
? ? struct uvc_device *dev; ? ? ? ? //uvc设备 ?
? ? struct list_head list; ? ? ? ? ?//uvc视频链链表头 ?
? ? struct list_head entities; ? ? ?//uvc实体链表头 ?
? ? struct uvc_entity *processing; ?//处理Unit实体 ?
? ? struct uvc_entity *selector; ? ?//选择器Unit实体 ?
? ? struct mutex ctrl_mutex; ? ? ? ?/* Protects ctrl.info */ ?
}; ?
10.2 uvc扫描设备
[cpp] ?
static int uvc_scan_device(struct uvc_device *dev) ?
{ ?
? ? struct uvc_video_chain *chain; ?//uvc视频链 ?
? ? struct uvc_entity *term; ? ?//uvc实体 ?
??
? ? list_for_each_entry(term, &dev->entities, list) { ? ?//遍历全局实体链表 ?
? ? ? ? if (!UVC_ENTITY_IS_OTERM(term)) //获取实体链表中的输出Terminal实体 ?
? ? ? ? ? ? continue; ?
? ? ? ? if (term->chain.next || term->chain.prev) //已经添加到uvc视频链中了 ?
? ? ? ? ? ? continue; ?
? ? ? ? chain = kzalloc(sizeof(*chain), GFP_KERNEL); ? ?//分配uvc视频链内存(有多少个输入Terminal就有多少个uvc_video_chain) ?
? ? ? ? if (chain == NULL) ?
? ? ? ? ? ? return -ENOMEM; ?
? ? ? ? INIT_LIST_HEAD(&chain->entities); ? ?//初始化视频链entities(实体)链表 ?
? ? ? ? mutex_init(&chain->ctrl_mutex); ?
? ? ? ? chain->dev = dev; ? ?//捆绑uvc视频链和uvc设备 ?
? ? ? ? if (uvc_scan_chain(chain, term) < 0) { ? //扫描uvc视频链(处理所有相关的输入pin) ?
? ? ? ? ? ? kfree(chain); ?
? ? ? ? ? ? continue; ?
? ? ? ? } ?
? ? ? ? uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",uvc_print_chain(chain)); ?
? ? ? ? list_add_tail(&chain->list, &dev->chains); ? ?//添加到uvc设备的uvc视频链链表 ?
? ? } ?
? ? if (list_empty(&dev->chains)) { ?
? ? ? ? uvc_printk(KERN_INFO, "No valid video chain found.\n"); ?
? ? ? ? return -1; ?
? ? } ?
? ? return 0; ?
} ?
10.3 uvc扫描视频链
[cpp] ?
static int uvc_scan_chain(struct uvc_video_chain *chain,struct uvc_entity *term) ?
{ ?
? ? struct uvc_entity *entity, *prev; ?
? ? uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:"); ?
? ? entity = term; ?//获取实体 ?
? ? prev = NULL; ? ?//前一个实体 ?
? ? while (entity != NULL) { ?
? ? ? ? /* Entity must not be part of an existing chain */ ?
? ? ? ? if (entity->chain.next || entity->chain.prev) { ? //已经添加到uvc视频链中了 ?
? ? ? ? ? ? uvc_trace(UVC_TRACE_DESCR, "Found reference to entity %d already in chain.\n", entity->id); ?
? ? ? ? ? ? return -EINVAL; ?
? ? ? ? } ?
? ? ? ? /* Process entity */ ?
? ? ? ? if (uvc_scan_chain_entity(chain, entity) < 0) ? ?//扫描当前实体 ?
? ? ? ? ? ? return -EINVAL; ?
? ? ? ? /* Forward scan */ ?
? ? ? ? if (uvc_scan_chain_forward(chain, entity, prev) < 0) //向前扫描实体 ?
? ? ? ? ? ? return -EINVAL; ?
? ? ? ? /* Backward scan */ ?
? ? ? ? prev = entity; ? ? ?//当前实体作为下一次while循环的前一个实体 ?
? ? ? ? if (uvc_scan_chain_backward(chain, &entity) < 0) //向后扫描实体 ?
? ? ? ? ? ? return -EINVAL; ?
? ? } ?
? ? return 0; ?
} ?
将uvc视频链的输入实体添加到uvc视频链的entities链表中
将uvc视频链添加到uvc设备的chains链表中
10.3.1 扫描当前实体
[cpp] ?
static int uvc_scan_chain_entity(struct uvc_video_chain *chain,struct uvc_entity *entity) ?
{ ?
? ? switch (UVC_ENTITY_TYPE(entity)) { ?
? ? case UVC_VC_EXTENSION_UNIT: //扩展Unit ?
? ? ? ? if (uvc_trace_param & UVC_TRACE_PROBE) ?
? ? ? ? ? ? printk(" <- XU %d", entity->id); ?
? ? ? ? if (entity->bNrInPins != 1) { ?
? ? ? ? ? ? uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more than 1 input pin.\n", entity->id); ?
? ? ? ? ? ? return -1; ?
? ? ? ? } ?
? ? ? ? break; ?
? ? case UVC_VC_PROCESSING_UNIT: ? ?//处理Unit ?
? ? ? ? if (uvc_trace_param & UVC_TRACE_PROBE) ?
? ? ? ? ? ? printk(" <- PU %d", entity->id); ?
? ? ? ? if (chain->processing != NULL) { ?
? ? ? ? ? ? uvc_trace(UVC_TRACE_DESCR, "Found multiple Processing Units in chain.\n"); ?
? ? ? ? ? ? return -1; ?
? ? ? ? } ?
? ? ? ? chain->processing = entity; ?//如果是处理Unit则设置其为uvc视频链的processing对象 ?
? ? ? ? break; ?
? ? case UVC_VC_SELECTOR_UNIT: ?//选择器Unit ?
? ? ? ? if (uvc_trace_param & UVC_TRACE_PROBE) ?
? ? ? ? ? ? printk(" <- SU %d", entity->id); ?
? ? ? ? /* Single-input selector units are ignored. */ ?
? ? ? ? if (entity->bNrInPins == 1) ?
? ? ? ? ? ? break; ?
? ? ? ? if (chain->selector != NULL) { ?
? ? ? ? ? ? uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector Units in chain.\n"); ?
? ? ? ? ? ? return -1; ?
? ? ? ? } ?
? ? ? ? chain->selector = entity; ? ?//如果是选择器Unit则设置其为uvc视频链的selector对象 ?
? ? ? ? break; ?
? ? case UVC_ITT_VENDOR_SPECIFIC: ? //厂商特殊 ?
? ? case UVC_ITT_CAMERA: ? ?//输入Terminal camera ?
? ? case UVC_ITT_MEDIA_TRANSPORT_INPUT: //输入Terminal Media transport ?
? ? ? ? if (uvc_trace_param & UVC_TRACE_PROBE) ?
? ? ? ? ? ? printk(" <- IT %d\n", entity->id); ?
? ? ? ? break; ?
? ? case UVC_TT_STREAMING: ?//输入Terminal stream ?
? ? ? ? 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; ?
? ? default: ?
? ? ? ? uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type 0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); ?
? ? ? ? return -1; ?
? ? } ?
? ? list_add_tail(&entity->chain, &chain->entities); ?//添加到uvc视频链的实体链表 ?
? ? return 0; ?
} ?
10.3.2 向前扫描实体
[cpp] ?
static int uvc_scan_chain_forward(struct uvc_video_chain *chain,struct uvc_entity *entity, struct uvc_entity *prev) ?
{ ?
? ? struct uvc_entity *forward; ?
? ? int found; ?
? ? /* Forward scan */ ?
? ? forward = NULL; ?
? ? found = 0; ?
? ? while (1) { //获取实体前面的所以实体处理直到前面的实体forward=NULL为止跳出死循环 ?
? ? ? ? forward = uvc_entity_by_reference(chain->dev, entity->id,forward); ? ?//获取前一个实体 ?
? ? ? ? if (forward == NULL) ?
? ? ? ? ? ? break; ?
? ? ? ? if (forward == prev) ?
? ? ? ? ? ? continue; ?
? ? ? ? switch (UVC_ENTITY_TYPE(forward)) { ?
? ? ? ? case UVC_VC_EXTENSION_UNIT: //扩展Unit ?
? ? ? ? ? ? if (forward->bNrInPins != 1) { ?
? ? ? ? ? ? ? ? uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more than 1 input pin.\n",entity->id); ?
? ? ? ? ? ? ? ? return -EINVAL; ?
? ? ? ? ? ? } ?
? ? ? ? ? ? list_add_tail(&forward->chain, &chain->entities); //添加uvc实体到uvc视频链的entities中 ?
? ? ? ? ? ? if (uvc_trace_param & UVC_TRACE_PROBE) { ?
? ? ? ? ? ? ? ? if (!found) ?
? ? ? ? ? ? ? ? ? ? printk(" (->"); ?
? ? ? ? ? ? ? ? printk(" XU %d", forward->id); ?
? ? ? ? ? ? ? ? found = 1; ?
? ? ? ? ? ? } ?
? ? ? ? ? ? break; ?
? ? ? ? case UVC_OTT_VENDOR_SPECIFIC: ? //厂商特殊 ?
? ? ? ? case UVC_OTT_DISPLAY: ? //输出Termianl display ?
? ? ? ? case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: ? ?//输出Terminal media transport ?
? ? ? ? case UVC_TT_STREAMING: //输出Terminal stream ?
? ? ? ? ? ? if (UVC_ENTITY_IS_ITERM(forward)) { ?
? ? ? ? ? ? ? ? uvc_trace(UVC_TRACE_DESCR, "Unsupported input ter