#include "usbd_custom_hid.h" #include #include "main.h" #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "usbd_core.h" #include "usbd_hid.h" #include "led_control.h" /* 描述符长度 */ #define HID_CONFIG_DESC_SIZE 41 //配置描述符长度 #define HID_CUSTOM_REPORT_DESC_SIZE 36 //HID报告描述符 /* 端点缓冲区 */ static USB_MEM_ALIGNX uint8_t read_buffer[CUSTOM_HID_OUT_EP_SIZE]; static USB_MEM_ALIGNX uint8_t send_buffer[CUSTOM_HID_IN_EP_SIZE]; /* 发送信号量 */ static TaskHandle_t sender_task_handle = NULL; /* USB描述符 */ static uint8_t usb_descriptor[] = { /* 设备(Device)描述符 所有设备有且只有一个 */ USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, USBD_PVN, 0x01), /* 配置(Configuration)描述符 所有设备至少有一个 */ USB_CONFIG_DESCRIPTOR_INIT(HID_CONFIG_DESC_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), /* 截至此处的配置描述符长度: 9 */ /* 接口(Interface)描述符 HID设备 */ 0x09, /* bLength: Interface Descriptor size */ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */ 0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x02, /* bNumEndpoints */ 0x03, /* bInterfaceClass: HID */ 0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ 0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ 0, /* iInterface: Index of string descriptor */ /* 截至此处的配置描述符长度: 18 */ /* HID描述符 自定义HID设备 */ 0x09, /* bLength: HID Descriptor size */ HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */ 0x11, /* bcdHID: HID Class Spec release number */ 0x01, 0x00, /* bCountryCode: Hardware target country */ 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ 0x22, /* bDescriptorType */ HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ 0x00, /* 截至此处的配置描述符长度: 27 */ /* 端点(Endpoint)描述符 HID IN */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ CUSTOM_HID_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */ 0x03, /* bmAttributes: Interrupt endpoint */ WBVAL(CUSTOM_HID_IN_EP_SIZE), /* wMaxPacketSize: 4 Byte max */ CUSTOM_HID_IN_INTERVAL, /* bInterval: Polling Interval */ /* 截至此处的配置描述符长度: 34 */ /* 端点(Endpoint)描述符 HID OUT */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */ CUSTOM_HID_OUT_EP, /* bEndpointAddress: Endpoint Address (OUT) */ 0x03, /* bmAttributes: Interrupt endpoint */ WBVAL(CUSTOM_HID_OUT_EP_SIZE), /* wMaxPacketSize: 4 Byte max */ CUSTOM_HID_OUT_EP_INTERVAL, /* bInterval: Polling Interval */ /* 截至此处的配置描述符长度: 41 配置描述符结束 */ /* 字符串(String)描述符 设备支持的语言描述符 */ USB_LANGID_INIT(USBD_LANGID_STRING), /* 字符串(String)描述符 制造商字符串 */ 0x0C, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 'S', 0x00, 'T', 0x00, 'M', 0x00, '3', 0x00, '2', 0x00, /* 5字符 */ /* 字符串(String)描述符 产品字符串 */ 0x2C, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 'H', 0x00, 'I', 0x00, 'D', 0x00, ' ', 0x00, 'C', 0x00, 'o', 0x00, 'n', 0x00, 't', 0x00, 'r', 0x00, 'o', 0x00, 'l', 0x00, ' ', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, /* 21字符 */ /* 字符串(String)描述符 序列号字符串 */ 0x32, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, '0', 0x00, /* 24字符 */ #ifdef CONFIG_USB_HS /* 设备限定(Device Qualifier)描述符 同时支持全速与高速的设备必须有 */ 0x0A, USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, #endif /* 空描述符 */ 0x00 }; /* 自定义HID报告描述符 */ static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = { 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined Page 0) */ 0x09, 0x01, /* USAGE (Vendor Usage 1) */ 0xA1, 0x01, /* COLLECTION (Application) */ 0x85, 0x01, /* REPORT ID (0x01) */ 0x09, 0x01, /* USAGE (Vendor Usage 1) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0xFF, /* LOGICAL_MAXIMUM (255) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, CUSTOM_HID_OUT_EP_SIZE-1, /* REPORT_COUNT (63) */ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ 0x85, 0x02, /* REPORT ID (0x02) */ 0x09, 0x01, /* USAGE (Vendor Usage 1) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0xFF, /* LOGICAL_MAXIMUM (255) */ 0x75, 0x08, /* REPORT_SIZE (8) */ 0x95, CUSTOM_HID_IN_EP_SIZE-1, /* REPORT_COUNT (63) */ 0x81, 0x02, /* INPUT (Data,Var,Abs) */ 0xC0 /* END_COLLECTION */ }; static void usbd_event_handler(uint8_t busid, uint8_t event) { switch (event) { case USBD_EVENT_RESET: break; case USBD_EVENT_CONNECTED: break; case USBD_EVENT_DISCONNECTED: break; case USBD_EVENT_RESUME: break; case USBD_EVENT_SUSPEND: break; case USBD_EVENT_CONFIGURED: /* setup first out ep read transfer */ usbd_ep_start_read(busid, CUSTOM_HID_OUT_EP, read_buffer, CUSTOM_HID_OUT_EP_SIZE); break; case USBD_EVENT_SET_REMOTE_WAKEUP: break; case USBD_EVENT_CLR_REMOTE_WAKEUP: break; default: break; } } static void usbd_hid_custom_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { xTaskNotifyGive(sender_task_handle); } static void usbd_hid_custom_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { if (read_buffer[0] == 1) { led_control_command_send_from_isr(&read_buffer[1]); } usbd_ep_start_read(busid, ep, read_buffer, CUSTOM_HID_IN_EP_SIZE); } static void fill_usb_descriptor_serial_number(void) { char uid_string[25]; sprintf(uid_string, "%08X%08X%08X", HAL_GetUIDw0(), HAL_GetUIDw1(), HAL_GetUIDw2()); uint16_t serial_number_offset = 0; for (uint16_t i = 0; i < sizeof(usb_descriptor) - 3; i ++) { //查找USB描述符中序列号字符描述符的偏移 if (usb_descriptor[i + 0] == '0' && usb_descriptor[i + 1] == 0x00 && usb_descriptor[i + 2] == '0' && usb_descriptor[i + 3] == 0x00) { serial_number_offset = i; break; } } if (serial_number_offset == 0) { //未找到 return; } for (uint8_t i = 0; i < 24; i ++) { //共24位 usb_descriptor[serial_number_offset + i * 2] = uid_string[i]; } } void usbd_custom_hid_start(uint8_t busid, uintptr_t reg_base) { static struct usbd_interface intf0; static struct usbd_endpoint custom_in_ep = { .ep_cb = usbd_hid_custom_in_callback, .ep_addr = CUSTOM_HID_IN_EP }; static struct usbd_endpoint custom_out_ep = { .ep_cb = usbd_hid_custom_out_callback, .ep_addr = CUSTOM_HID_OUT_EP }; fill_usb_descriptor_serial_number(); usbd_desc_register(busid, usb_descriptor); usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE)); usbd_add_endpoint(busid, &custom_in_ep); usbd_add_endpoint(busid, &custom_out_ep); usbd_initialize(busid, reg_base, usbd_event_handler); } uint8_t usbd_custom_hid_send(const uint8_t *data, uint16_t length) { send_buffer[0] = 0x02; //OUT if (length > CUSTOM_HID_IN_EP_SIZE - 1) { length = CUSTOM_HID_IN_EP_SIZE - 1; //限制发送长度 } else { memset(&send_buffer[1 + length], 0x00, CUSTOM_HID_IN_EP_SIZE - 1 - length); //缓冲区后部补0 } memcpy(&send_buffer[1], data, length); usbd_ep_start_write(0, CUSTOM_HID_IN_EP, send_buffer, CUSTOM_HID_IN_EP_SIZE); sender_task_handle = xTaskGetCurrentTaskHandle(); //获取当前任务的句柄 return xTaskNotifyWait(0, 0x00, NULL, pdMS_TO_TICKS(CUSTOM_HID_IN_INTERVAL)) == pdTRUE ? 0 : 1; //等待发送完成 }