* [PATCH v1 0/3] Input: cros_ec_keyb: add function key support
@ 2025-12-09 15:47 Fabio Baltieri
2025-12-09 15:47 ` [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message Fabio Baltieri
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Benson Leung, Guenter Roeck
Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
Hi,
this adds function key support to the cros_ec_keyb driver: the platform
can specify a key to be used as "function key", and that changes the
keycode emitted for other keys as long as the function key remains
pressed.
The Fn key omits its own code if pressed and released with no other
function key pressed in the meantime. Non mapped keys do not emit any
codes, this seems to be the behavior of other devices I have lying
around.
Fabio Baltieri (3):
Input: cros_ec_keyb: clarify key event error message
Input: cros_ec_keyb: add function key support
dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
.../bindings/input/google,cros-ec-keyb.yaml | 60 +++++-
drivers/input/keyboard/cros_ec_keyb.c | 193 ++++++++++++++++--
2 files changed, 227 insertions(+), 26 deletions(-)
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message
2025-12-09 15:47 [PATCH v1 0/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
@ 2025-12-09 15:47 ` Fabio Baltieri
2025-12-11 13:29 ` Simon Glass
2025-12-13 9:40 ` Dmitry Torokhov
2025-12-09 15:47 ` [PATCH v1 2/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
2025-12-09 15:47 ` [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props Fabio Baltieri
2 siblings, 2 replies; 11+ messages in thread
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Benson Leung, Guenter Roeck
Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
Reword one of the key event error messages to clarify its meaning: it's
not necessarily an incomplete message, more of a mismatch length.
Clarify that and log the expected and received length too.
Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
---
drivers/input/keyboard/cros_ec_keyb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 1c6b0461dc35..2822c592880b 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -269,7 +269,8 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
if (ckdev->ec->event_size != ckdev->cols) {
dev_err(ckdev->dev,
- "Discarded incomplete key matrix event.\n");
+ "Discarded key matrix event, unexpected length: %d != %d\n",
+ ckdev->ec->event_size, ckdev->cols);
return NOTIFY_OK;
}
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v1 2/3] Input: cros_ec_keyb: add function key support
2025-12-09 15:47 [PATCH v1 0/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
2025-12-09 15:47 ` [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message Fabio Baltieri
@ 2025-12-09 15:47 ` Fabio Baltieri
2025-12-11 13:29 ` Simon Glass
2025-12-09 15:47 ` [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props Fabio Baltieri
2 siblings, 1 reply; 11+ messages in thread
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Benson Leung, Guenter Roeck
Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
Add support for handling an Fn button and sending separate keycodes for
a subset of keys in the matrix.
Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
---
drivers/input/keyboard/cros_ec_keyb.c | 190 ++++++++++++++++++++++++--
1 file changed, 176 insertions(+), 14 deletions(-)
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 2822c592880b..b0965e5d20de 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -29,6 +29,14 @@
#include <linux/unaligned.h>
+/* Maximum number of Fn keys, limited by the key status mask size. */
+#define CROS_EC_FN_KEYMAP_MAX 32
+
+/* Maximum size of the normal key matrix, this is limited by the host command
+ * key_matrix field defined in ec_response_get_next_data_v3
+ */
+#define CROS_EC_KEYBOARD_COLS_MAX 18
+
/**
* struct cros_ec_keyb - Structure representing EC keyboard device
*
@@ -44,6 +52,13 @@
* @bs_idev: The input device for non-matrix buttons and switches (or NULL).
* @notifier: interrupt event notifier for transport devices
* @vdata: vivaldi function row data
+ * @fn_key: coordinate of the function key
+ * @fn_keymap: array of coordinate and codes for the function keys
+ * @fn_keymap_len: number of entries in the fn_keymap array
+ * @fn_key_status: active function keys bitmap
+ * @normal_key_status: active normal keys bitmap
+ * @fn_key_pressed: tracks the function key status
+ * @fn_key_triggered: tracks where any function key fired
*/
struct cros_ec_keyb {
unsigned int rows;
@@ -61,6 +76,14 @@ struct cros_ec_keyb {
struct notifier_block notifier;
struct vivaldi_data vdata;
+
+ uint32_t fn_key;
+ uint32_t *fn_keymap;
+ int fn_keymap_len;
+ uint32_t fn_key_status;
+ uint8_t normal_key_status[CROS_EC_KEYBOARD_COLS_MAX];
+ bool fn_key_pressed;
+ bool fn_key_triggered;
};
/**
@@ -166,16 +189,108 @@ static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf)
return false;
}
+static bool cros_ec_key_is(int row, int col, uint32_t key)
+{
+ if (row == KEY_ROW(key) && col == KEY_COL(key))
+ return true;
+
+ return false;
+}
+
+static void cros_ec_keyb_process_one(struct cros_ec_keyb *ckdev,
+ int row, int col, bool state)
+{
+ struct input_dev *idev = ckdev->idev;
+ const unsigned short *keycodes = idev->keycode;
+ int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
+ unsigned int code = keycodes[pos];
+
+ dev_dbg(ckdev->dev, "changed: [r%d c%d]: byte %02x\n", row, col, state);
+
+ if (ckdev->fn_keymap) {
+ if (cros_ec_key_is(row, col, ckdev->fn_key)) {
+ ckdev->fn_key_pressed = state;
+
+ if (state) {
+ ckdev->fn_key_triggered = false;
+ } else if (!ckdev->fn_key_triggered) {
+ /*
+ * Send the original code if nothing else has
+ * been pressed together with Fn.
+ */
+ input_event(idev, EV_MSC, MSC_SCAN, pos);
+ input_report_key(idev, code, true);
+ input_sync(ckdev->idev);
+
+ input_event(idev, EV_MSC, MSC_SCAN, pos);
+ input_report_key(idev, code, false);
+ }
+
+ return;
+ }
+
+ if (!state) {
+ /* Key release, may need to release the Fn code */
+ for (int i = 0; i < ckdev->fn_keymap_len; i++) {
+ if (!cros_ec_key_is(row, col,
+ ckdev->fn_keymap[i]))
+ continue;
+
+ if ((ckdev->fn_key_status & BIT(i)) == 0)
+ continue;
+
+ code = KEY_VAL(ckdev->fn_keymap[i]);
+ ckdev->fn_key_status &= ~BIT(i);
+
+ input_event(idev, EV_MSC, MSC_SCAN, pos);
+ input_report_key(idev, code, state);
+
+ return;
+ }
+
+ if ((ckdev->normal_key_status[col] & BIT(row)) == 0)
+ /* Discard, key press code was not sent */
+ return;
+ } else if (ckdev->fn_key_pressed) {
+ /* Key press while holding Fn */
+ ckdev->fn_key_triggered = true;
+
+ for (int i = 0; i < ckdev->fn_keymap_len; i++) {
+ if (!cros_ec_key_is(row, col,
+ ckdev->fn_keymap[i]))
+ continue;
+
+ code = KEY_VAL(ckdev->fn_keymap[i]);
+ ckdev->fn_key_status |= BIT(i);
+
+ input_event(idev, EV_MSC, MSC_SCAN, pos);
+ input_report_key(idev, code, state);
+
+ return;
+ }
+
+ /* Do not emit a code if the key is not mapped */
+ return;
+ }
+ }
+
+ if (state)
+ ckdev->normal_key_status[col] |= BIT(row);
+ else
+ ckdev->normal_key_status[col] &= ~BIT(row);
+
+ input_event(idev, EV_MSC, MSC_SCAN, pos);
+ input_report_key(idev, code, state);
+}
/*
* Compares the new keyboard state to the old one and produces key
- * press/release events accordingly. The keyboard state is 13 bytes (one byte
- * per column)
+ * press/release events accordingly. The keyboard state is one byte
+ * per column.
*/
static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
uint8_t *kb_state, int len)
{
- struct input_dev *idev = ckdev->idev;
int col, row;
int new_state;
int old_state;
@@ -192,20 +307,13 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
for (col = 0; col < ckdev->cols; col++) {
for (row = 0; row < ckdev->rows; row++) {
- int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
- const unsigned short *keycodes = idev->keycode;
-
new_state = kb_state[col] & (1 << row);
old_state = ckdev->old_kb_state[col] & (1 << row);
- if (new_state != old_state) {
- dev_dbg(ckdev->dev,
- "changed: [r%d c%d]: byte %02x\n",
- row, col, new_state);
- input_event(idev, EV_MSC, MSC_SCAN, pos);
- input_report_key(idev, keycodes[pos],
- new_state);
- }
+ if (new_state == old_state)
+ continue;
+
+ cros_ec_keyb_process_one(ckdev, row, col, new_state);
}
ckdev->old_kb_state[col] = kb_state[col];
}
@@ -604,6 +712,12 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
if (err)
return err;
+ if (ckdev->cols > CROS_EC_KEYBOARD_COLS_MAX) {
+ dev_err(dev, "keypad,num-columns too large: %d (max: %d)\n",
+ ckdev->cols, CROS_EC_KEYBOARD_COLS_MAX);
+ return -EINVAL;
+ }
+
ckdev->valid_keys = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
if (!ckdev->valid_keys)
return -ENOMEM;
@@ -660,6 +774,47 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
return 0;
}
+static int cros_ec_keyb_register_fn_keys(struct cros_ec_keyb *ckdev)
+{
+ struct device *dev = ckdev->dev;
+ uint32_t fn_key;
+ uint32_t *keymap;
+ int keymap_len;
+ int ret;
+
+ if (!(device_property_present(dev, "fn-key") &&
+ device_property_present(dev, "fn-keymap")))
+ return 0;
+
+ device_property_read_u32(dev, "fn-key", &fn_key);
+
+ keymap_len = device_property_count_u32(ckdev->dev, "fn-keymap");
+ if (keymap_len > CROS_EC_FN_KEYMAP_MAX) {
+ dev_err(dev, "fn-keymap too large: %d limit=%d",
+ keymap_len, CROS_EC_FN_KEYMAP_MAX);
+ return -EINVAL;
+ }
+
+ keymap = devm_kcalloc(dev, keymap_len, sizeof(*keymap), GFP_KERNEL);
+ if (!keymap)
+ return -ENOMEM;
+
+ ret = device_property_read_u32_array(dev, "fn-keymap", keymap, keymap_len);
+ if (ret) {
+ dev_err(dev, "failed to read fn-keymap property: %d\n", ret);
+ return ret;
+ }
+
+ for (int i = 0; i < keymap_len; i++)
+ __set_bit(KEY_VAL(keymap[i]), ckdev->idev->keybit);
+
+ ckdev->fn_key = fn_key;
+ ckdev->fn_keymap = keymap;
+ ckdev->fn_keymap_len = keymap_len;
+
+ return 0;
+}
+
static ssize_t function_row_physmap_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -734,6 +889,13 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
err);
return err;
}
+
+ err = cros_ec_keyb_register_fn_keys(ckdev);
+ if (err) {
+ dev_err(dev, "cannot register fn-keys inputs: %d\n",
+ err);
+ return err;
+ }
}
err = cros_ec_keyb_register_bs(ckdev, buttons_switches_only);
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
2025-12-09 15:47 [PATCH v1 0/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
2025-12-09 15:47 ` [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message Fabio Baltieri
2025-12-09 15:47 ` [PATCH v1 2/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
@ 2025-12-09 15:47 ` Fabio Baltieri
2025-12-09 17:24 ` Rob Herring (Arm)
2025-12-09 19:22 ` Rob Herring
2 siblings, 2 replies; 11+ messages in thread
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Benson Leung, Guenter Roeck
Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
Add binding documentation for the fn-key and fn-keymap properties,
verify that the two new properties are either both preseent or none.
Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
---
.../bindings/input/google,cros-ec-keyb.yaml | 60 +++++++++++++++----
1 file changed, 49 insertions(+), 11 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
index fefaaf46a240..56adf9026010 100644
--- a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
+++ b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
@@ -44,6 +44,20 @@ properties:
where the lower 16 bits are reserved. This property is specified only
when the keyboard has a custom design for the top row keys.
+ fn-key:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ An u32 containing the coordinate of the Fn key, use the MATRIX_KEY(row,
+ col, code) macro, code is ignored.
+
+ fn-keymap:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 32
+ description: |
+ An array of u32 mapping the row, column and codes for the function keys,
+ use the MATRIX_KEY macro to define the elements.
+
dependencies:
function-row-physmap: [ 'linux,keymap' ]
google,needs-ghost-filter: [ 'linux,keymap' ]
@@ -51,17 +65,28 @@ dependencies:
required:
- compatible
-if:
- properties:
- compatible:
- contains:
- const: google,cros-ec-keyb
-then:
- $ref: /schemas/input/matrix-keymap.yaml#
- required:
- - keypad,num-rows
- - keypad,num-columns
- - linux,keymap
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: google,cros-ec-keyb
+ then:
+ $ref: /schemas/input/matrix-keymap.yaml#
+ required:
+ - keypad,num-rows
+ - keypad,num-columns
+ - linux,keymap
+ - if:
+ anyOf:
+ - required:
+ - fn-key
+ - required:
+ - fn-keymap
+ then:
+ required:
+ - fn-key
+ - fn-keymap
unevaluatedProperties: false
@@ -132,6 +157,19 @@ examples:
/* UP LEFT */
0x070b0067 0x070c0069>;
};
+ fn-key = <MATRIX_KEY(0x04, 0x0a, 0)>;
+ fn-keymap = <
+ MATRIX_KEY(0x00, 0x02, KEY_F1) /* T1 */
+ MATRIX_KEY(0x03, 0x02, KEY_F2) /* T2 */
+ MATRIX_KEY(0x02, 0x02, KEY_F3) /* T3 */
+ MATRIX_KEY(0x01, 0x02, KEY_F4) /* T4 */
+ MATRIX_KEY(0x04, 0x04, KEY_F5) /* T5 */
+ MATRIX_KEY(0x02, 0x04, KEY_F6) /* T6 */
+ MATRIX_KEY(0x01, 0x04, KEY_F7) /* T7 */
+ MATRIX_KEY(0x02, 0x0b, KEY_F8) /* T8 */
+ MATRIX_KEY(0x01, 0x09, KEY_F9) /* T9 */
+ MATRIX_KEY(0x00, 0x04, KEY_F10) /* T10 */
+ >;
- |
/* No matrix keyboard, just buttons/switches */
keyboard-controller {
--
2.52.0.223.gf5cc29aaa4-goog
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
2025-12-09 15:47 ` [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props Fabio Baltieri
@ 2025-12-09 17:24 ` Rob Herring (Arm)
2025-12-09 19:22 ` Rob Herring
1 sibling, 0 replies; 11+ messages in thread
From: Rob Herring (Arm) @ 2025-12-09 17:24 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Tzung-Bi Shih, Dmitry Torokhov, linux-input, Krzysztof Kozlowski,
Simon Glass, devicetree, chrome-platform, Guenter Roeck,
Conor Dooley, Benson Leung, linux-kernel
On Tue, 09 Dec 2025 15:47:06 +0000, Fabio Baltieri wrote:
> Add binding documentation for the fn-key and fn-keymap properties,
> verify that the two new properties are either both preseent or none.
>
> Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
> ---
> .../bindings/input/google,cros-ec-keyb.yaml | 60 +++++++++++++++----
> 1 file changed, 49 insertions(+), 11 deletions(-)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
./Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml:83:11: [warning] wrong indentation: expected 12 but found 10 (indentation)
./Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml:85:11: [warning] wrong indentation: expected 12 but found 10 (indentation)
dtschema/dtc warnings/errors:
Error: Documentation/devicetree/bindings/input/google,cros-ec-keyb.example.dts:83.9-89 Properties must precede subnodes
FATAL ERROR: Unable to parse input tree
make[2]: *** [scripts/Makefile.dtbs:141: Documentation/devicetree/bindings/input/google,cros-ec-keyb.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1559: dt_binding_check] Error 2
make: *** [Makefile:248: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.kernel.org/project/devicetree/patch/20251209154706.529784-4-fabiobaltieri@chromium.org
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
2025-12-09 15:47 ` [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props Fabio Baltieri
2025-12-09 17:24 ` Rob Herring (Arm)
@ 2025-12-09 19:22 ` Rob Herring
2025-12-10 18:00 ` Fabio Baltieri
1 sibling, 1 reply; 11+ messages in thread
From: Rob Herring @ 2025-12-09 19:22 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Dmitry Torokhov, Krzysztof Kozlowski, Conor Dooley, Benson Leung,
Guenter Roeck, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
On Tue, Dec 09, 2025 at 03:47:06PM +0000, Fabio Baltieri wrote:
> Add binding documentation for the fn-key and fn-keymap properties,
> verify that the two new properties are either both preseent or none.
>
> Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
> ---
> .../bindings/input/google,cros-ec-keyb.yaml | 60 +++++++++++++++----
> 1 file changed, 49 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
> index fefaaf46a240..56adf9026010 100644
> --- a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
> +++ b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
> @@ -44,6 +44,20 @@ properties:
> where the lower 16 bits are reserved. This property is specified only
> when the keyboard has a custom design for the top row keys.
>
> + fn-key:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description: |
> + An u32 containing the coordinate of the Fn key, use the MATRIX_KEY(row,
> + col, code) macro, code is ignored.
> +
> + fn-keymap:
If keymap is linux,keymap, then this should perhaps be linux,fn-keymap.
Depends if we still think linux,keymap is Linux specific?
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + minItems: 1
> + maxItems: 32
> + description: |
> + An array of u32 mapping the row, column and codes for the function keys,
> + use the MATRIX_KEY macro to define the elements.
> +
> dependencies:
> function-row-physmap: [ 'linux,keymap' ]
> google,needs-ghost-filter: [ 'linux,keymap' ]
> @@ -51,17 +65,28 @@ dependencies:
> required:
> - compatible
>
> -if:
> - properties:
> - compatible:
> - contains:
> - const: google,cros-ec-keyb
> -then:
> - $ref: /schemas/input/matrix-keymap.yaml#
> - required:
> - - keypad,num-rows
> - - keypad,num-columns
> - - linux,keymap
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: google,cros-ec-keyb
> + then:
> + $ref: /schemas/input/matrix-keymap.yaml#
> + required:
> + - keypad,num-rows
> + - keypad,num-columns
> + - linux,keymap
> + - if:
> + anyOf:
> + - required:
> + - fn-key
> + - required:
> + - fn-keymap
> + then:
> + required:
> + - fn-key
> + - fn-keymap
This can be more concisely written as:
dependencies:
fn-key: [fn-keymap]
fn-keymap: [fn-key]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
2025-12-09 19:22 ` Rob Herring
@ 2025-12-10 18:00 ` Fabio Baltieri
2025-12-12 4:44 ` Dmitry Torokhov
0 siblings, 1 reply; 11+ messages in thread
From: Fabio Baltieri @ 2025-12-10 18:00 UTC (permalink / raw)
To: Rob Herring
Cc: Dmitry Torokhov, Krzysztof Kozlowski, Conor Dooley, Benson Leung,
Guenter Roeck, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
Hey Rob, thanks for the review.
On Tue, Dec 09, 2025 at 01:22:43PM -0600, Rob Herring wrote:
> On Tue, Dec 09, 2025 at 03:47:06PM +0000, Fabio Baltieri wrote:
> > + fn-key:
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + description: |
> > + An u32 containing the coordinate of the Fn key, use the MATRIX_KEY(row,
> > + col, code) macro, code is ignored.
> > +
> > + fn-keymap:
>
> If keymap is linux,keymap, then this should perhaps be linux,fn-keymap.
> Depends if we still think linux,keymap is Linux specific?
I'm open for suggestions, trying to understand the pattern, these are
specific to this binding I think if anything they should be
google,fn-key and google,fn-keymap, similarly to the existing
google,needs-ghost-filter -- no idea why function-row-physmap was not
prefixed but I guess it slipped in and now it's not worth changing it.
Would it make sense?
Thanks,
Fabio
--
Fabio Baltieri
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 2/3] Input: cros_ec_keyb: add function key support
2025-12-09 15:47 ` [PATCH v1 2/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
@ 2025-12-11 13:29 ` Simon Glass
0 siblings, 0 replies; 11+ messages in thread
From: Simon Glass @ 2025-12-11 13:29 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Benson Leung, Guenter Roeck, Tzung-Bi Shih, linux-input,
devicetree, chrome-platform, linux-kernel
Hi Fabio!
On Tue, 9 Dec 2025 at 08:47, Fabio Baltieri <fabiobaltieri@chromium.org> wrote:
>
> Add support for handling an Fn button and sending separate keycodes for
> a subset of keys in the matrix.
>
> Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
> ---
> drivers/input/keyboard/cros_ec_keyb.c | 190 ++++++++++++++++++++++++--
> 1 file changed, 176 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
> index 2822c592880b..b0965e5d20de 100644
> --- a/drivers/input/keyboard/cros_ec_keyb.c
> +++ b/drivers/input/keyboard/cros_ec_keyb.c
> @@ -29,6 +29,14 @@
>
> #include <linux/unaligned.h>
>
> +/* Maximum number of Fn keys, limited by the key status mask size. */
> +#define CROS_EC_FN_KEYMAP_MAX 32
> +
> +/* Maximum size of the normal key matrix, this is limited by the host command
> + * key_matrix field defined in ec_response_get_next_data_v3
> + */
> +#define CROS_EC_KEYBOARD_COLS_MAX 18
> +
> /**
> * struct cros_ec_keyb - Structure representing EC keyboard device
> *
> @@ -44,6 +52,13 @@
> * @bs_idev: The input device for non-matrix buttons and switches (or NULL).
> * @notifier: interrupt event notifier for transport devices
> * @vdata: vivaldi function row data
> + * @fn_key: coordinate of the function key
> + * @fn_keymap: array of coordinate and codes for the function keys
> + * @fn_keymap_len: number of entries in the fn_keymap array
> + * @fn_key_status: active function keys bitmap
> + * @normal_key_status: active normal keys bitmap
> + * @fn_key_pressed: tracks the function key status
> + * @fn_key_triggered: tracks where any function key fired
> */
> struct cros_ec_keyb {
> unsigned int rows;
> @@ -61,6 +76,14 @@ struct cros_ec_keyb {
> struct notifier_block notifier;
>
> struct vivaldi_data vdata;
> +
> + uint32_t fn_key;
Normally we use u32/u8 these days
> + uint32_t *fn_keymap;
> + int fn_keymap_len;
> + uint32_t fn_key_status;
> + uint8_t normal_key_status[CROS_EC_KEYBOARD_COLS_MAX];
> + bool fn_key_pressed;
> + bool fn_key_triggered;
> };
>
> /**
> @@ -166,16 +189,108 @@ static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf)
> return false;
> }
>
> +static bool cros_ec_key_is(int row, int col, uint32_t key)
> +{
> + if (row == KEY_ROW(key) && col == KEY_COL(key))
> + return true;
> +
> + return false;
> +}
> +
> +static void cros_ec_keyb_process_one(struct cros_ec_keyb *ckdev,
> + int row, int col, bool state)
> +{
> + struct input_dev *idev = ckdev->idev;
> + const unsigned short *keycodes = idev->keycode;
> + int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
> + unsigned int code = keycodes[pos];
> +
> + dev_dbg(ckdev->dev, "changed: [r%d c%d]: byte %02x\n", row, col, state);
> +
> + if (ckdev->fn_keymap) {
> + if (cros_ec_key_is(row, col, ckdev->fn_key)) {
> + ckdev->fn_key_pressed = state;
> +
> + if (state) {
> + ckdev->fn_key_triggered = false;
> + } else if (!ckdev->fn_key_triggered) {
> + /*
> + * Send the original code if nothing else has
> + * been pressed together with Fn.
> + */
> + input_event(idev, EV_MSC, MSC_SCAN, pos);
> + input_report_key(idev, code, true);
> + input_sync(ckdev->idev);
What is this function? I might be missing a patch?
> +
> + input_event(idev, EV_MSC, MSC_SCAN, pos);
> + input_report_key(idev, code, false);
> + }
> +
> + return;
> + }
> +
> + if (!state) {
> + /* Key release, may need to release the Fn code */
> + for (int i = 0; i < ckdev->fn_keymap_len; i++) {
> + if (!cros_ec_key_is(row, col,
> + ckdev->fn_keymap[i]))
> + continue;
> +
> + if ((ckdev->fn_key_status & BIT(i)) == 0)
> + continue;
> +
> + code = KEY_VAL(ckdev->fn_keymap[i]);
> + ckdev->fn_key_status &= ~BIT(i);
> +
> + input_event(idev, EV_MSC, MSC_SCAN, pos);
> + input_report_key(idev, code, state);
> +
> + return;
> + }
> +
> + if ((ckdev->normal_key_status[col] & BIT(row)) == 0)
> + /* Discard, key press code was not sent */
> + return;
> + } else if (ckdev->fn_key_pressed) {
> + /* Key press while holding Fn */
> + ckdev->fn_key_triggered = true;
> +
> + for (int i = 0; i < ckdev->fn_keymap_len; i++) {
> + if (!cros_ec_key_is(row, col,
> + ckdev->fn_keymap[i]))
> + continue;
> +
> + code = KEY_VAL(ckdev->fn_keymap[i]);
> + ckdev->fn_key_status |= BIT(i);
> +
> + input_event(idev, EV_MSC, MSC_SCAN, pos);
> + input_report_key(idev, code, state);
> +
> + return;
> + }
> +
> + /* Do not emit a code if the key is not mapped */
> + return;
> + }
> + }
I think this function could do with splitting a bit
> +
> + if (state)
> + ckdev->normal_key_status[col] |= BIT(row);
> + else
> + ckdev->normal_key_status[col] &= ~BIT(row);
> +
> + input_event(idev, EV_MSC, MSC_SCAN, pos);
> + input_report_key(idev, code, state);
> +}
>
> /*
> * Compares the new keyboard state to the old one and produces key
> - * press/release events accordingly. The keyboard state is 13 bytes (one byte
> - * per column)
> + * press/release events accordingly. The keyboard state is one byte
> + * per column.
> */
> static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
> uint8_t *kb_state, int len)
> {
> - struct input_dev *idev = ckdev->idev;
> int col, row;
> int new_state;
> int old_state;
> @@ -192,20 +307,13 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
>
> for (col = 0; col < ckdev->cols; col++) {
> for (row = 0; row < ckdev->rows; row++) {
> - int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
> - const unsigned short *keycodes = idev->keycode;
> -
> new_state = kb_state[col] & (1 << row);
> old_state = ckdev->old_kb_state[col] & (1 << row);
> - if (new_state != old_state) {
> - dev_dbg(ckdev->dev,
> - "changed: [r%d c%d]: byte %02x\n",
> - row, col, new_state);
>
> - input_event(idev, EV_MSC, MSC_SCAN, pos);
> - input_report_key(idev, keycodes[pos],
> - new_state);
> - }
> + if (new_state == old_state)
> + continue;
> +
> + cros_ec_keyb_process_one(ckdev, row, col, new_state);
> }
> ckdev->old_kb_state[col] = kb_state[col];
> }
> @@ -604,6 +712,12 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
> if (err)
> return err;
>
> + if (ckdev->cols > CROS_EC_KEYBOARD_COLS_MAX) {
> + dev_err(dev, "keypad,num-columns too large: %d (max: %d)\n",
> + ckdev->cols, CROS_EC_KEYBOARD_COLS_MAX);
> + return -EINVAL;
> + }
> +
> ckdev->valid_keys = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
> if (!ckdev->valid_keys)
> return -ENOMEM;
> @@ -660,6 +774,47 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
> return 0;
> }
>
> +static int cros_ec_keyb_register_fn_keys(struct cros_ec_keyb *ckdev)
> +{
> + struct device *dev = ckdev->dev;
> + uint32_t fn_key;
> + uint32_t *keymap;
> + int keymap_len;
> + int ret;
> +
> + if (!(device_property_present(dev, "fn-key") &&
> + device_property_present(dev, "fn-keymap")))
> + return 0;
> +
> + device_property_read_u32(dev, "fn-key", &fn_key);
> +
> + keymap_len = device_property_count_u32(ckdev->dev, "fn-keymap");
> + if (keymap_len > CROS_EC_FN_KEYMAP_MAX) {
> + dev_err(dev, "fn-keymap too large: %d limit=%d",
> + keymap_len, CROS_EC_FN_KEYMAP_MAX);
> + return -EINVAL;
> + }
> +
> + keymap = devm_kcalloc(dev, keymap_len, sizeof(*keymap), GFP_KERNEL);
> + if (!keymap)
> + return -ENOMEM;
> +
> + ret = device_property_read_u32_array(dev, "fn-keymap", keymap, keymap_len);
> + if (ret) {
> + dev_err(dev, "failed to read fn-keymap property: %d\n", ret);
> + return ret;
> + }
> +
> + for (int i = 0; i < keymap_len; i++)
> + __set_bit(KEY_VAL(keymap[i]), ckdev->idev->keybit);
> +
> + ckdev->fn_key = fn_key;
> + ckdev->fn_keymap = keymap;
> + ckdev->fn_keymap_len = keymap_len;
> +
> + return 0;
> +}
> +
> static ssize_t function_row_physmap_show(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> @@ -734,6 +889,13 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
> err);
> return err;
> }
> +
> + err = cros_ec_keyb_register_fn_keys(ckdev);
> + if (err) {
> + dev_err(dev, "cannot register fn-keys inputs: %d\n",
> + err);
> + return err;
> + }
> }
>
> err = cros_ec_keyb_register_bs(ckdev, buttons_switches_only);
> --
> 2.52.0.223.gf5cc29aaa4-goog
>
Can the sandbox driver support this too?
Regards,
Simon
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message
2025-12-09 15:47 ` [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message Fabio Baltieri
@ 2025-12-11 13:29 ` Simon Glass
2025-12-13 9:40 ` Dmitry Torokhov
1 sibling, 0 replies; 11+ messages in thread
From: Simon Glass @ 2025-12-11 13:29 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Benson Leung, Guenter Roeck, Tzung-Bi Shih, linux-input,
devicetree, chrome-platform, linux-kernel
On Tue, 9 Dec 2025 at 08:47, Fabio Baltieri <fabiobaltieri@chromium.org> wrote:
>
> Reword one of the key event error messages to clarify its meaning: it's
> not necessarily an incomplete message, more of a mismatch length.
> Clarify that and log the expected and received length too.
>
> Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
> ---
> drivers/input/keyboard/cros_ec_keyb.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass <simon.glass@canonical.com>
>
> diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
> index 1c6b0461dc35..2822c592880b 100644
> --- a/drivers/input/keyboard/cros_ec_keyb.c
> +++ b/drivers/input/keyboard/cros_ec_keyb.c
> @@ -269,7 +269,8 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
>
> if (ckdev->ec->event_size != ckdev->cols) {
> dev_err(ckdev->dev,
> - "Discarded incomplete key matrix event.\n");
> + "Discarded key matrix event, unexpected length: %d != %d\n",
> + ckdev->ec->event_size, ckdev->cols);
> return NOTIFY_OK;
> }
>
> --
> 2.52.0.223.gf5cc29aaa4-goog
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
2025-12-10 18:00 ` Fabio Baltieri
@ 2025-12-12 4:44 ` Dmitry Torokhov
0 siblings, 0 replies; 11+ messages in thread
From: Dmitry Torokhov @ 2025-12-12 4:44 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Benson Leung,
Guenter Roeck, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
On Wed, Dec 10, 2025 at 06:00:29PM +0000, Fabio Baltieri wrote:
> Hey Rob, thanks for the review.
>
> On Tue, Dec 09, 2025 at 01:22:43PM -0600, Rob Herring wrote:
> > On Tue, Dec 09, 2025 at 03:47:06PM +0000, Fabio Baltieri wrote:
> > > + fn-key:
> > > + $ref: /schemas/types.yaml#/definitions/uint32
> > > + description: |
> > > + An u32 containing the coordinate of the Fn key, use the MATRIX_KEY(row,
> > > + col, code) macro, code is ignored.
> > > +
> > > + fn-keymap:
> >
> > If keymap is linux,keymap, then this should perhaps be linux,fn-keymap.
> > Depends if we still think linux,keymap is Linux specific?
>
> I'm open for suggestions, trying to understand the pattern, these are
> specific to this binding I think if anything they should be
> google,fn-key and google,fn-keymap, similarly to the existing
> google,needs-ghost-filter -- no idea why function-row-physmap was not
> prefixed but I guess it slipped in and now it's not worth changing it.
Just double the number of rows in the regular keymap to accommodate the
FN modifier, no need for separate keymap. Also no need to have fn-key
property, use whatever key that reports KEY_FN. See how it is done in
drivers/input/keyboard/tegra-kbc.c
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message
2025-12-09 15:47 ` [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message Fabio Baltieri
2025-12-11 13:29 ` Simon Glass
@ 2025-12-13 9:40 ` Dmitry Torokhov
1 sibling, 0 replies; 11+ messages in thread
From: Dmitry Torokhov @ 2025-12-13 9:40 UTC (permalink / raw)
To: Fabio Baltieri
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Benson Leung,
Guenter Roeck, Tzung-Bi Shih, Simon Glass, linux-input,
devicetree, chrome-platform, linux-kernel
On Tue, Dec 09, 2025 at 03:47:04PM +0000, Fabio Baltieri wrote:
> Reword one of the key event error messages to clarify its meaning: it's
> not necessarily an incomplete message, more of a mismatch length.
> Clarify that and log the expected and received length too.
>
> Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
Applied, thank you.
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-12-13 9:40 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-09 15:47 [PATCH v1 0/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
2025-12-09 15:47 ` [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message Fabio Baltieri
2025-12-11 13:29 ` Simon Glass
2025-12-13 9:40 ` Dmitry Torokhov
2025-12-09 15:47 ` [PATCH v1 2/3] Input: cros_ec_keyb: add function key support Fabio Baltieri
2025-12-11 13:29 ` Simon Glass
2025-12-09 15:47 ` [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props Fabio Baltieri
2025-12-09 17:24 ` Rob Herring (Arm)
2025-12-09 19:22 ` Rob Herring
2025-12-10 18:00 ` Fabio Baltieri
2025-12-12 4:44 ` Dmitry Torokhov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).