stm32的USB问题

cekong   2008-3-23 09:24 楼主
为什么再XP下应用正常的STM32做的USB键盘,到win2000下不能识别?
系统提示设备不能启用,应该是没有正确装载HID驱动。此机器可以正常使用买来的USB键盘。
后用BUSHOUND抓包。看到原因是设备描述符发送不完整。但是在XP下没有任何问题,整个描述符为34字节,在win2000下只发送32字节。
这是什么原因?

回复评论 (19)

应该是驱动程序不同造成的。估计你的0端点大小为32字节

在设备未设置地址前的那次获取设备描述只获取0端点最大长度,剩下的就暂时先不去获取了,设置地址后才会获取完整的设备描述符。
不过我奇怪的是,你的设备描述符长度为何有34字节那么长?标准的设备描述符只有18字节长。
点赞  2008-3-23 09:58

什么样的USB程序?34字节的似乎是配置描述符

                                  
点赞  2008-3-24 10:38

汗了

设备描述符如下
const BYTE USB_DeviceDescriptor[] = {
  USB_DEVICE_DESC_SIZE,              /* bLength */
  USB_DEVICE_DESCRIPTOR_TYPE,        /* bDescriptorType */
  WBVAL(0x0110), /* 1.10 */          /* bcdUSB */
  0x00,                              /* bDeviceClass */
  0x00,                              /* bDeviceSubClass */
  0x00,                              /* bDeviceProtocol */
  USB_MAX_PACKET0,                   /* bMaxPacketSize0 */
  WBVAL(0xC251),                     /* idVendor */
  WBVAL(0x1C01),                     /* idProduct */
  WBVAL(0x0100), /* 1.00 */          /* bcdDevice */
  0x04,                              /* iManufacturer */
  0x20,                              /* iProduct */
  0x44,                              /* iSerialNumber */
  0x01                               /* bNumConfigurations */
};
配置描述符如下
const BYTE USB_ConfigDescriptor[] = {
/* Configuration 1 */
  USB_CONFIGUARTION_DESC_SIZE,       /* bLength */
  USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
  WBVAL(                             /* wTotalLength */
    USB_CONFIGUARTION_DESC_SIZE +
    USB_INTERFACE_DESC_SIZE     +
    HID_DESC_SIZE               +
    USB_ENDPOINT_DESC_SIZE
  ),
  0x01,                              /* bNumInterfaces */
  0x01,                              /* bConfigurationValue */
  0x00,                              /* iConfiguration */
  USB_CONFIG_BUS_POWERED /*|*/       /* bmAttributes */
/*USB_CONFIG_REMOTE_WAKEUP*/,
  USB_CONFIG_POWER_MA(50),          /* bMaxPower */
/* Interface 0, Alternate Setting 0, HID Class */
  USB_INTERFACE_DESC_SIZE,           /* bLength */
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
  0x00,                              /* bInterfaceNumber */
  0x00,                              /* bAlternateSetting */
  0x02,                              /* bNumEndpoints */
  USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass */
  HID_SUBCLASS_BOOT,                 /* bInterfaceSubClass */
  HID_PROTOCOL_KEYBOARD,                 /* bInterfaceProtocol */
  0x5E,                              /* iInterface */
/* HID Class Descriptor */
/* HID_DESC_OFFSET = 0x0012 */
  HID_DESC_SIZE,                     /* bLength */
  HID_HID_DESCRIPTOR_TYPE,           /* bDescriptorType */
  WBVAL(0x0100), /* 1.00 */          /* bcdHID */
  0x00,                              /* bCountryCode */
  0x01,                              /* bNumDescriptors */
  HID_REPORT_DESCRIPTOR_TYPE,        /* bDescriptorType */
  WBVAL(HID_REPORT_DESC_SIZE),       /* wDescriptorLength */
/* Endpoint, HID Interrupt In */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  USB_ENDPOINT_IN(1),                /* bEndpointAddress */
  USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
  WBVAL(0x0040),                     /* wMaxPacketSize */
  0x0A,          /* 32ms */          /* bInterval */
/* Terminator */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  USB_ENDPOINT_OUT(2),                /* bEndpointAddress */
  USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
  WBVAL(0x0040),                     /* wMaxPacketSize */
  0x0A,          /* 32ms */          /* bInterval */
};
实际使用中是在WIN2000下不能发送完整的配置描述符,只能发出32字节。
点赞  2008-3-25 08:07

