2.7 usb摄像头之usb摄像头描述符打印
学习目标:参考lsusb源码,打印USB摄像头的设备描述符、配置描述符、接口联合描述符、端点描述符;
一、lsusb命令和源码
使用命令lsusb可以看看设备的id,并执行 # lsusb -v -d 0x1b3b:2977 命令查看usb摄像头的描述符。
二、源码
打印以下描述符:
程序主要正在probe执行printk函数进行打印:
1 static int myuvc_probe(struct usb_interface *intf, 2 const struct usb_device_id *id) 3 { 4 static int cnt = 0; 5 struct usb_device *dev = interface_to_usbdev(intf); 6 struct usb_device_descriptor *descriptor = &dev->descriptor; 7 struct usb_host_config *hostconfig; 8 struct usb_config_descriptor *config; 9 struct usb_interface_assoc_descriptor *assoc_desc; 10 struct usb_interface_descriptor *interface; 11 struct usb_endpoint_descriptor *endpoint; 12 int i, j, k, l, m; 13 unsigned char *buffer; 14 int buflen; 15 int desc_len; 16 int desc_cnt; 17 18 printk("myuvc_probe : cnt = %d\n", cnt++); 19 20 /* 打印设备描述符 */ 21 printk("Device Descriptor:\n" 22 " bLength %5u\n" 23 " bDescriptorType %5u\n" 24 " bcdUSB %2x.%02x\n" 25 " bDeviceClass %5u \n" 26 " bDeviceSubClass %5u \n" 27 " bDeviceProtocol %5u \n" 28 " bMaxPacketSize0 %5u\n" 29 " idVendor 0x%04x \n" 30 " idProduct 0x%04x \n" 31 " bcdDevice %2x.%02x\n" 32 " iManufacturer %5u\n" 33 " iProduct %5u\n" 34 " iSerial %5u\n" 35 " bNumConfigurations %5u\n", 36 descriptor->bLength, descriptor->bDescriptorType, 37 descriptor->bcdUSB >> 8, descriptor->bcdUSB & 0xff, 38 descriptor->bDeviceClass, 39 descriptor->bDeviceSubClass, 40 descriptor->bDeviceProtocol, 41 descriptor->bMaxPacketSize0, 42 descriptor->idVendor, descriptor->idProduct, 43 descriptor->bcdDevice >> 8, descriptor->bcdDevice & 0xff, 44 descriptor->iManufacturer, 45 descriptor->iProduct, 46 descriptor->iSerialNumber, 47 descriptor->bNumConfigurations); 48 49 for (i = 0; i < descriptor->bNumConfigurations; i++) 50 { 51 hostconfig = &dev->config[i]; //第i个配置 52 config = &hostconfig->desc; 53 printk(" Configuration Descriptor %d:\n" 54 " bLength %5u\n" 55 " bDescriptorType %5u\n" 56 " wTotalLength %5u\n" 57 " bNumInterfaces %5u\n" 58 " bConfigurationValue %5u\n" 59 " iConfiguration %5u\n" 60 " bmAttributes 0x%02x\n", 61 i, 62 config->bLength, config->bDescriptorType, 63 le16_to_cpu(config->wTotalLength), 64 config->bNumInterfaces, config->bConfigurationValue, 65 config->iConfiguration, 66 config->bmAttributes); 67 68 assoc_desc = hostconfig->intf_assoc[0]; //IAD 69 printk(" Interface Association:\n" 70 " bLength %5u\n" 71 " bDescriptorType %5u\n" 72 " bFirstInterface %5u\n" 73 " bInterfaceCount %5u\n" 74 " bFunctionClass %5u\n" 75 " bFunctionSubClass %5u\n" 76 " bFunctionProtocol %5u\n" 77 " iFunction %5u\n", 78 assoc_desc->bLength, 79 assoc_desc->bDescriptorType, 80 assoc_desc->bFirstInterface, 81 assoc_desc->bInterfaceCount, 82 assoc_desc->bFunctionClass, 83 assoc_desc->bFunctionSubClass, 84 assoc_desc->bFunctionProtocol, 85 assoc_desc->iFunction); 86 87 for (j = 0; j < intf->num_altsetting; j++) 88 { 89 interface = &intf->altsetting[j].desc; //第j个设置的描述符 接口描述符 90 printk(" Interface Descriptor altsetting %d:\n" 91 " bLength %5u\n" 92 " bDescriptorType %5u\n" 93 " bInterfaceNumber %5u\n" 94 " bAlternateSetting %5u\n" 95 " bNumEndpoints %5u\n" 96 " bInterfaceClass %5u\n" 97 " bInterfaceSubClass %5u\n" 98 " bInterfaceProtocol %5u\n" 99 " iInterface %5u\n", 100 j, 101 interface->bLength, interface->bDescriptorType, interface->bInterfaceNumber, 102 interface->bAlternateSetting, interface->bNumEndpoints, interface->bInterfaceClass, 103 interface->bInterfaceSubClass, interface->bInterfaceProtocol, 104 interface->iInterface); 105 /* 打印端点描述符 */ 106 for (m = 0; m < interface->bNumEndpoints; m++) 107 { 108 endpoint = &intf->altsetting[j].endpoint[m].desc; 109 dump_endpoint(endpoint); 110 } 111 112 } 113 /*自定义描述符*/ 114 buffer = intf->cur_altsetting->extra; 115 buflen = intf->cur_altsetting->extralen; 116 printk("extra buffer of interface %d:\n", cnt-1); 117 k = 0; 118 desc_cnt = 0; 119 while (k < buflen) 120 { 121 desc_len = buffer[k]; 122 printk("extra desc %d: ", desc_cnt); 123 for (l = 0; l < desc_len; l++, k++) 124 { 125 printk("%02x ", buffer[k]); 126 } 127 desc_cnt++; 128 printk("\n"); 129 } 130 //模拟lsusb打印内核usb摄像头信息 131 interface = &intf->cur_altsetting->desc; 132 if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 1)) 133 { 134 parse_videocontrol_interface(intf, buffer, buflen); 135 } 136 if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 2)) 137 { 138 parse_videostreaming_interface(intf, buffer, buflen); 139 } 140 141 } 142 143 144 return 0; 145 }
分析:
1. VideoControl Interface的自定义描述符:
[318044.582155] extra buffer of interface 0: [318044.582156] extra desc 0: 0d 24 01 00 01 4d 00 80 c3 c9 01 01 01 [318044.582161] extra desc 1: 12 24 02 01 01 02 00 00 00 00 00 00 00 00 03 0e 00 00 [318044.582166] extra desc 2: 09 24 03 02 01 01 00 04 00 [318044.582170] extra desc 3: 0b 24 05 03 01 00 00 02 7f 14 00 [318044.582174] extra desc 4: 1a 24 06 04 ad cc b1 c2 f6 ab b8 48 8e 37 32 d4 f3 a3 fe ec 08 01 03 01 3f 00
解析:
extra buffer of interface 0:
extra desc 0: 0d 24 01 00 01 4d 00 80 c3 c9 01 01 01
VC_HEADER
extra desc 1: 12 24 02 01 01 02 00 00 00 00 00 00 00 00 03 0e 00 00
VC_INPUT_TERMINAL ID
extra desc 2: 09 24 03 02 01 01 00 04 00
VC_OUTPUT_TERMINAL ID wTerminalType bAssocTerminal bSourceID
extra desc 3: 0b 24 05 03 01 00 00 02 7f 14 00
VC_PROCESSING_UNIT ID bSourceID wMaxMultiplier bControlSize bmControls --->UVC 1.5 Class specification 69页
extra desc 0: 0d 24 01 00 01 4d 00 80 c3 c9 01 01 01
VC_HEADER
extra desc 1: 12 24 02 01 01 02 00 00 00 00 00 00 00 00 03 0e 00 00
VC_INPUT_TERMINAL ID
extra desc 2: 09 24 03 02 01 01 00 04 00
VC_OUTPUT_TERMINAL ID wTerminalType bAssocTerminal bSourceID
extra desc 3: 0b 24 05 03 01 00 00 02 7f 14 00
VC_PROCESSING_UNIT ID bSourceID wMaxMultiplier bControlSize bmControls --->UVC 1.5 Class specification 69页
bControlSize =2表示,后面2个字节,支持哪些功能,该位设为1表示为支持此功能;
extra desc 4: 1a 24 06 04 ad cc b1 c2 f6 ab b8 48 8e 37 32 d4 f3 a3 fe ec 08 01 03 01 3f 00
VC_EXTENSION_UNIT ID GUID bNumControls bNrInPins baSourceID
VC_EXTENSION_UNIT ID GUID bNumControls bNrInPins baSourceID
从而可知数据流向:IT(01) ===> PU(03) ===> EU(04) ===> OT(02)
1)第1字节为长度;
2)第2个字节表示为自定义的;
3)第3个字节为VC定义的子类:Video Class-Specific VC Interface Descriptor Subtypes 172页
VC_DESCRIPTOR_UNDEFINED 0x00
VC_HEADER 0x01
VC_INPUT_TERMINAL 0x02
VC_OUTPUT_TERMINAL 0x03
VC_SELECTOR_UNIT 0x04
VC_PROCESSING_UNIT 0x05
VC_EXTENSION_UNIT 0x06
VC_ENCODING_UNIT 0x07
4)第4个字节为bSourceID,来源
5)后面字节要根据手册分析;
2. VideoStreaming Interface的自定义描述符:
[318044.582312] extra buffer of interface 1: [318044.582313] extra desc 0: 0e 24 01 01 df 00 81 00 02 02 01 01 01 00 [318044.582317] extra desc 1: 1b 24 04 01 05 59 55 59 32 00 00 10 00 80 00 00 aa 00 38 9b 71 10 01 00 00 00 00 [318044.582325] extra desc 2: 1e 24 05 01 00 80 02 e0 01 00 00 ca 08 00 00 ca 08 00 60 09 00 15 16 05 00 01 15 16 05 00 [318044.582333] extra desc 3: 1e 24 05 02 00 60 01 20 01 00 80 e6 02 00 80 e6 02 00 18 03 00 15 16 05 00 01 15 16 05 00 [318044.582342] extra desc 4: 1e 24 05 03 00 40 01 f0 00 00 80 32 02 00 80 32 02 00 58 02 00 15 16 05 00 01 15 16 05 00 [318044.582350] extra desc 5: 1e 24 05 04 00 b0 00 90 00 00 a0 b9 00 00 a0 b9 00 00 c6 00 00 15 16 05 00 01 15 16 05 00 [318044.582358] extra desc 6: 1e 24 05 05 00 a0 00 78 00 00 a0 8c 00 00 a0 8c 00 00 96 00 00 15 16 05 00 01 15 16 05 00 [318044.582367] extra desc 7: 1a 24 03 00 05 80 02 e0 01 60 01 20 01 40 01 f0 00 b0 00 90 00 a0 00 78 00 00 [318044.582374] extra desc 8: 06 24 0d 01 01 04
分析:
第3个字节:数据来源
VS_INPUT_HEADER 0x01
VS_STILL_IMAGE_FRAME 0x03 // 表示支持静态图片,拍照功能
VS_FORMAT_UNCOMPRESSED 0x04 // 表示格式
VS_FRAME_UNCOMPRESSED 0x05 frame //表示一种格式下可支持多种分辨率
VS_COLORFORMAT 0x0D
VS_STILL_IMAGE_FRAME 0x03 // 表示支持静态图片,拍照功能
VS_FORMAT_UNCOMPRESSED 0x04 // 表示格式
VS_FRAME_UNCOMPRESSED 0x05 frame //表示一种格式下可支持多种分辨率
VS_COLORFORMAT 0x0D