Chinaunix首页 | 论坛 | 博客

fx

  • 博客访问: 1373076
  • 博文数量: 115
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3964
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-02 14:36
文章分类
文章存档

2022年(2)

2019年(2)

2018年(10)

2017年(1)

2016年(50)

2015年(12)

2014年(9)

2013年(29)

分类: 嵌入式

2016-06-14 16:48:55

开发环境:win7
开发板    :51单片机 + pdiusbd12 芯片


前言:
    在上一节的末尾,usb设备接收到了主机发送过来的数据 0x80 0x06 0x00 0x02 0x00 0x00 0xFF 0x00
    通过查看 :usb鼠标_USB标准请求之设备描述符(5) 
    可知主机是为了获取设备的配置描述符。
    
    每个 USB 设备至少有一个配置描述符,在当前例子中,只有一个配置描述符。
    每个配置描述符都有附属描述符,包括一个或多个接口描述符以及可选的端点描述符。主机通过发送 Get Descriptor 请求,
且使设置事务中wValue字段的高字节等于 02h,wLength 字段等于 wTotalLength 的方式,取得配置描述符及其附属描述符。



1,配置描述符
    

    sTotalLength 等于配置描述符以及其所有附属描述符(接口/端点 等描述符)的字节总和。
    bNumInterfaces 是接口配置中接口的数目,其最小值为01h。
    bConfigurationValue ,主机用 Set Configuration 请求来选择配置,用 Get Configuration 请求来获取当前配置的数目。
                                    其值必须为 01h或是更高值。取值为0的Set Device请求会使设备进入未配置状态(Not Configured state)。
    iConfiguration 是一个索引,指向描述配置的字符串。若没有字符描述符,该值为 0.
    bmAttribute 会将bit[6] 表示供电方式,当bit[6] 等于1时,表示设备是自供电的;当 bit[6] 为0时,表示设备是总线供电的。
                    bit[5]表示是否支持远程唤醒,当bit[5]等于1时,表示支持远程唤醒。为了与USB1.0兼容,bit[7]必须为1 ,bit[4~0] 保留,必须置为0。
    bMaxPower 表示设备要求多少的总线电流。对于 USB2.0 ,bMaxPower 以 2mA 为单位,如果设备要求200mA,则bMaxPower 等于(200/2)= 100。对于超高速应用,bMaxPower以 8 mA 为单位。设备可请求的最大总线电流时:对于USB2.0 为 500 mA,对于 超高速应用为 900mA。如果所请求的电流不可用,主机将拒绝对设备进行配置。

点击(此处)折叠或打开

  1. typedef    struct _configuration_descriptor
  2. {
  3.     uint8_t        bLength;            // 配置描述符的字节数大小(09h)
  4.     uint8_t        bDescriptorType;    // 配置描述符类型编号(02h)
  5.     uint16_t    sTotalLength;        // 配置描述符及其全部附属描述符(接口,端点描述符)的字节数
  6.     uint8_t        bNumInterfaces;        // 配置中接口的数目
  7.     uint8_t        bConfigurationValue;// Set/Get Configuration 请求的标识符
  8.     uint8_t        iConfiguration;        // 配置字符串描述符的索引
  9.     uint8_t        bmAttributes;        // 供电模式的选择,自供电,总想供电和远程唤醒的设置
  10.     uint8_t        bMaxPower;            // 设备从总线提取的最大电流,以2mA(USB2.0) 或 8mA(超高频)为单位所要求的总想功耗
  11. }configuration_descriptor_t;



