完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在网上搜了很多都是USB Host单独连接鼠标或键盘的样例, 而当前很多无线鼠标键盘都是并到一个USB口上的, 也就是同一个USB有两个interface. 而官方提供的USB Host库中只会对一个Interface进行处理, 要么键盘要么鼠标, 所以为了能够同时使用键盘和鼠标要对USB Host库进行修改才行.
具体修改如下: 首先使用CubeMX创建了一个带USB HID类功能的工程, 创建步骤很简单网上有很多文档不在这里讨论. 接着进入正题, 修改USB Host库文件. u***h_def.h 修改USBH_ClassTypeDef, 使当前Class支持多接口: /* USB Host Class structure */ typedef struct { const char *Name; uint8_t ClassCode; USBH_StatusTypeDef(*Init)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*DeInit)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*Requests)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*BgndProcess)(struct _USBH_HandleTypeDef *phost); USBH_StatusTypeDef(*SOFProcess)(struct _USBH_HandleTypeDef *phost); /* [ */ void *pData[USBH_MAX_NUM_INTERFACES]; /* HID interfaces Handle */ uint8_t InterfaceNum; /* interface 数量 */ __IO uint8_t CurrInterface; /* 当前interface */ /* ] */ } USBH_ClassTypeDef; 修改HID_HandleTypeDef, 记录interface的协议类型: /* Structure for HID process */ typedef struct _HID_Process { uint8_t OutPipe; uint8_t InPipe; HID_StateTypeDef state; uint8_t OutEp; uint8_t InEp; HID_CtlStateTypeDef ctl_state; FIFO_TypeDef fifo; uint8_t *pData; uint16_t length; uint8_t ep_addr; uint16_t poll; uint32_t timer; uint8_t DataReady; HID_DescTypeDef HID_Desc; USBH_StatusTypeDef(* Init)(USBH_HandleTypeDef *phost); /* [ */ uint8_t Protocol; /* 协议类型: HID_KEYBRD_BOOT_CODE / HID_MOUSE_BOOT_CODE */ /* ] */ } HID_HandleTypeDef; u***h_hid.c 修改USBH_HID_InterfaceInit函数, 在初始化的时候判断当前枚举了几个HID接口, 如果有多个接口, 则创建多个HID_HandleTypeDef: static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK; HID_HandleTypeDef *HID_Handle; uint8_t max_ep; uint8_t num = 0U; /* [ */ uint8_t boot = HID_KEYBRD_BOOT_CODE; uint8_t interface_num = 0; uint8_t interface; for (interface_num = 0; interface_num < phost->device.CfgDesc.bNumInterfaces; interface_num++) { interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, boot); /* ] */ if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */ { USBH_DbgLog("Cannot Find the interface for %s class.", phost->pActiveClass->Name); status = USBH_FAIL; break; } status = USBH_SelectInterface(phost, interface); if (status != USBH_OK) { return USBH_FAIL; } phost->pActiveClass->pData[interface_num] = (HID_HandleTypeDef *)USBH_malloc(sizeof(HID_HandleTypeDef)); /* [ */ phost->pActiveClass->InterfaceNumber++; phost->pActiveClass->CurrInterface = interface_num; /* ] */ HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[interface_num]; if (HID_Handle == NULL) { USBH_DbgLog("Cannot allocate memory for HID Handle"); return USBH_FAIL; } /* Initialize hid handler */ USBH_memset(HID_Handle, 0, sizeof(HID_HandleTypeDef)); HID_Handle->state = HID_ERROR; /*Decode Bootclass Protocol: Mouse or Keyboard*/ HID_Handle->Protocol = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol; ... ... /* 配置完成 */ if (boot == HID_KEYBRD_BOOT_CODE) boot = HID_MOUSE_BOOT_CODE; else boot = HID_KEYBRD_BOOT_CODE; } return status; } 修改USBH_HID_Process, 在POLL空闲时如果10次连续空闲未收到有效数据则切换接口, 使下次执行Process的时候切换到另一个接口: static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK; HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[phost->pActiveClass->CurrInterface]; uint32_t XferSize; /* [ */ uint8_t interface; uint8_t protocol; static __IO uint16_t num = 0; /* ] */ switch (HID_Handle->state) { ... case HID_POLL: if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_DONE) { XferSize = USBH_LL_GetLastXferSize(phost, HID_Handle->InPipe); if ((HID_Handle->DataReady == 0U) && (XferSize != 0U)) { USBH_HID_FifoWrite(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); HID_Handle->DataReady = 1U; USBH_HID_EventCallback(phost); #if (USBH_USE_OS == 1U) phost->os_msg = (uint32_t)USBH_URB_EVENT; #if (osCMSIS < 0x20000U) (void)osMessagePut(phost->os_event, phost->os_msg, 0U); #else (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL); #endif #endif /* 如果检测到有效数据, 则清除空闲计数 [ */ num = 0; /* ] */ } } else { /* 如果空闲计数达到10次, 则切换到其他interface [ */ num++; if (num > 10) { if (phost->pActiveClass->InterfaceNumber > 1) { if (phost->pActiveClass->CurrInterface == 0) phost->pActiveClass->CurrInterface = 1; else phost->pActiveClass->CurrInterface = 0; protocol = ((HID_HandleTypeDef *)phost->pActiveClass->pData[phost->pActiveClass->CurrInterface])->Protocol; interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, protocol); USBH_SelectInterface(phost, interface); } num = 0; } /* ] */ /* IN Endpoint Stalled */ if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_STALL) { /* Issue Clear Feature on interrupt IN endpoint */ if (USBH_ClrFeature(phost, HID_Handle->ep_addr) == USBH_OK) { /* Change state to issue next IN token */ HID_Handle->state = HID_GET_DATA; } } } break; ... } } 另外其他涉及到"phost->pActiveClass->pData"的地方全部改为"phost->pActiveClass->pData[phost->pActiveClass->CurrInterface]", 因为pData已经不再是一个结构体指针而是一个结构体指针数组, 主要涉及的文件包括: u***h_hid.c, u***h_hid_keybs.c, u***h_hid_mouse.c 3. 修改键盘和鼠标的驱动 最后就是按照键盘鼠标的协议定义相应的回调函数, 因为不同的无线鼠标键盘有不同的协议, 在此不做描述. 主要涉及的文件包括: u***_host.c, u***h_hid_keybs.c, u***h_hid_mouse.c 做好驱动以后就可以同时使用键盘和鼠标了, 此方法也可适用于USB连接其他多设备场景, 只要USB初始化的时候能够检测到相应的设备. |
|
|
|
只有小组成员才能发言,加入小组>>
3311 浏览 9 评论
2994 浏览 16 评论
3493 浏览 1 评论
9058 浏览 16 评论
4087 浏览 18 评论
1176浏览 3评论
604浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
598浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2334浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1895浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 21:32 , Processed in 1.094151 second(s), Total 49, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号