STM32 USB HOST HID 添加自定义设备驱动
简要记录一下流程
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_Process: USB Device Connected
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_Process: USB Device Reset Completed
USBH_UserProcess: id = 4
USBH_UserProcess: HOST_USER_CONNECTION
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_HandleEnum: PID: 5656h
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_HandleEnum: VID: 20bch
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_HandleEnum: Address (#1) assigned.
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_HandleEnum: Manufacturer : N/A
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_HandleEnum: Product : Controller
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_HandleEnum: Serial Number : N/A
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_Process: Enumeration done.
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_Process: This device has only 1 configuration.
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_Process: Default configuration set.
USBH_FindInterface: Class = 3(3), SubClass = 0(1), Protocol = 0(255)
USBH_FindInterface: Class = 0(3), SubClass = 0(1), Protocol = 0(255)
Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c#USBH_HID_InterfaceInit: DEBUG : Cannot Find the interface for HID c.
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_Process: Device not supporting HID class.
//自己插个手柄上去,基本上就只能跑到这里了!
开始添加代码,支持自己的设备
编辑函数:Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c#USBH_HID_InterfaceInit
interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFFU);
/* 增加开始 */
if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
{
debug_printf("%s: Cannot Find the interface for %s class of HID_BOOT_CODE. Try my custom device subclass number(0)...\r\n",
__func__, phost->pActiveClass->Name);
interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_CUSTOM_CODE, 0xFFU);
}
/* 增加完毕 */
if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
{
USBH_DbgLog("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
return USBH_FAIL;
}
其中HID_CUSTOM_CODE,定位为上面打印的log的SubClass的值!
USBH_HID_InterfaceInit: Cannot Find the interface for HID class of HID_BOOT_CODE. Try my custom device subclass number(0)…
USBH_FindInterface: Class = 3(3), SubClass = 0(0), Protocol = 0(255)
//修复后往USBH_SelectInterface走
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_SelectInterface: Switching to Interface (#0)
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_SelectInterface: Class : 3h
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_SelectInterface: SubClass : 0h
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_SelectInterface: Protocol : 0h
Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c#USBH_HID_InterfaceInit: Protocol not supported.
//这里开始需要添加自己的HID驱动接口了
Middlewares/ST/STM32_USB_Host_Library/Core/Src/usbh_core.c#USBH_Process: Device not supporting HID class.
这时要修改的地方是:Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c#USBH_HID_InterfaceInit
else if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE)
{
USBH_UsrLog("Mouse device found!");
HID_Handle->Init = USBH_HID_MouseInit;
}
/* 添加自己的接口协议 */
else if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_CUSTOM_DEVICE_CODE)
{
USBH_UsrLog("Custom device found!");
HID_Handle->Init = USBH_HID_CustomInit; //
}
/* 完成添加自己的接口协议 */
else
{
USBH_UsrLog("Protocol not supported.");
return USBH_FAIL;
}
还要修改Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c#USBH_HID_GetDeviceType函数:
HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost)
{
HID_TypeTypeDef type = HID_UNKNOWN;
uint8_t InterfaceProtocol;
if (phost->gState == HOST_CLASS)
{
InterfaceProtocol = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol;
//debug_printf("%s#%s: InterfaceProtocol = %d\r\n", __FILE__, __func__, InterfaceProtocol);
if (InterfaceProtocol == HID_KEYBRD_BOOT_CODE)
{
type = HID_KEYBOARD;
}
else if(InterfaceProtocol == HID_CUSTOM_DEVICE_CODE) //添加这个判断分支
{
type = HID_CUSTOM_DEVICE;
}
else
{
if (InterfaceProtocol == HID_MOUSE_BOOT_CODE)
{
type = HID_MOUSE;
}
}
}
return type;
}
然后在Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/添加自己的驱动文件usbh_hid_custom.c, usbh_hid_custom.h. (也可以放在其它路径,视情况而定)
修改Class/HID/Src/usbh_hid.c, Class/HID/Src/usbh_hid.h文件,主要是添加上述的代码和一些宏的定义。
/******************头文件*************************/
#include “usbh_core.h”
#include “usbh_hid_mouse.h”
#include “usbh_hid_keybd.h”
#include “usbh_hid_custom.h”
/********************宏定义***********************/
/* Interface Descriptor field values for HID Boot Protocol */
#define HID_BOOT_CODE 0x01U
#define HID_KEYBRD_BOOT_CODE 0x01U
#define HID_MOUSE_BOOT_CODE 0x02U
#define HID_CUSTOM_CODE 0x00U
#define HID_CUSTOM_DEVICE_CODE 0x00U
/********************枚举***********************/
typedef enum
{
HID_CUSTOM_DEVICE = 0x00,
HID_MOUSE = 0x01,
HID_KEYBOARD = 0x02,
HID_UNKNOWN = 0xFF,
}
HID_TypeTypeDef;
开始贴代码
Middlewares/ST/STM32_USB_Host_Library/Class/HID/Src/usbh_hid.c修改:
/**
* @brief USBH_HID_InterfaceInit
* The function init the HID class.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost)
{
USBH_StatusTypeDef status;
HID_HandleTypeDef *HID_Handle;
uint8_t max_ep;
uint8_t num = 0U;
uint8_t interface;
interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFFU);
if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
{
debug_printf("%s: Cannot Find the interface for %s class of HID_BOOT_CODE. Try my custom device subclass number(0)...\r\n",
__func__, phost->pActiveClass->Name);
interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_CUSTOM_CODE, 0xFFU);
}
if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
{
USBH_DbgLog("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
return USBH_FAIL;
}
status = USBH_SelectInterface(phost, interface);
if (status != USBH_OK)
{
return USBH_FAIL;
}
phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc(sizeof(HID_HandleTypeDef));
HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
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*/
if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE)
{
USBH_UsrLog("KeyBoard device found!");
HID_Handle->Init = USBH_HID_KeybdInit;
}
else if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE)
{
USBH_UsrLog("Mouse device found!");
HID_Handle->Init = USBH_HID_MouseInit;
}
else if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_CUSTOM_DEVICE_CODE)
{
USBH_UsrLog("Custom device found!");
HID_Handle->Init = USBH_HID_CustomInit; //My Custom HID device
}
else
{
USBH_UsrLog("Protocol not supported.");
return USBH_FAIL;
}
HID_Handle->state = HID_INIT;
HID_Handle->ctl_state = HID_REQ_INIT;
HID_Handle->ep_addr = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bEndpointAddress;
HID_Handle->length = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].wMaxPacketSize;
HID_Handle->poll = phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[0].bInterval;
if (HID_Handle->poll < HID_MIN_POLL)
{
HID_Handle->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 */
max_ep = ((phost->device.CfgDesc.Itf_Desc[interface].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
phost->device.CfgDesc.Itf_Desc[interface].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS);
/* Decode endpoint IN and OUT address from interface descriptor */
for (num = 0U; num < max_ep; num++)
{
if (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[num].bEndpointAddress & 0x80U)
{
HID_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[num].bEndpointAddress);
HID_Handle->InPipe = USBH_AllocPipe(phost, HID_Handle->InEp);
/* Open pipe for IN endpoint */
USBH_OpenPipe(phost, HID_Handle->InPipe, HID_Handle->InEp, phost->device.address,
phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length);
USBH_LL_SetToggle(phost, HID_Handle->InPipe, 0U);
}
else
{
HID_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[interface].Ep_Desc[num].bEndpointAddress);
HID_Handle->OutPipe = USBH_AllocPipe(phost, HID_Handle->OutEp);
/* Open pipe for OUT endpoint */
USBH_OpenPipe(phost, HID_Handle->OutPipe, HID_Handle->OutEp, phost->device.address,
phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length);
USBH_LL_SetToggle(phost, HID_Handle->OutPipe, 0U);
}
}
return USBH_OK;
}
usb_hid_custom.c
/**
******************************************************************************
* @file usbh_hid_custom.c
* @author Vince Zhang
* @brief This file is the application layer for USB Host HID custom Handling.
******************************************************************************
* @attention
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbh_hid_custom.h"
#include <string.h>
static USBH_StatusTypeDef USBH_HID_CustomDecode(USBH_HandleTypeDef *phost);
uint8_t joystick_info[64];
uint8_t report_data[64];
uint8_t rx_report_buf[64];
/**
* @brief USBH_HID_CustomInit
* The function init the HID mouse.
* @param phost: Host handle
* @retval USBH Status
*/
USBH_StatusTypeDef USBH_HID_CustomInit(USBH_HandleTypeDef *phost)
{
uint32_t i;
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
memset(report_data, 0x00, sizeof(report_data));
memset(rx_report_buf, 0x00, sizeof(rx_report_buf));
debug_printf("%s#%s: HID_Handle->length = %d\r\n", __FILE__, __func__, HID_Handle->length);
if (HID_Handle->length > sizeof(report_data))
{
HID_Handle->length = sizeof(report_data);
}
HID_Handle->pData = (uint8_t *)(void *)rx_report_buf;
USBH_HID_FifoInit(&HID_Handle->fifo, phost->device.Data, HID_QUEUE_SIZE * sizeof(report_data));
return USBH_OK;
}
/**
* @brief USBH_HID_GetDeviceInfo
* The function return device information.
* @param phost: Host handle
* @retval mouse information
*/
uint8_t* USBH_HID_GetJoystickInfo(USBH_HandleTypeDef *phost)
{
if (USBH_HID_CustomDecode(phost) == USBH_OK)
{
return joystick_info;
}
else
{
return NULL;
}
}
/**
* @brief USBH_HID_CustomDecode
* The function decode device data.
* @param phost: Host handle
* @retval USBH Status
*/
static USBH_StatusTypeDef USBH_HID_CustomDecode(USBH_HandleTypeDef *phost)
{
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
if (HID_Handle->length == 0U)
{
return USBH_FAIL;
}
/*Fill report */
if (USBH_HID_FifoRead(&HID_Handle->fifo, &report_data, HID_Handle->length) == HID_Handle->length)
{
/*Decode report */
memcpy(joystick_info, report_data, HID_Handle->length);
return USBH_OK;
}
return USBH_FAIL;
}
/************************ (C) COPYRIGHT Vince Zhang *****END OF FILE****/
usbh_hid_cutsom.h
/**
******************************************************************************
* @file usbh_hid_custom.h
* @author Vince Zhang
* @brief This file contains all the prototypes for the usbh_hid_custom.c
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Define to prevent recursive ----------------------------------------------*/
#ifndef __USBH_HID_CUSTOM_H
#define __USBH_HID_CUSTOM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbh_hid.h"
#define BeiTong_Asura_2 1
#define HID_CUSTOM_DEVICE_TYPE BeiTong_Asura_2
#if (HID_CUSTOM_DEVICE_TYPE == BeiTong_Asura_2)
#define HID_CUSTOM_BUFFER_SIZE 64
#else
#define HID_CUSTOM_BUFFER_SIZE 0
#endif
#if (HID_CUSTOM_BUFFER_SIZE == 0)
#error "Please select a HID_CUSTOM_DEVICE_TYPE"
#endif
#define KEYCODE_X 0x01
#define KEYCODE_A 0x02
#define KEYCODE_B 0x04
#define KEYCODE_Y 0x08
#define KEYCODE_LB 0x10
#define KEYCODE_RB 0x20
#define KEYCODE_LT 0x40
#define KEYCODE_RT 0x80
#define KEYCODE_BACK 0x01
#define KEYCODE_START 0x02
#define KEYCODE_AXIS1_M 0x04
#define KEYCODE_AXIS2_M 0x08
#define KEYCODE_LOGO 0x10
#define KEYCODE_AXIS0_Dft 0x0F
#define KEYCODE_AXIS0_UP 0x00
#define KEYCODE_AXIS0_RIGHT 0x02
#define KEYCODE_AXIS0_DOWN 0x04
#define KEYCODE_AXIS0_LEFT 0x06
typedef struct _HID_Joystick_Info
{
uint8_t Button_Key; //normal:0; LT:0x40; RT:0x80; LB:0x10; RB:0x20; X:0x01; A:0x02; B:0x04; Y:0x08;
uint8_t Button_Ctrl;
uint8_t Button_Axis0;
uint8_t Axis1_X;
uint8_t Axis1_Y;
uint8_t Axis2_X;
uint8_t Axis2_Y;
}
HID_Joystick_Info_TypeDef;
USBH_StatusTypeDef USBH_HID_CustomInit(USBH_HandleTypeDef *phost);
HID_Joystick_Info_TypeDef *USBH_HID_GetJoystickInfo(USBH_HandleTypeDef *phost);
uint8_t* USBH_HID_GetJoystickRawData(USBH_HandleTypeDef *phost);
#ifdef __cplusplus
}
#endif
#endif /* __USBH_HID_CUSTOM_H */
/************************ (C) COPYRIGHT Vince Zhang *****END OF FILE****/