您现在的位置: USB开发网 > USB技术文档 > USB MASS STORAGE
- USB MASS STORAGE

一个USB HID KEYBOARD和USB MASS STORAGE复合设备示例

------分隔线----------------------------

  usb真是很强很大,强是现在很多产品都用她来做,为了方便,不用开发驱动。大是因为usb协议太多了,就光hid都有好多种。还是扯回正题,这次总结复合型设备,前面总结了hid和mass storage设备,如果在正常情况下两个设备都正常了的,那么现在就可以来做做复合型设备了。

 
  百度和google都没找到她的定义,那么我来定义一下(见笑),复合型设备:具有两种usb设备功能的一种设备,无论是相同的设备功能,还是不同的设备功能,只要同时具有两种以上的功能就是复合型设备。其实很直白,大家都看的出来。
 
  现在就把hid keyboard and usb mass storage复合起来,组成一个设备。首先要说的是既然是复合型设备,那么就有多个interface,这里有两个设备,那么就需要两个interface,需要几个设备描述符呢,一个就够了,那配置描述符呢,也只需要一个就好了,那需要几个端点描述符呢,这个嘛,我就不知道了(开玩笑,你在总结你不知道),这个就得讲讲usb的几种传输
模式了。
 
  在usb里面一共有四种传输:控制传输、中断传输、批量传输、等时传输。控制和批量端点用于异步的数据传输,驱动需要他们就立马工作。中断和等时端点是周期性的,即在固定时间段连续的传输数据。是不是有点熟悉,的确,前面总结过的,在这里再提提。所以有几个端点,还是得看你在用哪种传输模式,hid keyboard和usb mass storage他们使用的传输方式是中断传输和批量传输。
 
