diff options
author | Nicolas Boichat <drinkcat@google.com> | 2017-05-17 18:15:15 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-05-18 06:03:52 -0700 |
commit | 11237d5e911d769cac995e2e1ab9d16598542bc8 (patch) | |
tree | 1e679437f36debf7a67e74891bb7bd937049234b /chip | |
parent | 0b077ad67173f11f8816b01213bc09f622326799 (diff) | |
download | chrome-ec-11237d5e911d769cac995e2e1ab9d16598542bc8.tar.gz |
hammer: Make keyboard work at firmware screen
First, libpayload expects the keyboard interface index to be 0.
Then, hid_iface_request needs to reply to USB_HID_DT_HID request
with the content of struct usb_hid_descriptor. With current code,
the variable name is generated (and therefore hard to guess), so
we create a new set of macros so that we can use a specific
variable name.
Also, add support for HID Get_Protocol and Set_Protocol, as they
are compulsory for devices supporting boot protocol, even though
those are mostly no-op for now.
Finally, add a note regarding USB HID keyboard boot protocol, to
make sure that we do not accidentally change the report format.
BRANCH=none
BUG=b:36538963
TEST=Keyboard works in FW screen, both trackpad and keyboard
still work when AP has booted.
TEST=hammer/staff can still be updated (both RO from RW, and RW
from RO)
Change-Id: Ibea4888385909c9ce3b430464e5805c039d4b9ed
Reviewed-on: https://chromium-review.googlesource.com/505796
Commit-Ready: Nicolas Boichat <drinkcat@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/stm32/usb_hid.c | 49 | ||||
-rw-r--r-- | chip/stm32/usb_hid_hw.h | 3 | ||||
-rw-r--r-- | chip/stm32/usb_hid_keyboard.c | 52 | ||||
-rw-r--r-- | chip/stm32/usb_hid_touchpad.c | 6 |
4 files changed, 85 insertions, 25 deletions
diff --git a/chip/stm32/usb_hid.c b/chip/stm32/usb_hid.c index 5561c8afad..4a89d9573c 100644 --- a/chip/stm32/usb_hid.c +++ b/chip/stm32/usb_hid.c @@ -17,6 +17,7 @@ #include "usb_descriptor.h" #include "usb_hw.h" #include "usb_hid.h" +#include "usb_hid_hw.h" /* Console output macro */ #define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) @@ -49,7 +50,8 @@ static int report_left; static const uint8_t *report_ptr; int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, - const uint8_t *report_desc, int report_size) + const uint8_t *report_desc, int report_size, + const struct usb_hid_descriptor *hid_desc) { if (!ep0_buf_rx) { /* @@ -68,26 +70,35 @@ int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, STM32_TOGGLE_EP(0, EP_TX_MASK, EP_TX_VALID, report_left ? 0 : EP_STATUS_OUT); return report_left ? 1 : 0; - } else if ((ep0_buf_rx[0] == (USB_DIR_IN | USB_RECIP_INTERFACE | - (USB_REQ_GET_DESCRIPTOR << 8))) && - (ep0_buf_rx[1] == (USB_HID_DT_REPORT << 8))) { - /* Setup : HID specific : Get Report descriptor */ - report_size = MIN(ep0_buf_rx[3], report_size); + } else if (ep0_buf_rx[0] == (USB_DIR_IN | USB_RECIP_INTERFACE | + (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 does not fit in one 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; + 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; + } else if (ep0_buf_rx[1] == (USB_HID_DT_HID << 8)) { + /* Setup : HID specific : Get HID descriptor */ + memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx), + hid_desc, sizeof(*hid_desc)); + btable_ep[0].tx_count = sizeof(*hid_desc); + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, + EP_STATUS_OUT); + return 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 -1; diff --git a/chip/stm32/usb_hid_hw.h b/chip/stm32/usb_hid_hw.h index 083bfbfeaa..6e53559bd0 100644 --- a/chip/stm32/usb_hid_hw.h +++ b/chip/stm32/usb_hid_hw.h @@ -12,6 +12,7 @@ void hid_tx(int ep); void hid_reset(int ep, usb_uint *hid_ep_buf, int len); int hid_iface_request(usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx, - const uint8_t *report_desc, int report_size); + const uint8_t *report_desc, int report_size, + const struct usb_hid_descriptor *hid_desc); #endif diff --git a/chip/stm32/usb_hid_keyboard.c b/chip/stm32/usb_hid_keyboard.c index da3c215050..4147fcad1c 100644 --- a/chip/stm32/usb_hid_keyboard.c +++ b/chip/stm32/usb_hid_keyboard.c @@ -26,6 +26,22 @@ /* Console output macro */ #define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) +enum hid_protocol { + HID_BOOT_PROTOCOL = 0, + HID_REPORT_PROTOCOL = 1, + HID_PROTOCOL_COUNT = 2, +}; + +/* Current protocol, behaviour is identical in both modes. */ +static enum hid_protocol protocol = HID_REPORT_PROTOCOL; + +/* + * Note: This report format cannot be changed without breaking HID Boot protocol + * compatibility (see HID 1.11 "Appendix B: Boot Interface Descriptors"). + * + * If this needs to be extended, we need to use this report in boot protocol + * mode, and an alternate one in report protocol mode. + */ struct __attribute__((__packed__)) usb_hid_keyboard_report { uint8_t modifiers; /* bitmap of modifiers 224-231 */ uint8_t reserved; /* 0x0 */ @@ -115,7 +131,9 @@ static const uint8_t report_desc[] = { 0xC0 /* End Collection */ }; -const struct usb_hid_descriptor USB_CUSTOM_DESC(USB_IFACE_HID_KEYBOARD, hid) = { +/* HID: HID Descriptor */ +const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_KEYBOARD, + hid, hid_desc_kb) = { .bLength = 9, .bDescriptorType = USB_HID_DT_HID, .bcdHID = 0x0100, @@ -199,8 +217,36 @@ USB_DECLARE_EP(USB_EP_HID_KEYBOARD, hid_keyboard_tx, hid_keyboard_tx, static int hid_keyboard_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)); + int ret = hid_iface_request(ep0_buf_rx, ep0_buf_tx, + report_desc, sizeof(report_desc), + &hid_desc_kb); + if (ret >= 0) + return ret; + + if (ep0_buf_rx[0] == (USB_DIR_OUT | USB_TYPE_CLASS | + USB_RECIP_INTERFACE | (USB_HID_REQ_SET_PROTOCOL << 8))) { + uint16_t value = ep0_buf_rx[1]; + + if (value >= HID_PROTOCOL_COUNT) + return -1; + + protocol = value; + + btable_ep[0].tx_count = 0; + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); + return 0; + } else if (ep0_buf_rx[0] == (USB_DIR_IN | USB_TYPE_CLASS | + USB_RECIP_INTERFACE | (USB_HID_REQ_GET_PROTOCOL << 8))) { + uint8_t value = protocol; + + memcpy_to_usbram((void *) usb_sram_addr(ep0_buf_tx), + &value, sizeof(value)); + btable_ep[0].tx_count = 1; + STM32_TOGGLE_EP(0, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); + return 0; + } + + return -1; } USB_DECLARE_IFACE(USB_IFACE_HID_KEYBOARD, hid_keyboard_iface_request) diff --git a/chip/stm32/usb_hid_touchpad.c b/chip/stm32/usb_hid_touchpad.c index 8f2d2c4dad..686abdcda3 100644 --- a/chip/stm32/usb_hid_touchpad.c +++ b/chip/stm32/usb_hid_touchpad.c @@ -250,7 +250,8 @@ static const uint8_t report_desc[] = { 0xC0, /* End Collection */ }; -const struct usb_hid_descriptor USB_CUSTOM_DESC(USB_IFACE_HID_TOUCHPAD, hid) = { +const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_TOUCHPAD, + hid, hid_desc_tp) = { .bLength = 9, .bDescriptorType = USB_HID_DT_HID, .bcdHID = 0x0100, @@ -309,6 +310,7 @@ 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)); + report_desc, sizeof(report_desc), + &hid_desc_tp); } USB_DECLARE_IFACE(USB_IFACE_HID_TOUCHPAD, hid_touchpad_iface_request) |