summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei-Ning Huang <wnhuang@google.com>2017-07-26 17:43:46 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-09-01 12:39:19 -0700
commit235d9a18c14dbfccaa48dd344d88fb3ba4309052 (patch)
tree9025147ec32937dbb40922c05320176d688fff8f
parent72252db3425a88f404f6d76eb15d02ace06747b7 (diff)
downloadchrome-ec-235d9a18c14dbfccaa48dd344d88fb3ba4309052.tar.gz
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 <wnhuang@google.com> Reviewed-on: https://chromium-review.googlesource.com/586348 Commit-Ready: Wei-Ning Huang <wnhuang@chromium.org> Tested-by: Wei-Ning Huang <wnhuang@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--chip/stm32/usb_hid.c33
-rw-r--r--chip/stm32/usb_hid_hw.h3
-rw-r--r--chip/stm32/usb_hid_keyboard.c87
-rw-r--r--chip/stm32/usb_hid_touchpad.c2
-rw-r--r--include/config.h3
-rw-r--r--include/usb_hid_touchpad.h4
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 */