From 3b7718e4939231f4e2546ef280fbf5d78cbf7f7c Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Thu, 7 Nov 2024 13:15:15 -0500 Subject: [PATCH] fwk: emit HID event when keyboard brightness changed via fn+space Currently, changing the keyboard backlight brightness via fn+space does not notify the OS in any way. Therefore, OS indicators like GNOME Shell's keyboard backlight slider will show the wrong values. This PR corrects this issue by emitting a "Keyboard Backlight Set Level" HID event on fn+space. Signed-off-by: Jules Bertholet --- board/hx20/i2c_hid_mediakeys.c | 46 +++++++++++++++++++++++++++-- board/hx20/i2c_hid_mediakeys.h | 3 +- board/hx20/keyboard_customization.c | 1 + board/hx30/i2c_hid_mediakeys.c | 43 +++++++++++++++++++++++++-- board/hx30/i2c_hid_mediakeys.h | 2 ++ board/hx30/keyboard_customization.c | 1 + 6 files changed, 90 insertions(+), 6 deletions(-) diff --git a/board/hx20/i2c_hid_mediakeys.c b/board/hx20/i2c_hid_mediakeys.c index bf0cd7576f..90de690018 100644 --- a/board/hx20/i2c_hid_mediakeys.c +++ b/board/hx20/i2c_hid_mediakeys.c @@ -23,6 +23,7 @@ #define REPORT_ID_RADIO 0x01 #define REPORT_ID_CONSUMER 0x02 +#define REPORT_ID_KEYBOARD_BACKLIGHT 0x05 /* * See hid usage tables for consumer page @@ -49,8 +50,13 @@ struct consumer_button_report { uint16_t button_id; } __packed; +struct keyboard_backlight_report { + uint8_t level; +} __packed; + static struct radio_report radio_button; static struct consumer_button_report consumer_button; +static struct keyboard_backlight_report keyboard_backlight; int update_hid_key(enum media_key key, bool pressed) @@ -58,7 +64,7 @@ int update_hid_key(enum media_key key, bool pressed) if (key >= HID_KEY_MAX) { return EC_ERROR_INVAL; } - if (key == HID_KEY_AIRPLANE_MODE) { + if (key == HID_KEY_AIRPLANE_MODE || key == HID_KEY_KEYBOARD_BACKLIGHT) { key_states[key] = pressed; if (pressed) task_set_event(TASK_ID_HID, 1 << key, 0); @@ -70,6 +76,13 @@ int update_hid_key(enum media_key key, bool pressed) return EC_SUCCESS; } + +void kblight_update_hid(uint8_t percent) +{ + keyboard_backlight.level = percent; + update_hid_key(HID_KEY_KEYBOARD_BACKLIGHT, 1); +} + /* Called on AP S5 -> S3 transition */ static void hid_startup(void) { @@ -121,6 +134,19 @@ static const uint8_t report_desc[] = { 0x81, 0x00, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ + /* Keyboard Backlight Level Collection */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, REPORT_ID_KEYBOARD_BACKLIGHT, /* Report ID (Keyboard Backlight) */ + 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ + 0x09, 0x7B, /* USAGE (Keyboard Backlight Set Level) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x64, /* LOGICAL_MAXIMUM (100) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xC0, }; @@ -220,6 +246,12 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer) &consumer_button, sizeof(struct consumer_button_report)); break; + case REPORT_ID_KEYBOARD_BACKLIGHT: + response_len = + fill_report(buffer, report_id, + &keyboard_backlight, + sizeof(struct keyboard_backlight_report)); + break; default: response_len = 2; buffer[0] = response_len; @@ -297,12 +329,17 @@ int i2c_hid_process(unsigned int len, uint8_t *buffer) fill_report(buffer, REPORT_ID_RADIO, &radio_button, sizeof(struct radio_report)); - } else { + } else if (input_mode == REPORT_ID_CONSUMER) { response_len = fill_report(buffer, REPORT_ID_CONSUMER, &consumer_button, sizeof(struct consumer_button_report)); - } + } else if (input_mode == REPORT_ID_KEYBOARD_BACKLIGHT) { + response_len = + fill_report(buffer, REPORT_ID_KEYBOARD_BACKLIGHT, + &keyboard_backlight, + sizeof(struct keyboard_backlight_report)); + }; break; case I2C_HID_COMMAND_REGISTER: response_len = i2c_hid_touchpad_command_process(len, buffer); @@ -399,6 +436,9 @@ void hid_handler_task(void *p) input_mode = REPORT_ID_RADIO; radio_button.state = key_states[i] ? 1 : 0; break; + case HID_KEY_KEYBOARD_BACKLIGHT: + input_mode = REPORT_ID_KEYBOARD_BACKLIGHT; + break; } hid_irq_to_host(); } diff --git a/board/hx20/i2c_hid_mediakeys.h b/board/hx20/i2c_hid_mediakeys.h index 50a60a5a2e..432cfe8108 100644 --- a/board/hx20/i2c_hid_mediakeys.h +++ b/board/hx20/i2c_hid_mediakeys.h @@ -28,12 +28,13 @@ enum media_key { HID_KEY_DISPLAY_BRIGHTNESS_UP, HID_KEY_DISPLAY_BRIGHTNESS_DN, HID_KEY_AIRPLANE_MODE, - + HID_KEY_KEYBOARD_BACKLIGHT, HID_KEY_MAX }; /*HID_KEY_MAX cannot be > TASK_EVENT_CUSTOM_BIT*/ BUILD_ASSERT(HID_KEY_MAX < 16); int update_hid_key(enum media_key key, bool pressed); +void kblight_update_hid(uint8_t percent); #endif /* __CROS_EC_I2C_HID_MEDIAKEYS_H */ \ No newline at end of file diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c index 2b91f2e0c1..3e3b6e94db 100644 --- a/board/hx20/keyboard_customization.c +++ b/board/hx20/keyboard_customization.c @@ -470,6 +470,7 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed) break; } kblight_set(bl_brightness); + kblight_update_hid(bl_brightness); } /* we dont want to pass the space key event to the OS */ return EC_ERROR_UNIMPLEMENTED; diff --git a/board/hx30/i2c_hid_mediakeys.c b/board/hx30/i2c_hid_mediakeys.c index 57dfe34f65..3945f8333c 100644 --- a/board/hx30/i2c_hid_mediakeys.c +++ b/board/hx30/i2c_hid_mediakeys.c @@ -25,6 +25,7 @@ #define REPORT_ID_RADIO 0x01 #define REPORT_ID_CONSUMER 0x02 #define REPORT_ID_SENSOR 0x03 +#define REPORT_ID_KEYBOARD_BACKLIGHT 0x05 #define ALS_REPORT_STOP 0x00 #define ALS_REPORT_POLLING 0x01 @@ -74,18 +75,22 @@ struct als_feature_report { uint16_t minimum; } __packed; +struct keyboard_backlight_report { + uint8_t level; +} __packed; static struct radio_report radio_button; static struct consumer_button_report consumer_button; static struct als_input_report als_sensor; static struct als_feature_report als_feature; +static struct keyboard_backlight_report keyboard_backlight; int update_hid_key(enum media_key key, bool pressed) { if (key >= HID_KEY_MAX) { return EC_ERROR_INVAL; } - if (key == HID_KEY_AIRPLANE_MODE) { + if (key == HID_KEY_AIRPLANE_MODE || key == HID_KEY_KEYBOARD_BACKLIGHT) { key_states[key] = pressed; if (pressed) task_set_event(TASK_ID_HID, 1 << key, 0); @@ -97,6 +102,12 @@ int update_hid_key(enum media_key key, bool pressed) return EC_SUCCESS; } +void kblight_update_hid(uint8_t percent) +{ + keyboard_backlight.level = percent; + update_hid_key(HID_KEY_KEYBOARD_BACKLIGHT, 1); +} + /* Called on AP S5 -> S3 transition */ static void hid_startup(void) { @@ -285,6 +296,20 @@ static const uint8_t report_desc[] = { 0x95, 0x01, /* Report Count (1) */ 0x81, 0x02, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ + + /* Keyboard Backlight Level Collection */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, REPORT_ID_KEYBOARD_BACKLIGHT, /* Report ID (Keyboard Backlight) */ + 0x05, 0x0C, /* USAGE_PAGE (Consumer Devices) */ + 0x09, 0x7B, /* USAGE (Keyboard Backlight Set Level) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x64, /* LOGICAL_MAXIMUM (100) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xC0, }; @@ -478,6 +503,12 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer) sizeof(struct als_feature_report)); } break; + case REPORT_ID_KEYBOARD_BACKLIGHT: + response_len = + fill_report(buffer, report_id, + &keyboard_backlight, + sizeof(struct keyboard_backlight_report)); + break; default: response_len = 2; buffer[0] = response_len; @@ -564,7 +595,12 @@ int i2c_hid_process(unsigned int len, uint8_t *buffer) fill_report(buffer, REPORT_ID_SENSOR, &als_sensor, sizeof(struct als_input_report)); - } + } else if (input_mode == REPORT_ID_KEYBOARD_BACKLIGHT) { + response_len = + fill_report(buffer, REPORT_ID_KEYBOARD_BACKLIGHT, + &keyboard_backlight, + sizeof(struct keyboard_backlight_report)); + }; break; case I2C_HID_COMMAND_REGISTER: response_len = i2c_hid_touchpad_command_process(len, buffer); @@ -673,6 +709,9 @@ void hid_handler_task(void *p) input_mode = REPORT_ID_RADIO; radio_button.state = key_states[i] ? 1 : 0; break; + case HID_KEY_KEYBOARD_BACKLIGHT: + input_mode = REPORT_ID_KEYBOARD_BACKLIGHT; + break; case HID_ALS_REPORT_LUX: input_mode = REPORT_ID_SENSOR; diff --git a/board/hx30/i2c_hid_mediakeys.h b/board/hx30/i2c_hid_mediakeys.h index 9635890dce..85db6bf8dc 100644 --- a/board/hx30/i2c_hid_mediakeys.h +++ b/board/hx30/i2c_hid_mediakeys.h @@ -81,6 +81,7 @@ enum media_key { HID_KEY_DISPLAY_BRIGHTNESS_UP, HID_KEY_DISPLAY_BRIGHTNESS_DN, HID_KEY_AIRPLANE_MODE, + HID_KEY_KEYBOARD_BACKLIGHT, HID_ALS_REPORT_LUX, HID_KEY_MAX }; @@ -89,5 +90,6 @@ BUILD_ASSERT(HID_KEY_MAX < 16); int update_hid_key(enum media_key key, bool pressed); void set_illuminance_value(uint16_t value); +void kblight_update_hid(uint8_t percent); #endif /* __CROS_EC_I2C_HID_MEDIAKEYS_H */ \ No newline at end of file diff --git a/board/hx30/keyboard_customization.c b/board/hx30/keyboard_customization.c index 2b91f2e0c1..3e3b6e94db 100644 --- a/board/hx30/keyboard_customization.c +++ b/board/hx30/keyboard_customization.c @@ -470,6 +470,7 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed) break; } kblight_set(bl_brightness); + kblight_update_hid(bl_brightness); } /* we dont want to pass the space key event to the OS */ return EC_ERROR_UNIMPLEMENTED;