中断传输:interrupt in ,在这里只需要interrupt in就ok了,既只要一个端点,至于interrupt out就不用管了。
批量传输:bulk in和bulk out,由于u盘是双向的,当然需要有两个端点哦,毕竟他们通信要有来回才行啊。
 
  所以要复合hid keyboard和usb mass storage就需要三个端点。好了,前面说来复合型设备的描述符分别是:设备描述符*1+配置描述符*1+端点描述符*3,那么到这里就完了吗,如果只是usb mass storage,在加一个端点就完了,但是这里是Hid,还需要一个子类,在hid里面还有很多子类,那么就需要区分他们,不然host不知道你是哪家的,好比有很多人叫张三,但是这个世界那么多是张三,你知道他应该是哪家的呢,还是只有slave主动说自己是谁方便。现在配置是设备描述符*1+配置描述符*1+端点描述符*3+子类描述符,但是描述符排列是有顺序的,写完一个在写另外一个。
 
 
  1. // Descriptors for the GET_DESCRIPTOR and SET_DESCRIPTOR requests. 
  2. typedef struct usb_device_descriptor { 
  3.    unsigned char      length;                // USB_DEVICE_DESCRIPTOR_LENGTH == 18 
  4.    unsigned char      type;                  // USB_DEVREQ_DESCRIPTOR_TYPE 
  5.    unsigned char      usb_spec_lo; 
  6.    unsigned char      usb_spec_hi; 
  7.    unsigned char      device_class; 
  8.    unsigned char      device_subclass; 
  9. unsigned char      device_protocol; 
  10.    unsigned char      max_packet_size; 
  11.    unsigned char      vendor_lo; 
  12.    unsigned char      vendor_hi; 
  13.    unsigned char      product_lo; 
  14.    unsigned char      product_hi; 
  15.    unsigned char      device_lo; 
  16.    unsigned char      device_hi; 
  17.    unsigned char      manufacturer_str; 
  18.    unsigned char      product_str; 
  19.    unsigned char      serial_number_str; 
  20.    unsigned char      number_configurations; 
  21. } __attribute__((packed)) usb_device_descriptor; 
  22.  
  23. /*设备描述符*/ 
  24.       const usb_device_descriptor  device_desc = { 
  25.                     .length = USB_DEVICE_DESC_SIZE, //0x12 
  26. .type = USB_DEVICE_DESCRIPTOR_TYPE, // 1 
  27.                     .usb_spec_lo =0x00, 
  28.                     .usb_spec_hi =0x02, 
  29.                     .device_class = 0x00, 
  30.                     .device_subclass = 0x00, 
  31.                     .device_protocol = 0x00, 
  32.                     .max_packet_size = USB_MAX_PACKET0, 
  33.                     .vendor_lo = 0x51, 
  34.                     .vendor_hi = 0xC2, 
  35.                     .product_lo = 0x03, 
  36.                     .product_hi = 0x20, 
  37.                     .device_lo =0x00, 
  38.                     .device_hi = 0x01, 
  39.                     .manufacturer_str = 0x01, 
  40.                     .product_str= 0x02, 
  41.                     .serial_number_str = 0x03, 
  42.                 .number_configurations = 0x01, // 
  43. }; 
  44.  
  45.  
  46. typedef struct usb_configuration_descriptor { 
  47.    unsigned char      length; 
  48.    unsigned char      type; 
  49.        
  50.    unsigned char      total_length_lo; 
  51.    unsigned char      total_length_hi; //totallength 
  52.        
  53.    unsigned char      number_interfaces;   
  54.    unsigned char      configuration_id; 
  55.    unsigned char      configuration_str; 
  56.    unsigned char      attributes; 
  57.    unsigned char      max_power; 
  58. } __attribute__((packed)) usb_configuration_descriptor; 
  59.  
  60. typedef struct usb_interface_descriptor { 
  61.    unsigned char      length; 
  62. unsigned char      type; 
  63.    unsigned char      interface_id; 
  64.    unsigned char      alternate_setting; 
  65.    unsigned char      number_endpoints; 
  66.    unsigned char      interface_class; 
  67.    unsigned char      interface_subclass; 
  68.    unsigned char      interface_protocol; 
  69.    unsigned char      interface_str; 
  70. } __attribute__((packed)) usb_interface_descriptor; 
  71.  
  72.  
  73. typedef struct usb_endpoint_descriptor { 
  74.    unsigned char      length; 
  75.    unsigned char      type; 
  76.    unsigned char      endpoint; 
  77.    unsigned char      attributes; 
  78.    unsigned char      max_packet_lo; 
  79.    unsigned char      max_packet_hi; 
  80.    unsigned char      interval; 
  81. } __attribute__((packed))  
  82. usb_endpoint_descriptor; 
  83.  
  84. typedef struct usb_hid_descriptor 
  85.    unsigned char      length; 
  86.    unsigned char      type; 
  87.    unsigned char      bcdhid_lo; 
  88.    unsigned char      bcdhid_hi; 
  89.    unsigned char      countrycode; 
  90.    unsigned char       numdescriptor; 
  91.    unsigned char      descriptortype; 
  92.    unsigned char      descriptorlength_lo; 
  93.    unsigned char      descriptorlength_hi; 
  94.        
  95. }__attribute__((packed)) usb_hid_descriptor; 
  96.  
  97.  
  98. typedef struct usb_scsi_hid_config 
  99.       const usb_configuration_descriptor config; 
  100.  
  101.       const usb_interface_descriptor    scsi_inter;                   
  102.       const usb_endpoint_descriptor     scsi_endpoint_in; 
  103.       const usb_endpoint_descriptor     scsi_endpoint_out; 
  104.  
  105.       const usb_interface_descriptor    hid_inter; 
  106.       const usb_hid_descriptor            hid_desc;       
  107.       const usb_endpoint_descriptor     hid_endpoint_in; 
  108.  
  109. }__attribute__((packed)) USB_CON_INT_ENDP_DESCRIPTOR_STRUCT; 
 
 
  1. #define USB_CON_INT_ENDP_DESCRIPTOR_STRUCT_LENGTH                (sizeof(USB_CON_INT_ENDP_DESCRIPTOR_STRUCT)) 
  2.  
  3. const USB_CON_INT_ENDP_DESCRIPTOR_STRUCT usb_scsi_hid_con_int_endp = { 
  4.  
  5.       /*config*/ 
  6.       { 
  7.       .length= USB_CONFIGUARTION_DESC_SIZE, 
  8.       .type = USB_CONFIGURATION_DESCRIPTOR_TYPE, 
  9.       .total_length_lo =  USB_CON_INT_ENDP_DESCRIPTOR_STRUCT_LENGTH&0xff, 
  10.       .total_length_hi = (USB_CON_INT_ENDP_DESCRIPTOR_STRUCT_LENGTH>>8)&0xff, 
  11.       .number_interfaces = 0x02, /*两个interface*/ 
  12.       .configuration_id = 0x01, /*一个configuration*/ 
  13. .configuration_str = 0x00, 
  14.       .attributes = USB_CONFIG_BUS_POWERED, 
  15.       .max_power = USB_CONFIG_POWER_MA(300) 
  16.       }, 
  17.  
  18.  
  19.  
  20.       /*usb mass storage interface descriptor*/     
  21.       { 
  22.       .length = USB_INTERFACE_DESC_SIZE, 
  23.       .type   = USB_INTERFACE_DESCRIPTOR_TYPE, 
  24.       .interface_id = 0x00, 
  25.       .alternate_setting = 0x00, 
  26.       .number_endpoints = 0x02, 
  27.       .interface_class = USB_DEVICE_CLASS_STORAGE, /*0x08表示mass storage*/ 
  28.       .interface_subclass = 0x06, /*表示支持SCSI Primary command-2*/ 
  29. .interface_protocol = 0x50, /*仅使用批量传输*/ 
  30.       .interface_str = 0x04 
  31.       }, 
  32.  
  33.  
  34.  
  35.       /*usb mass storage Bulk in 2*/ 
  36.       { 
  37.       /* Endpoint, EP2 Bulk IN */ 
  38.       .length = USB_ENDPOINT_DESC_SIZE,           /* bLength */ 
  39.       .type = USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType */ 
  40.       .endpoint = USB_ENDPOINT_IN(2),               /* bEndpointAddress */ 
  41.       .attributes = USB_ENDPOINT_TYPE_BULK,           /* bmAttributes */ 
  42.       .max_packet_lo = 0x40,                    /* wMaxPacketSize */ 
  43.       .max_packet_hi =0x00,                
  44. .interval = 0x00,    /* bInterval: ignore for Bulk transfer */                     }, 
  45.  
  46.  
  47.       /*usb mass storage Bulk out 3*/ 
  48.       { 
  49.       /* Endpoint, EP3 Bulk OUT */ 
  50.       .length = USB_ENDPOINT_DESC_SIZE,           /* bLength */ 
  51.       .type =   USB_ENDPOINT_DESCRIPTOR_TYPE,     /* bDescriptorType */ 
  52.       .endpoint = USB_ENDPOINT_OUT(3),              /* bEndpointAddress */ 
  53.       .attributes = USB_ENDPOINT_TYPE_BULK,           /* bmAttributes */ 
  54.       .max_packet_lo = 0x40,                    /* wMaxPacketSize */ 
  55.       .max_packet_hi =0x00,                              
  56.       .interval = 0x00,    /* bInterval: ignore for Bulk transfer */            
  57. }, 
  58.  
  59.  
  60.  
  61.  
  62.  
  63.              /*hid interface descriptor */ 
  64.       { 
  65.       .length = USB_INTERFACE_DESC_SIZE, 
  66.       .type   = USB_INTERFACE_DESCRIPTOR_TYPE, // 4 
  67.       .interface_id = 0x01, 
  68.       .alternate_setting = 0x00, 
  69.       .number_endpoints = 0x01, 
  70.       .interface_class = USB_DEVICE_CLASS_HUMAN_INTERFACE, //03 
  71.       .interface_subclass = HID_SUBCLASS_BOOT, /*0x01*/ 
  72.       .interface_protocol = HID_PROTOCOL_NONE, /*0x00,没有协议,也可以写你需要的协议具体的看hid协议*/ 
  73.       .interface_str = 0x00 
  74.       }, 
  75.  
  76.       /*hid subclass descriptor*/ 
  77.       { 
  78.       .length = HID_DESC_SIZE, 
  79.       .type = HID_HID_DESCRIPTOR_TYPE, 
  80.       .bcdhid_lo = 0x00, 
  81.       .bcdhid_hi =0x01, 
  82.       .countrycode = 0x00, 
  83.       .numdescriptor = 0x01, 
  84.       .descriptortype = HID_REPORT_DESCRIPTOR_TYPE, 
  85.       .descriptorlength_lo = HID_REPORT_DESC_SIZE&0xff, 
  86.       .descriptorlength_hi = (HID_REPORT_DESC_SIZE>>8)&0xff 
  87.       }, 
  88.  
  89.  
  90.       /*hid endpoint interrupt in 1*/ 
  91.       { 
  92.       .length = USB_ENDPOINT_DESC_SIZE, 
  93.       .type  
  94. USB_ENDPOINT_DESCRIPTOR_TYPE, 
  95.       .endpoint = USB_ENDPOINT_IN(1), 
  96.       .attributes = USB_ENDPOINT_TYPE_INTERRUPT, 
  97.       .max_packet_lo =0x08, 
  98.       .max_packet_hi =0x00, 
  99.       .interval = 0x20 
  100.       }, 
  101.  
  102. };                                    
 
 到这里基本就完成了复合设备,只要你的代码两部分都整合在一起,就好了。
------分隔线----------------------------
联系我们
  • Q Q: 1148374829 点击这里给我发消息
  • 旺旺:jhoneqhsieh 点击这里给我发消息
  • 电话:(0)15923141204
  • 淘宝网店
USB开源项目