uvc摄像头代码解析6

10.扫描视频设备链和注册视频设备
10.1 u vc视频链
[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是如何组建起来的
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值