stm32f072_usb_mouse_keyboard: update key events and fix pma address align issue

This commit is contained in:
wangyz1997 2024-09-29 21:40:30 +08:00
parent 011a94b870
commit 7f2a464bd2
5 changed files with 209 additions and 88 deletions

View File

@ -3,6 +3,10 @@
#include <stdint.h>
#define HID_MOUSE_BUTTON_LEFT 0x01
#define HID_MOUSE_BUTTON_MIDDLE 0x02
#define HID_MOUSE_BUTTON_RIGHT 0x04
#define HID_CONSUMER_USAGE_NEXTTRACK 0x00B5
#define HID_CONSUMER_USAGE_PREVTRACK 0x00B6
#define HID_CONSUMER_USAGE_STOP 0x00B7
@ -26,6 +30,19 @@
#define HID_SYSTEM_USAGE_SLEEP 0x02
#define HID_SYSTEM_USAGE_WAKEUP 0x04
#define USBD_VID 0x0483
#define USBD_PID 0x5750
#define USBD_MAX_POWER_MA 100
#define USBD_LANGID_STRING 1033
#define HID_KM_IN_EP 0x81
#define HID_KM_IN_EP_SIZE 8 //对于fsdev必须2字节对齐
#define HID_KM_IN_EP_INTERVAL 1
#define HID_KM_OUT_EP 0x02
#define HID_KM_OUT_EP_SIZE 2
#define HID_KM_OUT_EP_INTERVAL 1
void hid_keyboard_mouse_init(uint8_t busid, uint32_t reg_base);
void hid_keyboard_key_send(uint8_t busid, uint8_t modifier_keys, uint8_t key);
void hid_consumer_control_key_send(uint8_t busid, uint16_t consumer_control_key);

View File

