From 235d9a18c14dbfccaa48dd344d88fb3ba4309052 Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Wed, 26 Jul 2017 17:43:46 +0800 Subject: chip/stm32/usb_hid_keyboard: implement keyboard backlight control Implement keyboard backlight control through HID output report. One could enable CONFIG_USB_HID_KEYBOARD_BACKLIGHT to enable keyboard backlight support for a given board. Target board must implement the `void board_set_backlight(int brightness)` function in order correctly set backlight. BRANCH=none BUG=b:37971411,b:63364143 TEST=with follow up CLs 1. `make BOARD=hammer -j` 2. `echo 10 > /sys/class/leds/hammer\:\:kbd_backlight/brightness` console shows 'Keyboard backlight set to 10%' Change-Id: Ibeff510a0d996ddebf61b54ed6b500b02c35564a Signed-off-by: Wei-Ning Huang Reviewed-on: https://chromium-review.googlesource.com/586348 Commit-Ready: Wei-Ning Huang Tested-by: Wei-Ning Huang Reviewed-by: Nicolas Boichat Reviewed-by: Vincent Palatin --- chip/stm32/usb_hid.c | 33 +++++++++++----- chip/stm32/usb_hid_hw.h | 3 +- chip/stm32/usb_hid_keyboard.c | 87 +++++++++++++++++++++++++++++++++++++++---- chip/stm32/usb_hid_touchpad.c | 2 +- include/config.h | 3 ++ include/usb_hid_touchpad.h | 4 +- 6 files changed, 112 insertions(+), 20 deletions(-) diff --git a/chip/stm32/usb_hid.c b/chip/stm32/usb_hid.c index 4a89d9573c..f24bdd5982 100644 --- a/chip/stm32/usb_hid.c +++ b/chip/stm32/usb_hid.c @@ -28,18 +28,33 @@ void hid_tx(int ep) STM32_USB_EP(ep) = (STM32_USB_EP(ep) & EP_MASK); } -void hid_reset(int ep, usb_uint *hid_ep_buf, int len) +void hid_reset(int ep, usb_uint *hid_ep_tx_buf, int tx_len, + usb_uint *hid_ep_rx_buf, int rx_len) { int i; - /* HID interrupt endpoint 1 */ - btable_ep[ep].tx_addr = usb_sram_addr(hid_ep_buf); - btable_ep[ep].tx_count = len; - for (i = 0; i < (len+1)/2; i++) - hid_ep_buf[i] = 0; - STM32_USB_EP(ep) = (ep << 0) /* Endpoint Address */ | - (3 << 4) /* TX Valid */ | + uint16_t ep_reg; + + btable_ep[ep].tx_addr = usb_sram_addr(hid_ep_tx_buf); + btable_ep[ep].tx_count = tx_len; + + /* STM32 USB SRAM needs to be accessed one U16 at a time */ + for (i = 0; i < DIV_ROUND_UP(tx_len, 2); i++) + hid_ep_tx_buf[i] = 0; + + ep_reg = (ep << 0) /* Endpoint Address */ | + EP_TX_VALID | (3 << 9) /* interrupt EP */ | - (0 << 12) /* RX Disabled */; + EP_RX_DISAB; + + /* Enable RX for output reports */ + if (hid_ep_rx_buf && rx_len > 0) { + btable_ep[ep].rx_addr = usb_sram_addr(hid_ep_rx_buf); + btable_ep[ep].rx_count = ((rx_len + 1) / 2) << 10; + + ep_reg |= EP_RX_VALID; /* RX Valid */ + } + + STM32_USB_EP(ep) = ep_reg; } /* diff --git a/chip/stm32/usb_hid_hw.h b/chip/stm32/usb_hid_hw.h index 6e53559bd0..0133a0a16b 100644 --- a/chip/stm32/usb_hid_hw.h +++ b/chip/stm32/usb_hid_hw.h @@ -10,7 +10,8 @@ /* internal callbacks for HID class drivers */ void hid_tx(int ep); -void hid_reset(int ep, usb_uint *hid_ep_buf, int len); +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); diff --git a/chip/stm32/usb_hid_keyboard.c b/chip/stm32/usb_hid_keyboard.c index 607fa17299..0d30783a1e 100644 --- a/chip/stm32/usb_hid_keyboard.c +++ b/chip/stm32/usb_hid_keyboard.c @@ -14,6 +14,7 @@ #include "keyboard_config.h" #include "keyboard_protocol.h" #include "link_defs.h" +#include "pwm.h" #include "queue.h" #include "registers.h" #include "task.h" @@ -64,8 +65,15 @@ struct usb_hid_keyboard_report { #endif } __packed; +struct usb_hid_keyboard_output_report { + uint8_t brightness; +} __packed; + #define HID_KEYBOARD_BOOT_SIZE 8 + #define HID_KEYBOARD_REPORT_SIZE sizeof(struct usb_hid_keyboard_report) +#define HID_KEYBOARD_OUTPUT_REPORT_SIZE \ + sizeof(struct usb_hid_keyboard_output_report) #define HID_KEYBOARD_EP_INTERVAL_MS 16 /* ms */ @@ -124,7 +132,11 @@ const struct usb_interface_descriptor USB_IFACE_DESC(USB_IFACE_HID_KEYBOARD) = { .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = USB_IFACE_HID_KEYBOARD, .bAlternateSetting = 0, +#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT + .bNumEndpoints = 2, +#else .bNumEndpoints = 1, +#endif .bInterfaceClass = USB_CLASS_HID, .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT, .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, @@ -139,6 +151,17 @@ const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_KEYBOARD, 81) = { .bInterval = HID_KEYBOARD_EP_INTERVAL_MS /* ms polling interval */ }; +#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT +const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_KEYBOARD, 02) = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_EP_HID_KEYBOARD, + .bmAttributes = 0x03 /* Interrupt endpoint */, + .wMaxPacketSize = HID_KEYBOARD_OUTPUT_REPORT_SIZE, + .bInterval = HID_KEYBOARD_EP_INTERVAL_MS +}; +#endif + /* HID : Report Descriptor */ static const uint8_t report_desc[] = { 0x05, 0x01, /* Usage Page (Generic Desktop) */ @@ -184,6 +207,18 @@ static const uint8_t report_desc[] = { 0x81, 0x01, /* Input (Constant), ;7-bit padding */ #endif +#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT + 0xA1, 0x02, /* Collection (Logical) */ + 0x05, 0x14, /* Usage Page (Alphanumeric Display) */ + 0x09, 0x46, /* Usage (Display Brightness) */ + 0x95, 0x01, /* Report Count (1) */ + 0x75, 0x08, /* Report Size (8) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x64, /* Logical Maximum (100) */ + 0x91, 0x02, /* Output (Data, Variable, Absolute) */ + 0xC0, /* End Collection */ +#endif + 0xC0 /* End Collection */ }; @@ -201,11 +236,18 @@ const struct usb_hid_descriptor USB_CUSTOM_DESC_VAR(USB_IFACE_HID_KEYBOARD, }} }; -#define EP_BUF_SIZE DIV_ROUND_UP(HID_KEYBOARD_REPORT_SIZE, 2) +#define EP_TX_BUF_SIZE DIV_ROUND_UP(HID_KEYBOARD_REPORT_SIZE, 2) + +static usb_uint hid_ep_tx_buf[EP_TX_BUF_SIZE] __usb_ram; +static volatile int hid_current_buf; -static usb_uint hid_ep_buf[EP_BUF_SIZE] __usb_ram; static volatile int hid_ep_data_ready; +#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT +#define EP_RX_BUF_SIZE DIV_ROUND_UP(HID_KEYBOARD_OUTPUT_REPORT_SIZE, 2) +static usb_uint hid_ep_rx_buf[EP_RX_BUF_SIZE] __usb_ram; +#endif + static struct usb_hid_keyboard_report report; static void keyboard_process_queue(void); @@ -226,7 +268,7 @@ static void write_keyboard_report(void) * send the buffer: enable TX. */ - memcpy_to_usbram((void *) usb_sram_addr(hid_ep_buf), + memcpy_to_usbram((void *) usb_sram_addr(hid_ep_tx_buf), &report, sizeof(report)); STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, EP_TX_VALID, 0); @@ -240,11 +282,29 @@ static void write_keyboard_report(void) usb_wake(); } +#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT + +static void hid_keyboard_rx(void) +{ + struct usb_hid_keyboard_output_report report; + memcpy_from_usbram(&report, (void *) usb_sram_addr(hid_ep_rx_buf), + HID_KEYBOARD_OUTPUT_REPORT_SIZE); + + CPRINTF("Keyboard backlight set to %d%%\n", report.brightness); + + pwm_enable(PWM_CH_KBLIGHT, report.brightness > 0); + pwm_set_duty(PWM_CH_KBLIGHT, report.brightness); + + STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_RX_MASK, EP_TX_RX_VALID, 0); +} + +#endif + static void hid_keyboard_tx(void) { hid_tx(USB_EP_HID_KEYBOARD); if (hid_ep_data_ready) { - memcpy_to_usbram((void *) usb_sram_addr(hid_ep_buf), + memcpy_to_usbram((void *) usb_sram_addr(hid_ep_tx_buf), &report, sizeof(report)); STM32_TOGGLE_EP(USB_EP_HID_KEYBOARD, EP_TX_MASK, EP_TX_VALID, 0); @@ -260,8 +320,16 @@ static void hid_keyboard_event(enum usb_ep_event evt) if (evt == USB_EVENT_RESET) { protocol = HID_REPORT_PROTOCOL; - hid_reset(USB_EP_HID_KEYBOARD, hid_ep_buf, - HID_KEYBOARD_REPORT_SIZE); + hid_reset(USB_EP_HID_KEYBOARD, + hid_ep_tx_buf, + HID_KEYBOARD_REPORT_SIZE, +#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT + hid_ep_rx_buf, + HID_KEYBOARD_OUTPUT_REPORT_SIZE +#else + NULL, 0 +#endif + ); return; } @@ -269,7 +337,12 @@ static void hid_keyboard_event(enum usb_ep_event evt) hook_call_deferred(&keyboard_process_queue_data, 0); } -USB_DECLARE_EP(USB_EP_HID_KEYBOARD, hid_keyboard_tx, hid_keyboard_tx, +USB_DECLARE_EP(USB_EP_HID_KEYBOARD, hid_keyboard_tx, +#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT + hid_keyboard_rx, +#else + hid_keyboard_tx, +#endif hid_keyboard_event); static int hid_keyboard_iface_request(usb_uint *ep0_buf_rx, diff --git a/chip/stm32/usb_hid_touchpad.c b/chip/stm32/usb_hid_touchpad.c index f6624c24c7..a3174e4d94 100644 --- a/chip/stm32/usb_hid_touchpad.c +++ b/chip/stm32/usb_hid_touchpad.c @@ -310,7 +310,7 @@ static void hid_touchpad_event(enum usb_ep_event evt) { if (evt == USB_EVENT_RESET) hid_reset(USB_EP_HID_TOUCHPAD, hid_ep_buf, - HID_TOUCHPAD_REPORT_SIZE); + HID_TOUCHPAD_REPORT_SIZE, NULL, 0); else if (evt == USB_EVENT_DEVICE_RESUME && queue_count(&report_queue) > 0) hook_call_deferred(&hid_touchpad_process_queue_data, 0); diff --git a/include/config.h b/include/config.h index 270783ef48..07e6e34149 100644 --- a/include/config.h +++ b/include/config.h @@ -2677,6 +2677,9 @@ /* Support USB HID keyboard interface. */ #undef CONFIG_USB_HID_KEYBOARD +/* Support USB HID keyboard backlight. */ +#undef CONFIG_USB_HID_KEYBOARD_BACKLIGHT + /* Support USB HID touchpad interface. */ #undef CONFIG_USB_HID_TOUCHPAD diff --git a/include/usb_hid_touchpad.h b/include/usb_hid_touchpad.h index d7d6dc0363..39b6277b96 100644 --- a/include/usb_hid_touchpad.h +++ b/include/usb_hid_touchpad.h @@ -5,8 +5,8 @@ * USB HID definitions. */ -#ifndef __CROS_EC_USB_HID_KEYBOARD_H -#define __CROS_EC_USB_HID_KEYBOARD_H +#ifndef __CROS_EC_USB_HID_TOUCHPAD_H +#define __CROS_EC_USB_HID_TOUCHPAD_H #define USB_HID_TOUCHPAD_TIMESTAMP_UNIT 100 /* usec */ -- cgit v1.2.1