一 枚举过程之文字描述
? 主机集线器监视着每个端口的信号电压, 当有新设备接入时便可觉察.(集线器端口的两根信号线的每一根都有 15kΩ的下拉电阻, 而每一个设备在 D + 都有一个 1.5kΩ的上拉电阻. 当用 USB 线将 PC 和设备接通后, 设备的上拉电阻使信号线的电位升高, 因此被主机集线器检测到.)
? 连接了设备的 HUB 在 HOST 查询其状态改变端点 时返回对应的 bitmap, 告知 HOST 某个 PORT 状态发生了改变.
? 主机向 HUB 查询该 PORT 的状态, 得知有设备连接, 并知道了该设备的基本特性.
? 主机等待 (至少 100mS) 设备上电稳定, 然后向 HUB 发送请求, 复位并使能该 PORT.
? HUB 执行 PORT 复位操作, 复位完成后该 PORT 就使能了. 现在设备进入到 defalut 状态, 可以从 Vbus 获取不超过 100mA 的电流. 主机可以通过 0 地址与其通讯.
1 主机通过 0 地址向该设备发送 get_device_descriptor 标准请求, 获取设备的描述符. 目的是取得却缺省控制管道所支持的最大数据包长度, 该长度包含在设备描述符的 bMaxPacketSize0 字段中, 其地址偏移量为 7, 主机读取 64 字节, 但实际不一定能读到, 因为这时候还不知道一次能读取的最大长度, 但是肯定能读到前 8 个字节, 因为可能的值为(8,16,32,64).
? 主机再次向 HUB 发送请求, 复位该 PORT.
2 主机通过标准请求 set_address 给设备分配地址.
3 主机通过新地址向设备发送 get_device_descriptor 标准请求, 获取设备的描述符.
4 主机通过新地址向设备发送其他 get_configuration 请求, 获取设备的配置描述符.
- void usb_hub_port_connect_change(struct usb_device *dev, int port)
- {
- /* 获取端口状态变化信息 */
- usb_get_port_status(dev, port + 1, portsts) ;
- /* Clear the connection change status 清除端口变化 */
- usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
- /* 等待至少 100ms, 等待插入设备稳定 */
- mdelay(200);
- /* Reset the port 对设备的第一次操作, 复位设备; 对设备的第一次操作一定是复位. 先复位, 后获取
- * 注意 hub 端口和 usb 设备是不同的操作, 前面 usb_get_port_status 是对 hub 端口的操作.*/
- hub_port_reset(dev, port, &portstatus) ;
- /* 等待设备复位完成 */
- mdelay(200);
- /* 好戏来了 */
- usb_new_device(usb);
- }
- int usb_new_device(struct usb_device *dev) { /* 包大小先初始化一个值 64*/ dev->maxpacketsize = PACKET_SIZE_64; /*1 获取设备描述符, 读取长度 64*/ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); /* 获取最大包长度 */ dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; /* reset the port for the second time 第二次复位设备 */ err = hub_port_reset(dev->parent, port, &portstatus); dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; switch (dev->descriptor.bMaxPacketSize0) { case 8: dev->maxpacketsize = PACKET_SIZE_8; break; case 16: dev->maxpacketsize = PACKET_SIZE_16; break; case 32: dev->maxpacketsize = PACKET_SIZE_32; break; case 64: dev->maxpacketsize = PACKET_SIZE_64; break; } dev->devnum = addr; /*2 设置设备地址 */ err = usb_set_address(dev); /* set address */ mdelay(10); /* Let the SET_ADDRESS settle */ tmp = sizeof(dev->descriptor); /*3 用新设置的地址获取设备描述符 */ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, tmpbuf, sizeof(dev->descriptor)); memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor)); /* only support for one config for now */ /*4 和 5 封装成了一个函数 获取配置描述符 */ usb_get_configuration_no(dev, tmpbuf, 0); usb_parse_config(dev, tmpbuf, 0); usb_set_maxpacket(dev); /* we set the default configuration here */ /*6 配置设备 */ usb_set_configuration(dev, dev->config.desc.bConfigurationValue); return 0; }
- int usb_get_configuration_no(struct usb_device *dev,
- unsigned char *buffer, int cfgno)
- {
- struct usb_configuration_descriptor *config;
- config = (struct usb_configuration_descriptor *)&buffer[0];
- /*4 获取配置描述符, 仅配置描述使长度为 9*/
- result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
- /* 当前配置下的描述符总长度 */
- tmp = le16_to_cpu(config->wTotalLength);
- /*5 再一次获取当前配置下的全部配置, 接口, 端点信息 */
- result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp);
- return result;
- }
- /* device request (setup) */
- struct devrequest {
- unsigned char requesttype;
- unsigned char request;
- unsigned shortvalue;
- unsigned shortindex;
- unsigned shortlength;
- } __attribute__ ((packed));
- requesttype=0x80,request=0x06,value=0x0100,index=0x0000,length=0x0040;
- struct usb_device_descriptor {
- u8 bLength;
- u8 bDescriptorType;
- u16 bcdUSB;
- u8 bDeviceClass;
- u8 bDeviceSubClass;
- u8 bDeviceProtocol;
- u8 bMaxPacketSize0;
- u16 idVendor;
- u16 idProduct;
- u16 bcdDevice;
- u8 iManufacturer;
- u8 iProduct;
- u8 iSerialNumber;
- u8 bNumConfigurations;
- } __attribute__ ((packed));
- struct usb_configuration_descriptor {
- u8 bLength; /*09, 描述符长度为 9*/
- u8 bDescriptorType;/* 0x2, 表示配置描述符 */
- u16 wTotalLength; /*0x002E, 表示当前配置下的各种描述信息总长度为 46*/
- u8 bNumInterfaces; /*0x01, 当前配置下共一个接口 */
- u8 bConfigurationValue; /*0x01, 当前配置索引, 当设置某一配置时, 给 SetConfiguration(x)传递的参数 */
- u8 iConfiguration;/*0x00, 字符串描述索引 */
- u8 bmAttributes;/*0x60, 属性信息 */
- u8 bMaxPower;/*0x01 当前配置最大消耗电流 */
- } __attribute__ ((packed));
- 07 05 01 03 08 00 c8
- 07 05 82 02 40 00 00
- 07 05 02 02 40 00 00
- struct usb_interface_descriptor {
- u8 bLength; /*0x09, 描述符长度 */
- u8 bDescriptorType;/* 0x04 , 表示接口描述符 */
- u8 bInterfaceNumber; /*0, 接口号为 0*/
- u8 bAlternateSetting; /*0, 接口的可选设置 */
- u8 bNumEndpoints; /*04, 当前接口共 4 个端点 */
- u8 bInterfaceClass; /*0*/
- u8 bInterfaceSubClass;/*0*/
- u8 bInterfaceProtocol; /*0*/
- u8 iInterface; /*0*/
- } ;
- struct usb_endpoint_descriptor {
- u8 bLength; /*07, 描述符长度 */
- u8 bDescriptorType;/* 0x5 , 表端点描述符 */
- u8 bEndpointAddress;/*0x81,bit[7] =1, 表示输入端点, 0 表示输出端点; bit[6:4], 保留; bit[3:0]端点号, 为 1*/
- u8 bmAttributes;/*0x03,bit[1:0]=11, 表传输类型为中断传输 */
- u16 wMaxPacketSize;/*0x0008, 当前端点最大发送和接收包大小 */
- u8 bInterval;/*0xc8, 查询时发送数据的间隔时间 */
- } ;
- /* device request (setup) */
- struct devrequest {
- unsigned char requesttype; /*0x00, 表请求设置 */
- unsigned char request; /*0x09, 表示设置配置 */
- unsigned shortvalue; /*0x0001, 使用配置, 必须匹配从配置描述符都过来的 bConfigurationValue*/
- unsigned shortindex; /*0x0000, 协议规定设为 0*/
- unsigned shortlength; /*0x0000, 协议规定设为 0*/
- } __attribute__ ((packed));
来源: http://www.bubuko.com/infodetail-2976279.html