STM32

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****/