分类: LINUX
2011-05-12 22:35:45
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+子类描述符,但是描述符排列是有顺序的,写完一个在写另外一个。
// Descriptors for the GET_DESCRIPTOR and SET_DESCRIPTOR requests.
typedef struct usb_device_descriptor {
unsigned char length; // USB_DEVICE_DESCRIPTOR_LENGTH == 18
unsigned char type; // USB_DEVREQ_DESCRIPTOR_TYPE
unsigned char usb_spec_lo;
unsigned char usb_spec_hi;
unsigned char device_class;
unsigned char device_subclass;
unsigned char device_protocol;
unsigned char max_packet_size;
unsigned char vendor_lo;
unsigned char vendor_hi;
unsigned char product_lo;
unsigned char product_hi;
unsigned char device_lo;
unsigned char device_hi;
unsigned char manufacturer_str;
unsigned char product_str;
unsigned char serial_number_str;
unsigned char number_configurations;
} __attribute__((packed)) usb_device_descriptor;
/*设备描述符*/
const usb_device_descriptor device_desc = {
.length = USB_DEVICE_DESC_SIZE, //0x12
.type = USB_DEVICE_DESCRIPTOR_TYPE, // 1
.usb_spec_lo =0x00,
.usb_spec_hi =0x02,
.device_class = 0x00,
.device_subclass = 0x00,
.device_protocol = 0x00,
.max_packet_size = USB_MAX_PACKET0,
.vendor_lo = 0x51,
.vendor_hi = 0xC2,
.product_lo = 0x03,
.product_hi = 0x20,
.device_lo =0x00,
.device_hi = 0x01,
.manufacturer_str = 0x01,
.product_str= 0x02,
.serial_number_str = 0x03,
.number_configurations = 0x01, //
};
typedef struct usb_configuration_descriptor {
unsigned char length;
unsigned char type;
unsigned char total_length_lo;
unsigned char total_length_hi; //totallength
unsigned char number_interfaces;
unsigned char configuration_id;
unsigned char configuration_str;
unsigned char attributes;
unsigned char max_power;
} __attribute__((packed)) usb_configuration_descriptor;
typedef struct usb_interface_descriptor {
unsigned char length;
unsigned char type;
unsigned char interface_id;
unsigned char alternate_setting;
unsigned char number_endpoints;
unsigned char interface_class;
unsigned char interface_subclass;
unsigned char interface_protocol;
unsigned char interface_str;
} __attribute__((packed)) usb_interface_descriptor;
typedef struct usb_endpoint_descriptor {
unsigned char length;
unsigned char type;
unsigned char endpoint;
unsigned char attributes;
unsigned char max_packet_lo;
unsigned char max_packet_hi;
unsigned char interval;
} __attribute__((packed)) usb_endpoint_descriptor;
typedef struct usb_hid_descriptor
{
unsigned char length;
unsigned char type;
unsigned char bcdhid_lo;
unsigned char bcdhid_hi;
unsigned char countrycode;
unsigned char numdescriptor;
unsigned char descriptortype;
unsigned char descriptorlength_lo;
unsigned char descriptorlength_hi;
}__attribute__((packed)) usb_hid_descriptor;
typedef struct usb_scsi_hid_config
{
const usb_configuration_descriptor config;
const usb_interface_descriptor scsi_inter;
const usb_endpoint_descriptor scsi_endpoint_in;
const usb_endpoint_descriptor scsi_endpoint_out;
const usb_interface_descriptor hid_inter;
const usb_hid_descriptor hid_desc;
const usb_endpoint_descriptor hid_endpoint_in;
}__attribute__((packed)) USB_CON_INT_ENDP_DESCRIPTOR_STRUCT;
#define USB_CON_INT_ENDP_DESCRIPTOR_STRUCT_LENGTH (sizeof(USB_CON_INT_ENDP_DESCRIPTOR_STRUCT))
const USB_CON_INT_ENDP_DESCRIPTOR_STRUCT usb_scsi_hid_con_int_endp = {
/*config*/
{
.length= USB_CONFIGUARTION_DESC_SIZE,
.type = USB_CONFIGURATION_DESCRIPTOR_TYPE,
.total_length_lo = USB_CON_INT_ENDP_DESCRIPTOR_STRUCT_LENGTH&0xff,
.total_length_hi = (USB_CON_INT_ENDP_DESCRIPTOR_STRUCT_LENGTH>>8)&0xff,
.number_interfaces = 0x02, /*两个interface*/
.configuration_id = 0x01, /*一个configuration*/
.configuration_str = 0x00,
.attributes = USB_CONFIG_BUS_POWERED,
.max_power = USB_CONFIG_POWER_MA(300)
},
/*usb mass storage interface descriptor*/
{
.length = USB_INTERFACE_DESC_SIZE,
.type = USB_INTERFACE_DESCRIPTOR_TYPE,
.interface_id = 0x00,
.alternate_setting = 0x00,
.number_endpoints = 0x02,
.interface_class = USB_DEVICE_CLASS_STORAGE, /*0x08 表示mass storage*/
.interface_subclass = 0x06, /*表示支持SCSI Primary command-2*/
.interface_protocol = 0x50, /*仅使用批量传输*/
.interface_str = 0x04
},
/*usb mass storage Bulk in 2*/
{
/* Endpoint, EP2 Bulk IN */
.length = USB_ENDPOINT_DESC_SIZE, /* bLength */
.type = USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
.endpoint = USB_ENDPOINT_IN(2), /* bEndpointAddress */
.attributes = USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
.max_packet_lo = 0x40, /* wMaxPacketSize */
.max_packet_hi =0x00,
.interval = 0x00, /* bInterval: ignore for Bulk transfer */ },
/*usb mass storage Bulk out 3*/
{
/* Endpoint, EP3 Bulk OUT */
.length = USB_ENDPOINT_DESC_SIZE, /* bLength */
.type = USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
.endpoint = USB_ENDPOINT_OUT(3), /* bEndpointAddress */
.attributes = USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
.max_packet_lo = 0x40, /* wMaxPacketSize */
.max_packet_hi =0x00,
.interval = 0x00, /* bInterval: ignore for Bulk transfer */
},
/*hid interface descriptor */
{
.length = USB_INTERFACE_DESC_SIZE,
.type = USB_INTERFACE_DESCRIPTOR_TYPE, // 4
.interface_id = 0x01,
.alternate_setting = 0x00,
.number_endpoints = 0x01,
.interface_class = USB_DEVICE_CLASS_HUMAN_INTERFACE, //03
.interface_subclass = HID_SUBCLASS_BOOT, /*0x01*/
.interface_protocol = HID_PROTOCOL_NONE, /*0x00 ,没有协议,也可以写你需要的协议具体的看hid协议*/
.interface_str = 0x00
},
/*hid subclass descriptor*/
{
.length = HID_DESC_SIZE,
.type = HID_HID_DESCRIPTOR_TYPE,
.bcdhid_lo = 0x00,
.bcdhid_hi =0x01,
.countrycode = 0x00,
.numdescriptor = 0x01,
.descriptortype = HID_REPORT_DESCRIPTOR_TYPE,
.descriptorlength_lo = HID_REPORT_DESC_SIZE&0xff,
.descriptorlength_hi = (HID_REPORT_DESC_SIZE>>8)&0xff
},
/*hid endpoint interrupt in 1*/
{
.length = USB_ENDPOINT_DESC_SIZE,
.type = USB_ENDPOINT_DESCRIPTOR_TYPE,
.endpoint = USB_ENDPOINT_IN(1),
.attributes = USB_ENDPOINT_TYPE_INTERRUPT,
.max_packet_lo =0x08,
.max_packet_hi =0x00,
.interval = 0x20
},
};
到这里基本就完成了复合设备,只要你的代码两部分都整合在一起,就好了,