Received: by 2002:a05:6a10:2785:0:0:0:0 with SMTP id ia5csp125871pxb; Thu, 14 Jan 2021 21:42:38 -0800 (PST) X-Google-Smtp-Source: ABdhPJxjkob0m2Av3F+gGshkpG+d3LNcHUSAH1CRp0o2nyhv2pO2COR8tmpw4/p0JJcSA30xCIG2 X-Received: by 2002:a17:906:4a14:: with SMTP id w20mr7967736eju.192.1610689358315; Thu, 14 Jan 2021 21:42:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1610689358; cv=none; d=google.com; s=arc-20160816; b=IVHmSKI+ZNOHJYAWvfT5PQ6GLKLEBtbXl5MR30PB7P6dHv7qm2JaP+Jf0cbpWZGGDN ZW855C2kYnPx/TyoA3d92ByvTlgMPze5HeuHMntoJOBjuxKzTbWo7XcgtOvPuQnp2IbU +zVDy80zUQ783YG7+Yg6fdEZe7bUAtKf6kDhcRIDQzzIZ+JblgxFP18GHz4UYViH0aLX piDzJZdb8NH3pZWbo3kJF+7jjgnQzKpAGA8mGdqj+S36KE2pwzvcfLqMg0uMJ3Dr4TVc /MRD73s9eUusfeh0+PJu1EvP1gFFMS5JVwXn1KMzdDw4k1Hm9z0o/ss5qkbMbb9dKpTO 8hnw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=+gQLInJtarBaVsca/9Zi73auZk42R13LChAml9yBQjs=; b=Sxz3wRW65O3lj74xtDP2Qd5WLFth3blsrHOMuZOK+itR2rFPBNaXGUixFK7ehR8uXn ybtPul6sOq1rmIUFvxuEFghY06offxuM9mmioCQUukrx0ZTI5i7Hcz/4W+i3OTWO+YMb CLZHUfD2TTapIi74dt7zWx5VmUvaG8tN/4hc4v4ZLlAwSyV60CK+8JsIzpKpYcVKiXrc sCx4jErtCrRFfwJti3Y7r80I0XhV6Wp+UML1+b8qoMn3lsMQl9FlpwIL9lpndenVu5zx bUN4bs/AGyzCX6q7acdrYfMLbDZ99DybL2mMkvxW37kutzIPN1wbG2yIW+rJKJQIgJyw a1Bw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=bawylaeN; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u26si1934341ejg.642.2021.01.14.21.42.14; Thu, 14 Jan 2021 21:42:38 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=bawylaeN; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732129AbhAOCbT (ORCPT + 99 others); Thu, 14 Jan 2021 21:31:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51112 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732126AbhAOCbS (ORCPT ); Thu, 14 Jan 2021 21:31:18 -0500 Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90BF2C0613D6 for ; Thu, 14 Jan 2021 18:30:38 -0800 (PST) Received: by mail-pf1-x432.google.com with SMTP id a188so4541450pfa.11 for ; Thu, 14 Jan 2021 18:30:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+gQLInJtarBaVsca/9Zi73auZk42R13LChAml9yBQjs=; b=bawylaeN2YBTxilkUC4ATdKnIxiD9prdGPx1BaJMsUjsdCP6W00yK17kwIh8imypx7 3UNKuWECX+4pqybhB8a+rTtqIi1NFHJCA1Mth5/Edrs31TNdGQHFPIFZ6/UOvby98rEu TcdVhIeZV5ScWeBpQ6dNiML//6k6THPwgBdW0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+gQLInJtarBaVsca/9Zi73auZk42R13LChAml9yBQjs=; b=DAcpW6FitmFBADFoEZIV25hMrngyYS/N0fI9ZpvQDCWUfWC2iBr3Ft0a4B4teGxcWs dYmNkPHPdT8iTTg5M13nCXw/32nJlqt4Ldq8gyOyu6Ml3lwpMaBsSK6uaiF6fB9eT/73 ozFOKbhnwtUsUHcHGXBDK4hl1dNqp9OVAdcmjMnyDDFBwlzMfc0zAzNfdo4ycpOXtoF0 FfiCRcnDqM5mQsDhlsP2kTcH3z/WwGlFraQQYoSGv53T9xqIWhMDIpM+He8n3m+TeXrO gbGcsNPUJuLbILMkiuYgRvVa4MDJxC6BxykxaG5/STOgJX/0iW3fQDoICN3LgIMZz8x2 ewNA== X-Gm-Message-State: AOAM532bVDcgPGVUjmjd7yG9VskyXbew7oMEvkY4KsmHqkaM9PBt92sf K8myb3nFSHsNeM7cIHsCzWRsCu3cdVvwqA== X-Received: by 2002:a63:eb0c:: with SMTP id t12mr10496634pgh.7.1610677837917; Thu, 14 Jan 2021 18:30:37 -0800 (PST) Received: from philipchen.mtv.corp.google.com ([2620:15c:202:201:a6ae:11ff:fe11:fd59]) by smtp.gmail.com with ESMTPSA id b11sm6046429pjg.27.2021.01.14.18.30.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Jan 2021 18:30:37 -0800 (PST) From: Philip Chen To: LKML , dmitry.torokhov@gmail.com Cc: swboyd@chromium.org, dianders@chromium.org, Philip Chen , Benson Leung , Enric Balletbo i Serra , Guenter Roeck , Lee Jones , linux-input@vger.kernel.org Subject: [PATCH v6 2/2] Input: cros-ec-keyb - Expose function row physical map to userspace Date: Thu, 14 Jan 2021 18:30:31 -0800 Message-Id: <20210114183010.v6.2.I2c219435b0d06a84411ae35c3154e123c52fcd7d@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210114183010.v6.1.I025fb861cd5fa0ef5286b7dce514728e9df7ae74@changeid> References: <20210114183010.v6.1.I025fb861cd5fa0ef5286b7dce514728e9df7ae74@changeid> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- Changes in v6: - add to Documentation/ABI - update cros_ec_keyb_register_matrix() to improve readability Changes in v5: - change the data type for a few local variables - update function_row_physmap_show() and cros_ec_keyb_register_matrix() to improve readability/efficiency Changes in v4: - replace sysfs_create_group() with devm_device_add_group() - remove an unused member in struct cros_ec_keyb Changes in v3: - parse `function-row-physmap` from DT earlier, when we probe cros_ec_keyb, and then store the extracted info in struct cros_ec_keyb. Changes in v2: - create function-row-physmap file in sysfs by parsing `function-row-physmap` property from DT - assume the device already has a correct keymap to reflect the custom top-row keys (if they exist) .../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 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 0000000000000..c7afc2328045c --- /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 b379ed7628781..38457d9641bdf 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); -- 2.26.2