打印

关于STM32F107 USB HOST模式读取HID鼠标的问题?

[复制链接]
10957|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhuosifan|  楼主 | 2013-4-15 16:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
香竹,您好!
           由于项目需要用到USB HOST去读取一个HID类协议的红外触摸框数据,故选择了STM32F107里面的USB HOST 鼠标和键盘的库来做修改,能正常的读取鼠标和键盘的数据,本以为触摸框跟鼠标是走一个协议的,就插入进去,枚举通过了,但HID请求初始化失败,这个问题是因为STM32的库采用用户按键按下才进行类初始化,但这个初始化是根据枚举获取的接口描述符的中的bInterfaceSubClass和bInterfaceProtocol  来判断初始化驱动的,故我把他改成如下代码:


static USBH_Status USBH_HID_InterfaceInit ( USB_OTG_CORE_HANDLE *pdev,
                                           void *phost)
{       
  uint8_t maxEP;
  USBH_HOST *pphost = phost;
  uint8_t num =0;
  USBH_Status status = USBH_BUSY ;            //如果接口描述符中没有子类,那么返回USBH_BUSY;
  HID_Machine.state = HID_ERROR;                //HID_Machine  HID状态机状态,在这个文件上面定义了



/**************以下初始化主要围绕着HID_Machine HID 处理结构体******************/
//   printf("bInterfaceClass:%x\n",pphost->device_prop.Itf_Desc[0].bInterfaceClass);          //打印接口类别(是HID类还是音频类等)
//   printf("bInterfaceSubClass:%x\n",pphost->device_prop.Itf_Desc[0].bInterfaceSubClass);    //以16进制打印子类码(如Mouse,keyboard)
//   printf("bInterfaceProtocol:%x\n",pphost->device_prop.Itf_Desc[0].bInterfaceProtocol);    //以16进制打印子类协议
//   //USBH_HOST->USBH_Device_TypeDef->Itf_Desc[0]
   //判断是否接口描述符HID启动协议字段值
   //如果是则解码鼠标和键盘 否则打印 “Device not supported”
  if(pphost->device_prop.Itf_Desc[0].bInterfaceSubClass  == HID_BOOT_CODE)  //HID_BOOT_CODE 子类
  {
    /*Decode Bootclass Protocl: Mouse or Keyboard*/
        //解码Bootclass(引导类)协议:鼠标或键盘
    if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) //协议
    {
      HID_Machine.cb = &HID_KEYBRD_cb;           //如何是键盘协议,那么回调函数初始化为键盘函数,往后调用cb就是调用键盘
    }
    else if(pphost->device_prop.Itf_Desc[0].bInterfaceProtocol  == HID_MOUSE_BOOT_CODE)        //协议          
    {
      HID_Machine.cb = &HID_MOUSE_cb;           //如何是鼠标协议,那么回调函数初始化为鼠标函数,往后调用cb就是调用鼠标
    }

    HID_Machine.state     = HID_IDLE;
    HID_Machine.ctl_state = HID_REQ_IDLE;                                                                            //控制状态为请求空闲
    HID_Machine.ep_addr   = pphost->device_prop.Ep_Desc[0][0].bEndpointAddress;//端点地址(接口编号0中的端点0)
        printf("端点接口0端点0地址:%d\n",pphost->device_prop.Ep_Desc[0][0].bEndpointAddress);
    HID_Machine.length    = pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize;  //端点最大包(接口编号0中的端点0)
        printf("端点接口0端点0最大包:%d\n",pphost->device_prop.Ep_Desc[0][0].wMaxPacketSize);
        printf("HID_Machine.length:%d\n", HID_Machine.length);
    HID_Machine.poll      = pphost->device_prop.Ep_Desc[0][0].bInterval ;           //主机轮询间隔时间
        printf("端点接口0端点0间隔时间:%d\n",pphost->device_prop.Ep_Desc[0][0].bInterval);

    if (HID_Machine.poll  < HID_MIN_POLL)  //是否小于最短轮询时间
    {
       HID_Machine.poll = HID_MIN_POLL;
    }


    /* Check fo available number of endpoints */  //检查有效端点数
    /* Find the number of EPs in the Interface Descriptor */   //在接口描述符中寻找端点编号   
    /* Choose the lower number in order not to overrun the buffer allocated */ //为了不让缓存区溢出,选择最低的端点
        //该接口所使用的端点数
    maxEP = ( (pphost->device_prop.Itf_Desc[0].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
             pphost->device_prop.Itf_Desc[0].bNumEndpoints :
                 USBH_MAX_NUM_ENDPOINTS);


    /* Decode endpoint IN and OUT address from interface descriptor */
        //num代表端点号
    for (num=0; num < maxEP; num++)
    {
      if(pphost->device_prop.Ep_Desc[0][num].bEndpointAddress & 0x80)                     //判断端点是输入还是输出1输入 0输出
      {
        HID_Machine.HIDIntInEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);  //端点地址
        HID_Machine.hc_num_in  =\
               USBH_Alloc_Channel(pdev,                                                                                                   //用端点地址申请一个通道(主机通道编号)
                                  pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);

        /* Open channel for IN endpoint */ //打开通道IN端点(打开和配置一个新的通道)
        USBH_Open_Channel  (pdev,
                            HID_Machine.hc_num_in,                                 //主机通道编号
                            pphost->device_prop.address,                 //申请连接着的设备地址
                            pphost->device_prop.speed,                         //速率
                            EP_TYPE_INTR,                                                 //端点类型(要定义中断或者控制,批量,等时就在这里定义)
                            HID_Machine.length);                                  //最大包
      }
      else
      {
        HID_Machine.HIDIntOutEp = (pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);
        HID_Machine.hc_num_out  =\
                USBH_Alloc_Channel(pdev,
                                   pphost->device_prop.Ep_Desc[0][num].bEndpointAddress);

        /* Open channel for OUT endpoint */
        USBH_Open_Channel  (pdev,
                            HID_Machine.hc_num_out,
                            pphost->device_prop.address,
                            pphost->device_prop.speed,
                            EP_TYPE_INTR,
                            HID_Machine.length);
      }

    }   

     start_toggle =0;
     status = USBH_OK;
  }
  else
  {
//    pphost->usr_cb->DeviceNotSupported();  //打印 “Device not supported”
        printf("这个是用户自定义HID设备\n");

                if(pphost->device_prop.Itf_Desc[1].bInterfaceSubClass  == HID_BOOT_CODE)  //HID_BOOT_CODE 子类
          {
            /*Decode Bootclass Protocl: Mouse or Keyboard*/
                //解码Bootclass(引导类)协议:鼠标或键盘
            if(pphost->device_prop.Itf_Desc[1].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) //协议
            {
              HID_Machine.cb = &HID_TOUCH_cb;
            }
          
            
            HID_Machine.state     = HID_IDLE;
            HID_Machine.ctl_state = HID_REQ_IDLE;
            HID_Machine.ep_addr   = pphost->device_prop.Ep_Desc[1][0].bEndpointAddress;//端点地址
                printf("端点接口1端点0地址:%d\n",pphost->device_prop.Ep_Desc[1][0].bEndpointAddress);
            HID_Machine.length    = pphost->device_prop.Ep_Desc[1][0].wMaxPacketSize;  //端点最大包
                printf("端点接口0端点0最大包:%d\n",pphost->device_prop.Ep_Desc[1][0].wMaxPacketSize);
            HID_Machine.poll      = pphost->device_prop.Ep_Desc[1][0].bInterval ;           //端点轮询间隔时间
                printf("端点接口0端点0间隔时间:%d\n",pphost->device_prop.Ep_Desc[1][0].bInterval);
            
            if (HID_Machine.poll  < HID_MIN_POLL)  //是否小于最短轮询时间
            {
               HID_Machine.poll = HID_MIN_POLL;
            }
       
            
            /* Check fo available number of endpoints */
                //检查有效的端点数目
            /* Find the number of EPs in the Interface Descriptor */
                //在接口描述符中寻找EPs数目      
            /* Choose the lower number in order not to overrun the buffer allocated */
                //该接口所使用的端点数
            maxEP = ( (pphost->device_prop.Itf_Desc[1].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
                     pphost->device_prop.Itf_Desc[1].bNumEndpoints :
                         USBH_MAX_NUM_ENDPOINTS);
            
            
            /* Decode endpoint IN and OUT address from interface descriptor */
                //解码来自接口描述符中的端点输入地址和端点输出地址
            for (num=0; num < maxEP; num++)
            {
              if(pphost->device_prop.Ep_Desc[1][num].bEndpointAddress & 0x80) //判断端点是输入还是输出1输入 0输出
              {
                HID_Machine.HIDIntInEp = (pphost->device_prop.Ep_Desc[1][num].bEndpointAddress);  //端点地址
                HID_Machine.hc_num_in  =\
                       USBH_Alloc_Channel(pdev,
                                          pphost->device_prop.Ep_Desc[1][num].bEndpointAddress);
                
                /* Open channel for IN endpoint */
                USBH_Open_Channel  (pdev,
                                    HID_Machine.hc_num_in,
                                    pphost->device_prop.address,
                                    pphost->device_prop.speed,
                                    EP_TYPE_INTR,
                                    HID_Machine.length);
              }
              else
              {
                HID_Machine.HIDIntOutEp = (pphost->device_prop.Ep_Desc[1][num].bEndpointAddress);
                HID_Machine.hc_num_out  =\
                        USBH_Alloc_Channel(pdev,
                                           pphost->device_prop.Ep_Desc[1][num].bEndpointAddress);
                
                /* Open channel for OUT endpoint */
                USBH_Open_Channel  (pdev,
                                    HID_Machine.hc_num_out,
                                    pphost->device_prop.address,
                                    pphost->device_prop.speed,
                                    EP_TYPE_INTR,
                                    HID_Machine.length);
              }
             
            }   
            
             start_toggle =0;
             status = USBH_OK;
          }

  }

  return status;

}


