您的位置:首页 > 编程语言

uvc摄像头代码解析6

2017-09-14 17:48 567 查看
10.扫描视频设备链和注册视频设备

10.1 uvc视频链

[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 terminal %u.\n", forward->id);  

                return -EINVAL;  

            }  

            list_add_tail(&forward->chain, &chain->entities); //添加uvc实体到uvc视频链的entities中  

            if (uvc_trace_param & UVC_TRACE_PROBE) {  

                if (!found)  

                    printk(" (->");  

                printk(" OT %d", forward->id);  

                found = 1;  

            }  

            break;  

        }  

    }  

    if (found)  

        printk(")");  

    return 0;  

}  

10.3.3 向后扫描实体

[cpp]  

static int uvc_scan_chain_backward(struct uvc_video_chain *chain,struct uvc_entity **_entity)  

{  

    struct uvc_entity *entity = *_entity;  

    struct uvc_entity *term;  

    int id = -EINVAL, i;  

    switch (UVC_ENTITY_TYPE(entity)) {  

    case UVC_VC_EXTENSION_UNIT: //扩展Unit  

    case UVC_VC_PROCESSING_UNIT:    //处理Unit处理Unit的输入Terminal个数只能为1  

        id = entity->baSourceID[0];  //获取输入pin(Unit/Terminal)的ID  

        break;  

    case UVC_VC_SELECTOR_UNIT:  //选择器实体  

        /* Single-input selector units are ignored. */  

        if (entity->bNrInPins == 1) {    //若输入pin个数为1  

            id = entity->baSourceID[0];  //获取输入in(Unit/Terminal)的ID  

            break;  

        }  

        if (uvc_trace_param & UVC_TRACE_PROBE)  

            printk(" <- IT");  

        chain->selector = entity;    //uvc视频链的selector对象指向uvc实体  

        for (i = 0; i < entity->bNrInPins; ++i) { //总共有多少个输入pin  

            id = entity->baSourceID[i];  //获取输入in(Unit/Terminal)的ID  

            term = uvc_entity_by_id(chain->dev, id); //获取对应的输入pin实体  

            if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {  

                uvc_trace(UVC_TRACE_DESCR, "Selector unit %d input %d isn't connected to an input terminal\n", entity->id, i);  

                return -1;  

            }  

            if (uvc_trace_param & UVC_TRACE_PROBE)  

                printk(" %d", term->id);  

            list_add_tail(&term->chain, &chain->entities);    //添加uvc实体到uvc视频链的entities链表  

            uvc_scan_chain_forward(chain, term, entity);    //向前扫描实体  

        }  

        if (uvc_trace_param & UVC_TRACE_PROBE)  

            printk("\n");  

        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->baSourceID[0] : 0;  

        break;  

    }  

    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;  

}  

注意到trace打印的语句会发现有一条

[cpp]  

uvcvideo: Scanning UVC chain: OT 2 <- XU 5 <- XU 4 <- PU 3 <- IT 1  

可以看到这些Unit和Terminal是如何组建起来的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: