From patchwork Thu Aug 18 09:24:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Tissoires X-Patchwork-Id: 9287145 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3B3E66086A for ; Thu, 18 Aug 2016 09:42:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2AA6D29035 for ; Thu, 18 Aug 2016 09:42:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0D05028B01; Thu, 18 Aug 2016 09:42:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8C17A28FE6 for ; Thu, 18 Aug 2016 09:42:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753943AbcHRJlq (ORCPT ); Thu, 18 Aug 2016 05:41:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43142 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753538AbcHRJlo (ORCPT ); Thu, 18 Aug 2016 05:41:44 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4D710C0567A0; Thu, 18 Aug 2016 09:25:11 +0000 (UTC) Received: from plouf.banquise.eu.com (ovpn-116-62.ams2.redhat.com [10.36.116.62]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u7I9OpXO026888; Thu, 18 Aug 2016 05:25:09 -0400 From: Benjamin Tissoires To: Dmitry Torokhov , Lyude Paul , Andrew Duggan , Christopher Heiny , Dennis Wassenberg Cc: Peter Hutterer , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org Subject: [PATCH 07/11] Input: synaptics-rmi4 - f30/f03: Forward mechanical buttons on buttonpads to PS/2 guest Date: Thu, 18 Aug 2016 11:24:45 +0200 Message-Id: <1471512289-10648-8-git-send-email-benjamin.tissoires@redhat.com> In-Reply-To: <1471512289-10648-1-git-send-email-benjamin.tissoires@redhat.com> References: <1471512289-10648-1-git-send-email-benjamin.tissoires@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 18 Aug 2016 09:25:11 +0000 (UTC) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Lyude Paul On the latest series of ThinkPads, the button events for the TrackPoint are reported through the touchpad itself as opposed to the TrackPoint device. In order to report these buttons properly, we need to forward them to the TrackPoint device and send the button presses/releases through there instead. Signed-off-by: Lyude Paul Signed-off-by: Benjamin Tissoires --- drivers/input/rmi4/rmi_driver.h | 13 +++++++++ drivers/input/rmi4/rmi_f03.c | 28 ++++++++++++++++++ drivers/input/rmi4/rmi_f30.c | 64 +++++++++++++++++++++++++++++++++++------ 3 files changed, 97 insertions(+), 8 deletions(-) diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h index e4be773..a0b1978 100644 --- a/drivers/input/rmi4/rmi_driver.h +++ b/drivers/input/rmi4/rmi_driver.h @@ -99,6 +99,19 @@ struct rmi_function *rmi_find_function(struct rmi_device *rmi_dev, u8 number); char *rmi_f01_get_product_ID(struct rmi_function *fn); +#ifdef CONFIG_RMI4_F03 +int rmi_f03_overwrite_button(struct rmi_function *fn, unsigned int button, + int value); +void rmi_f03_commit_buttons(struct rmi_function *fn); +#else +static inline int rmi_f03_overwrite_button(struct rmi_function *fn, + unsigned int button, int value) +{ + return 0; +} +static inline void rmi_f03_commit_buttons(struct rmi_function *fn) {} +#endif + extern struct rmi_function_handler rmi_f01_handler; extern struct rmi_function_handler rmi_f03_handler; extern struct rmi_function_handler rmi_f11_handler; diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c index daae1c95..535f426 100644 --- a/drivers/input/rmi4/rmi_f03.c +++ b/drivers/input/rmi4/rmi_f03.c @@ -37,6 +37,34 @@ struct f03_data { u8 rx_queue_length; }; +int rmi_f03_overwrite_button(struct rmi_function *fn, unsigned int button, + int value) +{ + struct f03_data *f03 = dev_get_drvdata(&fn->dev); + unsigned int bit = BIT(button); + + if (button > 2) + return -EINVAL; + + if (value) + f03->overwrite_buttons |= bit; + else + f03->overwrite_buttons &= ~bit; + + return 0; +} + +void rmi_f03_commit_buttons(struct rmi_function *fn) +{ + struct f03_data *f03 = dev_get_drvdata(&fn->dev); + int i; + + f03->serio->extra_byte = f03->overwrite_buttons; + + for (i = 0; i < 3; i++) + serio_interrupt(f03->serio, 0x00, 0x00); +} + static int rmi_f03_pt_write(struct serio *id, unsigned char val) { struct f03_data *f03 = id->port_data; diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c index 7990bb0..14e3221 100644 --- a/drivers/input/rmi4/rmi_f30.c +++ b/drivers/input/rmi4/rmi_f30.c @@ -74,8 +74,11 @@ struct f30_data { u8 data_regs[RMI_F30_CTRL_MAX_BYTES]; u16 *gpioled_key_map; + u16 *gpio_passthrough_key_map; struct input_dev *input; + bool trackstick_buttons; + struct rmi_function *f03; }; static int rmi_f30_read_control_parameters(struct rmi_function *fn, @@ -108,6 +111,13 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits) if (!f30->input) return 0; + if (f30->trackstick_buttons && !f30->f03) { + f30->f03 = rmi_find_function(rmi_dev, 3); + + if (!f30->f03) + return -EBUSY; + } + /* Read the gpi led data. */ if (rmi_dev->xport->attn_data) { memcpy(f30->data_regs, rmi_dev->xport->attn_data, @@ -128,23 +138,29 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits) for (reg_num = 0; reg_num < f30->register_count; ++reg_num) { for (i = 0; gpiled < f30->gpioled_count && i < 8; ++i, ++gpiled) { - if (f30->gpioled_key_map[gpiled] != 0) { - /* buttons have pull up resistors */ - value = (((f30->data_regs[reg_num] >> i) & 0x01) - == 0); + /* buttons have pull up resistors */ + value = (((f30->data_regs[reg_num] >> i) & 0x01) == 0); + if (f30->gpioled_key_map[gpiled] != 0) { rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: call input report key (0x%04x) value (0x%02x)", __func__, f30->gpioled_key_map[gpiled], value); + input_report_key(f30->input, f30->gpioled_key_map[gpiled], value); + } else if (f30->gpio_passthrough_key_map[gpiled]) { + rmi_f03_overwrite_button(f30->f03, + f30->gpio_passthrough_key_map[gpiled] - BTN_LEFT, + value); } - } } + if (f30->trackstick_buttons) + rmi_f03_commit_buttons(f30->f03); + return 0; } @@ -242,10 +258,10 @@ static inline int rmi_f30_initialize(struct rmi_function *fn) int retval = 0; int control_address; int i; - int button; + int button, extra_button; u8 buf[RMI_F30_QUERY_SIZE]; u8 *ctrl_reg; - u8 *map_memory; + u8 *map_memory, *pt_memory; f30 = devm_kzalloc(&fn->dev, sizeof(struct f30_data), GFP_KERNEL); @@ -343,15 +359,47 @@ static inline int rmi_f30_initialize(struct rmi_function *fn) map_memory = devm_kzalloc(&fn->dev, (f30->gpioled_count * (sizeof(u16))), GFP_KERNEL); - if (!map_memory) { + pt_memory = devm_kzalloc(&fn->dev, + (f30->gpioled_count * (sizeof(u16))), + GFP_KERNEL); + if (!map_memory || !pt_memory) { dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n"); return -ENOMEM; } f30->gpioled_key_map = (u16 *)map_memory; + f30->gpio_passthrough_key_map = (u16 *)pt_memory; pdata = rmi_get_platform_data(rmi_dev); if (pdata && f30->has_gpio) { + /* + * For touchpads the buttons are mapped as: + * - bit 0 = Left, bit 1 = right, bit 2 = middle / clickbutton + * - 3, 4, 5 are extended buttons and + * - 6 and 7 are other sorts of GPIOs + */ + button = BTN_LEFT; + extra_button = BTN_LEFT; + for (i = 0; i < f30->gpioled_count - 2 && i < 3; i++) { + if (rmi_f30_is_valid_button(i, f30->ctrl)) + f30->gpioled_key_map[i] = button++; + } + + f30->trackstick_buttons = pdata && + pdata->f30_data.trackstick_buttons; + + if (f30->trackstick_buttons) { + for (i = 3; i < f30->gpioled_count - 2; i++) { + if (rmi_f30_is_valid_button(i, f30->ctrl)) + f30->gpio_passthrough_key_map[i] = extra_button++; + } + } else { + for (i = 3; i < f30->gpioled_count - 2; i++) { + if (rmi_f30_is_valid_button(i, f30->ctrl)) + f30->gpioled_key_map[i] = button++; + } + } + } else if (f30->has_gpio) { button = BTN_LEFT; for (i = 0; i < f30->gpioled_count; i++) { if (rmi_f30_is_valid_button(i, f30->ctrl)) {