diff options
Diffstat (limited to 'chip/stm32')
-rw-r--r-- | chip/stm32/usb_hid.c | 73 | ||||
-rw-r--r-- | chip/stm32/usb_hid_hw.h | 26 | ||||
-rw-r--r-- | chip/stm32/usb_hid_keyboard.c | 21 | ||||
-rw-r--r-- | chip/stm32/usb_hid_touchpad.c | 18 |
4 files changed, 104 insertions, 34 deletions
diff --git a/chip/stm32/usb_hid.c b/chip/stm32/usb_hid.c index 873d80009a..043c4f8082 100644 --- a/chip/stm32/usb_hid.c +++ b/chip/stm32/usb_hid.c @@ -64,10 +64,41 @@ void hid_reset(int ep, usb_uint *hid_ep_tx_buf, int tx_len, static int report_left; static const uint8_t *report_ptr; +/* + * Send report through ep0_buf_tx. + * + * If report size is greater than USB packet size (64 bytes), rest of the + * reports will be saved in `report_ptr` and `report_left`, so we can call this + * function again to send the remain parts. + * + * @return 0 if entire report is sent, 1 if there are remaining data. + */ +static int send_report(usb_uint *ep0_buf_tx, + const uint8_t *report, + int report_size) +{ + int packet_size = MIN(report_size, USB_MAX_PACKET_SIZE); + + memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx), + report, packet_size); + btable_ep[0].tx_count = packet_size; + /* report_left != 0 if report doesn't fit in 1 packet. */ + report_left = report_size - packet_size; + report_ptr = report + packet_size; + + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, + report_left ? 0 : EP_STATUS_OUT); + + return report_left ? 1 : 0; +} + int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, - const uint8_t *report_desc, int report_size, - const struct usb_hid_descriptor *hid_desc) + const struct usb_hid_config_t *config) { + const uint8_t *report_desc = config->report_desc; + int report_size = config->report_size; + const struct usb_hid_descriptor *hid_desc = config->hid_desc; + if (!ep0_buf_rx) { /* * Continue previous transfer. We ignore report_desc/size here, @@ -89,22 +120,8 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, (USB_REQ_GET_DESCRIPTOR << 8))) { if (ep0_buf_rx[1] == (USB_HID_DT_REPORT << 8)) { /* Setup : HID specific : Get Report descriptor */ - report_size = MIN(ep0_buf_rx[3], report_size); - - if (report_size > USB_MAX_PACKET_SIZE) { - /* Report descriptor doesn't fit in 1 packet. */ - report_left = report_size - USB_MAX_PACKET_SIZE; - report_ptr = report_desc + USB_MAX_PACKET_SIZE; - report_size = USB_MAX_PACKET_SIZE; - } else { - report_left = 0; - } - memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx), - report_desc, report_size); - btable_ep[0].tx_count = report_size; - STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, - report_left ? 0 : EP_STATUS_OUT); - return report_left ? 1 : 0; + return send_report(ep0_buf_tx, report_desc, + MIN(ep0_buf_rx[3], report_size)); } else if (ep0_buf_rx[1] == (USB_HID_DT_HID << 8)) { /* Setup : HID specific : Get HID descriptor */ memcpy_to_usbram_ep0_patch(hid_desc, sizeof(*hid_desc)); @@ -113,6 +130,26 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, EP_STATUS_OUT); return 0; } + } else if (ep0_buf_rx[0] == (USB_DIR_IN | + USB_RECIP_INTERFACE | + USB_TYPE_CLASS | + (USB_HID_REQ_GET_REPORT << 8))) { + const uint8_t report_type = (ep0_buf_rx[1] >> 8) & 0xFF; + const uint8_t report_id = ep0_buf_rx[1] & 0xFF; + int retval; + + report_left = ep0_buf_rx[3]; + if (!config->get_report) /* not supported */ + return -1; + + retval = config->get_report(report_id, + report_type, + &report_ptr, + &report_left); + if (retval) + return retval; + + return send_report(ep0_buf_tx, report_ptr, report_left); } return -1; diff --git a/chip/stm32/usb_hid_hw.h b/chip/stm32/usb_hid_hw.h index 0133a0a16b..d4d5ac3ca9 100644 --- a/chip/stm32/usb_hid_hw.h +++ b/chip/stm32/usb_hid_hw.h @@ -8,12 +8,34 @@ #ifndef __CROS_EC_USB_HID_HW_H #define __CROS_EC_USB_HID_HW_H +#include <common.h> + +struct usb_hid_config_t { + const uint8_t *report_desc; + int report_size; + const struct usb_hid_descriptor *hid_desc; + + /* + * Handle USB HID Get_Report request, can be NULL if not supported. + * + * @param report_id: ID of the report being requested + * @param report_type: 0x1 (INPUT) / 0x2 (OUTPUT) / 0x3 (FEATURE) + * @param buffer_ptr: handler should set it to the pointer of buffer to + * return. + * @param buffer_size: handler should set it to the size of returned + * buffer. + */ + int (*get_report)(uint8_t report_id, + uint8_t report_type, + const uint8_t **buffer_ptr, + int *buffer_size); +}; + /* internal callbacks for HID class drivers */ void hid_tx(int ep); void hid_reset(int ep, usb_uint *hid_ep_tx_buf, int tx_len, usb_uint *hid_ep_rx_buf, int rx_len); int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, - const uint8_t *report_desc, int report_size, - const struct usb_hid_descriptor *hid_desc); + const struct usb_hid_config_t *hid_config); #endif diff --git a/chip/stm32/usb_hid_keyboard.c b/chip/stm32/usb_hid_keyboard.c index 566be2440f..11cc42974c 100644 --- a/chip/stm32/usb_hid_keyboard.c +++ b/chip/stm32/usb_hid_keyboard.c @@ -422,22 +422,18 @@ USB_DECLARE_EP(USB_EP_HID_KEYBOARD, hid_keyboard_tx, #endif hid_keyboard_event); +static struct usb_hid_config_t hid_config_kb = { + .report_desc = report_desc, + .report_size = sizeof(report_desc), + .hid_desc = &hid_desc_kb, +}; + static int hid_keyboard_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx) { int ret; - const uint8_t *desc = report_desc; - uint32_t size = sizeof(report_desc); - -#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT - if (board_has_keyboard_backlight()) { - desc = report_desc_with_backlight; - size = sizeof(report_desc_with_backlight); - } -#endif - ret = hid_iface_request(ep0_buf_rx, ep0_buf_tx, - desc, size, &hid_desc_kb); + ret = hid_iface_request(ep0_buf_rx, ep0_buf_tx, &hid_config_kb); if (ret >= 0) return ret; @@ -644,6 +640,9 @@ void clear_typematic_key(void) void usb_hid_keyboard_init(void) { if (board_has_keyboard_backlight()) { + hid_config_kb.report_desc = report_desc_with_backlight; + hid_config_kb.report_size = sizeof(report_desc_with_backlight); + set_descriptor_patch(USB_DESC_KEYBOARD_BACKLIGHT, &hid_desc_kb.desc[0].wDescriptorLength, sizeof(report_desc_with_backlight)); diff --git a/chip/stm32/usb_hid_touchpad.c b/chip/stm32/usb_hid_touchpad.c index ebb8bd9ef4..6a658ce66d 100644 --- a/chip/stm32/usb_hid_touchpad.c +++ b/chip/stm32/usb_hid_touchpad.c @@ -324,11 +324,23 @@ static void hid_touchpad_event(enum usb_ep_event evt) USB_DECLARE_EP(USB_EP_HID_TOUCHPAD, hid_touchpad_tx, hid_touchpad_tx, hid_touchpad_event); +static int get_report(uint8_t report_id, uint8_t report_type, + const uint8_t **buffer_ptr, + int *buffer_size) +{ + return -1; +} + +static const struct usb_hid_config_t hid_config_tp = { + .report_desc = report_desc, + .report_size = sizeof(report_desc), + .hid_desc = &hid_desc_tp, + .get_report = get_report, +}; + static int hid_touchpad_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx) { - return hid_iface_request(ep0_buf_rx, ep0_buf_tx, - report_desc, sizeof(report_desc), - &hid_desc_tp); + return hid_iface_request(ep0_buf_rx, ep0_buf_tx, &hid_config_tp); } USB_DECLARE_IFACE(USB_IFACE_HID_TOUCHPAD, hid_touchpad_iface_request) |