Skip to content

Commit dd29b48

Browse files
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 <[email protected]>
1 parent 553827c commit dd29b48

12 files changed

+140
-15
lines changed

board/hx20/host_command_customization.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,13 @@ static enum ec_status standalone_mode(struct host_cmd_handler_args *args)
290290

291291
}
292292
DECLARE_HOST_COMMAND(EC_CMD_STANDALONE_MODE, standalone_mode, EC_VER_MASK(0));
293+
294+
static enum ec_status display_toggle_key_hid(struct host_cmd_handler_args *args)
295+
{
296+
const struct ec_params_display_toggle_key_hid *p = args->params;
297+
298+
set_display_toggle_key_hid(p->enable);
299+
return EC_RES_SUCCESS;
300+
301+
}
302+
DECLARE_HOST_COMMAND(EC_CMD_DISPLAY_TOGGLE_KEY_HID, display_toggle_key_hid, EC_VER_MASK(0));

board/hx20/host_command_customization.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,12 @@ struct ec_params_standalone_mode {
203203
uint8_t enable;
204204
} __ec_align1;
205205

206+
/* If enabled, display key emits HID System Display Toggle Int/Ext Mode;
207+
otherwise emits Win+P */
208+
#define EC_CMD_DISPLAY_TOGGLE_KEY_HID 0x3E16
209+
210+
struct ec_params_display_toggle_key_hid {
211+
uint8_t enable;
212+
} __ec_align1;
213+
206214
#endif /* __HOST_COMMAND_CUSTOMIZATION_H */

board/hx20/i2c_hid_mediakeys.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#define REPORT_ID_RADIO 0x01
2525
#define REPORT_ID_CONSUMER 0x02
26+
#define REPORT_ID_DISPLAY 0x04
2627

2728
/*
2829
* See hid usage tables for consumer page
@@ -49,16 +50,21 @@ struct consumer_button_report {
4950
uint16_t button_id;
5051
} __packed;
5152

53+
struct display_report {
54+
uint8_t state;
55+
} __packed;
56+
5257
static struct radio_report radio_button;
5358
static struct consumer_button_report consumer_button;
59+
static struct display_report display_button;
5460

5561

5662
int update_hid_key(enum media_key key, bool pressed)
5763
{
5864
if (key >= HID_KEY_MAX) {
5965
return EC_ERROR_INVAL;
6066
}
61-
if (key == HID_KEY_AIRPLANE_MODE) {
67+
if (key == HID_KEY_AIRPLANE_MODE || key == HID_KEY_DISPLAY_TOGGLE) {
6268
key_states[key] = pressed;
6369
if (pressed)
6470
task_set_event(TASK_ID_HID, 1 << key, 0);
@@ -121,6 +127,20 @@ static const uint8_t report_desc[] = {
121127
0x81, 0x00, /* Input (Data,Arr,Abs) */
122128
0xC0, /* END_COLLECTION */
123129

130+
/* Display Toggle Collection */
131+
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
132+
0x09, 0x80, /* USAGE (System Control) */
133+
0xA1, 0x01, /* COLLECTION (Application) */
134+
0x85, REPORT_ID_DISPLAY, /* Report ID (Display) */
135+
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
136+
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
137+
0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */
138+
0x95, 0x01, /* REPORT_COUNT (1) */
139+
0x75, 0x01, /* REPORT_SIZE (1) */
140+
0x81, 0x06, /* INPUT (Data,Var,Rel) */
141+
0x75, 0x07, /* REPORT_SIZE (7) */
142+
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
143+
0xC0, /* END_COLLECTION */
124144
};
125145

126146