2,接口配置描述符
    

    一个配置可含有多个同时行动的接口。这个接口可能联合于某个功能,也可能不相关。每个接口都有它自己的接口描述符和附属描述符。所有这些接口也可拥有一个或多个替代的接口设置,这些设置是互斥的,每次只有一个被激活。每个设置含有一个接口描述符及所属的附属描述符。使用等时传输的设备拥有替代的接口配置,因为缺省接口请求不了等时带宽。

    bInterfaceNumber 用于确认接口。在复合设备中,配置拥有多个同时活动的接口,每个接口的描述符中,该字段取值必须唯一。缺省接口的该值为00h。
    bAlternateSetting 用于确认缺省接口的设置或替代设置。对于每个 bInterfaceNumber,设备将提供一个bAlternateSetting 字段为 00h的接口描述符,这是缺省的设置。替代设置的描述符的bInterfaceNumber 字段于缺省设备的取值相同,但 bAlternateSetting 的取值唯一,随所需描述符的最后5个字节的取值而不同。对于每个 bInterfaceNumber,每次只有一个bAlternateSetting 可被激活。替代设置可使主机能够请求带有不同带宽或其他要求和性能的接口。 Get Interface请求会取得当前被激活的bAlternateSetting。 Set Interface 请求可选择特定bInterfaceNumber 所对应的bAlternateSetting.
    bNumEndpoints 等于除端点0外接口所支持的端点数目。对于只支持端点0的设备,这个字段为0.
    bInterfaceClass 除了用于由接口规定的设备外,其他与设备描述符中bDeviceClass字段相同。
    
    
    
    bInterfaceSubClass 除带有由接口定义的类的设备外,此字段于设备描述符中的bDeviceSubClass 相同。若 bInterfaceClass 等于00h,bInterfaceSubClass 也必须等于 00h。若 bInterfaceClass 取从 01h到FEh的值,bInterfaceSubClass则等于00h或等于一个为接口的类定义的值。FFh表明为厂商定义的子类。
    bInterfaceProtocol 除了带有接口定义的类的设备外,此字段于设备描述符中的bDeviceProtocol相同。此字段可为所选bInterfaceClass和bInterfaceSubClass 所规定的协议。若bInterfaceClass取从01h到FEh的值,bInterfaceProtocol必须等于00h,或等于为接口的类定义的值。FFh表明为厂商定义的协议。
    iInterface 是指向描述接口的字符串的索引。若没有字符串描述符,该值为0.   

点击(此处)折叠或打开

  1. typedef struct _initerface_descriptor
  2. {
  3.     uint8_t        bLength;            // 接口描述符的字节数大小(09h)
  4.     uint8_t        bDescriptorType;    // 接口描述符的类型编号
  5.     uint8_t        bInterfaceNumber;    // 该接口的编号
  6.     uint8_t        bAltenateSetting;    // 备用的接口描述符编号
  7.     uint8_t        bNumEndpoints;        // 该接口使用的端点数,不包括端点0
  8.     uint8_t        bInterfaceClass;    // 接口类型
  9.     uint8_t        bInterfaceSubClass;    // 接口子类型
  10.     uint8_t        bInterfaceProtocol;    // 接口遵循的协议
  11.     uint8_t        iInterface;            // 描述该接口的字符串索引值
  12. }interface_descriptor_t;

    3,HID描述符
    详情请看:usb鼠标_配置描述符集合(7)之 HID 

    4,端点描述符
    

    音频1.0类中的设备,将端点描述符拓展为两个额外的关于音频专属信息的字节。这是唯一被允许的改变标准描述符类型长度的操作。在需要的地方,类和其他规范应当定义单独的返回拓展信息的描述符。例如,USB3.0定义了endpoint companion(端点伙伴)描述符,来返回超高速专属端点信息。
    
    bEndpointAddress 规定了端点的数目和方向。bit[3~0]是端点号,低速设备可最多拥有3个端点号(通常取值为0~2),而全速和高速设备可拥有16个端点号(0~15)。bit[4~6]保留,必须设置为0。bit[7] 为方向,OUT为0,IN为1.    
    bmAttributes ,bit[1~0]规定了端点所支持的传输方式:00 为控制协议,01为等时传输,10为批量传输,11为中断传输。
                            bit[7~6] 保留,必须置为0。
                            对于等时端点,bit[5~2]可表明一个同步类型和数据或反馈的使用类型。
                            对于超高速中断端点,bit[5~4]表明Notification(通知)或Periodic(周期)的适用类型。
    wMaxPacketSize 规定了端点在一个事务中可传输的最大数据字节数。所允许的值会随着设备的速度和传输类型而改变。
                            对于USB2.0,bit[10~0]是最大信息包尺寸,范围是0~1024。bit[12~11]表明高手中断或等时端点在每个微帧所支持的额外事务数目:00表明没有额外事务(事务总数是每个微帧1个),01表示有1个额外事务(事务总数是每个微帧2个),10表示2个额外事务(事务总数为每微帧3个),11表示保留。对于USB1.x,其范围是0到1023.bit[15~11]保留,必须置为0
    bInterval 规定中断和等时端点的服务时距。服务时距(service interval)是一个周期,主机必须在这个周期内安排端点事务。这个周期是帧(低俗和全速),微帧(高速)或总线时距(超高速)的整数倍。对于低速中断端点,bInterval为最大等待时间,单位为ms,取值范围是10到255。对于usb1.x设备中的全速中断端点及等时端点,时距等于以ms为单位的bInterval。对于中断端点,可能的取值范围是1~255;对于usb1.x的等时端点,此值为1。对于usb2.0设备中的全速的等时端点,允许取值范围1到16,且时距按(以ms为单位)2^(bInterval-1)计算,时间范围是1ms到32.768s。对于高速和超高速端点,此值以125us为单位。中断和等时端点的取值为1到16,时距为2^(bInterval-1)计算,允许的时间范围是125us到4.096s。
            对于高速批量和控制OUT端点,此字段可含有一个最大NAK速率,即传输中要符合这个字段的要求。设备典型地将此值设为0,对于其他批量和控制传输,此值保留。