把你发送描述符的哪段程序贴出来

                                 每次发送你发几个字节?
点赞  2008-3-25 08:28

发送数据

每次定义的发送最多8字节,如果超过8字节的数据就分成多个部分发送,每次8字节。
__inline BOOL USB_GetDescriptor (void) {
  BYTE  *pD;
  DWORD len, n;

  switch (SetupPacket.bmRequestType.BM.Recipient) {
    case REQUEST_TO_DEVICE:
      switch (SetupPacket.wValue.WB.H) {
        case USB_DEVICE_DESCRIPTOR_TYPE:
          EP0Data.pData = (BYTE *)USB_DeviceDescriptor;
          len = USB_DEVICE_DESC_SIZE;
          break;
        case USB_CONFIGURATION_DESCRIPTOR_TYPE:
          pD = (BYTE *)USB_ConfigDescriptor;
          for (n = 0; n != SetupPacket.wValue.WB.L; n++) {
            if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength != 0) {
              pD += ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
            }
          }
          if (((USB_CONFIGURATION_DESCRIPTOR *)pD)->bLength == 0) {
            return (FALSE);
          }
          EP0Data.pData = pD;
          len = ((USB_CONFIGURATION_DESCRIPTOR *)pD)->wTotalLength;
          break;
        case USB_STRING_DESCRIPTOR_TYPE:
          EP0Data.pData = (BYTE *)USB_StringDescriptor + SetupPacket.wValue.WB.L;
          len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;
          break;
        default:
          return (FALSE);
      }
      break;
    case REQUEST_TO_INTERFACE:
      switch (SetupPacket.wValue.WB.H) {
#if USB_HID
        case HID_HID_DESCRIPTOR_TYPE:
          if (SetupPacket.wIndex.WB.L != USB_HID_IF_NUM) {
            return (FALSE);    /* Only Single HID Interface is supported */
          }
          EP0Data.pData = (BYTE *)USB_ConfigDescriptor + HID_DESC_OFFSET;
          len = HID_DESC_SIZE;
          break;
        case HID_REPORT_DESCRIPTOR_TYPE:
          if (SetupPacket.wIndex.WB.L != USB_HID_IF_NUM) {
            return (FALSE);    /* Only Single HID Interface is supported */
          }
          EP0Data.pData = (BYTE *)HID_ReportDescriptor;
          len = HID_ReportDescSize;
          break;
        case HID_PHYSICAL_DESCRIPTOR_TYPE:
          return (FALSE);      /* HID Physical Descriptor is not supported */
#endif
        default:
          return (FALSE);
      }
      break;
    default:
      return (FALSE);
  }

  if (EP0Data.Count > len) {
    EP0Data.Count = len;
  }
  USB_DataInStage();

  return (TRUE);
}

void USB_DataInStage (void) {
  DWORD cnt;

  if (EP0Data.Count > USB_MAX_PACKET0) {
    cnt = USB_MAX_PACKET0;
  } else {
    cnt = EP0Data.Count;
  }
  cnt = USB_WriteEP(0x80, EP0Data.pData, cnt);
  EP0Data.pData += cnt;
  EP0Data.Count -= cnt;
}
这些都是KEIL的demo程序,这部分代码没有做任何修改。
点赞  2008-3-25 09:38

Bus Hound 5.00 capture

Bus Hound 5.00 capture. Complements of www.perisoft.net

1

  Device - Device ID (followed by the endpoint for USB devices)
            (11) USB Root Hub
            (13) USB Mass Storage Device
            (16) USB 人体学输入设备
  Phase  - Phase Type
            CTL   USB control transfer       
            DI    Data in                    
            USTS  USB status                 
  Data   - Hex dump of the data transferred
  Descr  - Description of the phase
  Cmd... - Position in the captured data