@@ -220,6 +240,12 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer)
220240
&consumer_button,
221241
sizeof(struct consumer_button_report));
222242
break;
243+
case REPORT_ID_DISPLAY:
244+
response_len =
245+
fill_report(buffer, report_id,
246+
&display_button,
247+
sizeof(struct display_report));
248+
break;
223249
default:
224250
response_len = 2;
225251
buffer[0] = response_len;
@@ -297,11 +323,16 @@ int i2c_hid_process(unsigned int len, uint8_t *buffer)
297323
fill_report(buffer, REPORT_ID_RADIO,
298324
&radio_button,
299325
sizeof(struct radio_report));
300-
} else {
326+
} else if (input_mode == REPORT_ID_CONSUMER) {
301327
response_len =
302328
fill_report(buffer, REPORT_ID_CONSUMER,
303329
&consumer_button,
304330
sizeof(struct consumer_button_report));
331+
} else if (input_mode == REPORT_ID_DISPLAY) {
332+
response_len =
333+
fill_report(buffer, REPORT_ID_DISPLAY,
334+
&display_button,
335+
sizeof(struct display_report));
305336
}
306337
break;
307338
case I2C_HID_COMMAND_REGISTER:
@@ -399,6 +430,10 @@ void hid_handler_task(void *p)
399430
input_mode = REPORT_ID_RADIO;
400431
radio_button.state = key_states[i] ? 1 : 0;
401432
break;
433+
case HID_KEY_DISPLAY_TOGGLE:
434+
input_mode = REPORT_ID_DISPLAY;
435+
display_button.state = key_states[i] ? 1 : 0;
436+
break;
402437
}
403438
hid_irq_to_host();
404439
}

board/hx20/i2c_hid_mediakeys.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ enum media_key {
2828
HID_KEY_DISPLAY_BRIGHTNESS_UP,
2929
HID_KEY_DISPLAY_BRIGHTNESS_DN,
3030
HID_KEY_AIRPLANE_MODE,
31-
31+
HID_KEY_DISPLAY_TOGGLE,
3232
HID_KEY_MAX
3333
};
3434
/*HID_KEY_MAX cannot be > TASK_EVENT_CUSTOM_BIT*/

board/hx20/keyboard_customization.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ void board_kblight_init(void)
216216
}
217217
#endif
218218

219+
uint8_t display_toggle_key_hid = 0;
220+
221+
void set_display_toggle_key_hid(uint8_t enable)
222+
{
223+
CPRINTS("set display_toggle_key_hid = %hhd", enable);
224+
display_toggle_key_hid = enable;
225+
}
226+
219227
#ifdef CONFIG_KEYBOARD_CUSTOMIZATION_COMBINATION_KEY
220228
#define FN_PRESSED BIT(0)
221229
#define FN_LOCKED BIT(1)
@@ -329,12 +337,11 @@ int hotkey_F1_F12(uint16_t *key_code, uint16_t fn, int8_t pressed)
329337
break;
330338
case SCANCODE_F9: /* EXTERNAL_DISPLAY */
331339
if (fn_table_media_set(pressed, KB_FN_F9)) {
332-
if (pressed) {
333-
simulate_keyboard(SCANCODE_LEFT_WIN, 1);
334-
simulate_keyboard(SCANCODE_P, 1);
340+
if (display_toggle_key_hid) {
341+
update_hid_key(HID_KEY_DISPLAY_TOGGLE, pressed);
335342
} else {
336-
simulate_keyboard(SCANCODE_P, 0);
337-
simulate_keyboard(SCANCODE_LEFT_WIN, 0);
343+
simulate_keyboard(SCANCODE_LEFT_WIN, pressed);
344+
simulate_keyboard(SCANCODE_P, pressed);
338345
}
339346
return EC_ERROR_UNIMPLEMENTED;
340347
}

board/hx20/keyboard_customization.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,6 @@ int factory_status(void);
112112
void hx20_8042_led_control(int data);
113113
#endif
114114

115+
void set_display_toggle_key_hid(uint8_t enable);
116+
115117
#endif /* __KEYBOARD_CUSTOMIZATION_H */

board/hx30/host_command_customization.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,13 @@ static enum ec_status standalone_mode(struct host_cmd_handler_args *args)
351351
}
352352
DECLARE_HOST_COMMAND(EC_CMD_STANDALONE_MODE, standalone_mode, EC_VER_MASK(0));
353353