通过修改后,主机可以顺利通过初始化,程序运行没有出错,但读取的数据还是只有5个字节(是鼠标发送给PC的格式),我这边的触摸框是知道协议的,一共发14个字节给电脑,每个字节代表什么,我们也跟触摸框厂家拿到了,只要读取到这个完整的14个字节,那么任务就完成了,自己设想,如果读取了5个字节,那么前5个字节应该跟我这边的协议一样,但结果不是,是鼠标的数据,请香主解答下,我该如何读取这14个字节,


沙发
zhuosifan|  楼主 | 2013-4-15 16:49 | 只看该作者
我上传一下从串口上打印出来的各种描述符SB OTG FS HID Host
USB Host library started
USB Host Library v2.1.0
Please Insert USB Derive......
Device Attached
Full speed device detected
前8个描述符字节.
bLength:18
bDescriptorType:1
bcdUSB:110
bDeviceClass:0
bDeviceSubClass:0
bDeviceProtocol:0
bMaxPacketSize:64
前8个描述符字节.
bLength:18
bDescriptorType:1
bcdUSB:110
bDeviceClass:0
bDeviceSubClass:0
bDeviceProtocol:0
bMaxPacketSize:64
大于8个描述符字节.
idVendor:13ff
idProduct:8
bcdDevice:2023
iManufacturer:1
iProduct:2
iSerialNumber :0
bNumConfigurations:1
VID:13ff
设备地址分配成功!!配置描述符处理:
bLength:9
bDescriptorType:2
wTotalLength:3b
bNumInterfaces:2
bConfigurationValue:1
iConfiguration:0
bmAttributes:224
bMaxPower:150
配置描述符处理:
bLength:9
bDescriptorType:2
wTotalLength:3b
bNumInterfaces:2 //接口描述符数量:2
bConfigurationValue:1
iConfiguration:0
bmAttributes:224
bMaxPower:150