@ -7,28 +7,15 @@
#define HID_STATE_IDLE 0
#define HID_STATE_BUSY 1
#define USBD_VID 0x0483
#define USBD_PID 0x5750
#define USBD_MAX_POWER_MA 100
#define USBD_LANGID_STRING 1033
#define HID_KM_CONF_DESC_SIZE 41
#define HID_KM_REPORT_DESC_SIZE 187
#define HID_KM_IN_EP 0x81
#define HID_KM_IN_EP_SIZE 9
#define HID_KM_IN_EP_INTERVAL 1
#define HID_KM_OUT_EP 0x02
#define HID_KM_OUT_EP_SIZE 2
#define HID_KM_OUT_EP_INTERVAL 1
#define HID_CONFIG_DESCRIPTOR_SIZE 41
#define HID_KM_REPORT_DESC_SIZE 187
static const uint8_t hid_descriptor[] = {
static uint8_t hid_km_descriptor[] = {
/* 设备(Device)描述符 所有设备有且只有一个 */
USB_DEVICE_DESCRIPTOR_INIT(USB_1_1, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
/* 配置(Configuration)描述符 所有设备至少有一个 */
USB_CONFIG_DESCRIPTOR_INIT(HID_CONFIG_DESCRIPTOR_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER_MA),
USB_CONFIG_DESCRIPTOR_INIT(HID_KM_CONF_DESC_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER_MA),
/* 截至此处的配置描述符长度 = 09 */
/* 接口(Interface)描述符 键盘 */
@ -75,36 +62,65 @@ static const uint8_t hid_descriptor[] = {
USB_LANGID_INIT(USBD_LANGID_STRING),
/* 字符串(String)描述符 制造商字符串 */
0x02, /* bLength */
0x0C, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'S', 0x00,
'T', 0x00,
'M', 0x00,
'3', 0x00,
'2', 0x00, /* 5字符 */
/* 字符串(String)描述符 产品字符串 */
0x12, /* bLength */
0x2A, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'H', 0x00, /* wcChar0 */
'I', 0x00, /* wcChar1 */
'D', 0x00, /* wcChar2 */
' ', 0x00, /* wcChar3 */
'D', 0x00, /* wcChar4 */
'e', 0x00, /* wcChar5 */
'm', 0x00, /* wcChar6 */
'o', 0x00, /* wcChar7 */
'H', 0x00,
'I', 0x00,
'D', 0x00,
' ', 0x00,
'C', 0x00,
'o', 0x00,
'm', 0x00,
'p', 0x00,
'o', 0x00,
's', 0x00,
'i', 0x00,
't', 0x00,
'e', 0x00,
' ', 0x00,
'D', 0x00,
'e', 0x00,
'v', 0x00,
'i', 0x00,
'c', 0x00,
'e', 0x00, /* 共20字符 */
/* 字符串(String)描述符 序列号字符串 */
0x16, /* bLength */
0x32, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
'2', 0x00, /* wcChar0 */
'0', 0x00, /* wcChar1 */
'2', 0x00, /* wcChar2 */
'2', 0x00, /* wcChar3 */
'1', 0x00, /* wcChar4 */
'2', 0x00, /* wcChar5 */
'3', 0x00, /* wcChar6 */
'4', 0x00, /* wcChar7 */
'5', 0x00, /* wcChar8 */
'6', 0x00, /* wcChar9 */
'7', 0x00, /* wcChar10 */
'8', 0x00, /* wcChar11 */
'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)描述符 同时支持全速与高速的设备必须有 */
@ -144,7 +160,7 @@ static const uint8_t hid_km_report_desc[HID_KM_REPORT_DESC_SIZE] = {
0x15, 0x00, // Logical Minimum (0)
0x25, 0x65, // Logical Maximum (101)
0x75, 0x08, // Report Size (8)
0x95, 0x06, // Report Count (6)
0x95, 0x06, // Report Count (5)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x08, // Usage Page (LEDs)
0x19, 0x01, // Usage Minimum (Num Lock)
@ -238,9 +254,11 @@ static void usbd_hid_keyboard_out_callback(uint8_t busid, uint8_t ep, uint32_t n
{
usbd_ep_start_read(busid, ep, read_buffer, HID_KM_OUT_EP_SIZE);
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, read_buffer[1] & 0x01);
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, read_buffer[1] & 0x02);
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, read_buffer[1] & 0x04);
if (read_buffer[0] == 1) {
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, read_buffer[1] & 0x01);
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, read_buffer[1] & 0x02);
HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, read_buffer[1] & 0x04);
}
}
static void usbd_event_handler(uint8_t busid, uint8_t event)
@ -258,7 +276,7 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
break;
case USBD_EVENT_CONFIGURED:
hid_km_state = HID_STATE_IDLE;
usbd_ep_start_read(busid, HID_KM_OUT_EP, read_buffer, HID_KM_OUT_EP_SIZE);
usbd_ep_start_read(busid, HID_KM_OUT_EP, read_buffer, sizeof(read_buffer));
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@ -270,21 +288,45 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
}
}
static struct usbd_endpoint hid_keyboard_in_ep = {
.ep_cb = usbd_hid_keyboard_in_callback,
.ep_addr = HID_KM_IN_EP
};
static void fill_usb_descriptor_serial_number(void)
{
char uid_string[25];
sprintf(uid_string, "%08X%08X%08X", HAL_GetUIDw0(), HAL_GetUIDw1(), HAL_GetUIDw2());
static struct usbd_endpoint hid_keyboard_out_ep = {
.ep_cb = usbd_hid_keyboard_out_callback,
.ep_addr = HID_KM_OUT_EP
};
uint16_t serial_number_offset = 0;
for (uint16_t i = 0; i < sizeof(hid_km_descriptor) - 3; i ++) { //查找USB描述符中序列号字符描述符的偏移
if (hid_km_descriptor[i + 0] == '0' && hid_km_descriptor[i + 1] == 0x00 &&
hid_km_descriptor[i + 2] == '0' && hid_km_descriptor[i + 3] == 0x00) {
serial_number_offset = i;
break;
}
}
if (serial_number_offset == 0) { //未找到
return;
}
for (uint8_t i = 0; i < 24; i ++) { //共24位
hid_km_descriptor[serial_number_offset + i * 2] = uid_string[i];
}
}
void hid_keyboard_mouse_init(uint8_t busid, uint32_t reg_base)
{
static struct usbd_interface intf0;
static struct usbd_endpoint hid_keyboard_in_ep = {
.ep_cb = usbd_hid_keyboard_in_callback,
.ep_addr = HID_KM_IN_EP
};
static struct usbd_endpoint hid_keyboard_out_ep = {
.ep_cb = usbd_hid_keyboard_out_callback,
.ep_addr = HID_KM_OUT_EP
};
usbd_desc_register(busid, hid_descriptor);
fill_usb_descriptor_serial_number();
usbd_desc_register(busid, hid_km_descriptor);
usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_km_report_desc, HID_KM_REPORT_DESC_SIZE));
usbd_add_endpoint(busid, &hid_keyboard_in_ep); //添加键盘鼠标INT IN端点
usbd_add_endpoint(busid, &hid_keyboard_out_ep); //添加键盘鼠标INT OUT端点
@ -295,75 +337,82 @@ void hid_keyboard_mouse_init(uint8_t busid, uint32_t reg_base)
void hid_keyboard_key_send(uint8_t busid, uint8_t modifier_keys, uint8_t key)
{
static USB_MEM_ALIGNX uint8_t report[HID_KM_IN_EP_SIZE];
memset(report, 0, HID_KM_IN_EP_SIZE);
memset(report, 0, sizeof(report));
report[0] = 1; //ID
report[1] = modifier_keys; //修饰键
report[3] = key; //第一个按键
// report[4] = ...; //第二个按键
// ...
// report[8] = ...; //第六个按键
// report[7] = ...; //第五个按键
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, HID_KM_IN_EP_SIZE);
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, sizeof(report));
if (ret < 0) {
return;
}
HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_SET);
hid_km_state = HID_STATE_BUSY;
while (hid_km_state == HID_STATE_BUSY) {
HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_SET);
__WFI();
HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_RESET);
}
void hid_consumer_control_key_send(uint8_t busid, uint16_t consumer_control_key)
{
static USB_MEM_ALIGNX uint8_t report[HID_KM_IN_EP_SIZE];
memset(report, 0, HID_KM_IN_EP_SIZE);
memset(report, 0, sizeof(report));
report[0] = 2; //ID
report[1] = consumer_control_key & 0xFF; //键码低字节
report[2] = consumer_control_key >> 8; //键码高字节
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, HID_KM_IN_EP_SIZE);
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, sizeof(report));
if (ret < 0) {
return;
}
HAL_GPIO_WritePin(LED6_GPIO_Port, LED6_Pin, GPIO_PIN_SET);
hid_km_state = HID_STATE_BUSY;
while (hid_km_state == HID_STATE_BUSY) {
HAL_GPIO_WritePin(LED6_GPIO_Port, LED6_Pin, GPIO_PIN_SET);
__WFI();
HAL_GPIO_WritePin(LED6_GPIO_Port, LED6_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(LED6_GPIO_Port, LED6_Pin, GPIO_PIN_RESET);
}
void hid_system_control_key_send(uint8_t busid, uint16_t system_control_key)
{
static USB_MEM_ALIGNX uint8_t report[HID_KM_IN_EP_SIZE];
memset(report, 0, HID_KM_IN_EP_SIZE);
memset(report, 0, sizeof(report));
report[0] = 3; //ID
report[1] = system_control_key; //键码
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, HID_KM_IN_EP_SIZE);
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, sizeof(report));
if (ret < 0) {
return;
}
HAL_GPIO_WritePin(LED7_GPIO_Port, LED8_Pin, GPIO_PIN_SET);
hid_km_state = HID_STATE_BUSY;
while (hid_km_state == HID_STATE_BUSY) {
HAL_GPIO_WritePin(LED7_GPIO_Port, LED8_Pin, GPIO_PIN_SET);
__WFI();
HAL_GPIO_WritePin(LED7_GPIO_Port, LED8_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(LED7_GPIO_Port, LED8_Pin, GPIO_PIN_RESET);
}
void hid_mouse_send(uint8_t busid, uint8_t buttons, int8_t x, int8_t y, int8_t wheel)
{
static USB_MEM_ALIGNX uint8_t report[HID_KM_IN_EP_SIZE];
memset(report, 0, HID_KM_IN_EP_SIZE);
memset(report, 0, sizeof(report));
report[0] = 4; //ID
report[1] = buttons; //鼠标按键
@ -371,15 +420,17 @@ void hid_mouse_send(uint8_t busid, uint8_t buttons, int8_t x, int8_t y, int8_t w
report[3] = y; //Delta y
report[4] = wheel; //滚轮
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, HID_KM_IN_EP_SIZE);
int ret = usbd_ep_start_write(busid, HID_KM_IN_EP, report, sizeof(report));
if (ret < 0) {
return;
}
HAL_GPIO_WritePin(LED8_GPIO_Port, LED8_Pin, GPIO_PIN_SET);
hid_km_state = HID_STATE_BUSY;
while (hid_km_state == HID_STATE_BUSY) {
HAL_GPIO_WritePin(LED8_GPIO_Port, LED8_Pin, GPIO_PIN_SET);
__WFI();
HAL_GPIO_WritePin(LED8_GPIO_Port, LED8_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(LED8_GPIO_Port, LED8_Pin, GPIO_PIN_RESET);
}

View File

@ -108,28 +108,73 @@ int main(void)
bsp_key_event_type_e event;
bsp_key_get_event(&key, &event);
if (key != bsp_key_none) { //有按键按下
if (key == bsp_key1) { //触发USB键盘按键
if (event == bsp_key_event_press) { //按键短按 鼠标事件
switch (key) {
case bsp_key2: //鼠标向上移动
hid_mouse_send(0, 0, 0, -20, 0);
} else if (key == bsp_key2) {
hid_consumer_control_key_send(0, HID_CONSUMER_USAGE_MUTE); //静音
hid_consumer_control_key_send(0, 0); //抬起
} else if (key == bsp_key3) {
break;
case bsp_key6: //鼠标向下移动
hid_mouse_send(0, 0, 0, 20, 0);
break;
case bsp_key5: //鼠标向左移动
hid_mouse_send(0, 0, -20, 0, 0);
break;
case bsp_key7: //鼠标向右移动
hid_mouse_send(0, 0, 20, 0, 0);
break;
case bsp_key1: //鼠标左键
hid_mouse_send(0, HID_MOUSE_BUTTON_LEFT, 0, 0, 0);
hid_mouse_send(0, 0, 0, 0, 0);
break;
case bsp_key3: //鼠标右键
hid_mouse_send(0, HID_MOUSE_BUTTON_RIGHT, 0, 0, 0);
hid_mouse_send(0, 0, 0, 0, 0);
break;
case bsp_key4: //鼠标滚轮上
hid_mouse_send(0, 0, 0, 0, 1);
break;
case bsp_key8: //鼠标滚轮下
hid_mouse_send(0, 0, 0, 0, -1);
break;
default:
break;
}
} else if (event == bsp_key_event_long) {
switch (key) {
case bsp_key1: //键盘A
hid_keyboard_key_send(0, 0, HID_KBD_USAGE_A);
hid_keyboard_key_send(0, 0, 0);
} else if (key == bsp_key4) {
hid_mouse_send(0, 0, 0, 0, -1);
} else if (key == bsp_key5) {
hid_mouse_send(0, 0, 0, 20, 0);
} else if (key == bsp_key6) {
hid_consumer_control_key_send(0, HID_CONSUMER_USAGE_PLAYPAUSE); //静音
hid_consumer_control_key_send(0, 0); //抬起
} else if (key == bsp_key7) {
break;
case bsp_key2: //键盘1
hid_keyboard_key_send(0, 0, HID_KBD_USAGE_1);
hid_keyboard_key_send(0, 0, 0);
break;
case bsp_key3: //Win+L锁屏
hid_keyboard_key_send(0, HID_MODIFER_LGUI, HID_KBD_USAGE_A + ('L' - 'A'));
hid_keyboard_key_send(0, 0, 0);
} else if (key == bsp_key8) {
hid_system_control_key_send(0, HID_SYSTEM_USAGE_POWER); //关闭屏幕
hid_system_control_key_send(0, 0); //抬起
break;
case bsp_key4: //电源键
hid_system_control_key_send(0, HID_SYSTEM_USAGE_POWER);
hid_system_control_key_send(0, 0);
break;
case bsp_key5: //音量减
hid_consumer_control_key_send(0, HID_CONSUMER_USAGE_VOLUMEDEC);
hid_consumer_control_key_send(0, 0);
break;
case bsp_key6: //音量加
hid_consumer_control_key_send(0, HID_CONSUMER_USAGE_VOLUMEINC);
hid_consumer_control_key_send(0, 0);
break;
case bsp_key7: //静音
hid_consumer_control_key_send(0, HID_CONSUMER_USAGE_MUTE);
hid_consumer_control_key_send(0, 0);
break;
case bsp_key8: //播放/暂停
hid_consumer_control_key_send(0, HID_CONSUMER_USAGE_PLAYPAUSE);
hid_consumer_control_key_send(0, 0);
break;
default:
break;
}
} else {
__WFI();

View File

@ -137,7 +137,7 @@
<DriverSelection>4101</DriverSelection>
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2V8M.DLL</Flash2>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>

View File

@ -168,6 +168,10 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
g_fsdev_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_fsdev_udc.out_ep[ep_idx].ep_enable = true;
if (g_fsdev_udc.out_ep[ep_idx].ep_mps > g_fsdev_udc.out_ep[ep_idx].ep_pma_buf_len) {
/* PMA address must be halfword-aligned */
if (g_fsdev_udc.pma_offset % 2) {
g_fsdev_udc.pma_offset ++;
}
if (g_fsdev_udc.pma_offset + g_fsdev_udc.out_ep[ep_idx].ep_mps > CONFIG_USB_FSDEV_RAM_SIZE) {
USB_LOG_ERR("Ep pma %02x overflow\r\n", ep->bEndpointAddress);
return -1;
@ -186,6 +190,10 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
g_fsdev_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_fsdev_udc.in_ep[ep_idx].ep_enable = true;
if (g_fsdev_udc.in_ep[ep_idx].ep_mps > g_fsdev_udc.in_ep[ep_idx].ep_pma_buf_len) {
/* PMA address must be halfword-aligned */
if (g_fsdev_udc.pma_offset % 2) {
g_fsdev_udc.pma_offset ++;
}
if (g_fsdev_udc.pma_offset + g_fsdev_udc.in_ep[ep_idx].ep_mps > CONFIG_USB_FSDEV_RAM_SIZE) {
USB_LOG_ERR("Ep pma %02x overflow\r\n", ep->bEndpointAddress);
return -1;