354+
static enum ec_status display_toggle_key_hid(struct host_cmd_handler_args *args)
355+
{
356+
const struct ec_params_display_toggle_key_hid *p = args->params;
357+
358+
set_display_toggle_key_hid(p->enable);
359+
return EC_RES_SUCCESS;
360+
361+
}
362+
DECLARE_HOST_COMMAND(EC_CMD_DISPLAY_TOGGLE_KEY_HID, display_toggle_key_hid, EC_VER_MASK(0));
363+

board/hx30/host_command_customization.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,12 @@ struct ec_response_chassis_counter {
229229
uint8_t press_counter;
230230
} __ec_align1;
231231

232+
/* If enabled, display key emits HID System Display Toggle Int/Ext Mode;
233+
otherwise emits Win+P */
234+
#define EC_CMD_DISPLAY_TOGGLE_KEY_HID 0x3E16
235+
236+
struct ec_params_display_toggle_key_hid {
237+
uint8_t enable;
238+
} __ec_align1;
239+
232240
#endif /* __HOST_COMMAND_CUSTOMIZATION_H */

board/hx30/i2c_hid_mediakeys.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define REPORT_ID_RADIO 0x01
2626
#define REPORT_ID_CONSUMER 0x02
2727
#define REPORT_ID_SENSOR 0x03
28+
#define REPORT_ID_DISPLAY 0x04
2829

2930
#define ALS_REPORT_STOP 0x00
3031
#define ALS_REPORT_POLLING 0x01
@@ -74,18 +75,22 @@ struct als_feature_report {
7475
uint16_t minimum;
7576
} __packed;
7677

78+
struct display_report {
79+
uint8_t state;
80+
} __packed;
7781

7882
static struct radio_report radio_button;
7983
static struct consumer_button_report consumer_button;
8084
static struct als_input_report als_sensor;
8185
static struct als_feature_report als_feature;
86+
static struct display_report display_button;
8287

8388
int update_hid_key(enum media_key key, bool pressed)
8489
{
8590
if (key >= HID_KEY_MAX) {
8691
return EC_ERROR_INVAL;
8792
}
88-
if (key == HID_KEY_AIRPLANE_MODE) {
93+
if (key == HID_KEY_AIRPLANE_MODE || key == HID_KEY_DISPLAY_TOGGLE) {
8994
key_states[key] = pressed;
9095
if (pressed)
9196
task_set_event(TASK_ID_HID, 1 << key, 0);
@@ -285,6 +290,21 @@ static const uint8_t report_desc[] = {
285290
0x95, 0x01, /* Report Count (1) */
286291
0x81, 0x02, /* Input (Data,Arr,Abs) */
287292
0xC0, /* END_COLLECTION */
293+
294+
/* Display Toggle Collection */
295+
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
296+
0x09, 0x80, /* USAGE (System Control) */
297+
0xA1, 0x01, /* COLLECTION (Application) */
298+
0x85, REPORT_ID_DISPLAY, /* Report ID (Display) */
299+
0x15, 0x00, /* LOGICAL_MINIMUM (0) */
300+
0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
301+
0x09, 0xB5, /* USAGE (System Display Toggle Int/Ext Mode) */
302+
0x95, 0x01, /* REPORT_COUNT (1) */
303+
0x75, 0x01, /* REPORT_SIZE (1) */
304+
0x81, 0x06, /* INPUT (Data,Var,Rel) */
305+
0x75, 0x07, /* REPORT_SIZE (7) */
306+
0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
307+
0xC0, /* END_COLLECTION */
288308
};
289309

290310

@@ -478,6 +498,12 @@ static int i2c_hid_touchpad_command_process(size_t len, uint8_t *buffer)
478498
sizeof(struct als_feature_report));
479499
}
480500
break;
501+
case REPORT_ID_DISPLAY:
502+
response_len =
503+
fill_report(buffer, report_id,
504+
&display_button,
505+
sizeof(struct display_report));
506+
break;
481507
default:
482508
response_len = 2;
483509
buffer[0] = response_len;
@@ -564,7 +590,12 @@ int i2c_hid_process(unsigned int len, uint8_t *buffer)
564590
fill_report(buffer, REPORT_ID_SENSOR,
565591
&als_sensor,
566592
sizeof(struct als_input_report));
567-
}
593+
} else if (input_mode == REPORT_ID_DISPLAY) {
594+
response_len =
595+
fill_report(buffer, REPORT_ID_DISPLAY,
596+
&display_button,
597+
sizeof(struct display_report));
598+
}
568599
break;
569600
case I2C_HID_COMMAND_REGISTER:
570601
response_len = i2c_hid_touchpad_command_process(len, buffer);
@@ -673,6 +704,10 @@ void hid_handler_task(void *p)
673704
input_mode = REPORT_ID_RADIO;
674705
radio_button.state = key_states[i] ? 1 : 0;
675706
break;
707+
case HID_KEY_DISPLAY_TOGGLE:
708+
input_mode = REPORT_ID_DISPLAY;
709+
display_button.state = key_states[i] ? 1 : 0;
710+
break;
676711
case HID_ALS_REPORT_LUX:
677712