点击(此处)折叠或打开

  1. typedef struct _endpoint_descriptor
  2. {
  3.     uint8_t        bLength;            // 端点描述符字节数大小
  4.     uint8_t        bDescriptorType;    // 端点描述符类型编号
  5.     uint8_t        bEndpointAddress;    // 端点地址及输入输出属性
  6.     uint8_t        bmAttributes;        // 端点的传输类型属性
  7.     uint16_t    wMaxPacketSize;        // 端点收、发的最大包字节大小
  8.     uint8_t        bInterval;            // 主机查询端点的时间间隔
  9. }endpoint_descritpor_t;

    5,功能实现

点击(此处)折叠或打开

  1. #define    ENDPOINT_MAX                2



  2. typedef struct _configuration_set
  3. {
  4.     configuration_descriptor_t        configuration;
  5.     interface_descriptor_t            interface;
  6.     hid_descriptor_t                hid;
  7.     endpoint_descritpor_t            endpoint[ENDPOINT_MAX];
  8. }configuration_set_t;

点击(此处)折叠或打开

  1. int32_t        init_configuration_descriptor(configuration_descriptor_t * con)
  2. {
  3.     int32_t        ret = 0;

  4.     con->bLength             = sizeof(configuration_descriptor_t);
  5.     con->bDescriptorType    = DESC_TYPE_CONFIGURATION;    // 配置描述符类型编号(02h)
  6.     con->sTotalLength        = SWAP16(sizeof(configuration_set_t));        // 配置描述符及其全部附属描述符(接口,端点描述符)的字节数
  7.     con->bNumInterfaces        = 0x01;        // 配置中接口的数目
  8.     con->bConfigurationValue= 0x01;        // Set/Get Configuration 请求的标识符
  9.     con->iConfiguration        = 0x00;        // 配置字符串描述符的索引
  10.     con->bmAttributes        = 0xA0;        // 供电模式的选择,自供电,总想供电和远程唤醒的设置
  11.     con->bMaxPower            = 0xc8;        // 设备从总线提取的最大电流,以2mA(USB2.0) 或 8mA(超高频)为单位所要求的总想功耗


  12.     return ret;    
  13. }


  14. int32_t        init_interface_descriptor(interface_descriptor_t * interface)
  15. {
  16.     int32_t        ret = 0;

  17.     interface->bLength        = sizeof(interface_descriptor_t);    //接口描述符的字节数大小
  18.     interface->bDescriptorType    = DESC_TYPE_INTERFACE; //接口描述符类型编号
  19.     interface->bInterfaceNumber = 0x00; //接口编号为0
  20.     interface->bAltenateSetting = 0x00; //该接口描述符的编号
  21.     interface->bNumEndpoints     = ENDPOINT_MAX; //非0端点数量为2,只使用端点主端点输入和输出
  22.      interface->bInterfaceClass     = 0x03; //人机接口设备(HID)类
  23.     interface->bInterfaceSubClass    = 0x01;     //使用的子类:支持BIOS根启动Boot的子类
  24.     interface->bInterfaceProtocol     = 0x02;     //使用的协议:鼠标
  25.      interface->iInterface            = 0x00; //接口描述符字符串索引


  26.     return ret;    
  27. }

