From 311a27da6271394afdca5773f4272eb6f48fae2d Mon Sep 17 00:00:00 2001 From: Philip Chen Date: Mon, 22 Feb 2021 21:03:23 -0800 Subject: dt-bindings: input: cros-ec-keyb: Add a new property describing top row Add a new property `function-row-physmap` to the device tree for the custom keyboard top row design. The property describes the rows/columns of the top row keys from left to right. Signed-off-by: Philip Chen Reviewed-by: Stephen Boyd Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210115122412.v7.1.I025fb861cd5fa0ef5286b7dce514728e9df7ae74@changeid Signed-off-by: Dmitry Torokhov --- .../bindings/input/google,cros-ec-keyb.yaml | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml index 8e50c14a9d77..5377b232fa10 100644 --- a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml +++ b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml @@ -31,6 +31,17 @@ properties: if the EC does not have its own logic or hardware for this. type: boolean + function-row-physmap: + minItems: 1 + maxItems: 15 + description: | + An ordered u32 array describing the rows/columns (in the scan matrix) + of top row keys from physical left (KEY_F1) to right. Each entry + encodes the row/column as: + (((row) & 0xFF) << 24) | (((column) & 0xFF) << 16) + where the lower 16 bits are reserved. This property is specified only + when the keyboard has a custom design for the top row keys. + required: - compatible @@ -38,11 +49,24 @@ unevaluatedProperties: false examples: - | + #include cros-ec-keyb { compatible = "google,cros-ec-keyb"; keypad,num-rows = <8>; keypad,num-columns = <13>; google,needs-ghost-filter; + function-row-physmap = < + MATRIX_KEY(0x00, 0x02, 0) /* T1 */ + MATRIX_KEY(0x03, 0x02, 0) /* T2 */ + MATRIX_KEY(0x02, 0x02, 0) /* T3 */ + MATRIX_KEY(0x01, 0x02, 0) /* T4 */ + MATRIX_KEY(0x03, 0x04, 0) /* T5 */ + MATRIX_KEY(0x02, 0x04, 0) /* T6 */ + MATRIX_KEY(0x01, 0x04, 0) /* T7 */ + MATRIX_KEY(0x02, 0x09, 0) /* T8 */ + MATRIX_KEY(0x01, 0x09, 0) /* T9 */ + MATRIX_KEY(0x00, 0x04, 0) /* T10 */ + >; /* * Keymap entries take the form of 0xRRCCKKKK where * RR=Row CC=Column KKKK=Key Code -- cgit v1.2.3 From 820c8727956da82b7a841c299fabb2fdca9a37d4 Mon Sep 17 00:00:00 2001 From: Philip Chen Date: Mon, 22 Feb 2021 21:05:04 -0800 Subject: Input: cros-ec-keyb - expose function row physical map to userspace The top-row keys in a keyboard usually have dual functionalities. E.g. A function key "F1" is also an action key "Browser back". Therefore, when an application receives an action key code from a top-row key press, the application needs to know how to correlate the action key code with the function key code and do the conversion whenever necessary. Since the userpace already knows the key scanlines (row/column) associated with a received key code. Essentially, the userspace only needs a mapping between the key row/column and the matching physical location in the top row. So, enhance the cros-ec-keyb driver to create such a mapping and expose it to userspace in the form of a function_row_physmap attribute. The attribute would be a space separated ordered list of row/column codes for the keys in the function row, in a left-to-right order. The attribute will only be present when the device has a custom design for the top-row keys. Signed-off-by: Philip Chen Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20210115122412.v7.2.I6542d7d9d0b246e7079bb16b41e697b2ac4b4e39@changeid Signed-off-by: Dmitry Torokhov --- .../ABI/testing/sysfs-driver-input-cros-ec-keyb | 6 ++ drivers/input/keyboard/cros_ec_keyb.c | 79 ++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-input-cros-ec-keyb (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-driver-input-cros-ec-keyb b/Documentation/ABI/testing/sysfs-driver-input-cros-ec-keyb new file mode 100644 index 000000000000..c7afc2328045 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-input-cros-ec-keyb @@ -0,0 +1,6 @@ +What: /sys/class/input/input(x)/device/function_row_physmap +Date: January 2021 +Contact: Philip Chen +Description: A space separated list of scancodes for the top row keys, + ordered by the physical positions of the keys, from left + to right. diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index b379ed762878..38457d9641bd 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -27,6 +27,8 @@ #include +#define MAX_NUM_TOP_ROW_KEYS 15 + /** * struct cros_ec_keyb - Structure representing EC keyboard device * @@ -42,6 +44,9 @@ * @idev: The input device for the matrix keys. * @bs_idev: The input device for non-matrix buttons and switches (or NULL). * @notifier: interrupt event notifier for transport devices + * @function_row_physmap: An array of the encoded rows/columns for the top + * row function keys, in an order from left to right + * @num_function_row_keys: The number of top row keys in a custom keyboard */ struct cros_ec_keyb { unsigned int rows; @@ -58,6 +63,9 @@ struct cros_ec_keyb { struct input_dev *idev; struct input_dev *bs_idev; struct notifier_block notifier; + + u16 function_row_physmap[MAX_NUM_TOP_ROW_KEYS]; + size_t num_function_row_keys; }; /** @@ -527,6 +535,11 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) struct input_dev *idev; const char *phys; int err; + struct property *prop; + const __be32 *p; + u16 *physmap; + u32 key_pos; + int row, col; err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols); if (err) @@ -578,6 +591,21 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) ckdev->idev = idev; cros_ec_keyb_compute_valid_keys(ckdev); + physmap = ckdev->function_row_physmap; + of_property_for_each_u32(dev->of_node, "function-row-physmap", + prop, p, key_pos) { + if (ckdev->num_function_row_keys == MAX_NUM_TOP_ROW_KEYS) { + dev_warn(dev, "Only support up to %d top row keys\n", + MAX_NUM_TOP_ROW_KEYS); + break; + } + row = KEY_ROW(key_pos); + col = KEY_COL(key_pos); + *physmap = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); + physmap++; + ckdev->num_function_row_keys++; + } + err = input_register_device(ckdev->idev); if (err) { dev_err(dev, "cannot register input device\n"); @@ -587,6 +615,51 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) return 0; } +static ssize_t function_row_physmap_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t size = 0; + int i; + struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); + u16 *physmap = ckdev->function_row_physmap; + + for (i = 0; i < ckdev->num_function_row_keys; i++) + size += scnprintf(buf + size, PAGE_SIZE - size, + "%s%02X", size ? " " : "", physmap[i]); + if (size) + size += scnprintf(buf + size, PAGE_SIZE - size, "\n"); + + return size; +} + +static DEVICE_ATTR_RO(function_row_physmap); + +static struct attribute *cros_ec_keyb_attrs[] = { + &dev_attr_function_row_physmap.attr, + NULL, +}; + +static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj, + struct attribute *attr, + int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); + + if (attr == &dev_attr_function_row_physmap.attr && + !ckdev->num_function_row_keys) + return 0; + + return attr->mode; +} + +static const struct attribute_group cros_ec_keyb_attr_group = { + .is_visible = cros_ec_keyb_attr_is_visible, + .attrs = cros_ec_keyb_attrs, +}; + + static int cros_ec_keyb_probe(struct platform_device *pdev) { struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); @@ -617,6 +690,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) return err; } + err = devm_device_add_group(dev, &cros_ec_keyb_attr_group); + if (err) { + dev_err(dev, "failed to create attributes. err=%d\n", err); + return err; + } + ckdev->notifier.notifier_call = cros_ec_keyb_work; err = blocking_notifier_chain_register(&ckdev->ec->event_notifier, &ckdev->notifier); -- cgit v1.2.3