Device  Phase  Data                                                Description       Cmd.Phase.Ofs(rep)
------  -----  --------------------------------------------------  ----------------  ------------------
  11.1  DI     04                                                  .                        1.1.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS               2.1.0(2)     
  11.0  DI     01 01 01 00                                         ....                     2.2.0        
  11.0  CTL    23 01 10 00  02 00 00 00                            CLEAR FEATURE            4.1.0        
  11.0  CTL    a3 00 00 00  01 00 04 00                            GET STATUS               5.1.0        
  11.0  DI     00 03 00 00                                         ....                     5.2.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS               6.1.0(2)     
  11.0  DI     01 01 00 00                                         ....                     6.2.0        
  11.0  CTL    23 03 04 00  02 00 00 00                            SET FEATURE              8.1.0        
  11.1  DI     04                                                  .                        9.1.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS              10.1.0        
  11.0  DI     03 01 10 00                                         ....                    10.2.0        
  11.0  CTL    23 01 14 00  02 00 00 00                            CLEAR FEATURE           11.1.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS              12.1.0        
  11.0  DI     03 01 00 00                                         ....                    12.2.0        
  11.0  CTL    80 06 00 01  00 00 40 00                            GET DESCRIPTOR          13.1.0        
  11.0  USTS   05 00 00 80                                         no response             13.2.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS              14.1.0        
  11.0  DI     03 01 00 00                                         ....                    14.2.0        
  11.0  CTL    23 03 04 00  02 00 00 00                            SET FEATURE             15.1.0        
  11.1  DI     04                                                  .                       16.1.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS              17.1.0        
  11.0  DI     03 01 10 00                                         ....                    17.2.0        
  11.0  CTL    23 01 14 00  02 00 00 00                            CLEAR FEATURE           18.1.0        
  11.0  CTL    80 06 00 01  00 00 40 00                            GET DESCRIPTOR          19.1.0        
  11.0  DI     12 01 10 01  00 00 00 08                            ........                19.2.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS              20.1.0        
  11.0  DI     03 01 00 00                                         ....                    20.2.0        
  11.0  CTL    23 03 04 00  02 00 00 00                            SET FEATURE             21.1.0        
  11.1  DI     04                                                  .                       22.1.0        
  11.0  CTL    a3 00 00 00  02 00 04 00                            GET STATUS              23.1.0        
  11.0  DI     03 01 10 00                                         ....                    23.2.0        
  11.0  CTL    23 01 14 00  02 00 00 00                            CLEAR FEATURE           24.1.0        
  11.0  CTL    00 05 02 00  00 00 00 00                            SET ADDRESS             25.1.0        
  11.0  CTL    80 06 00 01  00 00 12 00                            GET DESCRIPTOR          26.1.0        
  11.0  DI     12 01 10 01  00 00 00 08  51 c2 01 1c  00 01 04 20  ........Q......         26.2.0        
               44 01                                               D.                      26.2.16       
  11.0  CTL    80 06 00 02  00 00 09 00                            GET DESCRIPTOR          27.1.0        
  11.0  DI     09 02 22 00  01 01 00 80  19                        .."......               27.2.0        
  16.0  CTL    80 06 00 01  00 00 12 00                            GET DESCRIPTOR          28.1.0        
  16.0  DI     12 01 10 01  00 00 00 08  51 c2 01 1c  00 01 04 20  ........Q......         28.2.0        
               44 01                                               D.                      28.2.16       
  16.0  CTL    80 06 00 02  00 00 09 00                            GET DESCRIPTOR          29.1.0        
  16.0  DI     09 02 22 00  01 01 00 80  19                        .."......               29.2.0        
  16.0  CTL    80 06 00 02  00 00 22 00                            GET DESCRIPTOR          30.1.0        
  16.0  DI     09 02 22 00  01 01 00 80  19 09 04 00  00 02 03 01  ..".............        30.2.0        
               01 5e 09 21  00 01 00 01  22 3b 00 07  05 81 03 40  .^.!....";.....@        30.2.16       
  16.0  CTL    00 09 01 00  00 00 00 00                            SET CONFIG              31.1.0        
  16.0  USTS   00 05 00 80                                         request failed          31.2.0        
  11.0  CTL    23 01 01 00  02 00 00 00                            CLEAR FEATURE           32.1.0        
点赞  2008-3-25 09:46

都已经发送SetConfig了,估计配置描述符集合已经返回成功