点击(此处)折叠或打开

  1. void        init_configuration_set(configuration_set_t *set)
  2. {
  3.     init_configuration_descriptor(&(set->configuration));
  4.     init_interface_descriptor(&(set->interface));

  5.     // hid
  6.     {
  7.         set->hid.bLength         = sizeof(hid_descriptor_t); //HID描述符的字节数大小
  8.         set->hid.bDescriptorType     = DESC_TYPE_HID;             //HID描述符类型编号
  9.         set->hid.bcdHID                 = SWAP16(0x0110);             //HID类协议版本号,为1.1
  10.         set->hid.bCountryCode         = 0x21;                      //固件的国家地区代号,0x21为美国
  11.         set->hid.bNumDescriptors     = HID_SUB_DESCRIPTOR_MAX;    //下级描述符的数量

  12.         set->hid.hidSubDescriptors[0].bDescriptorType    = DESC_TYPE_REPORT;             //下级描述符为报告描述符
  13.         set->hid.hidSubDescriptors[0].wDescriptorLength    = SWAP16(sizeof(MouseReportDescriptor)); //下级描述符的长度
  14.     }

  15.     //endpoint
  16.     {
  17.         set->endpoint[0].bLength             = sizeof(endpoint_descritpor_t);//端点描述符的字节数大小
  18.         set->endpoint[0].bDescriptorType    = DESC_TYPE_ENDPOINT;             //端点描述符类型编号
  19.         set->endpoint[0].bEndpointAddress    = MAIN_POINT_IN;                 //端点号,主输入端点
  20.         set->endpoint[0].bmAttributes        = TRANSFER_INTERRUPT;            //使用的传输类型:中断传输
  21.         set->endpoint[0].wMaxPacketSize         = SWAP16(0x0040);                 //该端点支持的最大包尺寸,64字节
  22.         set->endpoint[0].bInterval             = 0x0A;                             //中断扫描时间:设置为10ms
  23.         
  24.         
  25.         set->endpoint[1].bLength             = sizeof(endpoint_descritpor_t);//端点描述符的字节数大小
  26.         set->endpoint[1].bDescriptorType    = DESC_TYPE_ENDPOINT;             //端点描述符类型编号
  27.         set->endpoint[1].bEndpointAddress    = MAIN_POINT_OUT;                 //端点号,主输出端点
  28.         set->endpoint[1].bmAttributes        = TRANSFER_INTERRUPT;            //使用的传输类型:中断传输
  29.         set->endpoint[1].wMaxPacketSize         = SWAP16(0x0040);                 //该端点支持的最大包尺寸,64字节
  30.         set->endpoint[1].bInterval             = 0x0A;                             //中断扫描时间:设置为10ms
  31.     }
  32. }


    6,运行结果



    7,待解决问题:字符串描述符的实现

    8,源码    
            mouse.zip

欲知详情,请看下回分解


阅读(1555) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~