海思hi3536上uvc驱动问题

最近在海思hi3536平台上开发usb设备检测的驱动,其中有一项功能是usb摄像头相关的,通过usb分析仪确定该usb摄像头有四个接口。我主要关注前两个接口,一个是uvc control,一个是uvc stream,这两个是uvc正常工作必须的接口。

然后再看uvc_driver驱动的usb_device_id列表,里面只有uvc control这一接口会在总线match函数中匹配,那么问题来了,第二个接口没有和总线匹配,那么它是如何和uvc驱动关联起来的,难道是驱动的id列表忘了这一个接口? 于是我手动在usb_device_id增加了第二个接口对应的相关id,接下来看看会发生什么。

重新加载修改过的驱动后发现还是只调用了一次uvc_probe函数,这是为什么呢?接下来只能从usb相关驱动源码上找一找原因了。

首先看usb_set_configuration函数,

    for (i = 0; i < nintf; ++i) {
		struct usb_interface_cache *intfc;
		struct usb_interface *intf;
		struct usb_host_interface *alt;

		cp->interface[i] = intf = new_interfaces[i];
		intfc = cp->intf_cache[i];
		intf->altsetting = intfc->altsetting;
		intf->num_altsetting = intfc->num_altsetting;
		kref_get(&intfc->ref);

		alt = usb_altnum_to_altsetting(intf, 0);

		/* No altsetting 0?  We'll assume the first altsetting.
		 * We could use a GetInterface call, but if a device is
		 * so non-compliant that it doesn't have altsetting 0
		 * then I wouldn't trust its reply anyway.
		 */
		if (!alt)
			alt = &intf->altsetting[0];

		intf->intf_assoc =
			find_iad(dev, cp, alt->desc.bInterfaceNumber);
		intf->cur_altsetting = alt;
		usb_enable_interface(dev, intf, true);
		intf->dev.parent = &dev->dev;
		intf->dev.driver = NULL;
		intf->dev.bus = &usb_bus_type;
		intf->dev.type = &usb_if_device_type;
		intf->dev.groups = usb_interface_groups;
		intf->dev.dma_mask = dev->dev.dma_mask;
		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
		intf->minor = -1;
		device_initialize(&intf->dev);
		pm_runtime_no_callbacks(&intf->dev);
		dev_set_name(&intf->dev, "%d-%s:%d.%d",
			dev->bus->busnum, dev->devpath,
			configuration, alt->desc.bInterfaceNumber);
	}

    for (i = 0; i < nintf; ++i) {
		struct usb_interface *intf = cp->interface[i];

		dev_dbg(&dev->dev,
			"adding %s (config #%d, interface %d)\n",
			dev_name(&intf->dev), configuration,
			intf->cur_altsetting->desc.bInterfaceNumber);
		device_enable_async_suspend(&intf->dev);
		ret = device_add(&intf->dev);
		if (ret != 0) {
			dev_err(&dev->dev, "device_add(%s) --> %d\n",
				dev_name(&intf->dev), ret);
			continue;
		}
		create_intf_ep_devs(intf);
	}

 

该函数功能主要是根据usb设备的配置描述符给接口描述符分配资源,初始化各个接口描述符,然后调用device_add函数注册usb接口设备。

具体到uvc驱动的话,此处应该是分配并初始化了四个usb interface,调用device_add注册了四个usb interface设备,遇到的问题是,注册第二个usb接口时发现没有调用uvc_probe,进一步跟踪发现在注册第二个接口时intf->dev.driver已经不是NULL了(理论上似乎应该时NULL才对),所以在device_attach中提前返回了。猜测只能是uvc_probe函数中对第二个usb 接口的intf->dev.driver赋值了,将uvc_probe函数中的代码注释掉,再次重新加载驱动,此时注册第二个usb接口时发现intf->dev.driver变成了NULL,因此可以确定是uvc_probe函数中对第二个usb接口的intf->dev.driver赋值了。

走读一遍uvc_probe函数,最终发现是在uvc_parse_standard_control函数中的第一个switch分支中对对第二个usb接口的intf->dev.driver赋值的。

通过上面的追踪得到了一个结论,对于有些usb组合设备并不一定需要每个接口都匹配不同的驱动。以前做过usb键盘、鼠标、U盘的组合设备,在这个设备中因为三个接口各个功能独立,因此需要加载三个不同的驱动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值