From bec72e5d4c3e7359ba9e6787896b5421958bc852 Mon Sep 17 00:00:00 2001 From: zhugengyu Date: Thu, 22 Sep 2022 18:32:42 +0800 Subject: [PATCH] xhci keyboard and mouse ok --- class/hid/usb_hid.h | 10 +- class/hid/usbh_hid.c | 29 +- demo/phytium-e2000/usbhost/inc/usb_host.h | 2 +- demo/phytium-e2000/usbhost/src/cmd_usb.c | 2 +- demo/phytium-e2000/usbhost/src/usb_host.c | 50 ---- demo/phytium-e2000/usbhost/src/usb_input.c | 313 +++++++++++++++++++++ port/xhci/usb_config.h | 1 + port/xhci/usb_hc_xhci.c | 4 +- 8 files changed, 354 insertions(+), 57 deletions(-) create mode 100644 demo/phytium-e2000/usbhost/src/usb_input.c diff --git a/class/hid/usb_hid.h b/class/hid/usb_hid.h index 9a36676f..19539e7f 100644 --- a/class/hid/usb_hid.h +++ b/class/hid/usb_hid.h @@ -191,6 +191,12 @@ #define HID_MOUSE_INPUT_REPORT_BUTTON3 (1 << 2) #define HID_MOUSE_INPUT_REPORT_BUTTON_MASK (7) +#define HID_MOUSE_INPUT_BUTTON_LEFT (1 << 0) +#define HID_MOUSE_INPUT_BUTTON_RIGHT (1 << 1) +#define HID_MOUSE_INPUT_BUTTON_MIDDLE (1 << 2) +#define HID_MOUSE_INPUT_BUTTON_BACKWARD (1 << 3) +#define HID_MOUSE_INPUT_BUTTON_FORWARD (1 << 4) + /* Joystick input report (4 bytes) (HID D.1) */ #define HID_JS_INPUT_REPORT_HATSWITCH_SHIFT (0) #define HID_JS_INPUT_REPORT_HATSWITCH_MASK (15 << HID_JSIN_HATSWITCH_SHIFT) @@ -546,7 +552,7 @@ struct usb_hid_descriptor { /* Keyboard input report (8 bytes) (HID B.1) */ struct usb_hid_kbd_report { - uint8_t modifier; /* Modifier keys. See USBHID_MODIFIER_* definitions */ + uint8_t modifier; /* Modifier keys. See HID_MODIFER_* definitions */ uint8_t reserved; uint8_t key[6]; /* Keycode 1-6 */ }; @@ -558,7 +564,7 @@ struct usb_hid_kbd_report /* Mouse input report (HID B.2) */ struct usb_hid_mouse_report { - uint8_t buttons; /* See USBHID_MOUSEIN_* definitions */ + uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */ uint8_t xdisp; /* X displacement */ uint8_t ydisp; /* y displacement */ /* Device specific additional bytes may follow */ diff --git a/class/hid/usbh_hid.c b/class/hid/usbh_hid.c index e844177b..99909e90 100644 --- a/class/hid/usbh_hid.c +++ b/class/hid/usbh_hid.c @@ -84,8 +84,14 @@ int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t dur setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = HID_REQUEST_SET_IDLE; - setup->wValue = report_id; - setup->wIndex = (duration << 8) | hid_class->intf; + //setup->wValue = report_id; + //setup->wIndex = (duration << 8) | hid_class->intf; + /* wValue, high-bytes sets the duration, or the max amount of time between reports + 0x00 = hid will send a report only when report data has changed or duration time elapsed + low-bytes indicate the report id that the requeset applies to */ + setup->wValue = (duration << 8) | report_id; + /* wIndex, num of interface that supports the request */ + setup->wIndex = hid_class->intf; setup->wLength = 0; return usbh_control_transfer(hid_class->hport->ep0, setup, NULL); @@ -110,6 +116,19 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer) return ret; } +int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol) +{ + struct usb_setup_packet *setup = &hid_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = HID_REQUEST_SET_PROTOCOL; + setup->wValue = protocol; + setup->wIndex = 0; + setup->wLength = 0; + + return usbh_control_transfer(hid_class->hport->ep0, setup, NULL); +} + int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) { struct usb_endpoint_descriptor *ep_desc; @@ -128,6 +147,12 @@ int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) hport->config.intf[intf].priv = hid_class; + // /* 0x0 = boot protocol, 0x1 = report protocol */ + // ret = usbh_hid_set_protocol(hid_class, 0x1); + // if (ret < 0) { + // return ret; + // } + ret = usbh_hid_set_idle(hid_class, 0, 0); if (ret < 0) { return ret; diff --git a/demo/phytium-e2000/usbhost/inc/usb_host.h b/demo/phytium-e2000/usbhost/inc/usb_host.h index 11aaab8e..223910f1 100644 --- a/demo/phytium-e2000/usbhost/inc/usb_host.h +++ b/demo/phytium-e2000/usbhost/inc/usb_host.h @@ -41,7 +41,7 @@ extern "C" /*****************************************************************************/ BaseType_t FFreeRTOSInitUsb(void); BaseType_t FFreeRTOSWriteReadUsbDisk(void); -BaseType_t FFreeRTOSRecvHidInput(void); +BaseType_t FFreeRTOSRecvInput(void); #ifdef __cplusplus } diff --git a/demo/phytium-e2000/usbhost/src/cmd_usb.c b/demo/phytium-e2000/usbhost/src/cmd_usb.c index a6c8465c..4416fb4c 100644 --- a/demo/phytium-e2000/usbhost/src/cmd_usb.c +++ b/demo/phytium-e2000/usbhost/src/cmd_usb.c @@ -47,7 +47,7 @@ static int USBCmdEntry(int argc, char *argv[]) } else if (!strcmp(argv[1], "hid")) { - ret = FFreeRTOSRecvHidInput(); + ret = FFreeRTOSRecvInput(); } return ret; diff --git a/demo/phytium-e2000/usbhost/src/usb_host.c b/demo/phytium-e2000/usbhost/src/usb_host.c index 69367c0c..f78eb04f 100644 --- a/demo/phytium-e2000/usbhost/src/usb_host.c +++ b/demo/phytium-e2000/usbhost/src/usb_host.c @@ -184,38 +184,6 @@ err_exit: vTaskDelete(NULL); } -static void UsbHidTask(void * args) -{ - int ret; - struct usbh_hid *hid_class; - static uint8_t hid_buffer[128] = {0}; - - while (TRUE) - { - hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0"); - if (hid_class == NULL) - { - USB_LOG_RAW("do not find /dev/input0\r\n"); - goto err_exit; - } - - ret = usbh_int_transfer(hid_class->intin, hid_buffer, 8, 1000); - if (ret < 0) - { - USB_LOG_RAW("intr in error,ret:%d\r\n", ret); - goto err_exit; - } - USB_LOG_RAW("recv len:%d, key:[0x%x, 0x%x, 0x%x, 0x%x]\r\n", - ret, - hid_buffer[0], hid_buffer[1], hid_buffer[2], hid_buffer[3]); - - vTaskDelay(10); - } - -err_exit: - vTaskDelete(NULL); -} - BaseType_t FFreeRTOSInitUsb(void) { BaseType_t ret = pdPASS; @@ -254,21 +222,3 @@ BaseType_t FFreeRTOSWriteReadUsbDisk(void) return ret; } -BaseType_t FFreeRTOSRecvHidInput(void) -{ - BaseType_t ret = pdPASS; - - taskENTER_CRITICAL(); /* no schedule when create task */ - - ret = xTaskCreate((TaskFunction_t )UsbHidTask, - (const char* )"UsbHidTask", - (uint16_t )2048, - NULL, - (UBaseType_t )configMAX_PRIORITIES - 1, - NULL); - FASSERT_MSG(pdPASS == ret, "create task failed"); - - taskEXIT_CRITICAL(); /* allow schedule since task created */ - - return ret; -} \ No newline at end of file diff --git a/demo/phytium-e2000/usbhost/src/usb_input.c b/demo/phytium-e2000/usbhost/src/usb_input.c new file mode 100644 index 00000000..28ae26b6 --- /dev/null +++ b/demo/phytium-e2000/usbhost/src/usb_input.c @@ -0,0 +1,313 @@ +/* + * Copyright : (C) 2022 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Phytium Public License for more details. + * + * + * FilePath: usb_input.c + * Date: 2022-07-22 13:57:42 + * LastEditTime: 2022-07-22 13:57:43 + * Description:  This files is for + * + * Modify History: + * Ver   Who        Date         Changes + * ----- ------     --------    -------------------------------------- + * 1.0 zhugengyu 2022/9/20 init commit + */ +/***************************** Include Files *********************************/ +#include +#include + +#include "FreeRTOS.h" +#include "task.h" + +#include "ft_assert.h" +#include "interrupt.h" +#include "cpu_info.h" +#include "ft_debug.h" + +#include "usbh_core.h" +#include "usbh_hid.h" +/************************** Constant Definitions *****************************/ +#define HID_KEYCODE_TO_ASCII \ + {0 , 0 }, /* 0x00 */ \ + {0 , 0 }, /* 0x01 */ \ + {0 , 0 }, /* 0x02 */ \ + {0 , 0 }, /* 0x03 */ \ + {'a' , 'A' }, /* 0x04 */ \ + {'b' , 'B' }, /* 0x05 */ \ + {'c' , 'C' }, /* 0x06 */ \ + {'d' , 'D' }, /* 0x07 */ \ + {'e' , 'E' }, /* 0x08 */ \ + {'f' , 'F' }, /* 0x09 */ \ + {'g' , 'G' }, /* 0x0a */ \ + {'h' , 'H' }, /* 0x0b */ \ + {'i' , 'I' }, /* 0x0c */ \ + {'j' , 'J' }, /* 0x0d */ \ + {'k' , 'K' }, /* 0x0e */ \ + {'l' , 'L' }, /* 0x0f */ \ + {'m' , 'M' }, /* 0x10 */ \ + {'n' , 'N' }, /* 0x11 */ \ + {'o' , 'O' }, /* 0x12 */ \ + {'p' , 'P' }, /* 0x13 */ \ + {'q' , 'Q' }, /* 0x14 */ \ + {'r' , 'R' }, /* 0x15 */ \ + {'s' , 'S' }, /* 0x16 */ \ + {'t' , 'T' }, /* 0x17 */ \ + {'u' , 'U' }, /* 0x18 */ \ + {'v' , 'V' }, /* 0x19 */ \ + {'w' , 'W' }, /* 0x1a */ \ + {'x' , 'X' }, /* 0x1b */ \ + {'y' , 'Y' }, /* 0x1c */ \ + {'z' , 'Z' }, /* 0x1d */ \ + {'1' , '!' }, /* 0x1e */ \ + {'2' , '@' }, /* 0x1f */ \ + {'3' , '#' }, /* 0x20 */ \ + {'4' , '$' }, /* 0x21 */ \ + {'5' , '%' }, /* 0x22 */ \ + {'6' , '^' }, /* 0x23 */ \ + {'7' , '&' }, /* 0x24 */ \ + {'8' , '*' }, /* 0x25 */ \ + {'9' , '(' }, /* 0x26 */ \ + {'0' , ')' }, /* 0x27 */ \ + {'\r' , '\r' }, /* 0x28 */ \ + {'\x1b', '\x1b' }, /* 0x29 */ \ + {'\b' , '\b' }, /* 0x2a */ \ + {'\t' , '\t' }, /* 0x2b */ \ + {' ' , ' ' }, /* 0x2c */ \ + {'-' , '_' }, /* 0x2d */ \ + {'=' , '+' }, /* 0x2e */ \ + {'[' , '{' }, /* 0x2f */ \ + {']' , '}' }, /* 0x30 */ \ + {'\\' , '|' }, /* 0x31 */ \ + {'#' , '~' }, /* 0x32 */ \ + {';' , ':' }, /* 0x33 */ \ + {'\'' , '\"' }, /* 0x34 */ \ + {'`' , '~' }, /* 0x35 */ \ + {',' , '<' }, /* 0x36 */ \ + {'.' , '>' }, /* 0x37 */ \ + {'/' , '?' }, /* 0x38 */ \ + \ + {0 , 0 }, /* 0x39 */ \ + {0 , 0 }, /* 0x3a */ \ + {0 , 0 }, /* 0x3b */ \ + {0 , 0 }, /* 0x3c */ \ + {0 , 0 }, /* 0x3d */ \ + {0 , 0 }, /* 0x3e */ \ + {0 , 0 }, /* 0x3f */ \ + {0 , 0 }, /* 0x40 */ \ + {0 , 0 }, /* 0x41 */ \ + {0 , 0 }, /* 0x42 */ \ + {0 , 0 }, /* 0x43 */ \ + {0 , 0 }, /* 0x44 */ \ + {0 , 0 }, /* 0x45 */ \ + {0 , 0 }, /* 0x46 */ \ + {0 , 0 }, /* 0x47 */ \ + {0 , 0 }, /* 0x48 */ \ + {0 , 0 }, /* 0x49 */ \ + {0 , 0 }, /* 0x4a */ \ + {0 , 0 }, /* 0x4b */ \ + {0 , 0 }, /* 0x4c */ \ + {0 , 0 }, /* 0x4d */ \ + {0 , 0 }, /* 0x4e */ \ + {0 , 0 }, /* 0x4f */ \ + {0 , 0 }, /* 0x50 */ \ + {0 , 0 }, /* 0x51 */ \ + {0 , 0 }, /* 0x52 */ \ + {0 , 0 }, /* 0x53 */ \ + \ + {'/' , '/' }, /* 0x54 */ \ + {'*' , '*' }, /* 0x55 */ \ + {'-' , '-' }, /* 0x56 */ \ + {'+' , '+' }, /* 0x57 */ \ + {'\r' , '\r' }, /* 0x58 */ \ + {'1' , 0 }, /* 0x59 */ \ + {'2' , 0 }, /* 0x5a */ \ + {'3' , 0 }, /* 0x5b */ \ + {'4' , 0 }, /* 0x5c */ \ + {'5' , '5' }, /* 0x5d */ \ + {'6' , 0 }, /* 0x5e */ \ + {'7' , 0 }, /* 0x5f */ \ + {'8' , 0 }, /* 0x60 */ \ + {'9' , 0 }, /* 0x61 */ \ + {'0' , 0 }, /* 0x62 */ \ + {'0' , 0 }, /* 0x63 */ \ + {'=' , '=' }, /* 0x67 */ \ + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ +static u8 const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +/***************** Macros (Inline Functions) Definitions *********************/ +#define FUSB_DEBUG_TAG "USB-INPUT" +#define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__) +#define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__) +#define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__) +#define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__) + +/************************** Function Prototypes ******************************/ + + +/*****************************************************************************/ +static inline void UsbMouseLeftButtonCB(void) +{ + printf(" Button Left\r\n"); +} + +static inline void UsbMouseRightButtonCB(void) +{ + printf(" Button Right\r\n"); +} + +static inline void UsbMouseMiddleButtonCB(void) +{ + printf(" Button Middle\r\n"); +} + +static void UsbMouseHandleInput(struct usb_hid_mouse_report *input) +{ + /*------------- button state -------------*/ + if (input->buttons & HID_MOUSE_INPUT_BUTTON_LEFT) + { + UsbMouseLeftButtonCB(); + } + + if (input->buttons & HID_MOUSE_INPUT_BUTTON_MIDDLE) + { + UsbMouseMiddleButtonCB(); + } + + if (input->buttons & HID_MOUSE_INPUT_BUTTON_RIGHT) + { + UsbMouseRightButtonCB(); + } + + /*------------- cursor movement -------------*/ + printf(" Cursor %d %d %d\r\n", input->xdisp, input->ydisp, input->wdisp); +} + +/* look up new key in previous keys */ +static inline boolean FindKeyInPrevInput(const struct usb_hid_kbd_report *report, u8 keycode) +{ + for(u8 i=0; i < 6; i++) + { + if (report->key[i] == keycode) + return TRUE; + } + + return FALSE; +} + +static void UsbKeyBoardHandleInput(struct usb_hid_kbd_report *input) +{ + static struct usb_hid_kbd_report prev_input = { 0, 0, {0} }; /* previous report to check key released */ + + /* ------------- example code ignore control (non-printable) key affects ------------- */ + for (u8 i = 0; i < 6; i++) + { + if (input->key[i]) + { + if (FindKeyInPrevInput(&prev_input, input->key[i])) + { + /* exist in previous report means the current key is holding */ + } + else + { + /* not existed in previous report means the current key is pressed */ + boolean is_shift = input->modifier & (HID_MODIFER_LSHIFT | HID_MODIFER_RSHIFT); + u8 ch = keycode2ascii[input->key[i]][is_shift ? 1 : 0]; + putchar(ch); + if ('\r' == ch) + { + putchar('\n'); + } + + fflush(stdout); /* flush right away, else libc will wait for newline */ + } + } + } + + prev_input = *input; +} + +static u8 UsbInputGetInterfaceProtocol(struct usbh_hid *hid_class) +{ + struct usbh_hubport *hport = hid_class->hport; + u8 intf = hid_class->intf; + const struct usb_interface_descriptor *intf_desc = &hport->config.intf->altsetting[intf].intf_desc; + + return intf_desc->bInterfaceProtocol; +} + +static void UsbInputTask(void * args) +{ + int ret; + struct usbh_hid *hid_class; + static uint8_t hid_buffer[128] = {0}; + u8 intf_protocol; + + FUSB_INFO("%s", __func__); + + while (TRUE) + { + hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0"); + if (hid_class == NULL) + { + USB_LOG_RAW("do not find /dev/input0\r\n"); + goto err_exit; + } + + ret = usbh_int_transfer(hid_class->intin, hid_buffer, 8, 1000); + if (ret < 0) + { + USB_LOG_RAW("intr in error,ret:%d\r\n", ret); + } + + intf_protocol = UsbInputGetInterfaceProtocol(hid_class); + if (HID_PROTOCOL_KEYBOARD == intf_protocol) + { + UsbKeyBoardHandleInput((struct usb_hid_kbd_report *)hid_buffer); + } + else if (HID_PROTOCOL_MOUSE == intf_protocol) + { + UsbMouseHandleInput((struct usb_hid_mouse_report *)hid_buffer); + } + else + { + FUSB_ERROR("unsupported hid interface %d", intf_protocol); + goto err_exit; + } + + vTaskDelay(10); + } + +err_exit: + vTaskDelete(NULL); +} + +BaseType_t FFreeRTOSRecvInput(void) +{ + BaseType_t ret = pdPASS; + + taskENTER_CRITICAL(); /* no schedule when create task */ + + ret = xTaskCreate((TaskFunction_t )UsbInputTask, + (const char* )"UsbInputTask", + (uint16_t )2048, + NULL, + (UBaseType_t )configMAX_PRIORITIES - 1, + NULL); + FASSERT_MSG(pdPASS == ret, "create task failed"); + + taskEXIT_CRITICAL(); /* allow schedule since task created */ + + return ret; +} \ No newline at end of file diff --git a/port/xhci/usb_config.h b/port/xhci/usb_config.h index 29954dfc..743ab283 100644 --- a/port/xhci/usb_config.h +++ b/port/xhci/usb_config.h @@ -72,6 +72,7 @@ // #define CONFIG_USBHOST_GET_STRING_DESC // #define CONFIG_USBDEV_MSC_THREAD +#define CONFIG_INPUT_MOUSE_WHEEL #ifdef CONFIG_USBDEV_MSC_THREAD #ifndef CONFIG_USBDEV_MSC_STACKSIZE diff --git a/port/xhci/usb_hc_xhci.c b/port/xhci/usb_hc_xhci.c index da07da8d..d709a6b1 100644 --- a/port/xhci/usb_hc_xhci.c +++ b/port/xhci/usb_hc_xhci.c @@ -1092,7 +1092,9 @@ int usbh_submit_urb(struct usbh_urb *urb) /* wait all ring handled by xHc */ int cc = xhci_event_wait(xhci, ppipe, &ppipe->reqs); - if (cc != CC_SUCCESS) { + if ((cc != CC_SUCCESS) && + !((cc == CC_TIMEOUT) && (ppipe->eptype == USB_ENDPOINT_TYPE_INTERRUPT))) { + /* ignore transfer timeout for interrupt type */ USB_LOG_ERR("%s: xfer failed (cc %d)\n", __func__, cc); ret = -1; urb->errorcode = cc;