From patchwork Mon Mar 20 00:22:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 9632947 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 7B9F960249 for ; Mon, 20 Mar 2017 00:24:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6EC1427FAC for ; Mon, 20 Mar 2017 00:24:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 63A0E2807E; Mon, 20 Mar 2017 00:24:11 +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.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham 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 CF6BD27FAC for ; Mon, 20 Mar 2017 00:24:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752751AbdCTAYJ (ORCPT ); Sun, 19 Mar 2017 20:24:09 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:35447 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752744AbdCTAWl (ORCPT ); Sun, 19 Mar 2017 20:22:41 -0400 Received: by mail-pg0-f67.google.com with SMTP id g2so17178877pge.2; Sun, 19 Mar 2017 17:22:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=r+J4/wE1zTbWRenmWHKScSKXd/BcteJOLvWN2/ogGyA=; b=CuJlEYLIsP0zQ+ETyz/6zIV1JTqCVwCUxvUlG/F9gad54oL5My4ux85+e4DkxC71fH 780hr7bJSRmNsi6Pi3jsfcx7HlyXVJkifEbyvu4L3fL8m1zecvU2cLkXleAQ3eM93uro JFhgZAFmhz7QjYWXpXRExjJbgEp0B8UCGfZMSeoHR8+4a8BznqZs93aWjIysorYVnk/s GmperVYo8XKW/o24isccjiXmk59gFYSk6ovbOTm1vpVCH5X2JIxnqc4519hDDwPPZywc kU/c8IkahvjPUfC0g1KnRLnafT3u70AI0QyLxSqi4rvXOBy7wgTQgv6g95Yj8AIksIIl u3bQ== 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; bh=r+J4/wE1zTbWRenmWHKScSKXd/BcteJOLvWN2/ogGyA=; b=T+oaaB7ulxyHeH7WznOGjtDHQNCA/XK96g0/I0JTSYio07kVwIYVDpCP4Y2h1NYEVw IwR0rl4UqfPQOeWmYLOQUox1SfPCw7cyO88D0Q+KvHU0CUsIjMIzh4Uwtc9vieOqBvoH //91PXwt6m0oCBfSimS4Ki//v6xX/Ikc4qHpVd0nl4LTWFKTWM36FRQmpAnf05H4k/O/ QRh8iFNgXM0/otWu5HDipI9tu9f5ZYzn5soc9oVMlvJpEH3A2tixCwRP+6sWm4DhICR7 5p9Sf6fLQcQJLW0EQcgvbstDiaIbLhoHkyj54j7jFDxsmUgLK7HCMoq2kI0jZY+DRcFD Yk1A== X-Gm-Message-State: AFeK/H19+JVRS/TjKs8u5ucvwGTe4xEK+CXoyqfyJpgaHqBvaRZWaY9yg2JqbKlz2BS5Hw== X-Received: by 10.99.114.70 with SMTP id c6mr29049722pgn.163.1489969359518; Sun, 19 Mar 2017 17:22:39 -0700 (PDT) Received: from dtor-ws.mtv.corp.google.com ([172.22.152.34]) by smtp.gmail.com with ESMTPSA id n185sm29134460pga.9.2017.03.19.17.22.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 19 Mar 2017 17:22:37 -0700 (PDT) From: Dmitry Torokhov To: Benjamin Tissoires Cc: Andrew Duggan , linux-kernel@vger.kernel.org, linux-input@vger.kernel.org Subject: [PATCH v3 5/9] Input: psmouse - introduce notion of SMBus companions Date: Sun, 19 Mar 2017 17:22:27 -0700 Message-Id: <20170320002231.31152-6-dmitry.torokhov@gmail.com> X-Mailer: git-send-email 2.12.0.367.g23dc2f6d3c-goog In-Reply-To: <20170320002231.31152-1-dmitry.torokhov@gmail.com> References: <20170320002231.31152-1-dmitry.torokhov@gmail.com> 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 Prepare PS/2 mouse drivers to work with devices that are accessible both via PS/2 and SMBus, which provides higher bandwidth, and thus suits better for modern multi-touch devices. We expect that SMBus drivers will take control over the device, so when we detect SMBus "protocol" we forego registering input device, or enabling PS/2 device reports (as it usually makes device unresponsive to access over SMBus). Reviewed-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 100 +++++++++++++++++++++++++------------ drivers/input/mouse/psmouse.h | 1 + 2 files changed, 68 insertions(+), 33 deletions(-) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index bb5d164849ea..40f09ce84f14 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1424,9 +1424,8 @@ static void psmouse_cleanup(struct serio *serio) */ static void psmouse_disconnect(struct serio *serio) { - struct psmouse *psmouse, *parent = NULL; - - psmouse = serio_get_drvdata(serio); + struct psmouse *psmouse = serio_get_drvdata(serio); + struct psmouse *parent = NULL; sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group); @@ -1454,7 +1453,10 @@ static void psmouse_disconnect(struct serio *serio) serio_close(serio); serio_set_drvdata(serio, NULL); - input_unregister_device(psmouse->dev); + + if (psmouse->dev) + input_unregister_device(psmouse->dev); + kfree(psmouse); if (parent) @@ -1575,12 +1577,18 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse_switch_protocol(psmouse, NULL); - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - psmouse_initialize(psmouse); + if (!psmouse->protocol->smbus_companion) { + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + psmouse_initialize(psmouse); - error = input_register_device(psmouse->dev); - if (error) - goto err_protocol_disconnect; + error = input_register_device(input_dev); + if (error) + goto err_protocol_disconnect; + } else { + /* Smbus companion will be reporting events, not us. */ + input_free_device(input_dev); + psmouse->dev = input_dev = NULL; + } if (parent && parent->pt_activate) parent->pt_activate(parent); @@ -1589,7 +1597,12 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) if (error) goto err_pt_deactivate; - psmouse_activate(psmouse); + /* + * PS/2 devices having SMBus companions should stay disabled + * on PS/2 side, in order to have SMBus part operable. + */ + if (!psmouse->protocol->smbus_companion) + psmouse_activate(psmouse); out: /* If this is a pass-through port the parent needs to be re-activated */ @@ -1602,8 +1615,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) err_pt_deactivate: if (parent && parent->pt_deactivate) parent->pt_deactivate(parent); - input_unregister_device(psmouse->dev); - input_dev = NULL; /* so we don't try to free it below */ + if (input_dev) { + input_unregister_device(input_dev); + input_dev = NULL; /* so we don't try to free it below */ + } err_protocol_disconnect: if (psmouse->disconnect) psmouse->disconnect(psmouse); @@ -1665,14 +1680,21 @@ static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect) * OK, the device type (and capabilities) match the old one, * we can continue using it, complete initialization */ - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - - psmouse_initialize(psmouse); + if (!psmouse->protocol->smbus_companion) { + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + psmouse_initialize(psmouse); + } if (parent && parent->pt_activate) parent->pt_activate(parent); - psmouse_activate(psmouse); + /* + * PS/2 devices having SMBus companions should stay disabled + * on PS/2 side, in order to have SMBus part operable. + */ + if (!psmouse->protocol->smbus_companion) + psmouse_activate(psmouse); + rc = 0; out: @@ -1732,9 +1754,11 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de { struct serio *serio = to_serio_port(dev); struct psmouse_attribute *attr = to_psmouse_attr(devattr); - struct psmouse *psmouse; + struct psmouse *psmouse = serio_get_drvdata(serio); - psmouse = serio_get_drvdata(serio); + if (psmouse->protocol->smbus_companion && + devattr != &psmouse_attr_protocol.dattr) + return -ENOENT; return attr->show(psmouse, attr->data, buf); } @@ -1753,6 +1777,12 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev psmouse = serio_get_drvdata(serio); + if (psmouse->protocol->smbus_companion && + devattr != &psmouse_attr_protocol.dattr) { + retval = -ENOENT; + goto out_unlock; + } + if (attr->protect) { if (psmouse->state == PSMOUSE_IGNORE) { retval = -ENODEV; @@ -1764,13 +1794,14 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev psmouse_deactivate(parent); } - psmouse_deactivate(psmouse); + if (!psmouse->protocol->smbus_companion) + psmouse_deactivate(psmouse); } retval = attr->set(psmouse, attr->data, buf, count); if (attr->protect) { - if (retval != -ENODEV) + if (retval != -ENODEV && !psmouse->protocol->smbus_companion) psmouse_activate(psmouse); if (parent) @@ -1879,23 +1910,26 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co psmouse_initialize(psmouse); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - error = input_register_device(psmouse->dev); - if (error) { - if (psmouse->disconnect) - psmouse->disconnect(psmouse); + if (!psmouse->protocol->smbus_companion) { + error = input_register_device(psmouse->dev); + if (error) { + if (psmouse->disconnect) + psmouse->disconnect(psmouse); - psmouse_set_state(psmouse, PSMOUSE_IGNORE); - input_free_device(new_dev); - psmouse->dev = old_dev; - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - psmouse_switch_protocol(psmouse, old_proto); - psmouse_initialize(psmouse); - psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + psmouse_set_state(psmouse, PSMOUSE_IGNORE); + input_free_device(new_dev); + psmouse->dev = old_dev; + psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); + psmouse_switch_protocol(psmouse, old_proto); + psmouse_initialize(psmouse); + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - return error; + return error; + } } - input_unregister_device(old_dev); + if (old_dev) + input_unregister_device(old_dev); if (parent && parent->pt_activate) parent->pt_activate(parent); diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 36bd42179456..e853dee05e79 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -76,6 +76,7 @@ struct psmouse_protocol { bool maxproto; bool ignore_parity; /* Protocol should ignore parity errors from KBC */ bool try_passthru; /* Try protocol also on passthrough ports */ + bool smbus_companion; /* "Protocol" is a stub, device is on SMBus */ const char *name; const char *alias; int (*detect)(struct psmouse *, bool);