/***********第一个接口描述符***************/
接口描述符处理:
bLength:9
bDescriptorType:4
bInterfaceNumber:0
bNumInterfaces:0
bNumEndpoints:1
bInterfaceClass:3
bInterfaceSubClass:0
bInterfaceProtocol:0
iInterface:0
接口描述符处理:
bLength:9

bDescriptorType:4
bInterfaceNumber:0
bNumInterfaces:0
bNumEndpoints:1
bInterfaceClass:3
bInterfaceSubClass:0
bInterfaceProtocol:0
iInterface:0
端点描述符处理:
bLength:7
bDescriptorType:5
bEndpointAddress:81
bmAttributes:3
wMaxPacketSize:64
bInterval:1      //轮询时间

/*************第二个接口描述符**********/
接口描述符处理:
bLength:9
bDescriptorType:4
bInterfaceNumber:1
bNumInterfaces:0
bNumEndpoints:1
bInterfaceClass:3
bInterfaceSubClass:1 //引导协议
bInterfaceProtocol:1 //键盘协议
iInterface:0
接口描述符处理:
bLength:9
bDescriptorType:4
bInterfaceNumber:1
bNumInterfaces:0
bNumEndpoints:1
bInterfaceClass:3
bInterfaceSubClass:1
bInterfaceProtocol:1
iInterface:0
端点描述符处理:
bLength:7
bDescriptorType:5
bEndpointAddress:82
bmAttributes:3     //中断端点
wMaxPacketSize:64
bInterval:1
HID device connected
Manufacturer : SZiB0rdelectronics
Product : 1622261e13262a2251293125342433
Serial Number : N/A
Enumeration completed
To start the HID class operations:
Press Key...:
这个是用户自定义HID设备HID_Machine.length:64
主机端状态错误!
HID描述符数据:
描述符的长度:9
该描述符类型(0x21):21
HID协议版本: 110
国家代码: 33
下级描述符的数量:1
下级描述符的类型:22
下级描述符的长度:295
获取HID描述符成功!!
主机端状态错误!
主机端状态错误!
60ff90a11851115025ff191293f758957812851219129

