From 80591104d606ab366c6b408ba98db847fd15c560 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 2 Nov 2024 18:21:42 -0400 Subject: [PATCH 1/2] fwk: add option to emit HID display toggle from F9 display key By default, this key emits Win+P, which is not portable to non-QWERTY keyboard layouts and non-Windows OSes. This adds an option (off by default, set with 0x3E16 flag) to emit the HID display toggle key instead. This should be exposed in the BIOS settings. Signed-off-by: Jules Bertholet --- board/hx20/host_command_customization.c | 10 +++++++ board/hx20/host_command_customization.h | 8 +++++ board/hx20/i2c_hid_mediakeys.c | 39 +++++++++++++++++++++++-- board/hx20/i2c_hid_mediakeys.h | 2 +- board/hx20/keyboard_customization.c | 17 +++++++---- board/hx20/keyboard_customization.h | 2 ++ board/hx30/host_command_customization.c | 10 +++++++ board/hx30/host_command_customization.h | 8 +++++ board/hx30/i2c_hid_mediakeys.c | 39 +++++++++++++++++++++++-- board/hx30/i2c_hid_mediakeys.h | 1 + board/hx30/keyboard_customization.c | 17 +++++++---- board/hx30/keyboard_customization.h | 2 ++ 12 files changed, 140 insertions(+), 15 deletions(-) diff --git a/board/hx20/host_command_customization.c b/board/hx20/host_command_customization.c index a98f8eb8bf..2b90d445ec 100644 --- a/board/hx20/host_command_customization.c +++ b/board/hx20/host_command_customization.c @@ -290,3 +290,13 @@ static enum ec_status standalone_mode(struct host_cmd_handler_args *args) } DECLARE_HOST_COMMAND(EC_CMD_STANDALONE_MODE, standalone_mode, EC_VER_MASK(0)); + +static enum ec_status display_toggle_key_hid(struct host_cmd_handler_args *args) +{ + const struct ec_params_display_toggle_key_hid *p = args->params; + + set_display_toggle_key_hid(p->enable); + return EC_RES_SUCCESS; + +} +DECLARE_HOST_COMMAND(EC_CMD_DISPLAY_TOGGLE_KEY_HID, display_toggle_key_hid, EC_VER_MASK(0)); diff --git a/board/hx20/host_command_customization.h b/board/hx20/host_command_customization.h index 12ceaa81a7..5f8a44bb3f 100644 --- a/board/hx20/host_command_customization.h +++ b/board/hx20/host_command_customization.h @@ -203,4 +203,12 @@ struct ec_params_standalone_mode { uint8_t enable; } __ec_align1; +/* If enabled, display key emits HID System Display Toggle Int/Ext Mode; + otherwise emits Win+P */ +#define EC_CMD_DISPLAY_TOGGLE_KEY_HID 0x3E16 + +struct ec_params_display_toggle_key_hid { + uint8_t enable; +} __ec_align1; + #endif /* __HOST_COMMAND_CUSTOMIZATION_H */ diff --git a/board/hx20/i2c_hid_mediakeys.c b/board/hx20/i2c_hid_mediakeys.c index bf0cd7576f..f7a3466a53 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_DISPLAY 0x04 /* * See hid usage tables for consumer page @@ -49,8 +50,13 @@ struct consumer_button_report { uint16_t button_id; } __packed; +struct display_report { + uint8_t state; +} __packed; + static struct radio_report radio_button; static struct consumer_button_report consumer_button; +static struct display_report display_button; 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_DISPLAY_TOGGLE) { key_states[key] = pressed; if (pressed) task_set_event(TASK_ID_HID, 1 << key, 0); @@ -121,6 +127,20 @@ static const uint8_t report_desc[] = { 0x81, 0x00, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ + /* Display Toggle Collection */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, REPORT_ID_DISPLAY, /* Report ID (Display) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + 0xC0, /* END_COLLECTION */ }; @@ -220,6 +240,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_DISPLAY: + response_len = + fill_report(buffer, report_id, + &display_button, + sizeof(struct display_report)); + break; default: response_len = 2; buffer[0] = response_len; @@ -297,11 +323,16 @@ 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_DISPLAY) { + response_len = + fill_report(buffer, REPORT_ID_DISPLAY, + &display_button, + sizeof(struct display_report)); } break; case I2C_HID_COMMAND_REGISTER: @@ -399,6 +430,10 @@ void hid_handler_task(void *p) input_mode = REPORT_ID_RADIO; radio_button.state = key_states[i] ? 1 : 0; break; + case HID_KEY_DISPLAY_TOGGLE: + input_mode = REPORT_ID_DISPLAY; + display_button.state = key_states[i] ? 1 : 0; + break; } hid_irq_to_host(); } diff --git a/board/hx20/i2c_hid_mediakeys.h b/board/hx20/i2c_hid_mediakeys.h index 50a60a5a2e..52797647ef 100644 --- a/board/hx20/i2c_hid_mediakeys.h +++ b/board/hx20/i2c_hid_mediakeys.h @@ -28,7 +28,7 @@ enum media_key { HID_KEY_DISPLAY_BRIGHTNESS_UP, HID_KEY_DISPLAY_BRIGHTNESS_DN, HID_KEY_AIRPLANE_MODE, - + HID_KEY_DISPLAY_TOGGLE, HID_KEY_MAX }; /*HID_KEY_MAX cannot be > TASK_EVENT_CUSTOM_BIT*/ diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c index 2b91f2e0c1..32bebb7b7d 100644 --- a/board/hx20/keyboard_customization.c +++ b/board/hx20/keyboard_customization.c @@ -216,6 +216,14 @@ void board_kblight_init(void) } #endif +uint8_t display_toggle_key_hid = 0; + +void set_display_toggle_key_hid(uint8_t enable) +{ + CPRINTS("set display_toggle_key_hid = %hhd", enable); + display_toggle_key_hid = enable; +} + #ifdef CONFIG_KEYBOARD_CUSTOMIZATION_COMBINATION_KEY #define FN_PRESSED BIT(0) #define FN_LOCKED BIT(1) @@ -329,12 +337,11 @@ int hotkey_F1_F12(uint16_t *key_code, uint16_t fn, int8_t pressed) break; case SCANCODE_F9: /* EXTERNAL_DISPLAY */ if (fn_table_media_set(pressed, KB_FN_F9)) { - if (pressed) { - simulate_keyboard(SCANCODE_LEFT_WIN, 1); - simulate_keyboard(SCANCODE_P, 1); + if (display_toggle_key_hid) { + update_hid_key(HID_KEY_DISPLAY_TOGGLE, pressed); } else { - simulate_keyboard(SCANCODE_P, 0); - simulate_keyboard(SCANCODE_LEFT_WIN, 0); + simulate_keyboard(SCANCODE_LEFT_WIN, pressed); + simulate_keyboard(SCANCODE_P, pressed); } return EC_ERROR_UNIMPLEMENTED; } diff --git a/board/hx20/keyboard_customization.h b/board/hx20/keyboard_customization.h index bda89c4d8c..b173eeff24 100644 --- a/board/hx20/keyboard_customization.h +++ b/board/hx20/keyboard_customization.h @@ -112,4 +112,6 @@ int factory_status(void); void hx20_8042_led_control(int data); #endif +void set_display_toggle_key_hid(uint8_t enable); + #endif /* __KEYBOARD_CUSTOMIZATION_H */ diff --git a/board/hx30/host_command_customization.c b/board/hx30/host_command_customization.c index 8dcf1fc761..394e5c0822 100644 --- a/board/hx30/host_command_customization.c +++ b/board/hx30/host_command_customization.c @@ -353,3 +353,13 @@ static enum ec_status standalone_mode(struct host_cmd_handler_args *args) } DECLARE_HOST_COMMAND(EC_CMD_STANDALONE_MODE, standalone_mode, EC_VER_MASK(0)); +static enum ec_status display_toggle_key_hid(struct host_cmd_handler_args *args) +{ + const struct ec_params_display_toggle_key_hid *p = args->params; + + set_display_toggle_key_hid(p->enable); + return EC_RES_SUCCESS; + +} +DECLARE_HOST_COMMAND(EC_CMD_DISPLAY_TOGGLE_KEY_HID, display_toggle_key_hid, EC_VER_MASK(0)); + diff --git a/board/hx30/host_command_customization.h b/board/hx30/host_command_customization.h index aae3345efb..1f9744ca03 100644 --- a/board/hx30/host_command_customization.h +++ b/board/hx30/host_command_customization.h @@ -229,4 +229,12 @@ struct ec_response_chassis_counter { uint8_t press_counter; } __ec_align1; +/* If enabled, display key emits HID System Display Toggle Int/Ext Mode; + otherwise emits Win+P */ +#define EC_CMD_DISPLAY_TOGGLE_KEY_HID 0x3E16 + +struct ec_params_display_toggle_key_hid { + uint8_t enable; +} __ec_align1; + #endif /* __HOST_COMMAND_CUSTOMIZATION_H */ diff --git a/board/hx30/i2c_hid_mediakeys.c b/board/hx30/i2c_hid_mediakeys.c index 57dfe34f65..4580fb9c44 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_DISPLAY 0x04 #define ALS_REPORT_STOP 0x00 #define ALS_REPORT_POLLING 0x01 @@ -74,18 +75,22 @@ struct als_feature_report { uint16_t minimum; } __packed; +struct display_report { + uint8_t state; +} __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 display_report display_button; 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_DISPLAY_TOGGLE) { key_states[key] = pressed; if (pressed) task_set_event(TASK_ID_HID, 1 << key, 0); @@ -285,6 +290,21 @@ static const uint8_t report_desc[] = { 0x95, 0x01, /* Report Count (1) */ 0x81, 0x02, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ + + /* Display Toggle Collection */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, REPORT_ID_DISPLAY, /* Report ID (Display) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + 0xC0, /* END_COLLECTION */ }; @@ -478,6 +498,12 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer) sizeof(struct als_feature_report)); } break; + case REPORT_ID_DISPLAY: + response_len = + fill_report(buffer, report_id, + &display_button, + sizeof(struct display_report)); + break; default: response_len = 2; buffer[0] = response_len; @@ -564,7 +590,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_DISPLAY) { + response_len = + fill_report(buffer, REPORT_ID_DISPLAY, + &display_button, + sizeof(struct display_report)); + } break; case I2C_HID_COMMAND_REGISTER: response_len = i2c_hid_touchpad_command_process(len, buffer); @@ -673,6 +704,10 @@ void hid_handler_task(void *p) input_mode = REPORT_ID_RADIO; radio_button.state = key_states[i] ? 1 : 0; break; + case HID_KEY_DISPLAY_TOGGLE: + input_mode = REPORT_ID_DISPLAY; + display_button.state = key_states[i] ? 1 : 0; + 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..02b4f41cb5 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_DISPLAY_TOGGLE, HID_ALS_REPORT_LUX, HID_KEY_MAX }; diff --git a/board/hx30/keyboard_customization.c b/board/hx30/keyboard_customization.c index 2b91f2e0c1..32bebb7b7d 100644 --- a/board/hx30/keyboard_customization.c +++ b/board/hx30/keyboard_customization.c @@ -216,6 +216,14 @@ void board_kblight_init(void) } #endif +uint8_t display_toggle_key_hid = 0; + +void set_display_toggle_key_hid(uint8_t enable) +{ + CPRINTS("set display_toggle_key_hid = %hhd", enable); + display_toggle_key_hid = enable; +} + #ifdef CONFIG_KEYBOARD_CUSTOMIZATION_COMBINATION_KEY #define FN_PRESSED BIT(0) #define FN_LOCKED BIT(1) @@ -329,12 +337,11 @@ int hotkey_F1_F12(uint16_t *key_code, uint16_t fn, int8_t pressed) break; case SCANCODE_F9: /* EXTERNAL_DISPLAY */ if (fn_table_media_set(pressed, KB_FN_F9)) { - if (pressed) { - simulate_keyboard(SCANCODE_LEFT_WIN, 1); - simulate_keyboard(SCANCODE_P, 1); + if (display_toggle_key_hid) { + update_hid_key(HID_KEY_DISPLAY_TOGGLE, pressed); } else { - simulate_keyboard(SCANCODE_P, 0); - simulate_keyboard(SCANCODE_LEFT_WIN, 0); + simulate_keyboard(SCANCODE_LEFT_WIN, pressed); + simulate_keyboard(SCANCODE_P, pressed); } return EC_ERROR_UNIMPLEMENTED; } diff --git a/board/hx30/keyboard_customization.h b/board/hx30/keyboard_customization.h index 8b8bdcc145..d120d93a7a 100644 --- a/board/hx30/keyboard_customization.h +++ b/board/hx30/keyboard_customization.h @@ -112,4 +112,6 @@ int factory_status(void); void hx20_8042_led_control(int data); #endif +void set_display_toggle_key_hid(uint8_t enable); + #endif /* __KEYBOARD_CUSTOMIZATION_H */ From 7ef0e39ebf80b77453404f3c534215114844e955 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 30 Nov 2024 12:43:16 -0500 Subject: [PATCH 2/2] fwk: report fn key and lock states via HID Fn key state is reported as "System Function Shift", FnLock *key* (Fn+Esc) state as "System Function Shift Lock", and Fn lock state is reported as "System Function Shift Lock Indicator". This allows the OS to detect when the Fn key is pressed, enabling the user to configure custom keybinds involving it; it also allows the OS to report the state of the Fn lock feature to the user. Signed-off-by: Jules Bertholet --- board/hx20/i2c_hid_mediakeys.c | 79 +++++++++++++++++++++-------- board/hx20/i2c_hid_mediakeys.h | 3 ++ board/hx20/keyboard_customization.c | 23 ++++++--- board/hx30/i2c_hid_mediakeys.c | 79 +++++++++++++++++++++-------- board/hx30/i2c_hid_mediakeys.h | 3 ++ board/hx30/keyboard_customization.c | 22 +++++--- 6 files changed, 152 insertions(+), 57 deletions(-) diff --git a/board/hx20/i2c_hid_mediakeys.c b/board/hx20/i2c_hid_mediakeys.c index f7a3466a53..74dd641d0d 100644 --- a/board/hx20/i2c_hid_mediakeys.c +++ b/board/hx20/i2c_hid_mediakeys.c @@ -23,7 +23,7 @@ #define REPORT_ID_RADIO 0x01 #define REPORT_ID_CONSUMER 0x02 -#define REPORT_ID_DISPLAY 0x04 +#define REPORT_ID_SYSTEM 0x04 /* * See hid usage tables for consumer page @@ -50,13 +50,20 @@ struct consumer_button_report { uint16_t button_id; } __packed; -struct display_report { +struct system_report { uint8_t state; } __packed; +enum system_buttons: uint8_t { + SYSTEM_KEY_FN = BIT(0), + SYSTEM_KEY_FN_LOCK = BIT(1), + SYSTEM_FN_LOCK_INDICATOR = BIT(2), + SYSTEM_KEY_DISPLAY_TOGGLE = BIT(3), +}; + static struct radio_report radio_button; static struct consumer_button_report consumer_button; -static struct display_report display_button; +static struct system_report system_buttons; int update_hid_key(enum media_key key, bool pressed) @@ -64,11 +71,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 || key == HID_KEY_DISPLAY_TOGGLE) { - key_states[key] = pressed; - if (pressed) - task_set_event(TASK_ID_HID, 1 << key, 0); - } else if (key_states[key] != pressed) { + if (key_states[key] != pressed) { key_states[key] = pressed; task_set_event(TASK_ID_HID, 1 << key, 0); } @@ -127,18 +130,24 @@ static const uint8_t report_desc[] = { 0x81, 0x00, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ - /* Display Toggle Collection */ + /* System Control Collection */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 0x09, 0x80, /* USAGE (System Control) */ 0xA1, 0x01, /* COLLECTION (Application) */ - 0x85, REPORT_ID_DISPLAY, /* Report ID (Display) */ + 0x85, REPORT_ID_SYSTEM, /* Report ID (System) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x09, 0x97, /* USAGE (System Function Shift) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x09, 0x98, /* USAGE (System Function Shift Lock) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0x09, 0x99, /* USAGE (System Function Shift Lock Indicator) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */ 0x81, 0x06, /* INPUT (Data,Var,Rel) */ - 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x75, 0x04, /* REPORT_SIZE (4) */ 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ 0xC0, /* END_COLLECTION */ }; @@ -240,11 +249,11 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer) &consumer_button, sizeof(struct consumer_button_report)); break; - case REPORT_ID_DISPLAY: + case REPORT_ID_SYSTEM: response_len = fill_report(buffer, report_id, - &display_button, - sizeof(struct display_report)); + &system_buttons, + sizeof(struct system_report)); break; default: response_len = 2; @@ -328,11 +337,11 @@ int i2c_hid_process(unsigned int len, uint8_t *buffer) fill_report(buffer, REPORT_ID_CONSUMER, &consumer_button, sizeof(struct consumer_button_report)); - } else if (input_mode == REPORT_ID_DISPLAY) { + } else if (input_mode == REPORT_ID_SYSTEM) { response_len = - fill_report(buffer, REPORT_ID_DISPLAY, - &display_button, - sizeof(struct display_report)); + fill_report(buffer, REPORT_ID_SYSTEM, + &system_buttons, + sizeof(struct system_report)); } break; case I2C_HID_COMMAND_REGISTER: @@ -430,9 +439,37 @@ void hid_handler_task(void *p) input_mode = REPORT_ID_RADIO; radio_button.state = key_states[i] ? 1 : 0; break; + case HID_KEY_FN: + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_KEY_FN; + } else { + system_buttons.state &= ~SYSTEM_KEY_FN; + } + break; + case HID_KEY_FN_LOCK: + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_KEY_FN_LOCK; + } else { + system_buttons.state &= ~SYSTEM_KEY_FN_LOCK; + } + break; + case HID_FN_LOCK_INDICATOR: + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_FN_LOCK_INDICATOR; + } else { + system_buttons.state &= ~SYSTEM_FN_LOCK_INDICATOR; + } + break; case HID_KEY_DISPLAY_TOGGLE: - input_mode = REPORT_ID_DISPLAY; - display_button.state = key_states[i] ? 1 : 0; + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_KEY_DISPLAY_TOGGLE; + } else { + system_buttons.state &= ~SYSTEM_KEY_DISPLAY_TOGGLE; + } break; } hid_irq_to_host(); diff --git a/board/hx20/i2c_hid_mediakeys.h b/board/hx20/i2c_hid_mediakeys.h index 52797647ef..8fea9da566 100644 --- a/board/hx20/i2c_hid_mediakeys.h +++ b/board/hx20/i2c_hid_mediakeys.h @@ -28,6 +28,9 @@ enum media_key { HID_KEY_DISPLAY_BRIGHTNESS_UP, HID_KEY_DISPLAY_BRIGHTNESS_DN, HID_KEY_AIRPLANE_MODE, + HID_KEY_FN, + HID_KEY_FN_LOCK, + HID_FN_LOCK_INDICATOR, HID_KEY_DISPLAY_TOGGLE, HID_KEY_MAX }; diff --git a/board/hx20/keyboard_customization.c b/board/hx20/keyboard_customization.c index 32bebb7b7d..717cba4c31 100644 --- a/board/hx20/keyboard_customization.c +++ b/board/hx20/keyboard_customization.c @@ -281,6 +281,8 @@ void fnkey_startup(void) { Fn_key |= FN_LOCKED; } } + + update_hid_key(HID_FN_LOCK_INDICATOR, (Fn_key & FN_LOCKED) != 0); } DECLARE_HOOK(HOOK_CHIPSET_STARTUP, fnkey_startup, HOOK_PRIO_DEFAULT); @@ -422,11 +424,15 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed) switch (prss_key) { case SCANCODE_ESC: /* TODO: FUNCTION_LOCK */ if (fn_table_set(pressed, KB_FN_ESC)) { + update_hid_key(HID_KEY_FN_LOCK, pressed); if (pressed) { - if (Fn_key & FN_LOCKED) + if (Fn_key & FN_LOCKED) { Fn_key &= ~FN_LOCKED; - else + update_hid_key(HID_FN_LOCK_INDICATOR, 0); + } else { Fn_key |= FN_LOCKED; + update_hid_key(HID_FN_LOCK_INDICATOR, 1); + } } return EC_ERROR_UNIMPLEMENTED; } @@ -495,12 +501,13 @@ enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, if (factory_status()) return EC_SUCCESS; - if (pressed_key == SCANCODE_FN && pressed) { - Fn_key |= FN_PRESSED; - return EC_ERROR_UNIMPLEMENTED; - } else if (pressed_key == SCANCODE_FN && !pressed) { - Fn_key &= ~FN_PRESSED; - return EC_ERROR_UNIMPLEMENTED; + if (pressed_key == SCANCODE_FN) { + if (pressed) { + Fn_key |= FN_PRESSED; + } else { + Fn_key &= ~FN_PRESSED; + } + update_hid_key(HID_KEY_FN, pressed); } /* diff --git a/board/hx30/i2c_hid_mediakeys.c b/board/hx30/i2c_hid_mediakeys.c index 4580fb9c44..bf28ad3a25 100644 --- a/board/hx30/i2c_hid_mediakeys.c +++ b/board/hx30/i2c_hid_mediakeys.c @@ -25,7 +25,7 @@ #define REPORT_ID_RADIO 0x01 #define REPORT_ID_CONSUMER 0x02 #define REPORT_ID_SENSOR 0x03 -#define REPORT_ID_DISPLAY 0x04 +#define REPORT_ID_SYSTEM 0x04 #define ALS_REPORT_STOP 0x00 #define ALS_REPORT_POLLING 0x01 @@ -75,26 +75,29 @@ struct als_feature_report { uint16_t minimum; } __packed; -struct display_report { +struct system_report { uint8_t state; } __packed; +enum system_buttons: uint8_t { + SYSTEM_KEY_FN = BIT(0), + SYSTEM_KEY_FN_LOCK = BIT(1), + SYSTEM_FN_LOCK_INDICATOR = BIT(2), + SYSTEM_KEY_DISPLAY_TOGGLE = BIT(3), +}; + 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 display_report display_button; +static struct system_report system_buttons; 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 || key == HID_KEY_DISPLAY_TOGGLE) { - key_states[key] = pressed; - if (pressed) - task_set_event(TASK_ID_HID, 1 << key, 0); - } else if (key_states[key] != pressed) { + if (key_states[key] != pressed) { key_states[key] = pressed; task_set_event(TASK_ID_HID, 1 << key, 0); } @@ -291,18 +294,24 @@ static const uint8_t report_desc[] = { 0x81, 0x02, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ - /* Display Toggle Collection */ + /* System Control Collection */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 0x09, 0x80, /* USAGE (System Control) */ 0xA1, 0x01, /* COLLECTION (Application) */ - 0x85, REPORT_ID_DISPLAY, /* Report ID (Display) */ + 0x85, REPORT_ID_SYSTEM, /* Report ID (System) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */ 0x95, 0x01, /* REPORT_COUNT (1) */ 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x09, 0x97, /* USAGE (System Function Shift) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x09, 0x98, /* USAGE (System Function Shift Lock) */ 0x81, 0x06, /* INPUT (Data,Var,Rel) */ - 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x09, 0x99, /* USAGE (System Function Shift Lock Indicator) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0x75, 0x04, /* REPORT_SIZE (4) */ 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ 0xC0, /* END_COLLECTION */ }; @@ -498,11 +507,11 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer) sizeof(struct als_feature_report)); } break; - case REPORT_ID_DISPLAY: + case REPORT_ID_SYSTEM: response_len = fill_report(buffer, report_id, - &display_button, - sizeof(struct display_report)); + &system_buttons, + sizeof(struct system_report)); break; default: response_len = 2; @@ -590,11 +599,11 @@ 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_DISPLAY) { + } else if (input_mode == REPORT_ID_SYSTEM) { response_len = - fill_report(buffer, REPORT_ID_DISPLAY, - &display_button, - sizeof(struct display_report)); + fill_report(buffer, REPORT_ID_SYSTEM, + &system_buttons, + sizeof(struct system_report)); } break; case I2C_HID_COMMAND_REGISTER: @@ -704,9 +713,37 @@ void hid_handler_task(void *p) input_mode = REPORT_ID_RADIO; radio_button.state = key_states[i] ? 1 : 0; break; + case HID_KEY_FN: + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_KEY_FN; + } else { + system_buttons.state &= ~SYSTEM_KEY_FN; + } + break; + case HID_KEY_FN_LOCK: + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_KEY_FN_LOCK; + } else { + system_buttons.state &= ~SYSTEM_KEY_FN_LOCK; + } + break; + case HID_FN_LOCK_INDICATOR: + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_FN_LOCK_INDICATOR; + } else { + system_buttons.state &= ~SYSTEM_FN_LOCK_INDICATOR; + } + break; case HID_KEY_DISPLAY_TOGGLE: - input_mode = REPORT_ID_DISPLAY; - display_button.state = key_states[i] ? 1 : 0; + input_mode = REPORT_ID_SYSTEM; + if (key_states[i]) { + system_buttons.state |= SYSTEM_KEY_DISPLAY_TOGGLE; + } else { + system_buttons.state &= ~SYSTEM_KEY_DISPLAY_TOGGLE; + } break; case HID_ALS_REPORT_LUX: diff --git a/board/hx30/i2c_hid_mediakeys.h b/board/hx30/i2c_hid_mediakeys.h index 02b4f41cb5..f969ab0e09 100644 --- a/board/hx30/i2c_hid_mediakeys.h +++ b/board/hx30/i2c_hid_mediakeys.h @@ -81,6 +81,9 @@ enum media_key { HID_KEY_DISPLAY_BRIGHTNESS_UP, HID_KEY_DISPLAY_BRIGHTNESS_DN, HID_KEY_AIRPLANE_MODE, + HID_KEY_FN, + HID_KEY_FN_LOCK, + HID_FN_LOCK_INDICATOR, HID_KEY_DISPLAY_TOGGLE, HID_ALS_REPORT_LUX, HID_KEY_MAX diff --git a/board/hx30/keyboard_customization.c b/board/hx30/keyboard_customization.c index 32bebb7b7d..9d9950f8b4 100644 --- a/board/hx30/keyboard_customization.c +++ b/board/hx30/keyboard_customization.c @@ -281,6 +281,8 @@ void fnkey_startup(void) { Fn_key |= FN_LOCKED; } } + + update_hid_key(HID_FN_LOCK_INDICATOR, (Fn_key & FN_LOCKED) != 0); } DECLARE_HOOK(HOOK_CHIPSET_STARTUP, fnkey_startup, HOOK_PRIO_DEFAULT); @@ -422,11 +424,15 @@ int functional_hotkey(uint16_t *key_code, int8_t pressed) switch (prss_key) { case SCANCODE_ESC: /* TODO: FUNCTION_LOCK */ if (fn_table_set(pressed, KB_FN_ESC)) { + update_hid_key(HID_KEY_FN_LOCK, pressed); if (pressed) { - if (Fn_key & FN_LOCKED) + if (Fn_key & FN_LOCKED) { Fn_key &= ~FN_LOCKED; - else + update_hid_key(HID_FN_LOCK_INDICATOR, 0); + } else { Fn_key |= FN_LOCKED; + update_hid_key(HID_FN_LOCK_INDICATOR, 1); + } } return EC_ERROR_UNIMPLEMENTED; } @@ -495,11 +501,13 @@ enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, if (factory_status()) return EC_SUCCESS; - if (pressed_key == SCANCODE_FN && pressed) { - Fn_key |= FN_PRESSED; - return EC_ERROR_UNIMPLEMENTED; - } else if (pressed_key == SCANCODE_FN && !pressed) { - Fn_key &= ~FN_PRESSED; + if (pressed_key == SCANCODE_FN) { + if (pressed) { + Fn_key |= FN_PRESSED; + } else { + Fn_key &= ~FN_PRESSED; + } + update_hid_key(HID_KEY_FN, pressed); return EC_ERROR_UNIMPLEMENTED; }