【STM32】USB Custom HID

前言

本篇將以Custom HID達到64 bytes的資料傳輸



1. STM32CubeMX

勾選USB > Device(FS),下面的參數不改

Middleware and Software Packs > 勾選USB_DEVICE

選擇 Custom Human Interface Device Class(HID)

下面的參數這邊先不改,之後直接修改header裡的設定

MX產生出來的Configuration Descriptor在usbd_customhid.c的 USBD_CUSTOM_HID_CfgFSDesc[]

bNumEndpoints:2個(IN和OUT)

CUSTOM_HID_EPIN_SIZE和CUSTOM_HID_EPOUT_SIZE預設2 bytes,後面會改為64 bytes


/* USB CUSTOM_HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgFSDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
  0x09, /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
  USB_CUSTOM_HID_CONFIG_DESC_SIZ,
  /* wTotalLength: Bytes returned */
  0x00,
  0x01,         /*bNumInterfaces: 1 interface*/
  0x01,         /*bConfigurationValue: Configuration value*/
  0x00,         /*iConfiguration: Index of string descriptor describing
  the configuration*/
  0xC0,         /*bmAttributes: bus powered */
  0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/

  /************** Descriptor of CUSTOM HID interface ****************/
  /* 09 */
  0x09,         /*bLength: Interface Descriptor size*/
  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
  0x00,         /*bInterfaceNumber: Number of Interface*/
  0x00,         /*bAlternateSetting: Alternate setting*/
  0x02,         /*bNumEndpoints*/
  0x03,         /*bInterfaceClass: CUSTOM_HID*/
  0x00,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
  0x00,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
  0,            /*iInterface: Index of string descriptor*/
  /******************** Descriptor of CUSTOM_HID *************************/
  /* 18 */
  0x09,         /*bLength: CUSTOM_HID Descriptor size*/
  CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: CUSTOM_HID*/
  0x11,         /*bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number*/
  0x01,
  0x00,         /*bCountryCode: Hardware target country*/
  0x01,         /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/
  0x22,         /*bDescriptorType*/
  USBD_CUSTOM_HID_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
  0x00,
  /******************** Descriptor of Custom HID endpoints ********************/
  /* 27 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/

  CUSTOM_HID_EPIN_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
  0x00,
  CUSTOM_HID_FS_BINTERVAL,          /*bInterval: Polling Interval */
  /* 34 */

  0x07,          /* bLength: Endpoint Descriptor size */
  USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */
  CUSTOM_HID_EPOUT_ADDR,  /*bEndpointAddress: Endpoint Address (OUT)*/
  0x03, /* bmAttributes: Interrupt endpoint */
  CUSTOM_HID_EPOUT_SIZE,  /* wMaxPacketSize: 2 Bytes max  */
  0x00,
  CUSTOM_HID_FS_BINTERVAL,  /* bInterval: Polling Interval */
  /* 41 */
};



2. HID Descriptor

usbd_custom_hid_if.c

定義了INPUT及OUTPUT各64 bytes的report,複製到 CUSTOM_HID_ReportDesc_FS[]


/* USER CODE BEGIN 0 */
0x06, 0x00, 0xff, // Usage Page(Undefined )
0x09, 0x01, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x40, // REPORT_COUNT (64)
0x09, 0x01, // USAGE (Undefined)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x40, // REPORT_COUNT (64)
0x09, 0x01, // USAGE (Undefined)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x09, 0x01, // USAGE (Undefined)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
/* USER CODE END 0 */
0xC0    /*     END_COLLECTION	             */

usbd_conf.h

USBD_CUSTOM_HID_REPORT_DESC_SIZE 改長度33 bytes

#define USBD_CUSTOM_HID_REPORT_DESC_SIZE     33

main.c

在main.c先加入作為資料存取的buffer


/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_customhid.h"
/* USER CODE END Includes */


/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
uint8_t tx_buffer[64];
uint8_t report_buffer[64];
uint8_t flag_rx = 0;
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE END PM */

usbd_custom_hid.c

當主機有資料OUT時會觸發 CUSTOM_HID_OutEvent_FS(),在裡頭加入buffer儲存資料


static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
  /* USER CODE BEGIN 6 */
  extern uint8_t report_buffer[64];
  extern uint8_t flag_rx;

  memcpy(report_buffer, hUsbDeviceFS.pClassData, 64);
  memset(hUsbDeviceFS.pClassData, 0, 64);
  flag_rx = 1;

  return (USBD_OK);
  /* USER CODE END 6 */
}

usbd_conf.h

#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE     64

usbd_customhid.h

IN/OUT的endpoint小大皆改為64 bytes

#define CUSTOM_HID_EPIN_SIZE                 64U

#define CUSTOM_HID_EPOUT_SIZE                64U

usbd_conf.h

#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE     64

usbd_customhid.h

應用上加入2個function,MCU再接收到host送出的資料後,隨即再原資料送回host

接下User button(PA0)後送出64 bytes的data(1到64),每次點擊資料內容加1


int main(void)
{
  uint8_t j = 0;

  while(1)
  {
    if(flag_rx == 1)
    {
      flag_rx = 0;
      for(int i=0; i<64; i++) tx_buffer[i] = report_buffer[i];
      USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, tx_buffer, 64);
      memset(report_buffer, 0, 64);
      memset(tx_buffer, 0, 64);
    }

    if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1)
    {
      for(int i=0; i<64; i++)
      {
          tx_buffer[i] = i+1+j;
      }
      j++;
      USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, tx_buffer, 64);
      HAL_Delay(300);
    }
  }
}


3. HID Host軟體

SimpleHIDWrite

填入數值後按下 Set Report送出資料,隨即收到MCU返回的data