10.扫描视频设备链和注册视频设备
10.1 uvc视频链
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扫描设备
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扫描视频链
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 扫描当前实体
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则