3f9128510191293fb12c05192a1191a10851591912931

50251953获取报告描述符成功!!
HID Demo Device : Iboard Touch

使用特权

评论回复
板凳
zhuosifan|  楼主 | 2013-4-15 16:49 | 只看该作者
没有启动类和协议

使用特权

评论回复
地板
zhuosifan|  楼主 | 2013-4-15 17:04 | 只看该作者
期待二姨家大婶解答下

使用特权

评论回复
5
IJK| | 2013-4-15 17:19 | 只看该作者
最好先把这个设备插入电脑,看电脑能否识别它,识**看能否正确读取起数据

使用特权

评论回复
6
zhuosifan|  楼主 | 2013-4-15 17:33 | 只看该作者
我再顶

使用特权

评论回复
7
zhuosifan|  楼主 | 2013-4-15 22:05 | 只看该作者
IJK 发表于 2013-4-15 17:19
最好先把这个设备插入电脑,看电脑能否识别它,识**看能否正确读取起数据 ...

电脑可以读取这个设备,能正常运行的

使用特权

评论回复
8
zhuosifan|  楼主 | 2013-4-16 08:49 | 只看该作者
香主献身说法

使用特权

评论回复
9
zhuosifan|  楼主 | 2013-4-17 09:29 | 只看该作者
既然没人鸟呀,这个东西没多少人做吗,还是我说的问题不明朗

使用特权

评论回复
10
IJK| | 2013-4-17 09:40 | 只看该作者
可以比较一下PC作为host跟STM32F107作为host 它们的USB通信区别哪里。PC识别它的过程,可以用BUSHOUND之类的USB 监控软件来抓

使用特权

评论回复
11
zhuosifan|  楼主 | 2013-4-18 11:43 | 只看该作者
IJK 发表于 2013-4-17 09:40
可以比较一下PC作为host跟STM32F107作为host 它们的USB通信区别哪里。PC识别它的过程,可以用BUSHOUND之类 ...

已经抓取了数据,但主机端的程序是根据ST提供的例程里面进行修改的,他们全部采用状态机

使用特权

评论回复
12
zhuosifan|  楼主 | 2013-4-22 09:12 | 只看该作者
USB HOST真难搞

使用特权

评论回复
13
zhuosifan|  楼主 | 2013-4-23 09:54 | 只看该作者
最近大家都很忙呀

使用特权

评论回复
14
是电子爱好者| | 2014-2-22 15:58 | 只看该作者
可以上传一下工程吗?我现在在搞stm32f4discovery读取usb手柄,通过按键实现通讯,可以交流一下吗

使用特权

评论回复
15
真的好多巧合| | 2014-12-6 22:07 | 只看该作者
是电子爱好者 发表于 2014-2-22 15:58
可以上传一下工程吗?我现在在搞stm32f4discovery读取usb手柄,通过按键实现通讯,可以交流一下吗 ...

不知兄台弄得咋样了?
我现在也正在弄?希望可以交流下。。
:)

使用特权

评论回复
16
yutianxiang618| | 2017-3-17 18:05 | 只看该作者
zhuosifan 发表于 2013-4-15 16:49
我上传一下从串口上打印出来的各种描述符SB OTG FS HID Host
USB Host library started
USB Host Library v ...

请问一下,我想使用F107 usb host给键盘发送数据,是不是在USBH_HID_Handle函数里面通过什么函数发送数据啊,谢谢啦

使用特权

评论回复
17
wahahaheihei| | 2017-3-17 19:55 | 只看该作者
USB这个会的人不多啊。

使用特权

评论回复
18
fentianyou| | 2017-3-17 21:43 | 只看该作者
去看看iceut的usb开发。

使用特权

评论回复
19
fentianyou| | 2017-3-17 21:47 | 只看该作者
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

14

帖子

0

粉丝