至于为什么只看到32字节,估计是你的Bus Hound设置它只让它显示这么一点的。
默认好象是显示16字节,我第一次使用时都将它改成1024字节。

这里显示是在SET CONFIG失败,是不是你没有正确回应这个请求啊。
点赞  2008-3-25 09:51

没看出程序有问题,请把抓到的图像发上来看看

从4楼给出的描述符看,有一个配置描述符、一个接口描述符、一个HID描述符和两个端口描述符,接口描述符中标示有两个端口描述符,但配置描述符中在描述符总长度中却不包括最后一个(OUT)端口描述符;这是一个明显的漏洞!

其他地方还没有看出来。
点赞  2008-3-25 10:11

圈圈厉害啊!

检查过了的确是设置的问题,Bus Hound默认设置是32字节,实际返回的也是34字节数据,有两个没显示出来。
不过那个SET CONFIG的响应在XP的系统上可以正确响应啊!不明白为什么。
在win2000下的设备列表中看的就是已经认识为一个USB人体学输入设备,但是前面有个黄色的叹号。提示设备不能启用,要想启用此设备,必须重新启动电脑。可是重新启动了也不行。
点赞  2008-3-25 10:20

从抓到的数据看,你的系统有个严重的问题

为什么连续2次Get Device Descriptor失败呢?

还有我在4楼中的关于描述符不匹配的疑问,如何解释?
点赞  2008-3-25 10:27

按照香版主的说法改了

                                 把总长度改了,包含最后一个端口描述符了,长度增加为41字节。但还是出现问题。
点赞  2008-3-25 10:29

这个估计就是香版所说的那个问题了,总长度不对,还差7字

因为有两个端点,你只计算了一个端点的长度,实际有41字节。

XP下可以使用,应该是它的驱动做得兼容性更好吧,不过这样的输出端点是无法启用的。
点赞  2008-3-25 10:30

我对Win2000是否支持HID的OUT端点表示怀疑

在USB 1.0中没有中断输出端点(Interrupt OUT),USB 1.1才加上去的,而USB 1.1是98年底才发布,所以我对Win2000是否支持HID的OUT端点表示怀疑。

请把这个多余的,估计是你自己加上去的中断输出端点去掉试试看。
点赞  2008-3-25 10:35

补充一点:印象中USB键盘是不需要使用中断输出端点

不知道你是哪里抄来的描述符?请把你的HID描述符贴上来。

另外,SET_CONFIG失败表示你的程序有问题。
点赞  2008-3-25 10:42

我的看法:既然驱动程序已经发了set config,

                                 那么就说明这个驱动程序已经认这个设备了。跟踪一下set config你的设备是如何响应的。
点赞  2008-3-25 10:44

奇怪!好了!

难道就是香版主说的描述符长度的问题???
重新插拔了几次,居然好了!!!
点赞  2008-3-25 10:47

谢谢两位大侠啊!

效率真是高啊!
我加了一个端点是想实现与PC上的一个程序通信用的,还不知道能不能实现呢。
要是用STM32虚拟一个U盘,能不能跟这个键盘做成符合设备呢?
点赞  2008-3-25 10:51

U盘与键盘可以做成复合设备

但印象中不是Win2000就是另一个Windows系统,在复合设备有BUG,可惜记不清了。

“重新插拔了几次,居然好了!”——这种事情很蹊跷,还是好好查查原因吧。
点赞  2008-3-25 10:55

呵呵,HID键盘可以不使用中断端点,当然也可以使用

如果没有中断端点,就通过获取报告和设置报告来实现。

如果有输入中断端点,则数据通过中断端点返回。如果有中断输出端点,则输出数据通过中断
端点输出,例如设置caps lock,num lock等灯的输出数据。

在修改了描述符后,重新使用设备时,最好先在设备管理器中将原来的驱动卸载,然后再重新
接入调试,否则很有可能操作系统会加载旧的驱动程序而导致你的设备不能正常工作。因为
操作系统搜索驱动程序时,是根据你的VID和PID来查找的,记录在注册表中。如果以前已经
安装过这个驱动,那么系统就会直接加载,而不会更新驱动。
点赞  2008-3-25 10:58
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复