设备描述符(通用)
USB设备描述符(白色的是每一个USB设备必须支持的,灰色的是UVC规范自己定义的):一个接口里面可能有多个设置,是不是指灰色部分,和端点的关系是怎样的?
1th讲解:
文件夹1th中myuvc.c的编写参考了uvc_driver.c。
static int myuvc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
static int cnt = 0;
printk("myuvc_probe : cnt = %d\n", cnt++); //打印interface的个数,该设备有几个接口probe函数就会被调用 几次
return 0;
}
static void myuvc_disconnect(struct usb_interface *intf)
{
static int cnt = 0;
printk("myuvc_disconnect : cnt = %d\n", cnt++);
}
static struct usb_device_id myuvc_ids[] = {
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, /* VideoControl Interface */ //1表示视频控制接口
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 2, 0) }, /* VideoStreaming Interface */ //2表示视频流接口,这一行不加也 行,视频流接口可以理解为是从属 于控制接口的,找到控制接口后会自 动找到对应的视频流接口
{}};
/* 1. 分配usb_driver */
/* 2. 设置 */
static struct usb_driver myuvc_driver = {
.name = "myuvc",
.probe = myuvc_probe, //该设备有几个接口就被调用几次
.disconnect = myuvc_disconnect,
.id_table = myuvc_ids, //表示能支持哪一些设备
};
static int myuvc_init(void)
{
/* 3. 注册 */
usb_register(&myuvc_driver);
return 0;
}
static void myuvc_exit(void)
{
usb_deregister(&myuvc_driver);
}
module_init(myuvc_init);
module_exit(myuvc_exit);
MODULE_LICENSE("GPL");
执行lsusb命令可以查看usb摄像头是否被连接成功,lsusb -v -d 0x1e4e:命令可以打印USB设备0x1e4e的描述符。
这些描述符都是我们接上USB设备后USB总线驱动程序读取设备得到的,已经事先存在内存里面了。
5th详解:
for (j = 0; j < intf->num_altsetting; j++) //一个接口下可以有多个设置
{
interface = &intf->altsetting[j].desc;
printk(" Interface Descriptor altsetting %d:\n"
" bLength %5u\n"
" bDescriptorType %5u\n"
" bInterfaceNumber %5u\n"
" bAlternateSetting %5u\n"
" bNumEndpoints %5u\n"
" bInterfaceClass %5u\n"
" bInterfaceSubClass %5u\n"
" bInterfaceProtocol %5u\n"
" iInterface %5u\n",
j,
interface->bLength, interface->bDescriptorType, interface->bInterfaceNumber, //interface是prob函数传入的变量
interface->bAlternateSetting, interface->bNumEndpoints, interface->bInterfaceClass,
interface->bInterfaceSubClass, interface->bInterfaceProtocol,
interface->iInterface);
}
6th详解(打印UVC规范自己定义的描述符):
buffer = intf->cur_altsetting->extra; //UVC规范自己定义的所有描述符都存在这个buffer里面
buflen = intf->cur_altsetting->extralen; //表示所有描述符的总长度
printk("extra buffer of interface %d:\n", cnt-1);
k = 0;
desc_cnt = 0;
while (k < buflen)
{
desc_len = buffer[k]; //每一个描述符的长度是desc_len,每一个自定义描述符的最开始位置记录着该描述符的长度,因此 desc_len = buffer[k];
printk("extra desc %d: ", desc_cnt); //表示第几个描述符(UVC自己定义的)
for (l = 0; l < desc_len; l++, k++)
{
printk("%02x ", buffer[k]); //打印第k个描述符
}
desc_cnt++;
printk("\n");
}
自定义描述符对应的应该是VS与VC拓扑图中的unit和terminal,以及他们的关系。VS接口中的自定义描述符表示了摄像头能支持哪种格式,某种格式下支持哪几种frame(分辨率等),是否支持拍照功能等。VC_HEADER等表示的是描述符的类型或者说是作用。
7th详解:
interface = &intf->cur_altsetting->desc;
if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 1)) //如果buffer[1]是0x24的话(即自定义描述符中的第二位),并且,分辨一下是视频类里面的VC与否。
{
parse_videocontrol_interface(intf, buffer, buflen); //解析VC接口,应该就是把VC里面的unit和terminal解释一遍,也就是解析自定义描述符,也就是解析那一串数字
}
if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 2))
{
parse_videostreaming_interface(intf, buffer, buflen);
}