xhci keyboard and mouse ok

This commit is contained in:
zhugengyu
2022-09-22 18:32:42 +08:00
committed by sakumisu
parent 590ffc8847
commit bec72e5d4c
8 changed files with 354 additions and 57 deletions

View File

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

View File

@@ -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;

View File

@@ -41,7 +41,7 @@ extern "C"
/*****************************************************************************/
BaseType_t FFreeRTOSInitUsb(void);
BaseType_t FFreeRTOSWriteReadUsbDisk(void);
BaseType_t FFreeRTOSRecvHidInput(void);
BaseType_t FFreeRTOSRecvInput(void);
#ifdef __cplusplus
}

View File

@@ -47,7 +47,7 @@ static int USBCmdEntry(int argc, char *argv[])
}
else if (!strcmp(argv[1], "hid"))
{
ret = FFreeRTOSRecvHidInput();
ret = FFreeRTOSRecvInput();
}
return ret;

View File

@@ -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;
}

View File

@@ -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 <stdio.h>
#include <string.h>
#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;
}

View File

@@ -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

View File

@@ -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;