678713
input_mode = REPORT_ID_SENSOR;

board/hx30/i2c_hid_mediakeys.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ enum media_key {
8181
HID_KEY_DISPLAY_BRIGHTNESS_UP,
8282
HID_KEY_DISPLAY_BRIGHTNESS_DN,
8383
HID_KEY_AIRPLANE_MODE,
84+
HID_KEY_DISPLAY_TOGGLE,
8485
HID_ALS_REPORT_LUX,
8586
HID_KEY_MAX
8687
};

board/hx30/keyboard_customization.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ void board_kblight_init(void)
216216
}
217217
#endif
218218

219+
uint8_t display_toggle_key_hid = 0;
220+
221+
void set_display_toggle_key_hid(uint8_t enable)
222+
{
223+
CPRINTS("set display_toggle_key_hid = %hhd", enable);
224+
display_toggle_key_hid = enable;
225+
}
226+
219227
#ifdef CONFIG_KEYBOARD_CUSTOMIZATION_COMBINATION_KEY
220228
#define FN_PRESSED BIT(0)
221229
#define FN_LOCKED BIT(1)
@@ -329,12 +337,11 @@ int hotkey_F1_F12(uint16_t *key_code, uint16_t fn, int8_t pressed)
329337
break;
330338
case SCANCODE_F9: /* EXTERNAL_DISPLAY */
331339
if (fn_table_media_set(pressed, KB_FN_F9)) {
332-
if (pressed) {
333-
simulate_keyboard(SCANCODE_LEFT_WIN, 1);
334-
simulate_keyboard(SCANCODE_P, 1);
340+
if (display_toggle_key_hid) {
341+
update_hid_key(HID_KEY_DISPLAY_TOGGLE, pressed);
335342
} else {
336-
simulate_keyboard(SCANCODE_P, 0);
337-
simulate_keyboard(SCANCODE_LEFT_WIN, 0);
343+
simulate_keyboard(SCANCODE_LEFT_WIN, pressed);
344+
simulate_keyboard(SCANCODE_P, pressed);
338345
}
339346
return EC_ERROR_UNIMPLEMENTED;
340347
}

board/hx30/keyboard_customization.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,6 @@ int factory_status(void);
112112
void hx20_8042_led_control(int data);
113113
#endif
114114

115+
void set_display_toggle_key_hid(uint8_t enable);
116+
115117
#endif /* __KEYBOARD_CUSTOMIZATION_H */

0 commit comments

Comments
 (0)