Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp681743pxu; Thu, 7 Jan 2021 15:44:09 -0800 (PST) X-Google-Smtp-Source: ABdhPJzr9NGSNoJYGU0qTwYH2e9MtpjT2cVGqZgLwsd/rjpFGdPrZ3Z1SA58znch0FylqkpK3leD X-Received: by 2002:a17:906:5285:: with SMTP id c5mr895349ejm.17.1610063049642; Thu, 07 Jan 2021 15:44:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1610063049; cv=none; d=google.com; s=arc-20160816; b=D68cznlMeXAcuFKjOZW/tX6/DvCeXtW8uIcPVygciPvNv/CbsyHCVAiDj5BCvivR2/ HMmtr/HDpsvPIQyCo3EKHLVt+1426BOU+qQeLpOqkkFrcxsuG+NYmwrer1PGnJcgUKms gLxf6sl6H+4qmhZ4QnKvQisC9+trv6SUeJHxPvGlkD4WzOFjWbe7rB7FfLvtshlQjMaS /iRyO8WbzjRw3HiNl3WLQhq6DoP0IMRejF+QKX4CL/8c3Oepqp52peRmxRHlItHXaYgg 0K779e8+t4WUPYCNekGG+ZIBFfDy7kJHhvcH3zcAFn5Jba5Ce+KbVVoEt6fs5xkl8zYs BqeQ== 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=6DrvTW/D8DeEAOBHByFNZGq7CUGM4Fwgn7nIcrSh7JA=; b=AAIKw4JUZb0AVSsobFkDaBAA0/1xOodcMAz+CGslMjQlGpNh81ZIxddo1GJEDySykF xIlthSabUcg1rWzRMEcUWI7HrSFOJPoiosswUjp+5wMfgC5Y1ygAPV14EHQAYpDqyr6Y +u1TpdhMHszfBuBBxrRIlI45f91yDP1GY3/orBLmHfYd7V4SHce1K1aAlfbAQ64PJGfz KdjbTvzaKHE10UKbpBHy9NKVHFnwfNWq0lRQBcvCqbCki8dTgI1aUb85Fvot2q6hvjQO 8qWlYuYeEgsGUleg+x6G5bo5AIIC8Y4Gkix8ogEXb0TKWH+evl48VWFC0uoi43RWdIUa pKng== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=QMD4zbTE; 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 e23si2947142edu.203.2021.01.07.15.43.45; Thu, 07 Jan 2021 15:44:09 -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=QMD4zbTE; 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 S1729254AbhAGXnD (ORCPT + 99 others); Thu, 7 Jan 2021 18:43:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58558 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728691AbhAGXnD (ORCPT ); Thu, 7 Jan 2021 18:43:03 -0500 Received: from mail-pl1-x62e.google.com (mail-pl1-x62e.google.com [IPv6:2607:f8b0:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7CD9C0612FD for ; Thu, 7 Jan 2021 15:42:16 -0800 (PST) Received: by mail-pl1-x62e.google.com with SMTP id x18so4703756pln.6 for ; Thu, 07 Jan 2021 15:42:16 -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=6DrvTW/D8DeEAOBHByFNZGq7CUGM4Fwgn7nIcrSh7JA=; b=QMD4zbTEXpRoQxtNZrxO2CjlOSwg2aEsM1vb5Ds59KnlTR0gx9zYY7DUI3zPhetfVa zj/rJxe0GmP6AYq1SeNdQzStp/cx2akXqRVvikt6/GtL32AZuek8Of8CgJ47LUtH6LjX sAxYFIOW7fHlU4c0tWS6xv0hnqKmQVxDYb9Bg= 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=6DrvTW/D8DeEAOBHByFNZGq7CUGM4Fwgn7nIcrSh7JA=; b=N+/z7jL6mGj1yxdNOW/QxKWqC/bX1Z4UUijfEVCG8PyNKVYAK6mLOwnpwKPUdwS8LD fHzs56krcBJ/cGWu1tKUbP+258hAOERWwnpG+xavOobGEwlS0zuHirKVRCPPK0HFMU0E wfeeDCyq15AaGFlfMRiXkKJJqFBU+RtcLueUrPYARkwfqwfqoWWEmvc7eXYy5YCaZBd0 LPM14IYxcYH5Lq5krBaWCehNGJqQ0KOZ97+3NcxbU1pDogfP7e7i2ESx+sk916VdMIS3 eAyp8J95WP1spT6VqtZwh1fTUAyl998ul9/8JF8Hn8p760qLly5m3QPKZ/RSH92PGVDo SmsA== X-Gm-Message-State: AOAM533HCOWlhAlM89AP/PBJw0TVosJPeYabxNBKwQ/yg7PrMiSnDB6K 2Hj5J8vbgXDgiGo6erkUUmUoy5dLLXr4Ow== X-Received: by 2002:a17:90a:d308:: with SMTP id p8mr865175pju.110.1610062936305; Thu, 07 Jan 2021 15:42:16 -0800 (PST) Received: from philipchen.mtv.corp.google.com ([2620:15c:202:201:a6ae:11ff:fe11:fd59]) by smtp.gmail.com with ESMTPSA id h8sm7376487pjc.2.2021.01.07.15.42.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Jan 2021 15:42:15 -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 v4 2/2] Input: cros-ec-keyb - Expose function row physical map to userspace Date: Thu, 7 Jan 2021 15:42:09 -0800 Message-Id: <20210107154200.v4.2.Ibe7d7d53c5b4fe72c60de90111ff763b53f38dbb@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210107154200.v4.1.I025fb861cd5fa0ef5286b7dce514728e9df7ae74@changeid> References: <20210107154200.v4.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. This patch enhances 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 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) drivers/input/keyboard/cros_ec_keyb.c | 78 +++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index b379ed7628781..75d1cb29734ce 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]; + u8 num_function_row_keys; }; /** @@ -527,6 +535,8 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) struct input_dev *idev; const char *phys; int err; + u32 top_row_key_pos[MAX_NUM_TOP_ROW_KEYS] = {0}; + u8 i; err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols); if (err) @@ -578,6 +588,22 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) ckdev->idev = idev; cros_ec_keyb_compute_valid_keys(ckdev); + if (of_property_read_variable_u32_array(dev->of_node, + "function-row-physmap", + top_row_key_pos, + 0, + MAX_NUM_TOP_ROW_KEYS) > 0) { + for (i = 0; i < MAX_NUM_TOP_ROW_KEYS; i++) { + if (!top_row_key_pos[i]) + break; + ckdev->function_row_physmap[i] = MATRIX_SCAN_CODE( + KEY_ROW(top_row_key_pos[i]), + KEY_COL(top_row_key_pos[i]), + ckdev->row_shift); + } + ckdev->num_function_row_keys = i; + } + err = input_register_device(ckdev->idev); if (err) { dev_err(dev, "cannot register input device\n"); @@ -587,6 +613,52 @@ 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; + u8 i; + struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); + + if (!ckdev->num_function_row_keys) + return 0; + + for (i = 0; i < ckdev->num_function_row_keys; i++) + size += scnprintf(buf + size, PAGE_SIZE - size, "%02X ", + ckdev->function_row_physmap[i]); + 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 +689,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