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..74dd641d0d 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_SYSTEM 0x04 /* * See hid usage tables for consumer page @@ -49,8 +50,20 @@ struct consumer_button_report { uint16_t button_id; } __packed; +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 system_report system_buttons; int update_hid_key(enum media_key key, bool pressed) @@ -58,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_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); } @@ -121,6 +130,26 @@ static const uint8_t report_desc[] = { 0x81, 0x00, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ + /* System Control Collection */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, REPORT_ID_SYSTEM, /* Report ID (System) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 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, 0x04, /* REPORT_SIZE (4) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + 0xC0, /* END_COLLECTION */ }; @@ -220,6 +249,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_SYSTEM: + response_len = + fill_report(buffer, report_id, + &system_buttons, + sizeof(struct system_report)); + break; default: response_len = 2; buffer[0] = response_len; @@ -297,11 +332,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_SYSTEM) { + response_len = + fill_report(buffer, REPORT_ID_SYSTEM, + &system_buttons, + sizeof(struct system_report)); } break; case I2C_HID_COMMAND_REGISTER: @@ -399,6 +439,38 @@ 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_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 50a60a5a2e..8fea9da566 100644 --- a/board/hx20/i2c_hid_mediakeys.h +++ b/board/hx20/i2c_hid_mediakeys.h @@ -28,7 +28,10 @@ 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 }; /*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..717cba4c31 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) @@ -273,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); @@ -329,12 +339,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; } @@ -415,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; } @@ -488,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/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..bf28ad3a25 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_SYSTEM 0x04 #define ALS_REPORT_STOP 0x00 #define ALS_REPORT_POLLING 0x01 @@ -74,22 +75,29 @@ struct als_feature_report { uint16_t minimum; } __packed; +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 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_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); } @@ -285,6 +293,27 @@ static const uint8_t report_desc[] = { 0x95, 0x01, /* Report Count (1) */ 0x81, 0x02, /* Input (Data,Arr,Abs) */ 0xC0, /* END_COLLECTION */ + + /* System Control Collection */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x80, /* USAGE (System Control) */ + 0xA1, 0x01, /* COLLECTION (Application) */ + 0x85, REPORT_ID_SYSTEM, /* Report ID (System) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 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, 0x04, /* REPORT_SIZE (4) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + 0xC0, /* END_COLLECTION */ }; @@ -478,6 +507,12 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer) sizeof(struct als_feature_report)); } break; + case REPORT_ID_SYSTEM: + response_len = + fill_report(buffer, report_id, + &system_buttons, + sizeof(struct system_report)); + break; default: response_len = 2; buffer[0] = response_len; @@ -564,7 +599,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_SYSTEM) { + response_len = + fill_report(buffer, REPORT_ID_SYSTEM, + &system_buttons, + sizeof(struct system_report)); + } break; case I2C_HID_COMMAND_REGISTER: response_len = i2c_hid_touchpad_command_process(len, buffer); @@ -673,6 +713,38 @@ 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_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: input_mode = REPORT_ID_SENSOR; diff --git a/board/hx30/i2c_hid_mediakeys.h b/board/hx30/i2c_hid_mediakeys.h index 9635890dce..f969ab0e09 100644 --- a/board/hx30/i2c_hid_mediakeys.h +++ b/board/hx30/i2c_hid_mediakeys.h @@ -81,6 +81,10 @@ 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 2b91f2e0c1..9d9950f8b4 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) @@ -273,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); @@ -329,12 +339,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; } @@ -415,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; } @@ -488,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; } 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 */