香竹,您好!
由于项目需要用到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个字节,
|