* Re: [PATCH] input: remove at32psif
From: Hans-Christian Noren Egtvedt @ 2018-01-19 7:25 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Corentin Labbe, linux-input, linux-kernel
In-Reply-To: <20180118195543.wn6tl57zd2jg3on4@dtor-ws>
Around Thu 18 Jan 2018 11:55:43 -0800 or thereabout, Dmitry Torokhov wrote:
> On Thu, Jan 18, 2018 at 08:48:24PM +0100, Corentin Labbe wrote:
>> On Thu, Jan 18, 2018 at 11:20:17AM -0800, Dmitry Torokhov wrote:
>> > On Thu, Jan 18, 2018 at 07:58:11PM +0100, Corentin Labbe wrote:
>> > > Since AVR32 arch is gone, at32psif driver is useless.
>> > > This patch remove it.
>> > >
>> > > Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
>> >
>> > Applied, thank you.
>> >
>> > What about:
>> >
>> > config TOUCHSCREEN_WM97XX_ATMEL
>> > tristate "WM97xx Atmel accelerated touch"
>> > depends on TOUCHSCREEN_WM97XX && AVR32
>> >
>> > ?
>> >
>>
>> It was my second target BUT the code content reference to AT91 (wm97xx continuous touch driver for Atmel AT91 and AVR32) so perhaps it could be keeped.
>>
>> But someone need to test it.
>
> "&& AVR32" means that nobody ever ran it on AT91 though...
> Hans-Christian, any ideas?
I never tested accelerating WM97xx codecs on AT91, hence it is AVR32 only. It
can be removed.
Thanks for cleaning (-:
--
Best regards,
Hans-Christian Noren Egtvedt
^ permalink raw reply
* [PATCH] input: touchscreen: remove atmel-wm97xx
From: Corentin Labbe @ 2018-01-19 8:17 UTC (permalink / raw)
To: alexandre.belloni, dmitry.torokhov, nicolas.ferre, egtvedt
Cc: linux-arm-kernel, linux-input, linux-kernel, Corentin Labbe
Since AVR32 arch is gone, atmel-wm97xx driver is useless.
Remove it.
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
drivers/input/touchscreen/Kconfig | 15 --
drivers/input/touchscreen/Makefile | 1 -
drivers/input/touchscreen/atmel-wm97xx.c | 436 -------------------------------
3 files changed, 452 deletions(-)
delete mode 100644 drivers/input/touchscreen/atmel-wm97xx.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 38a226f9fcbd..4f15496fec8b 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -795,21 +795,6 @@ config TOUCHSCREEN_WM9713
Say Y here to enable support for the Wolfson Microelectronics
WM9713 touchscreen controller.
-config TOUCHSCREEN_WM97XX_ATMEL
- tristate "WM97xx Atmel accelerated touch"
- depends on TOUCHSCREEN_WM97XX && AVR32
- help
- Say Y here for support for streaming mode with WM97xx touchscreens
- on Atmel AT91 or AVR32 systems with an AC97C module.
-
- Be aware that this will use channel B in the controller for
- streaming data, this must not conflict with other AC97C drivers.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the module will
- be called atmel-wm97xx.
-
config TOUCHSCREEN_WM97XX_MAINSTONE
tristate "WM97xx Mainstone/Palm accelerated touch"
depends on TOUCHSCREEN_WM97XX && ARCH_PXA
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index d2a2b3b7af27..dddae7973436 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -97,7 +97,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
-obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c
deleted file mode 100644
index 9140a43cfe20..000000000000
--- a/drivers/input/touchscreen/atmel-wm97xx.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Atmel AT91 and AVR32 continuous touch screen driver for Wolfson WM97xx AC97
- * codecs.
- *
- * Copyright (C) 2008 - 2009 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/wm97xx.h>
-#include <linux/timer.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#define AC97C_ICA 0x10
-#define AC97C_CBRHR 0x30
-#define AC97C_CBSR 0x38
-#define AC97C_CBMR 0x3c
-#define AC97C_IER 0x54
-#define AC97C_IDR 0x58
-
-#define AC97C_RXRDY (1 << 4)
-#define AC97C_OVRUN (1 << 5)
-
-#define AC97C_CMR_SIZE_20 (0 << 16)
-#define AC97C_CMR_SIZE_18 (1 << 16)
-#define AC97C_CMR_SIZE_16 (2 << 16)
-#define AC97C_CMR_SIZE_10 (3 << 16)
-#define AC97C_CMR_CEM_LITTLE (1 << 18)
-#define AC97C_CMR_CEM_BIG (0 << 18)
-#define AC97C_CMR_CENA (1 << 21)
-
-#define AC97C_INT_CBEVT (1 << 4)
-
-#define AC97C_SR_CAEVT (1 << 3)
-
-#define AC97C_CH_MASK(slot) \
- (0x7 << (3 * (slot - 3)))
-#define AC97C_CH_ASSIGN(slot, channel) \
- (AC97C_CHANNEL_##channel << (3 * (slot - 3)))
-#define AC97C_CHANNEL_NONE 0x0
-#define AC97C_CHANNEL_B 0x2
-
-#define ac97c_writel(chip, reg, val) \
- __raw_writel((val), (chip)->regs + AC97C_##reg)
-#define ac97c_readl(chip, reg) \
- __raw_readl((chip)->regs + AC97C_##reg)
-
-#ifdef CONFIG_CPU_AT32AP700X
-#define ATMEL_WM97XX_AC97C_IOMEM (0xfff02800)
-#define ATMEL_WM97XX_AC97C_IRQ (29)
-#define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */
-#else
-#error Unknown CPU, this driver only supports AT32AP700X CPUs.
-#endif
-
-struct continuous {
- u16 id; /* codec id */
- u8 code; /* continuous code */
- u8 reads; /* number of coord reads per read cycle */
- u32 speed; /* number of coords per second */
-};
-
-#define WM_READS(sp) ((sp / HZ) + 1)
-
-static const struct continuous cinfo[] = {
- {WM9705_ID2, 0, WM_READS(94), 94},
- {WM9705_ID2, 1, WM_READS(188), 188},
- {WM9705_ID2, 2, WM_READS(375), 375},
- {WM9705_ID2, 3, WM_READS(750), 750},
- {WM9712_ID2, 0, WM_READS(94), 94},
- {WM9712_ID2, 1, WM_READS(188), 188},
- {WM9712_ID2, 2, WM_READS(375), 375},
- {WM9712_ID2, 3, WM_READS(750), 750},
- {WM9713_ID2, 0, WM_READS(94), 94},
- {WM9713_ID2, 1, WM_READS(120), 120},
- {WM9713_ID2, 2, WM_READS(154), 154},
- {WM9713_ID2, 3, WM_READS(188), 188},
-};
-
-/* Continuous speed index. */
-static int sp_idx;
-
-/*
- * Pen sampling frequency (Hz) in continuous mode.
- */
-static int cont_rate = 188;
-module_param(cont_rate, int, 0);
-MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
-
-/*
- * Pen down detection.
- *
- * This driver can either poll or use an interrupt to indicate a pen down
- * event. If the irq request fails then it will fall back to polling mode.
- */
-static int pen_int = 1;
-module_param(pen_int, int, 0);
-MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
-
-/*
- * Pressure readback.
- *
- * Set to 1 to read back pen down pressure.
- */
-static int pressure;
-module_param(pressure, int, 0);
-MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
-
-/*
- * AC97 touch data slot.
- *
- * Touch screen readback data ac97 slot.
- */
-static int ac97_touch_slot = 5;
-module_param(ac97_touch_slot, int, 0);
-MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
-
-/*
- * GPIO line number.
- *
- * Set to GPIO number where the signal from the WM97xx device is hooked up.
- */
-static int atmel_gpio_line = ATMEL_WM97XX_GPIO_DEFAULT;
-module_param(atmel_gpio_line, int, 0);
-MODULE_PARM_DESC(atmel_gpio_line, "GPIO line number connected to WM97xx");
-
-struct atmel_wm97xx {
- struct wm97xx *wm;
- struct timer_list pen_timer;
- void __iomem *regs;
- unsigned long ac97c_irq;
- unsigned long gpio_pen;
- unsigned long gpio_irq;
- unsigned short x;
- unsigned short y;
-};
-
-static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id)
-{
- struct atmel_wm97xx *atmel_wm97xx = dev_id;
- struct wm97xx *wm = atmel_wm97xx->wm;
- int status = ac97c_readl(atmel_wm97xx, CBSR);
- irqreturn_t retval = IRQ_NONE;
-
- if (status & AC97C_OVRUN) {
- dev_dbg(&wm->touch_dev->dev, "AC97C overrun\n");
- ac97c_readl(atmel_wm97xx, CBRHR);
- retval = IRQ_HANDLED;
- } else if (status & AC97C_RXRDY) {
- u16 data;
- u16 value;
- u16 source;
- u16 pen_down;
-
- data = ac97c_readl(atmel_wm97xx, CBRHR);
- value = data & 0x0fff;
- source = data & WM97XX_ADCSEL_MASK;
- pen_down = (data & WM97XX_PEN_DOWN) >> 8;
-
- if (source == WM97XX_ADCSEL_X)
- atmel_wm97xx->x = value;
- if (source == WM97XX_ADCSEL_Y)
- atmel_wm97xx->y = value;
-
- if (!pressure && source == WM97XX_ADCSEL_Y) {
- input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
- input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
- input_report_key(wm->input_dev, BTN_TOUCH, pen_down);
- input_sync(wm->input_dev);
- } else if (pressure && source == WM97XX_ADCSEL_PRES) {
- input_report_abs(wm->input_dev, ABS_X, atmel_wm97xx->x);
- input_report_abs(wm->input_dev, ABS_Y, atmel_wm97xx->y);
- input_report_abs(wm->input_dev, ABS_PRESSURE, value);
- input_report_key(wm->input_dev, BTN_TOUCH, value);
- input_sync(wm->input_dev);
- }
-
- retval = IRQ_HANDLED;
- }
-
- return retval;
-}
-
-static void atmel_wm97xx_acc_pen_up(struct wm97xx *wm)
-{
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
- struct input_dev *input_dev = wm->input_dev;
- int pen_down = gpio_get_value(atmel_wm97xx->gpio_pen);
-
- if (pen_down != 0) {
- mod_timer(&atmel_wm97xx->pen_timer,
- jiffies + msecs_to_jiffies(1));
- } else {
- if (pressure)
- input_report_abs(input_dev, ABS_PRESSURE, 0);
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_sync(input_dev);
- }
-}
-
-static void atmel_wm97xx_pen_timer(struct timer_list *t)
-{
- struct atmel_wm97xx *atmel_wm97xx = from_timer(atmel_wm97xx, t,
- pen_timer);
-
- atmel_wm97xx_acc_pen_up(atmel_wm97xx->wm);
-}
-
-static int atmel_wm97xx_acc_startup(struct wm97xx *wm)
-{
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(wm->touch_dev);
- int idx = 0;
-
- if (wm->ac97 == NULL)
- return -ENODEV;
-
- for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
- if (wm->id != cinfo[idx].id)
- continue;
-
- sp_idx = idx;
-
- if (cont_rate <= cinfo[idx].speed)
- break;
- }
-
- wm->acc_rate = cinfo[sp_idx].code;
- wm->acc_slot = ac97_touch_slot;
- dev_info(&wm->touch_dev->dev, "atmel accelerated touchscreen driver, "
- "%d samples/sec\n", cinfo[sp_idx].speed);
-
- if (pen_int) {
- unsigned long reg;
-
- wm->pen_irq = atmel_wm97xx->gpio_irq;
-
- switch (wm->id) {
- case WM9712_ID2: /* Fall through. */
- case WM9713_ID2:
- /*
- * Use GPIO 13 (PEN_DOWN) to assert GPIO line 3
- * (PENDOWN).
- */
- wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
- WM97XX_GPIO_POL_HIGH,
- WM97XX_GPIO_STICKY,
- WM97XX_GPIO_WAKE);
- wm97xx_config_gpio(wm, WM97XX_GPIO_3, WM97XX_GPIO_OUT,
- WM97XX_GPIO_POL_HIGH,
- WM97XX_GPIO_NOTSTICKY,
- WM97XX_GPIO_NOWAKE);
- case WM9705_ID2: /* Fall through. */
- /*
- * Enable touch data slot in AC97 controller channel B.
- */
- reg = ac97c_readl(atmel_wm97xx, ICA);
- reg &= ~AC97C_CH_MASK(wm->acc_slot);
- reg |= AC97C_CH_ASSIGN(wm->acc_slot, B);
- ac97c_writel(atmel_wm97xx, ICA, reg);
-
- /*
- * Enable channel and interrupt for RXRDY and OVERRUN.
- */
- ac97c_writel(atmel_wm97xx, CBMR, AC97C_CMR_CENA
- | AC97C_CMR_CEM_BIG
- | AC97C_CMR_SIZE_16
- | AC97C_OVRUN
- | AC97C_RXRDY);
- /* Dummy read to empty RXRHR. */
- ac97c_readl(atmel_wm97xx, CBRHR);
- /*
- * Enable interrupt for channel B in the AC97
- * controller.
- */
- ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
- break;
- default:
- dev_err(&wm->touch_dev->dev, "pen down irq not "
- "supported on this device\n");
- pen_int = 0;
- break;
- }
- }
-
- return 0;
-}
-
-static void atmel_wm97xx_acc_shutdown(struct wm97xx *wm)
-{
- if (pen_int) {
- struct atmel_wm97xx *atmel_wm97xx =
- platform_get_drvdata(wm->touch_dev);
- unsigned long ica;
-
- switch (wm->id & 0xffff) {
- case WM9705_ID2: /* Fall through. */
- case WM9712_ID2: /* Fall through. */
- case WM9713_ID2:
- /* Disable slot and turn off channel B interrupts. */
- ica = ac97c_readl(atmel_wm97xx, ICA);
- ica &= ~AC97C_CH_MASK(wm->acc_slot);
- ac97c_writel(atmel_wm97xx, ICA, ica);
- ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
- ac97c_writel(atmel_wm97xx, CBMR, 0);
- wm->pen_irq = 0;
- break;
- default:
- dev_err(&wm->touch_dev->dev, "unknown codec\n");
- break;
- }
- }
-}
-
-static void atmel_wm97xx_irq_enable(struct wm97xx *wm, int enable)
-{
- /* Intentionally left empty. */
-}
-
-static struct wm97xx_mach_ops atmel_mach_ops = {
- .acc_enabled = 1,
- .acc_pen_up = atmel_wm97xx_acc_pen_up,
- .acc_startup = atmel_wm97xx_acc_startup,
- .acc_shutdown = atmel_wm97xx_acc_shutdown,
- .irq_enable = atmel_wm97xx_irq_enable,
- .irq_gpio = WM97XX_GPIO_3,
-};
-
-static int __init atmel_wm97xx_probe(struct platform_device *pdev)
-{
- struct wm97xx *wm = platform_get_drvdata(pdev);
- struct atmel_wm97xx *atmel_wm97xx;
- int ret;
-
- atmel_wm97xx = kzalloc(sizeof(struct atmel_wm97xx), GFP_KERNEL);
- if (!atmel_wm97xx)
- return -ENOMEM;
-
- atmel_wm97xx->wm = wm;
- atmel_wm97xx->regs = (void *)ATMEL_WM97XX_AC97C_IOMEM;
- atmel_wm97xx->ac97c_irq = ATMEL_WM97XX_AC97C_IRQ;
- atmel_wm97xx->gpio_pen = atmel_gpio_line;
- atmel_wm97xx->gpio_irq = gpio_to_irq(atmel_wm97xx->gpio_pen);
-
- timer_setup(&atmel_wm97xx->pen_timer, atmel_wm97xx_pen_timer, 0);
-
- ret = request_irq(atmel_wm97xx->ac97c_irq,
- atmel_wm97xx_channel_b_interrupt,
- IRQF_SHARED, "atmel-wm97xx-ch-b", atmel_wm97xx);
- if (ret) {
- dev_dbg(&pdev->dev, "could not request ac97c irq\n");
- goto err;
- }
-
- platform_set_drvdata(pdev, atmel_wm97xx);
-
- ret = wm97xx_register_mach_ops(wm, &atmel_mach_ops);
- if (ret)
- goto err_irq;
-
- return ret;
-
-err_irq:
- free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
-err:
- kfree(atmel_wm97xx);
- return ret;
-}
-
-static int __exit atmel_wm97xx_remove(struct platform_device *pdev)
-{
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
- struct wm97xx *wm = atmel_wm97xx->wm;
-
- ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
- free_irq(atmel_wm97xx->ac97c_irq, atmel_wm97xx);
- del_timer_sync(&atmel_wm97xx->pen_timer);
- wm97xx_unregister_mach_ops(wm);
- kfree(atmel_wm97xx);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int atmel_wm97xx_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
-
- ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT);
- disable_irq(atmel_wm97xx->gpio_irq);
- del_timer_sync(&atmel_wm97xx->pen_timer);
-
- return 0;
-}
-
-static int atmel_wm97xx_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev);
- struct wm97xx *wm = atmel_wm97xx->wm;
-
- if (wm->input_dev->users) {
- enable_irq(atmel_wm97xx->gpio_irq);
- ac97c_writel(atmel_wm97xx, IER, AC97C_INT_CBEVT);
- }
-
- return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(atmel_wm97xx_pm_ops,
- atmel_wm97xx_suspend, atmel_wm97xx_resume);
-
-static struct platform_driver atmel_wm97xx_driver = {
- .remove = __exit_p(atmel_wm97xx_remove),
- .driver = {
- .name = "wm97xx-touch",
- .pm = &atmel_wm97xx_pm_ops,
- },
-};
-
-module_platform_driver_probe(atmel_wm97xx_driver, atmel_wm97xx_probe);
-
-MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
-MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32");
-MODULE_LICENSE("GPL");
--
2.13.6
^ permalink raw reply related
* Re: [PATCH] input: touchscreen: remove atmel-wm97xx
From: Hans-Christian Noren Egtvedt @ 2018-01-19 10:50 UTC (permalink / raw)
To: Corentin Labbe
Cc: alexandre.belloni, dmitry.torokhov, nicolas.ferre,
linux-arm-kernel, linux-input, linux-kernel
In-Reply-To: <20180119081745.17557-1-clabbe.montjoie@gmail.com>
Around Fri 19 Jan 2018 09:17:45 +0100 or thereabout, Corentin Labbe wrote:
> Since AVR32 arch is gone, atmel-wm97xx driver is useless.
> Remove it.
In theory it could have been rewritten to work with AT91 devices, but I would
recommend starting from scratch. This driver is from the platform data era,
and IIRC a bit hard coded to work on AVR32 hardware variant of the AC97C
peripheral.
> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
>
Acked-by: Hans-Christian Noren Egtvedt <egtvedt@samfundet.no>
> ---
> drivers/input/touchscreen/Kconfig | 15 --
> drivers/input/touchscreen/Makefile | 1 -
> drivers/input/touchscreen/atmel-wm97xx.c | 436 -------------------------------
> 3 files changed, 452 deletions(-)
> delete mode 100644 drivers/input/touchscreen/atmel-wm97xx.c
>
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 38a226f9fcbd..4f15496fec8b 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -795,21 +795,6 @@ config TOUCHSCREEN_WM9713
> Say Y here to enable support for the Wolfson Microelectronics
> WM9713 touchscreen controller.
>
> -config TOUCHSCREEN_WM97XX_ATMEL
> - tristate "WM97xx Atmel accelerated touch"
> - depends on TOUCHSCREEN_WM97XX && AVR32
> - help
> - Say Y here for support for streaming mode with WM97xx touchscreens
> - on Atmel AT91 or AVR32 systems with an AC97C module.
> -
> - Be aware that this will use channel B in the controller for
> - streaming data, this must not conflict with other AC97C drivers.
> -
> - If unsure, say N.
> -
> - To compile this driver as a module, choose M here: the module will
> - be called atmel-wm97xx.
> -
> config TOUCHSCREEN_WM97XX_MAINSTONE
> tristate "WM97xx Mainstone/Palm accelerated touch"
> depends on TOUCHSCREEN_WM97XX && ARCH_PXA
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index d2a2b3b7af27..dddae7973436 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -97,7 +97,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
> wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
> wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
> wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
> -obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
> obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
> obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
> obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
<snipp diff>
--
mvh
Hans-Christian Noren Egtvedt
^ permalink raw reply
* [PATCH v1] i2c-hid: Use ACPI_COMPANION() directly
From: Andy Shevchenko @ 2018-01-19 14:35 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, linux-input; +Cc: Andy Shevchenko
Instead of doing additional checks and functional calls,
just get ACPI companion device directly.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
drivers/hid/i2c-hid/i2c-hid.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 7230243b94d3..0d3ca542e987 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -891,10 +891,10 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
static void i2c_hid_acpi_fix_up_power(struct device *dev)
{
- acpi_handle handle = ACPI_HANDLE(dev);
struct acpi_device *adev;
- if (handle && acpi_bus_get_device(handle, &adev) == 0)
+ adev = ACPI_COMPANION(dev);
+ if (adev)
acpi_device_fix_up_power(adev);
}
--
2.15.1
^ permalink raw reply related
* Re: [PATCH] input: touchscreen: remove atmel-wm97xx
From: Dmitry Torokhov @ 2018-01-19 17:32 UTC (permalink / raw)
To: Hans-Christian Noren Egtvedt
Cc: Corentin Labbe, alexandre.belloni, nicolas.ferre,
linux-arm-kernel, linux-input, linux-kernel
In-Reply-To: <20180119105058.bjh2gatrmga5yrni@samfundet.no>
On Fri, Jan 19, 2018 at 11:50:58AM +0100, Hans-Christian Noren Egtvedt wrote:
> Around Fri 19 Jan 2018 09:17:45 +0100 or thereabout, Corentin Labbe wrote:
> > Since AVR32 arch is gone, atmel-wm97xx driver is useless.
> > Remove it.
>
> In theory it could have been rewritten to work with AT91 devices, but I would
> recommend starting from scratch. This driver is from the platform data era,
> and IIRC a bit hard coded to work on AVR32 hardware variant of the AC97C
> peripheral.
>
> > Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
> >
>
> Acked-by: Hans-Christian Noren Egtvedt <egtvedt@samfundet.no>
Applied, thank you.
>
> > ---
> > drivers/input/touchscreen/Kconfig | 15 --
> > drivers/input/touchscreen/Makefile | 1 -
> > drivers/input/touchscreen/atmel-wm97xx.c | 436 -------------------------------
> > 3 files changed, 452 deletions(-)
> > delete mode 100644 drivers/input/touchscreen/atmel-wm97xx.c
> >
> > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> > index 38a226f9fcbd..4f15496fec8b 100644
> > --- a/drivers/input/touchscreen/Kconfig
> > +++ b/drivers/input/touchscreen/Kconfig
> > @@ -795,21 +795,6 @@ config TOUCHSCREEN_WM9713
> > Say Y here to enable support for the Wolfson Microelectronics
> > WM9713 touchscreen controller.
> >
> > -config TOUCHSCREEN_WM97XX_ATMEL
> > - tristate "WM97xx Atmel accelerated touch"
> > - depends on TOUCHSCREEN_WM97XX && AVR32
> > - help
> > - Say Y here for support for streaming mode with WM97xx touchscreens
> > - on Atmel AT91 or AVR32 systems with an AC97C module.
> > -
> > - Be aware that this will use channel B in the controller for
> > - streaming data, this must not conflict with other AC97C drivers.
> > -
> > - If unsure, say N.
> > -
> > - To compile this driver as a module, choose M here: the module will
> > - be called atmel-wm97xx.
> > -
> > config TOUCHSCREEN_WM97XX_MAINSTONE
> > tristate "WM97xx Mainstone/Palm accelerated touch"
> > depends on TOUCHSCREEN_WM97XX && ARCH_PXA
> > diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> > index d2a2b3b7af27..dddae7973436 100644
> > --- a/drivers/input/touchscreen/Makefile
> > +++ b/drivers/input/touchscreen/Makefile
> > @@ -97,7 +97,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
> > wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
> > wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
> > wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
> > -obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
> > obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
> > obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
> > obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
>
> <snipp diff>
>
> --
> mvh
> Hans-Christian Noren Egtvedt
--
Dmitry
^ permalink raw reply
* Re: [RESEND PATCH] Documentation: input: ff: fix small typos
From: Dmitry Torokhov @ 2018-01-19 17:33 UTC (permalink / raw)
To: Jean-François Têtu
Cc: Jonathan Corbet, linux-input, linux-doc, linux-kernel
In-Reply-To: <20180118214903.21017-1-jean-francois.tetu@savoirfairelinux.com>
On Thu, Jan 18, 2018 at 04:49:03PM -0500, Jean-François Têtu wrote:
> Fix small typos in the Instructions and Uploading sections. Fix a typo in
> the start/stop effect example usage code.
>
> Signed-off-by: Jean-François Têtu <jean-francois.tetu@savoirfairelinux.com>
Applied, thank you.
> ---
> Documentation/input/ff.rst | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/input/ff.rst b/Documentation/input/ff.rst
> index 26d461998e08..0c02e87ee86d 100644
> --- a/Documentation/input/ff.rst
> +++ b/Documentation/input/ff.rst
> @@ -31,7 +31,7 @@ To enable force feedback, you have to:
>
> Before you start, let me WARN you that some devices shake violently during the
> initialisation phase. This happens for example with my "AVB Top Shot Pegasus".
> -To stop this annoying behaviour, move you joystick to its limits. Anyway, you
> +To stop this annoying behaviour, move your joystick to its limits. Anyway, you
> should keep a hand on your device, in order to avoid it to break down if
> something goes wrong.
>
> @@ -121,7 +121,7 @@ uploaded, but not played.
> The content of effect may be modified. In particular, its field "id" is set
> to the unique id assigned by the driver. This data is required for performing
> some operations (removing an effect, controlling the playback).
> -This if field must be set to -1 by the user in order to tell the driver to
> +The "id" field must be set to -1 by the user in order to tell the driver to
> allocate a new effect.
>
> Effects are file descriptor specific.
> @@ -178,7 +178,7 @@ Control of playing is done with write(). Below is an example:
> stop.code = effect.id;
> stop.value = 0;
>
> - write(fd, (const void*) &play, sizeof(stop));
> + write(fd, (const void*) &stop, sizeof(stop));
>
> Setting the gain
> ----------------
> --
> 2.15.1
>
--
Dmitry
^ permalink raw reply
* [git pull] Input updates for v4.15-rc8
From: Dmitry Torokhov @ 2018-01-19 17:42 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-input
Hi Linus,
Please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
to receive updates for the input subsystem. You will get:
- a fix for use-after-free in Synaptics RMI4 driver
- correction to multitouch contact tracking on certain ALPS touchpads
(whicj got broken when we tried to fix the 2-finger scrolling)
- touchpad on Lenovo T640p is switched over to SMbus/RMI
- a few device node refcount fixes
Changelog:
---------
Arnd Bergmann (1):
Input: of_touchscreen - add MODULE_LICENSE
Johan Hovold (3):
Input: twl4030-vibra - fix sibling-node lookup
Input: twl6040-vibra - fix child-node lookup
Input: 88pm860x-ts - fix child-node lookup
Nick Desaulniers (1):
Input: synaptics-rmi4 - prevent UAF reported by KASAN
Nir Perry (1):
Input: ALPS - fix multi-touch decoding on SS4 plus touchpads
王振杰 (1):
Input: synaptics - Lenovo Thinkpad T460p devices should use RMI
Diffstat:
--------
drivers/input/misc/twl4030-vibra.c | 6 ++++--
drivers/input/misc/twl6040-vibra.c | 3 +--
drivers/input/mouse/alps.c | 23 +++++++++++++----------
drivers/input/mouse/alps.h | 10 ++++++----
drivers/input/mouse/synaptics.c | 1 +
drivers/input/rmi4/rmi_driver.c | 4 +++-
drivers/input/touchscreen/88pm860x-ts.c | 16 ++++++++++++----
drivers/input/touchscreen/of_touchscreen.c | 4 ++++
8 files changed, 44 insertions(+), 23 deletions(-)
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 2/3] Input: synaptics_rmi4 - unmask F03 interrupts when port is opened
From: thatslyude @ 2018-01-19 18:08 UTC (permalink / raw)
To: Dmitry Torokhov, Benjamin Tissoires, Damjan Georgievski
Cc: linux-input, linux-kernel, Andrew Duggan, stable
In-Reply-To: <20180119004955.247190-3-dmitry.torokhov@gmail.com>
Looks good to me.
Reviewed-by: Lyude Paul <lyude@redhat.com>
On Thu, 2018-01-18 at 16:49 -0800, Dmitry Torokhov wrote:
> Currently we register the pass-through serio port when we probe the F03 RMI
> function, and then, in sensor configure phase, we unmask interrupts.
> Unfortunately this is too late, as other drivers are free probe devices
> attached to the serio port as soon as it is probed. Because interrupts are
> masked, the IO times out, which may result in not being able to detect
> trackpoints on the pass-through port.
>
> To fix the issue we implement open() and close() methods for the
> pass-through serio port and unmask interrupts from there. We also move
> creation of the pass-through port form probe to configure stage, as RMI
> driver does not enable transport interrupt until all functions are probed
> (we should change this, but this is a separate topic).
>
> We also try to clear the pending data before unmasking interrupts, because
> some devices like to spam the system with multiple 0xaa 0x00 announcements,
> which may interfere with us trying to query ID of the device.
>
> Fixes: c5e8848fc98e ("Input: synaptics-rmi4 - add support for F03")
> Cc: stable@vger.kernel.org
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/rmi4/rmi_f03.c | 64 +++++++++++++++++++++++++++++++++++++--
> -----
> 1 file changed, 54 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
> index ad71a5e768dc4..7ccbb370a9a81 100644
> --- a/drivers/input/rmi4/rmi_f03.c
> +++ b/drivers/input/rmi4/rmi_f03.c
> @@ -32,6 +32,7 @@ struct f03_data {
> struct rmi_function *fn;
>
> struct serio *serio;
> + bool serio_registered;
>
> unsigned int overwrite_buttons;
>
> @@ -138,6 +139,37 @@ static int rmi_f03_initialize(struct f03_data *f03)
> return 0;
> }
>
> +static int rmi_f03_pt_open(struct serio *serio)
> +{
> + struct f03_data *f03 = serio->port_data;
> + struct rmi_function *fn = f03->fn;
> + const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
> + const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET;
> + u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
> + int error;
> +
> + /*
> + * Consume any pending data. Some devices like to spam with
> + * 0xaa 0x00 announcements which may confuse us as we try to
> + * probe the device.
> + */
> + error = rmi_read_block(fn->rmi_dev, data_addr, &obs, ob_len);
> + if (!error)
> + rmi_dbg(RMI_DEBUG_FN, &fn->dev,
> + "%s: Consumed %*ph (%d) from PS2 guest\n",
> + __func__, ob_len, obs, ob_len);
> +
> + return fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn-
> >irq_mask);
> +}
> +
> +static void rmi_f03_pt_close(struct serio *serio)
> +{
> + struct f03_data *f03 = serio->port_data;
> + struct rmi_function *fn = f03->fn;
> +
> + fn->rmi_dev->driver->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
> +}
> +
> static int rmi_f03_register_pt(struct f03_data *f03)
> {
> struct serio *serio;
> @@ -148,6 +180,8 @@ static int rmi_f03_register_pt(struct f03_data *f03)
>
> serio->id.type = SERIO_PS_PSTHRU;
> serio->write = rmi_f03_pt_write;
> + serio->open = rmi_f03_pt_open;
> + serio->close = rmi_f03_pt_close;
> serio->port_data = f03;
>
> strlcpy(serio->name, "Synaptics RMI4 PS/2 pass-through",
> @@ -184,17 +218,27 @@ static int rmi_f03_probe(struct rmi_function *fn)
> f03->device_count);
>
> dev_set_drvdata(dev, f03);
> -
> - error = rmi_f03_register_pt(f03);
> - if (error)
> - return error;
> -
> return 0;
> }
>
> static int rmi_f03_config(struct rmi_function *fn)
> {
> - fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
> + struct f03_data *f03 = dev_get_drvdata(&fn->dev);
> + int error;
> +
> + if (!f03->serio_registered) {
> + error = rmi_f03_register_pt(f03);
> + if (error)
> + return error;
> +
> + f03->serio_registered = true;
> + } else {
> + /*
> + * We must be re-configuring the sensor, just enable
> + * interrupts for this function.
> + */
> + fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn-
> >irq_mask);
> + }
>
> return 0;
> }
> @@ -204,7 +248,7 @@ static int rmi_f03_attention(struct rmi_function *fn,
> unsigned long *irq_bits)
> struct rmi_device *rmi_dev = fn->rmi_dev;
> struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
> struct f03_data *f03 = dev_get_drvdata(&fn->dev);
> - u16 data_addr = fn->fd.data_base_addr;
> + const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET;
> const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
> u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
> u8 ob_status;
> @@ -226,8 +270,7 @@ static int rmi_f03_attention(struct rmi_function *fn,
> unsigned long *irq_bits)
> drvdata->attn_data.size -= ob_len;
> } else {
> /* Grab all of the data registers, and check them for data
> */
> - error = rmi_read_block(fn->rmi_dev, data_addr +
> RMI_F03_OB_OFFSET,
> - &obs, ob_len);
> + error = rmi_read_block(fn->rmi_dev, data_addr, &obs,
> ob_len);
> if (error) {
> dev_err(&fn->dev,
> "%s: Failed to read F03 output buffers:
> %d\n",
> @@ -266,7 +309,8 @@ static void rmi_f03_remove(struct rmi_function *fn)
> {
> struct f03_data *f03 = dev_get_drvdata(&fn->dev);
>
> - serio_unregister_port(f03->serio);
> + if (f03->serio_registered)
> + serio_unregister_port(f03->serio);
> }
>
> struct rmi_function_handler rmi_f03_handler = {
^ permalink raw reply
* Re: [PATCH 3/3] Input: synaptics-rmi4 - log when we create a guest serio port
From: thatslyude @ 2018-01-19 18:10 UTC (permalink / raw)
To: Dmitry Torokhov, Benjamin Tissoires, Damjan Georgievski
Cc: linux-input, linux-kernel, Andrew Duggan
In-Reply-To: <20180119004955.247190-4-dmitry.torokhov@gmail.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
On Thu, 2018-01-18 at 16:49 -0800, Dmitry Torokhov wrote:
> To ease analyzing boot behavior from logs, let's log when we are about to
> register the pass-through serio port.
>
> Also, let's drop "Synaptics" prefix from the port name, as RMI4 is good
> enough indicator already, and having the prefix means that the name does
> not fit into serio->name field. While at it move from hard-coded seio->phys
> to one mentioning the sensor ID (such as "rmi4-00.fn03/serio0").
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/rmi4/rmi_f03.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
> index 7ccbb370a9a81..88822196d6b72 100644
> --- a/drivers/input/rmi4/rmi_f03.c
> +++ b/drivers/input/rmi4/rmi_f03.c
> @@ -184,14 +184,15 @@ static int rmi_f03_register_pt(struct f03_data *f03)
> serio->close = rmi_f03_pt_close;
> serio->port_data = f03;
>
> - strlcpy(serio->name, "Synaptics RMI4 PS/2 pass-through",
> - sizeof(serio->name));
> - strlcpy(serio->phys, "synaptics-rmi4-pt/serio1",
> - sizeof(serio->phys));
> + strlcpy(serio->name, "RMI4 PS/2 pass-through", sizeof(serio-
> >name));
> + snprintf(serio->phys, sizeof(serio->phys), "%s/serio0",
> + dev_name(&f03->fn->dev));
> serio->dev.parent = &f03->fn->dev;
>
> f03->serio = serio;
>
> + printk(KERN_INFO "serio: %s port at %s\n",
> + serio->name, dev_name(&f03->fn->dev));
> serio_register_port(serio);
>
> return 0;
^ permalink raw reply
* Re: [PATCH v2] Input: mms114 - drop platform data and use generic APIs
From: Rob Herring @ 2018-01-19 18:42 UTC (permalink / raw)
To: Simon Shields; +Cc: Andi Shyti, Dmitry Torokhov, linux-input, devicetree
In-Reply-To: <20180116085206.GA18232@lineageos.org>
On Tue, Jan 16, 2018 at 07:52:06PM +1100, Simon Shields wrote:
> Hi Andi,
>
> Thanks for the review!
>
> On Tue, Jan 16, 2018 at 04:56:11PM +0900, Andi Shyti wrote:
> > Hi Simon,
> >
> > On Sat, Jan 13, 2018 at 01:04:56PM +1100, Simon Shields wrote:
> > > The MMS114 platform data has no in-tree users, so drop it,
> > > and make the driver depend on CONFIG_OF.
> > >
> > > Switch to using the standard touchscreen properties via
> > > touchscreen_parse_properties(), and move the old DT parsing code
> > > to use device_property_*() APIs.
> > >
> > > Finally, use touchscreen_report_pos to report x/y coordinates
> > > and drop the custom x/y inversion code.
> > >
> > > Signed-off-by: Simon Shields <simon@lineageos.org>
> > > ---
> > > .../bindings/input/touchscreen/mms114.txt | 29 ++--
> > > drivers/input/touchscreen/Kconfig | 1 +
> > > drivers/input/touchscreen/mms114.c | 152 +++++++++------------
> > > include/linux/platform_data/mms114.h | 24 ----
> > > 4 files changed, 83 insertions(+), 123 deletions(-)
> > > delete mode 100644 include/linux/platform_data/mms114.h
> > >
> >
> > The patch looks good, but you would also need to update the dtsi
> > files in this same patch:
Yes, but dts updates should be a separate patch. Really, the DT docs are
supposed to be too, but I let that go if there's no other review
changes.
> >
> > ./arch/arm/boot/dts/exynos4412-trats2.dts
> > ./arch/arm/boot/dts/exynos4210-trats.dts
> >
> > and Cc the Samsung-soc mailing list.
> >
> > For now it's a nack because the touchscreen would not work
> > anymore with the trats boards.
>
> This patch keeps support for the old bindings. I've verified that both
> the old and new bindings work on a GT-I9300 (trats2 with a different
> bootloader/partition layout).
The driver needs to support both old and new. The dts files can be
updated as long as they'd still work the same. Old dtb and new kernel is
the primary case we care about preserving the ABI.
>
> >
> > One more thing, you forgot Rob's ACK.
>
> I wasn't sure whether or not to keep the Reviewed-By tag, since
> this is a new version of the patch. In the future, I'll keep it.
Yes, you should as long as the binding doesn't change significantly.
Rob
^ permalink raw reply
* Elantech touchpad very slow and laggy with high CPU usage
From: Will Roberts @ 2018-01-19 19:15 UTC (permalink / raw)
To: linux-input
Hi all,
I'm having an issue with an Elantech 1200 touchpad behaving poorly on
an asus laptop. I think I can show that recording the touchpad with
hid-recorder delivers a clean event stream, but recording with
evemu-record produces the funky behaviour.
If anybody on here gets a chance, can you take a quick look at the bug
report I opened:
https://bugzilla.kernel.org/show_bug.cgi?id=198473
I would be very grateful for any tips on how to diagnose this further,
or any guesses as to what the problem could be. Thanks in advance!
Best wishes,
Will Roberts
^ permalink raw reply
* [PATCH 5/7] Input: libps2 - add debugging statements
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-1-dmitry.torokhov@gmail.com>
Debugging via i8042.debug and analyzing raw PS/2 data stream may be
cumbersome as you need to locate the boundaries of commands, decipher the
sliced commands, etc, etc. Let's add a bit more high level debug statements
for ps2_sendbyte(), ps2_command(), and ps2_sliced_command().
We do not introduce a new module parameter, but rater rely on the kernel
having dynamic debug facility enabled (which most everyone has nowadays).
Enable with:
echo "file libps2.c +pf" > /sys/kernel/debug/dynamic_debug/control
or add "libps2.dyndbg=+pf" to the kernel command line.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/serio/libps2.c | 52 +++++++++++++++++++++++++++++++++-----------
1 file changed, 39 insertions(+), 13 deletions(-)
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index e96ae477f0b56..82befae4dab04 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -26,22 +26,20 @@ MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
MODULE_DESCRIPTION("PS/2 driver library");
MODULE_LICENSE("GPL");
-/*
- * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
- * It doesn't handle retransmission, though it could - because if there
- * is a need for retransmissions device has to be replaced anyway.
- *
- * ps2_sendbyte() can only be called from a process context.
- */
-
-int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
+static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
{
+ int error;
+
serio_pause_rx(ps2dev->serio);
ps2dev->nak = 1;
ps2dev->flags |= PS2_FLAG_ACK;
serio_continue_rx(ps2dev->serio);
- if (serio_write(ps2dev->serio, byte) == 0)
+ error = serio_write(ps2dev->serio, byte);
+ if (error)
+ dev_dbg(&ps2dev->serio->dev,
+ "failed to write %#02x: %d\n", byte, error);
+ else
wait_event_timeout(ps2dev->wait,
!(ps2dev->flags & PS2_FLAG_ACK),
msecs_to_jiffies(timeout));
@@ -52,6 +50,24 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
return -ps2dev->nak;
}
+
+/*
+ * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
+ * It doesn't handle retransmission, though it could - because if there
+ * is a need for retransmissions device has to be replaced anyway.
+ *
+ * ps2_sendbyte() can only be called from a process context.
+ */
+
+int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
+{
+ int retval;
+
+ retval = ps2_do_sendbyte(ps2dev, byte, timeout);
+ dev_dbg(&ps2dev->serio->dev, "%02x - %x\n", byte, ps2dev->nak);
+
+ return retval;
+}
EXPORT_SYMBOL(ps2_sendbyte);
void ps2_begin_command(struct ps2dev *ps2dev)
@@ -186,6 +202,7 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
unsigned int receive = (command >> 8) & 0xf;
int rc = -1;
int i;
+ u8 send_param[16];
if (receive > sizeof(ps2dev->cmdbuf)) {
WARN_ON(1);
@@ -197,6 +214,8 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
return -1;
}
+ memcpy(send_param, param, send);
+
serio_pause_rx(ps2dev->serio);
ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
ps2dev->cmdcnt = receive;
@@ -210,14 +229,14 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
* ACKing the reset command, and so it can take a long
* time before the ACK arrives.
*/
- if (ps2_sendbyte(ps2dev, command & 0xff,
- command == PS2_CMD_RESET_BAT ? 1000 : 200)) {
+ if (ps2_do_sendbyte(ps2dev, command & 0xff,
+ command == PS2_CMD_RESET_BAT ? 1000 : 200)) {
serio_pause_rx(ps2dev->serio);
goto out_reset_flags;
}
for (i = 0; i < send; i++) {
- if (ps2_sendbyte(ps2dev, param[i], 200)) {
+ if (ps2_do_sendbyte(ps2dev, param[i], 200)) {
serio_pause_rx(ps2dev->serio);
goto out_reset_flags;
}
@@ -253,6 +272,12 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
ps2dev->flags = 0;
serio_continue_rx(ps2dev->serio);
+ dev_dbg(&ps2dev->serio->dev,
+ "%02x [%*ph] - %x/%08lx [%*ph]\n",
+ command & 0xff, send, send_param,
+ ps2dev->nak, ps2dev->flags,
+ receive, param ?: send_param);
+
return rc;
}
EXPORT_SYMBOL(__ps2_command);
@@ -296,6 +321,7 @@ int ps2_sliced_command(struct ps2dev *ps2dev, u8 command)
}
out:
+ dev_dbg(&ps2dev->serio->dev, "%02x - %d\n", command, retval);
ps2_end_command(ps2dev);
return retval;
}
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 6/7] Input: libps2 - support retransmission of command data
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-1-dmitry.torokhov@gmail.com>
The devices are allowed to respond to either command byte or command
parameter with a NAK (0xfe), and the host is supposed to resend the
"correct" byte. The device then will either respond with ACK or ERR (0xfc).
Let's teach libps2 to handle the NAK responses properly, so that individual
drivers do not need to handle them.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/serio/libps2.c | 103 +++++++++++++++++++++++++++++--------------
1 file changed, 71 insertions(+), 32 deletions(-)
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 82befae4dab04..f05c407b31f3d 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -26,35 +26,63 @@ MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
MODULE_DESCRIPTION("PS/2 driver library");
MODULE_LICENSE("GPL");
-static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
+static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte,
+ unsigned int timeout, unsigned int max_attempts)
+ __releases(&ps2dev->serio->lock) __acquires(&ps2dev->serio->lock)
{
+ int attempt = 0;
int error;
- serio_pause_rx(ps2dev->serio);
- ps2dev->nak = 1;
- ps2dev->flags |= PS2_FLAG_ACK;
- serio_continue_rx(ps2dev->serio);
+ lockdep_assert_held(&ps2dev->serio->lock);
- error = serio_write(ps2dev->serio, byte);
- if (error)
- dev_dbg(&ps2dev->serio->dev,
- "failed to write %#02x: %d\n", byte, error);
- else
- wait_event_timeout(ps2dev->wait,
- !(ps2dev->flags & PS2_FLAG_ACK),
- msecs_to_jiffies(timeout));
+ do {
+ ps2dev->nak = 1;
+ ps2dev->flags |= PS2_FLAG_ACK;
+
+ serio_continue_rx(ps2dev->serio);
+
+ error = serio_write(ps2dev->serio, byte);
+ if (error)
+ dev_dbg(&ps2dev->serio->dev,
+ "failed to write %#02x: %d\n", byte, error);
+ else
+ wait_event_timeout(ps2dev->wait,
+ !(ps2dev->flags & PS2_FLAG_ACK),
+ msecs_to_jiffies(timeout));
+
+ serio_pause_rx(ps2dev->serio);
+ } while (ps2dev->nak == PS2_RET_NAK && ++attempt < max_attempts);
- serio_pause_rx(ps2dev->serio);
ps2dev->flags &= ~PS2_FLAG_ACK;
- serio_continue_rx(ps2dev->serio);
- return -ps2dev->nak;
+ if (!error) {
+ switch (ps2dev->nak) {
+ case 0:
+ break;
+ case PS2_RET_NAK:
+ error = -EAGAIN;
+ break;
+ case PS2_RET_ERR:
+ error = -EPROTO;
+ break;
+ default:
+ error = -EIO;
+ break;
+ }
+ }
+
+ if (error || attempt > 1)
+ dev_dbg(&ps2dev->serio->dev,
+ "%02x - %d (%x), attempt %d\n",
+ byte, error, ps2dev->nak, attempt);
+
+ return error;
}
/*
* ps2_sendbyte() sends a byte to the device and waits for acknowledge.
- * It doesn't handle retransmission, though it could - because if there
- * is a need for retransmissions device has to be replaced anyway.
+ * It doesn't handle retransmission, the caller is expected to handle
+ * it when needed.
*
* ps2_sendbyte() can only be called from a process context.
*/
@@ -63,9 +91,13 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
{
int retval;
- retval = ps2_do_sendbyte(ps2dev, byte, timeout);
+ serio_pause_rx(ps2dev->serio);
+
+ retval = ps2_do_sendbyte(ps2dev, byte, timeout, 1);
dev_dbg(&ps2dev->serio->dev, "%02x - %x\n", byte, ps2dev->nak);
+ serio_continue_rx(ps2dev->serio);
+
return retval;
}
EXPORT_SYMBOL(ps2_sendbyte);
@@ -200,48 +232,48 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
unsigned int timeout;
unsigned int send = (command >> 12) & 0xf;
unsigned int receive = (command >> 8) & 0xf;
- int rc = -1;
+ int rc;
int i;
u8 send_param[16];
if (receive > sizeof(ps2dev->cmdbuf)) {
WARN_ON(1);
- return -1;
+ return -EINVAL;
}
if (send && !param) {
WARN_ON(1);
- return -1;
+ return -EINVAL;
}
memcpy(send_param, param, send);
serio_pause_rx(ps2dev->serio);
+
ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
ps2dev->cmdcnt = receive;
if (receive && param)
for (i = 0; i < receive; i++)
ps2dev->cmdbuf[(receive - 1) - i] = param[i];
- serio_continue_rx(ps2dev->serio);
/*
* Some devices (Synaptics) peform the reset before
* ACKing the reset command, and so it can take a long
* time before the ACK arrives.
*/
- if (ps2_do_sendbyte(ps2dev, command & 0xff,
- command == PS2_CMD_RESET_BAT ? 1000 : 200)) {
- serio_pause_rx(ps2dev->serio);
+ rc = ps2_do_sendbyte(ps2dev, command & 0xff,
+ command == PS2_CMD_RESET_BAT ? 1000 : 200, 2);
+ if (rc)
goto out_reset_flags;
- }
for (i = 0; i < send; i++) {
- if (ps2_do_sendbyte(ps2dev, param[i], 200)) {
- serio_pause_rx(ps2dev->serio);
+ rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2);
+ if (rc)
goto out_reset_flags;
- }
}
+ serio_continue_rx(ps2dev->serio);
+
/*
* The reset command takes a long time to execute.
*/
@@ -263,8 +295,11 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
for (i = 0; i < receive; i++)
param[i] = ps2dev->cmdbuf[(receive - 1) - i];
- if (ps2dev->cmdcnt && (command != PS2_CMD_RESET_BAT || ps2dev->cmdcnt != 1))
+ if (ps2dev->cmdcnt &&
+ (command != PS2_CMD_RESET_BAT || ps2dev->cmdcnt != 1)) {
+ rc = -EPROTO;
goto out_reset_flags;
+ }
rc = 0;
@@ -278,7 +313,11 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
ps2dev->nak, ps2dev->flags,
receive, param ?: send_param);
- return rc;
+ /*
+ * ps_command() handles resends itself, so do not leak -EAGAIN
+ * to the callers.
+ */
+ return rc != -EAGAIN ? rc : -EPROTO;
}
EXPORT_SYMBOL(__ps2_command);
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 0/7] libps2 facelift
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
Hi,
The main reason for the patch series is to have a bit more manageable
debug info for PS/2 init sequence: raw i8042 debug is way too noisy,
one has to decode sliced commands by hand, etc, etc. With proposed
changes you get a nice parsed command flow:
[14421.985416] __ps2_command: psmouse serio2: f5 [] - 0/00000000 []
[14421.993112] __ps2_command: psmouse serio2: f6 [] - 0/00000000 []
[14422.007738] __ps2_command: psmouse serio2: e1 [] - 0/00000000 [03 04]
[14422.042522] __ps2_command: psmouse serio2: e2 [81 4a 80] - 0/00000000 []
[14422.057091] __ps2_command: psmouse serio2: e2 [2c] - 0/00000000 [20]
[14422.057118] psmouse serio2: trackpoint: Elan TrackPoint firmware: 0x04, buttons: 3/3
[14422.072062] __ps2_command: psmouse serio2: f3 [64] - 0/00000000 []
[14422.086839] __ps2_command: psmouse serio2: e8 [03] - 0/00000000 []
[14422.094306] __ps2_command: psmouse serio2: e6 [] - 0/00000000 []
[14422.094504] input: TPPS/2 Elan TrackPoint as /devices/rmi4-00/rmi4-00.fn03/serio2/input/input33
[14422.128629] __ps2_command: psmouse serio2: f4 [] - 0/00000000 []
Additionally libps2 now can handle command and parameter byte
retransmissions and we relaxed rules for getting initial ACK to the
command byte, which hopefully will help properly detect devices that
are not silent when we start probing them.
Thanks.
Dmitry Torokhov (7):
Input: libps2 - fix switch statement formatting
Input: libps2 - use u8 for byte data
Input: libps2 - use BIT() for bitmask constants
Input: psmouse - move sliced command implementation to libps2
Input: libps2 - add debugging statements
Input: libps2 - support retransmission of command data
Input: libps2 - relax command byte ACK handling
drivers/input/mouse/elantech.c | 12 +-
drivers/input/mouse/logips2pp.c | 2 +-
drivers/input/mouse/psmouse-base.c | 26 ---
drivers/input/mouse/psmouse.h | 1 -
drivers/input/mouse/synaptics.c | 8 +-
drivers/input/serio/libps2.c | 322 +++++++++++++++++++++++++------------
include/linux/libps2.h | 34 ++--
7 files changed, 249 insertions(+), 156 deletions(-)
--
Dmitry
^ permalink raw reply
* [PATCH 1/7] Input: libps2 - fix switch statement formatting
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-1-dmitry.torokhov@gmail.com>
Individual labels of switch statements should have the same indentation
level as the switch statement itself.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/serio/libps2.c | 131 +++++++++++++++++++++----------------------
1 file changed, 65 insertions(+), 66 deletions(-)
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 83e9c663aa672..21aea5169a99c 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -126,46 +126,46 @@ EXPORT_SYMBOL(ps2_is_keyboard_id);
static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
{
switch (command) {
- case PS2_CMD_RESET_BAT:
- /*
- * Device has sent the first response byte after
- * reset command, reset is thus done, so we can
- * shorten the timeout.
- * The next byte will come soon (keyboard) or not
- * at all (mouse).
- */
- if (timeout > msecs_to_jiffies(100))
- timeout = msecs_to_jiffies(100);
- break;
+ case PS2_CMD_RESET_BAT:
+ /*
+ * Device has sent the first response byte after
+ * reset command, reset is thus done, so we can
+ * shorten the timeout.
+ * The next byte will come soon (keyboard) or not
+ * at all (mouse).
+ */
+ if (timeout > msecs_to_jiffies(100))
+ timeout = msecs_to_jiffies(100);
+ break;
- case PS2_CMD_GETID:
- /*
- * Microsoft Natural Elite keyboard responds to
- * the GET ID command as it were a mouse, with
- * a single byte. Fail the command so atkbd will
- * use alternative probe to detect it.
- */
- if (ps2dev->cmdbuf[1] == 0xaa) {
- serio_pause_rx(ps2dev->serio);
- ps2dev->flags = 0;
- serio_continue_rx(ps2dev->serio);
- timeout = 0;
- }
-
- /*
- * If device behind the port is not a keyboard there
- * won't be 2nd byte of ID response.
- */
- if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) {
- serio_pause_rx(ps2dev->serio);
- ps2dev->flags = ps2dev->cmdcnt = 0;
- serio_continue_rx(ps2dev->serio);
- timeout = 0;
- }
- break;
+ case PS2_CMD_GETID:
+ /*
+ * Microsoft Natural Elite keyboard responds to
+ * the GET ID command as it were a mouse, with
+ * a single byte. Fail the command so atkbd will
+ * use alternative probe to detect it.
+ */
+ if (ps2dev->cmdbuf[1] == 0xaa) {
+ serio_pause_rx(ps2dev->serio);
+ ps2dev->flags = 0;
+ serio_continue_rx(ps2dev->serio);
+ timeout = 0;
+ }
- default:
- break;
+ /*
+ * If device behind the port is not a keyboard there
+ * won't be 2nd byte of ID response.
+ */
+ if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) {
+ serio_pause_rx(ps2dev->serio);
+ ps2dev->flags = ps2dev->cmdcnt = 0;
+ serio_continue_rx(ps2dev->serio);
+ timeout = 0;
+ }
+ break;
+
+ default:
+ break;
}
return timeout;
@@ -289,39 +289,38 @@ EXPORT_SYMBOL(ps2_init);
int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
{
switch (data) {
- case PS2_RET_ACK:
- ps2dev->nak = 0;
+ case PS2_RET_ACK:
+ ps2dev->nak = 0;
+ break;
+
+ case PS2_RET_NAK:
+ ps2dev->flags |= PS2_FLAG_NAK;
+ ps2dev->nak = PS2_RET_NAK;
+ break;
+
+ case PS2_RET_ERR:
+ if (ps2dev->flags & PS2_FLAG_NAK) {
+ ps2dev->flags &= ~PS2_FLAG_NAK;
+ ps2dev->nak = PS2_RET_ERR;
break;
+ }
- case PS2_RET_NAK:
- ps2dev->flags |= PS2_FLAG_NAK;
- ps2dev->nak = PS2_RET_NAK;
+ /*
+ * Workaround for mice which don't ACK the Get ID command.
+ * These are valid mouse IDs that we recognize.
+ */
+ case 0x00:
+ case 0x03:
+ case 0x04:
+ if (ps2dev->flags & PS2_FLAG_WAITID) {
+ ps2dev->nak = 0;
break;
-
- case PS2_RET_ERR:
- if (ps2dev->flags & PS2_FLAG_NAK) {
- ps2dev->flags &= ~PS2_FLAG_NAK;
- ps2dev->nak = PS2_RET_ERR;
- break;
- }
-
- /*
- * Workaround for mice which don't ACK the Get ID command.
- * These are valid mouse IDs that we recognize.
- */
- case 0x00:
- case 0x03:
- case 0x04:
- if (ps2dev->flags & PS2_FLAG_WAITID) {
- ps2dev->nak = 0;
- break;
- }
- /* Fall through */
- default:
- return 0;
+ }
+ /* Fall through */
+ default:
+ return 0;
}
-
if (!ps2dev->nak) {
ps2dev->flags &= ~PS2_FLAG_NAK;
if (ps2dev->cmdcnt)
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 2/7] Input: libps2 - use u8 for byte data
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-1-dmitry.torokhov@gmail.com>
Instead of using unsigned char for the byte data switch to using u8. Also
use unsigned int for the command codes and timeouts, and have
ps2_handle_ack() and ps2_handle_response() return bool instead of int, as
they do not return error codes but rather signal whether a byte was handled
or not handled. ps2_is_keyboard_id() now returns bool as well.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/serio/libps2.c | 31 ++++++++++++++++---------------
include/linux/libps2.h | 20 ++++++++++----------
2 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 21aea5169a99c..c3712f0a47b50 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -34,7 +34,7 @@ MODULE_LICENSE("GPL");
* ps2_sendbyte() can only be called from a process context.
*/
-int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout)
+int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
{
serio_pause_rx(ps2dev->serio);
ps2dev->nak = 1;
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(ps2_end_command);
* and discards them.
*/
-void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
+void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout)
{
if (maxbytes > sizeof(ps2dev->cmdbuf)) {
WARN_ON(1);
@@ -102,9 +102,9 @@ EXPORT_SYMBOL(ps2_drain);
* known keyboard IDs.
*/
-int ps2_is_keyboard_id(char id_byte)
+bool ps2_is_keyboard_id(u8 id_byte)
{
- static const char keyboard_ids[] = {
+ static const u8 keyboard_ids[] = {
0xab, /* Regular keyboards */
0xac, /* NCD Sun keyboard */
0x2b, /* Trust keyboard, translated */
@@ -123,7 +123,8 @@ EXPORT_SYMBOL(ps2_is_keyboard_id);
* completion.
*/
-static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
+static int ps2_adjust_timeout(struct ps2dev *ps2dev,
+ unsigned int command, unsigned int timeout)
{
switch (command) {
case PS2_CMD_RESET_BAT:
@@ -178,11 +179,11 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
* ps2_command() can only be called from a process context
*/
-int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
+int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
{
- int timeout;
- int send = (command >> 12) & 0xf;
- int receive = (command >> 8) & 0xf;
+ unsigned int timeout;
+ unsigned int send = (command >> 12) & 0xf;
+ unsigned int receive = (command >> 8) & 0xf;
int rc = -1;
int i;
@@ -256,7 +257,7 @@ int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
}
EXPORT_SYMBOL(__ps2_command);
-int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
+int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
{
int rc;
@@ -286,7 +287,7 @@ EXPORT_SYMBOL(ps2_init);
* to properly process ACK/NAK of a command from a PS/2 device.
*/
-int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
+bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
{
switch (data) {
case PS2_RET_ACK:
@@ -318,7 +319,7 @@ int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
}
/* Fall through */
default:
- return 0;
+ return false;
}
if (!ps2dev->nak) {
@@ -333,7 +334,7 @@ int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
if (data != PS2_RET_ACK)
ps2_handle_response(ps2dev, data);
- return 1;
+ return true;
}
EXPORT_SYMBOL(ps2_handle_ack);
@@ -343,7 +344,7 @@ EXPORT_SYMBOL(ps2_handle_ack);
* waiting for completion of the command.
*/
-int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data)
+bool ps2_handle_response(struct ps2dev *ps2dev, u8 data)
{
if (ps2dev->cmdcnt)
ps2dev->cmdbuf[--ps2dev->cmdcnt] = data;
@@ -359,7 +360,7 @@ int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data)
wake_up(&ps2dev->wait);
}
- return 1;
+ return true;
}
EXPORT_SYMBOL(ps2_handle_response);
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index 4ad06e824f76f..365c50b097ded 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -36,21 +36,21 @@ struct ps2dev {
wait_queue_head_t wait;
unsigned long flags;
- unsigned char cmdbuf[8];
- unsigned char cmdcnt;
- unsigned char nak;
+ u8 cmdbuf[8];
+ u8 cmdcnt;
+ u8 nak;
};
void ps2_init(struct ps2dev *ps2dev, struct serio *serio);
-int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout);
-void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout);
+int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout);
+void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout);
void ps2_begin_command(struct ps2dev *ps2dev);
void ps2_end_command(struct ps2dev *ps2dev);
-int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command);
-int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command);
-int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data);
-int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data);
+int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command);
+int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command);
+bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data);
+bool ps2_handle_response(struct ps2dev *ps2dev, u8 data);
void ps2_cmd_aborted(struct ps2dev *ps2dev);
-int ps2_is_keyboard_id(char id);
+bool ps2_is_keyboard_id(u8 id);
#endif /* _LIBPS2_H */
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 3/7] Input: libps2 - use BIT() for bitmask constants
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-1-dmitry.torokhov@gmail.com>
Let's explicitly document bit numbers with BIT() macro.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
include/linux/libps2.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index 365c50b097ded..649295a5ff47d 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -20,11 +20,11 @@
#define PS2_RET_NAK 0xfe
#define PS2_RET_ERR 0xfc
-#define PS2_FLAG_ACK 1 /* Waiting for ACK/NAK */
-#define PS2_FLAG_CMD 2 /* Waiting for command to finish */
-#define PS2_FLAG_CMD1 4 /* Waiting for the first byte of command response */
-#define PS2_FLAG_WAITID 8 /* Command execiting is GET ID */
-#define PS2_FLAG_NAK 16 /* Last transmission was NAKed */
+#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */
+#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */
+#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */
+#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */
+#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */
struct ps2dev {
struct serio *serio;
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 4/7] Input: psmouse - move sliced command implementation to libps2
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-1-dmitry.torokhov@gmail.com>
In preparation to adding some debugging statements to PS/2 control
sequences let's move psmouse_sliced_command() into libps2 and rename it
to ps2_sliced_command().
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/mouse/elantech.c | 12 ++++++------
drivers/input/mouse/logips2pp.c | 2 +-
drivers/input/mouse/psmouse-base.c | 26 --------------------------
drivers/input/mouse/psmouse.h | 1 -
drivers/input/mouse/synaptics.c | 8 ++++----
drivers/input/serio/libps2.c | 32 ++++++++++++++++++++++++++++++++
include/linux/libps2.h | 3 +++
7 files changed, 46 insertions(+), 38 deletions(-)
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index af7fc17c14d96..db47a5e1d114d 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -35,7 +35,7 @@
static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c,
unsigned char *param)
{
- if (psmouse_sliced_command(psmouse, c) ||
+ if (ps2_sliced_command(&psmouse->ps2dev, c) ||
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
return -1;
@@ -107,8 +107,8 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
switch (etd->hw_version) {
case 1:
- if (psmouse_sliced_command(psmouse, ETP_REGISTER_READ) ||
- psmouse_sliced_command(psmouse, reg) ||
+ if (ps2_sliced_command(&psmouse->ps2dev, ETP_REGISTER_READ) ||
+ ps2_sliced_command(&psmouse->ps2dev, reg) ||
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
rc = -1;
}
@@ -162,9 +162,9 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
switch (etd->hw_version) {
case 1:
- if (psmouse_sliced_command(psmouse, ETP_REGISTER_WRITE) ||
- psmouse_sliced_command(psmouse, reg) ||
- psmouse_sliced_command(psmouse, val) ||
+ if (ps2_sliced_command(&psmouse->ps2dev, ETP_REGISTER_WRITE) ||
+ ps2_sliced_command(&psmouse->ps2dev, reg) ||
+ ps2_sliced_command(&psmouse->ps2dev, val) ||
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) {
rc = -1;
}
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 7f4813fc3c6dd..51a156afa6c21 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -116,7 +116,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, u8 *param, u8 command)
{
int error;
- error = psmouse_sliced_command(psmouse, command);
+ error = ps2_sliced_command(&psmouse->ps2dev, command);
if (error)
return error;
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index e3523143296ad..cbe12671f784c 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -429,32 +429,6 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
return IRQ_HANDLED;
}
-/*
- * psmouse_sliced_command() sends an extended PS/2 command to the mouse
- * using sliced syntax, understood by advanced devices, such as Logitech
- * or Synaptics touchpads. The command is encoded as:
- * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
- * is the command.
- */
-int psmouse_sliced_command(struct psmouse *psmouse, u8 command)
-{
- int i;
- int error;
-
- error = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
- if (error)
- return error;
-
- for (i = 6; i >= 0; i -= 2) {
- u8 d = (command >> i) & 3;
- error = ps2_command(&psmouse->ps2dev, &d, PSMOUSE_CMD_SETRES);
- if (error)
- return error;
- }
-
- return 0;
-}
-
/*
* psmouse_reset() resets the mouse into power-on state.
*/
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 8bc99691494e9..71ac50082c8b4 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -131,7 +131,6 @@ struct psmouse {
void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
unsigned long delay);
-int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
int psmouse_reset(struct psmouse *psmouse);
void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 3d2e23a0ae39d..588408abc17e0 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -84,7 +84,7 @@ static int synaptics_mode_cmd(struct psmouse *psmouse, u8 mode)
u8 param[1];
int error;
- error = psmouse_sliced_command(psmouse, mode);
+ error = ps2_sliced_command(&psmouse->ps2dev, mode);
if (error)
return error;
@@ -190,7 +190,7 @@ static int synaptics_send_cmd(struct psmouse *psmouse, u8 cmd, u8 *param)
{
int error;
- error = psmouse_sliced_command(psmouse, cmd);
+ error = ps2_sliced_command(&psmouse->ps2dev, cmd);
if (error)
return error;
@@ -547,7 +547,7 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
static u8 param = 0xc8;
int error;
- error = psmouse_sliced_command(psmouse, SYN_QUE_MODEL);
+ error = ps2_sliced_command(&psmouse->ps2dev, SYN_QUE_MODEL);
if (error)
return error;
@@ -614,7 +614,7 @@ static int synaptics_pt_write(struct serio *serio, u8 c)
u8 rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
int error;
- error = psmouse_sliced_command(parent, c);
+ error = ps2_sliced_command(&parent->ps2dev, c);
if (error)
return error;
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index c3712f0a47b50..e96ae477f0b56 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -269,6 +269,38 @@ int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
}
EXPORT_SYMBOL(ps2_command);
+/*
+ * ps2_sliced_command() sends an extended PS/2 command to the mouse
+ * using sliced syntax, understood by advanced devices, such as Logitech
+ * or Synaptics touchpads. The command is encoded as:
+ * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
+ * is the command.
+ */
+
+int ps2_sliced_command(struct ps2dev *ps2dev, u8 command)
+{
+ int i;
+ int retval;
+
+ ps2_begin_command(ps2dev);
+
+ retval = __ps2_command(ps2dev, NULL, PS2_CMD_SETSCALE11);
+ if (retval)
+ goto out;
+
+ for (i = 6; i >= 0; i -= 2) {
+ u8 d = (command >> i) & 3;
+ retval = __ps2_command(ps2dev, &d, PS2_CMD_SETRES);
+ if (retval)
+ break;
+ }
+
+out:
+ ps2_end_command(ps2dev);
+ return retval;
+}
+EXPORT_SYMBOL(ps2_sliced_command);
+
/*
* ps2_init() initializes ps2dev structure
*/
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index 649295a5ff47d..cd4454502a042 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -11,6 +11,8 @@
*/
+#define PS2_CMD_SETSCALE11 0x00e6
+#define PS2_CMD_SETRES 0x10e8
#define PS2_CMD_GETID 0x02f2
#define PS2_CMD_RESET_BAT 0x02ff
@@ -48,6 +50,7 @@ void ps2_begin_command(struct ps2dev *ps2dev);
void ps2_end_command(struct ps2dev *ps2dev);
int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command);
int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command);
+int ps2_sliced_command(struct ps2dev *ps2dev, u8 command);
bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data);
bool ps2_handle_response(struct ps2dev *ps2dev, u8 data);
void ps2_cmd_aborted(struct ps2dev *ps2dev);
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 7/7] Input: libps2 - relax command byte ACK handling
From: Dmitry Torokhov @ 2018-01-19 19:41 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-1-dmitry.torokhov@gmail.com>
When we probe PS/2 devices we first issue "Get ID" command and only if we
receive what we consider a valid keyboard or mouse ID we disable the device
and continue with protocol detection. That means that the device may be
transmitting motion or keystroke data, while we expect ACK response.
Instead of signaling failure if we see anything but ACK/NAK let's ignore
"garbage" response until we see ACK for the command byte (first byte). The
checks for subsequent ACKs of command parameters will continue be strict.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/serio/libps2.c | 25 ++++++++++++++++++++++---
include/linux/libps2.h | 1 +
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index f05c407b31f3d..e6a07e68d1ff6 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -256,16 +256,23 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
for (i = 0; i < receive; i++)
ps2dev->cmdbuf[(receive - 1) - i] = param[i];
+ /* Signal that we are sending the command byte */
+ ps2dev->flags |= PS2_FLAG_ACK_CMD;
+
/*
* Some devices (Synaptics) peform the reset before
* ACKing the reset command, and so it can take a long
* time before the ACK arrives.
*/
- rc = ps2_do_sendbyte(ps2dev, command & 0xff,
- command == PS2_CMD_RESET_BAT ? 1000 : 200, 2);
+ timeout = command == PS2_CMD_RESET_BAT ? 1000 : 200;
+
+ rc = ps2_do_sendbyte(ps2dev, command & 0xff, timeout, 2);
if (rc)
goto out_reset_flags;
+ /* Now we are sending command parameters, if any */
+ ps2dev->flags &= ~PS2_FLAG_ACK_CMD;
+
for (i = 0; i < send; i++) {
rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2);
if (rc)
@@ -416,7 +423,19 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
}
/* Fall through */
default:
- return false;
+ /*
+ * Do not signal errors if we get unexpected reply while
+ * waiting for an ACK to the initial (first) command byte:
+ * the device might not be quiesced yet and continue
+ * delivering data.
+ * Note that we reset PS2_FLAG_WAITID flag, so the workaround
+ * for mice not acknowledging the Get ID command only triggers
+ * on the 1st byte; if device spews data we really want to see
+ * a real ACK from it.
+ */
+ dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data);
+ ps2dev->flags &= ~PS2_FLAG_WAITID;
+ return ps2dev->flags & PS2_FLAG_ACK_CMD;
}
if (!ps2dev->nak) {
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index cd4454502a042..8b8139337e552 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -27,6 +27,7 @@
#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */
#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */
#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */
+#define PS2_FLAG_ACK_CMD BIT(5) /* Waiting to ACK the command (first) byte */
struct ps2dev {
struct serio *serio;
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* Re: [PATCH] HID: sony: Report DS4 version info through sysfs
From: Colenbrander, Roelof @ 2018-01-19 22:20 UTC (permalink / raw)
To: roderick@gaikai.com, linux-input@vger.kernel.org
Cc: Benjamin Tissoires, Jiri Kosina
In-Reply-To: <20171219190443.52950-1-roderick@gaikai.com>
Hi all,
Any thoughts on this patch?
Thanks,
Roderick
On 12/19/2017 11:05 AM, Roderick Colenbrander wrote:
> From: Roderick Colenbrander <roderick.colenbrander@sony.com>
>
> Report DS4 firmware and hardware version through sysfs for both
> USB and Bluetooth. This information is important for userspace
> in particular for device specific quirks (e.g. in Bluetooth stacks).
>
> Signed-off-by: Roderick Colenbrander <roderick.colenbrander@sony.com>
> ---
> drivers/hid/hid-sony.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 83 insertions(+)
>
> diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
> index b9dc3ac4d4aa..432d9a47cab0 100644
> --- a/drivers/hid/hid-sony.c
> +++ b/drivers/hid/hid-sony.c
> @@ -473,6 +473,7 @@ struct motion_output_report_02 {
> #define DS4_FEATURE_REPORT_0x02_SIZE 37
> #define DS4_FEATURE_REPORT_0x05_SIZE 41
> #define DS4_FEATURE_REPORT_0x81_SIZE 7
> +#define DS4_FEATURE_REPORT_0xA3_SIZE 49
> #define DS4_INPUT_REPORT_0x11_SIZE 78
> #define DS4_OUTPUT_REPORT_0x05_SIZE 32
> #define DS4_OUTPUT_REPORT_0x11_SIZE 78
> @@ -544,6 +545,8 @@ struct sony_sc {
> struct power_supply *battery;
> struct power_supply_desc battery_desc;
> int device_id;
> + unsigned fw_version;
> + unsigned hw_version;
> u8 *output_report_dmabuf;
>
> #ifdef CONFIG_SONY_FF
> @@ -627,6 +630,29 @@ static ssize_t ds4_store_poll_interval(struct device *dev,
> static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval,
> ds4_store_poll_interval);
>
> +static ssize_t sony_show_firmware_version(struct device *dev,
> + struct device_attribute
> + *attr, char *buf)
> +{
> + struct hid_device *hdev = to_hid_device(dev);
> + struct sony_sc *sc = hid_get_drvdata(hdev);
> +
> + return snprintf(buf, PAGE_SIZE, "0x%04x\n", sc->fw_version);
> +}
> +
> +static DEVICE_ATTR(firmware_version, 0444, sony_show_firmware_version, NULL);
> +
> +static ssize_t sony_show_hardware_version(struct device *dev,
> + struct device_attribute
> + *attr, char *buf)
> +{
> + struct hid_device *hdev = to_hid_device(dev);
> + struct sony_sc *sc = hid_get_drvdata(hdev);
> +
> + return snprintf(buf, PAGE_SIZE, "0x%04x\n", sc->hw_version);
> +}
> +
> +static DEVICE_ATTR(hardware_version, 0444, sony_show_hardware_version, NULL);
>
> static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
> unsigned int *rsize)
> @@ -1646,6 +1672,31 @@ static void dualshock4_calibration_work(struct work_struct *work)
> spin_unlock_irqrestore(&sc->lock, flags);
> }
>
> +static int dualshock4_get_version_info(struct sony_sc *sc)
> +{
> + u8 *buf;
> + int ret;
> +
> + buf = kmalloc(DS4_FEATURE_REPORT_0xA3_SIZE, GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + ret = hid_hw_raw_request(sc->hdev, 0xA3, buf,
> + DS4_FEATURE_REPORT_0xA3_SIZE,
> + HID_FEATURE_REPORT,
> + HID_REQ_GET_REPORT);
> + if (ret < 0) {
> + kfree(buf);
> + return ret;
> + }
> +
> + sc->hw_version = get_unaligned_le16(&buf[35]);
> + sc->fw_version = get_unaligned_le16(&buf[41]);
> +
> + kfree(buf);
> + return 0;
> +}
> +
> static void sixaxis_set_leds_from_id(struct sony_sc *sc)
> {
> static const u8 sixaxis_leds[10][4] = {
> @@ -2619,6 +2670,28 @@ static int sony_input_configured(struct hid_device *hdev,
> goto err_stop;
> }
>
> + ret = dualshock4_get_version_info(sc);
> + if (ret < 0) {
> + hid_err(sc->hdev, "Failed to get version data from Dualshock 4\n");
> + goto err_stop;
> + }
> +
> + ret = device_create_file(&sc->hdev->dev, &dev_attr_firmware_version);
> + if (ret) {
> + /* Make zero for cleanup reasons of sysfs entries. */
> + sc->fw_version = 0;
> + sc->hw_version = 0;
> + hid_err(sc->hdev, "can't create sysfs firmware_version attribute err: %d\n", ret);
> + goto err_stop;
> + }
> +
> + ret = device_create_file(&sc->hdev->dev, &dev_attr_hardware_version);
> + if (ret) {
> + sc->hw_version = 0;
> + hid_err(sc->hdev, "can't create sysfs hardware_version attribute err: %d\n", ret);
> + goto err_stop;
> + }
> +
> /*
> * The Dualshock 4 touchpad supports 2 touches and has a
> * resolution of 1920x942 (44.86 dots/mm).
> @@ -2695,6 +2768,10 @@ static int sony_input_configured(struct hid_device *hdev,
> */
> if (sc->ds4_bt_poll_interval)
> device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
> + if (sc->fw_version)
> + device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
> + if (sc->hw_version)
> + device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
> if (sc->quirks & SONY_LED_SUPPORT)
> sony_leds_remove(sc);
> if (sc->quirks & SONY_BATTERY_SUPPORT)
> @@ -2796,6 +2873,12 @@ static void sony_remove(struct hid_device *hdev)
> if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
> device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
>
> + if (sc->fw_version)
> + device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
> +
> + if (sc->hw_version)
> + device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
> +
> sony_cancel_work_sync(sc);
>
> kfree(sc->output_report_dmabuf);
>
^ permalink raw reply
* Re: [PATCH 3/7] Input: libps2 - use BIT() for bitmask constants
From: Randy Dunlap @ 2018-01-19 22:26 UTC (permalink / raw)
To: Dmitry Torokhov, Benjamin Tissoires, Hans de Goede, Lyude Paul
Cc: linux-input, linux-kernel
In-Reply-To: <20180119194111.185590-4-dmitry.torokhov@gmail.com>
On 01/19/2018 11:41 AM, Dmitry Torokhov wrote:
> Let's explicitly document bit numbers with BIT() macro.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Makes sense, but something should
#include <linux/bitops.h>
per Documentation/process/submit-checklist.rst Rule #1:
1) If you use a facility then #include the file that defines/declares
that facility. Don't depend on other header files pulling in ones
that you use.
> ---
> include/linux/libps2.h | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/libps2.h b/include/linux/libps2.h
> index 365c50b097ded..649295a5ff47d 100644
> --- a/include/linux/libps2.h
> +++ b/include/linux/libps2.h
> @@ -20,11 +20,11 @@
> #define PS2_RET_NAK 0xfe
> #define PS2_RET_ERR 0xfc
>
> -#define PS2_FLAG_ACK 1 /* Waiting for ACK/NAK */
> -#define PS2_FLAG_CMD 2 /* Waiting for command to finish */
> -#define PS2_FLAG_CMD1 4 /* Waiting for the first byte of command response */
> -#define PS2_FLAG_WAITID 8 /* Command execiting is GET ID */
> -#define PS2_FLAG_NAK 16 /* Last transmission was NAKed */
> +#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */
> +#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */
> +#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */
> +#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */
> +#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */
>
> struct ps2dev {
> struct serio *serio;
>
--
~Randy
^ permalink raw reply
* Re: [PATCH 3/7] Input: libps2 - use BIT() for bitmask constants
From: Dmitry Torokhov @ 2018-01-19 22:39 UTC (permalink / raw)
To: Randy Dunlap
Cc: Benjamin Tissoires, Hans de Goede, Lyude Paul, linux-input,
linux-kernel
In-Reply-To: <2d0591a7-ccab-872f-d52d-c8adf51d4373@infradead.org>
On Fri, Jan 19, 2018 at 02:26:20PM -0800, Randy Dunlap wrote:
> On 01/19/2018 11:41 AM, Dmitry Torokhov wrote:
> > Let's explicitly document bit numbers with BIT() macro.
> >
> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>
> Makes sense, but something should
> #include <linux/bitops.h>
Indeed, I'll add it, thanks.
>
> per Documentation/process/submit-checklist.rst Rule #1:
> 1) If you use a facility then #include the file that defines/declares
> that facility. Don't depend on other header files pulling in ones
> that you use.
>
>
> > ---
> > include/linux/libps2.h | 10 +++++-----
> > 1 file changed, 5 insertions(+), 5 deletions(-)
> >
> > diff --git a/include/linux/libps2.h b/include/linux/libps2.h
> > index 365c50b097ded..649295a5ff47d 100644
> > --- a/include/linux/libps2.h
> > +++ b/include/linux/libps2.h
> > @@ -20,11 +20,11 @@
> > #define PS2_RET_NAK 0xfe
> > #define PS2_RET_ERR 0xfc
> >
> > -#define PS2_FLAG_ACK 1 /* Waiting for ACK/NAK */
> > -#define PS2_FLAG_CMD 2 /* Waiting for command to finish */
> > -#define PS2_FLAG_CMD1 4 /* Waiting for the first byte of command response */
> > -#define PS2_FLAG_WAITID 8 /* Command execiting is GET ID */
> > -#define PS2_FLAG_NAK 16 /* Last transmission was NAKed */
> > +#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */
> > +#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */
> > +#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */
> > +#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */
> > +#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */
> >
> > struct ps2dev {
> > struct serio *serio;
> >
>
>
> --
> ~Randy
--
Dmitry
^ permalink raw reply
* [PATCH 5/7] Input: psmouse - add support for 2nd wheel on A4Tech Dual-Scroll wheel mice
From: Dmitry Torokhov @ 2018-01-19 23:06 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul
Cc: Stephen Lyons, linux-input, linux-kernel
In-Reply-To: <20180119230629.49428-1-dmitry.torokhov@gmail.com>
From: Stephen Lyons <slysven@virginmedia.com>
This Far-Eastern company's PS/2 mice use a deviant format for the data
relating to movement of the scroll wheels for, at least, their dual wheel
mice, such as their "Optical GreatEye Wheelmouse" model "WOP-35". This
product has five "buttons" (one of which is the click action on the first
wheel) and TWO scroll wheels. However for a byte comprising d0-d7 instead
of setting one of d6-7 in the forth byte of the mouse data packet and a
twos complement number of scroll steps in the remaining d5-d0 (or d3-d0
should there be a fourth (BTN_SIDE - d4) or fifth (BTN_EXTRA - d5) button
to report; they only report a single +/- event for each wheel and use a bit
pattern that corresponds to +/-1 for the first wheel and +/- 2 for the
second in the lower nibble of the fourth byte.
The effect with existing code is that the second mouse wheel merely repeats
the effect of the first but providing two steps per click rather than the
one of the first wheel - so there is no HORIZONTAL scroll wheel movement
detected from the device as far as the rest of the kernel sees it.
This patch, if enabled by the "a4tech_workaround" module parameter modifies
the handling just for mice of type PSMOUSE_IMEX so that the second scroll
wheel movement gets correctly reported as REL_HWHEEL events. Should this
module parameter be activated for other mice of the same PSMOUSE_IMEX type
then it is possible that at the point where the mouse reports more than a
single movement step the user may start seeing horizontal rather than
vertical wheel events, but should the movement steps get to be more than
two at a time the hack will get immediately deactivated and the behaviour
will revert to the past code.
This was discussed around *fifteen* *years* *ago* on the LKML and the best
summary is in post https://lkml.org/lkml/2002/7/18/111 "Re: PS2 Input Core
Support" by Vojtech Pavlik. I was not able to locate any discussion later
than this on this topic.
Given that most users of the "psmouse" module will NOT want this additional
feature enabled I have taken the apparently erroneous step of defaulting
the module parameter that enables it to be "disabled" - this functionality
may interfere with the operation of "normal" mice of this type (until a
large enough scroll wheel movement is detected) so I cannot see how it
would want to be enabled for "normal" users - i.e. everyone without this
brand of mouse.
I am using this patch at the moment and I can confirm that it is working
for me as both a module and compiled into the kernel for my mouse that is
of the type (WOP-35) described - I note that it is still available from
certain on-line retailers and that the manufacturers site does not list
GNU/Linux as being supported on the product page - this patch however does
enable full use of this product:
http://www.a4tech.com/product.asp?cid=3D1&scid=3D8&id=3D22
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/mouse/psmouse-base.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index cbca668bb931f..d0e45124e7f43 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -70,6 +70,10 @@ static bool psmouse_smartscroll = true;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
+static bool psmouse_a4tech_2wheels;
+module_param_named(a4tech_workaround, psmouse_a4tech_2wheels, bool, 0644);
+MODULE_PARM_DESC(a4tech_workaround, "A4Tech second scroll wheel workaround, 1 = enabled, 0 = disabled (default).");
+
static unsigned int psmouse_resetafter = 5;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
@@ -150,6 +154,7 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
u8 *packet = psmouse->packet;
+ int wheel;
if (psmouse->pktcnt < psmouse->pktsize)
return PSMOUSE_GOOD_DATA;
@@ -175,8 +180,18 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
break;
case 0x00:
case 0xC0:
- input_report_rel(dev, REL_WHEEL,
- -sign_extend32(packet[3], 3));
+ wheel = sign_extend32(packet[3], 3);
+
+ /*
+ * Some A4Tech mice have two scroll wheels, with first
+ * one reporting +/-1 in the lower nibble, and second
+ * one reporting +/-2.
+ */
+ if (psmouse_a4tech_2wheels && abs(wheel) > 1)
+ input_report_rel(dev, REL_HWHEEL, wheel / 2);
+ else
+ input_report_rel(dev, REL_WHEEL, -wheel);
+
input_report_key(dev, BTN_SIDE, BIT(4));
input_report_key(dev, BTN_EXTRA, BIT(5));
break;
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 0/7] psmouse assorted cleanups
From: Dmitry Torokhov @ 2018-01-19 23:06 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
Hi,
Just a few cleanups to psmouse code: BIT(), sign_extend(), u8 for data,
etc. Plus a patch from Stephen Lyons to handle A4Tech mice with 2 scroll
wheels.
Thanks.
Dmitry Torokhov (6):
Input: psmouse - create helper for reporting standard buttons/motion
Input: psmouse - clean up code
Input: logips2pp - clean up code
Input: lifebook - clean up code
Input: synaptics - switch to using input_set_capability
Input: synaptics - handle errors from input_mt_init_slots()
Stephen Lyons (1):
Input: psmouse - add support for 2nd wheel on A4Tech Dual-Scroll wheel
mice
drivers/input/mouse/alps.c | 30 ++----
drivers/input/mouse/elantech.c | 28 ++----
drivers/input/mouse/lifebook.c | 62 +++++++------
drivers/input/mouse/logips2pp.c | 152 ++++++++++++++++++-------------
drivers/input/mouse/psmouse-base.c | 181 +++++++++++++++++++++++--------------
drivers/input/mouse/psmouse.h | 4 +
drivers/input/mouse/sentelic.c | 11 +--
drivers/input/mouse/synaptics.c | 82 ++++++++++-------
8 files changed, 302 insertions(+), 248 deletions(-)
--
Dmitry
^ permalink raw reply
* [PATCH 1/7] Input: psmouse - create helper for reporting standard buttons/motion
From: Dmitry Torokhov @ 2018-01-19 23:06 UTC (permalink / raw)
To: Benjamin Tissoires, Hans de Goede, Lyude Paul; +Cc: linux-input, linux-kernel
In-Reply-To: <20180119230629.49428-1-dmitry.torokhov@gmail.com>
Many protocol driver re-implement code to parse buttons or motion data from
the standard PS/2 protocol. Let's split the parsing into separate
functions and reuse them in protocol drivers.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/mouse/alps.c | 30 +++++++-----------------------
drivers/input/mouse/elantech.c | 28 ++++++++++------------------
drivers/input/mouse/lifebook.c | 12 ++++--------
drivers/input/mouse/logips2pp.c | 10 ++++------
drivers/input/mouse/psmouse-base.c | 26 ++++++++++++++++++++------
drivers/input/mouse/psmouse.h | 4 ++++
drivers/input/mouse/sentelic.c | 11 +----------
7 files changed, 50 insertions(+), 71 deletions(-)
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index dbe57da8c1a1b..f9c7f24522644 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -827,7 +827,7 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
unsigned char *packet = psmouse->packet;
struct input_dev *dev = psmouse->dev;
struct input_dev *dev2 = priv->dev2;
- int x, y, z, left, right, middle;
+ int x, y, z;
/*
* We can use Byte5 to distinguish if the packet is from Touchpad
@@ -847,9 +847,6 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
x = packet[1] | ((packet[3] & 0x20) << 2);
y = packet[2] | ((packet[3] & 0x40) << 1);
z = packet[4];
- left = packet[3] & 0x01;
- right = packet[3] & 0x02;
- middle = packet[3] & 0x04;
/* To prevent the cursor jump when finger lifted */
if (x == 0x7F && y == 0x7F && z == 0x7F)
@@ -859,9 +856,7 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
input_report_rel(dev2, REL_X, (char)x / 4);
input_report_rel(dev2, REL_Y, -((char)y / 4));
- input_report_key(dev2, BTN_LEFT, left);
- input_report_key(dev2, BTN_RIGHT, right);
- input_report_key(dev2, BTN_MIDDLE, middle);
+ psmouse_report_standard_buttons(dev2, packet[3]);
input_sync(dev2);
return;
@@ -871,8 +866,6 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
x = packet[1] | ((packet[3] & 0x78) << 4);
y = packet[2] | ((packet[4] & 0x78) << 4);
z = packet[5];
- left = packet[3] & 0x01;
- right = packet[3] & 0x02;
if (z > 30)
input_report_key(dev, BTN_TOUCH, 1);
@@ -888,8 +881,8 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
/* v6 touchpad does not have middle button */
- input_report_key(dev, BTN_LEFT, left);
- input_report_key(dev, BTN_RIGHT, right);
+ packet[3] &= ~BIT(2);
+ psmouse_report_standard_buttons(dev2, packet[3]);
input_sync(dev);
}
@@ -1098,7 +1091,7 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
struct input_dev *dev2 = priv->dev2;
- int x, y, z, left, right, middle;
+ int x, y, z;
/* It should be a DualPoint when received trackstick packet */
if (!(priv->flags & ALPS_DUALPOINT)) {
@@ -1112,16 +1105,10 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
((packet[3] & 0x20) << 1);
z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
- left = (packet[1] & 0x01);
- right = (packet[1] & 0x02) >> 1;
- middle = (packet[1] & 0x04) >> 2;
-
input_report_rel(dev2, REL_X, (char)x);
input_report_rel(dev2, REL_Y, -((char)y));
- input_report_key(dev2, BTN_LEFT, left);
- input_report_key(dev2, BTN_RIGHT, right);
- input_report_key(dev2, BTN_MIDDLE, middle);
+ psmouse_report_standard_buttons(dev2, packet[1]);
input_sync(dev2);
}
@@ -1503,10 +1490,7 @@ static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
alps_report_buttons(dev, dev2,
packet[0] & 1, packet[0] & 2, packet[0] & 4);
- input_report_rel(dev, REL_X,
- packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
- input_report_rel(dev, REL_Y,
- packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
+ psmouse_report_standard_motion(dev, packet);
input_sync(dev);
}
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index a4aaa748e987f..af7fc17c14d96 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -279,8 +279,8 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
- input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+
+ psmouse_report_standard_buttons(dev, packet[0]);
if (etd->fw_version < 0x020000 &&
(etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
@@ -390,8 +390,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
- input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+ psmouse_report_standard_buttons(dev, packet[0]);
if (etd->reports_pressure) {
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
@@ -434,9 +433,7 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
x = packet[4] - (int)((packet[1]^0x80) << 1);
y = (int)((packet[2]^0x80) << 1) - packet[5];
- input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
- input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
+ psmouse_report_standard_buttons(tp_dev, packet[0]);
input_report_rel(tp_dev, REL_X, x);
input_report_rel(tp_dev, REL_Y, y);
@@ -526,12 +523,10 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
/* For clickpads map both buttons to BTN_LEFT */
- if (etd->fw_version & 0x001000) {
+ if (etd->fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
- } else {
- input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
- }
+ else
+ psmouse_report_standard_buttons(dev, packet[0]);
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
@@ -546,13 +541,10 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
unsigned char *packet = psmouse->packet;
/* For clickpads map both buttons to BTN_LEFT */
- if (etd->fw_version & 0x001000) {
+ if (etd->fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
- } else {
- input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
- input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04);
- }
+ else
+ psmouse_report_standard_buttons(dev, packet[0]);
input_mt_report_pointer_emulation(dev, true);
input_sync(dev);
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 13d324cef7df5..65efaade0820d 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -188,14 +188,10 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
}
if (dev2) {
- if (relative_packet) {
- input_report_rel(dev2, REL_X,
- ((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
- input_report_rel(dev2, REL_Y,
- -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
- }
- input_report_key(dev2, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev2, BTN_RIGHT, packet[0] & 0x02);
+ if (relative_packet)
+ psmouse_report_standard_motion(dev2, packet);
+
+ psmouse_report_standard_buttons(dev2, packet[0]);
input_sync(dev2);
}
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index ef9c97f5e3d78..b7d17db632fc0 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -88,16 +88,14 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse)
(packet[1] >> 4) | (packet[0] & 0x30));
break;
}
+
+ psmouse_report_standard_buttons(dev, packet[0]);
+
} else {
/* Standard PS/2 motion data */
- input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0);
- input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
+ psmouse_report_standard_packet(dev, packet);
}
- input_report_key(dev, BTN_LEFT, packet[0] & 1);
- input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1);
- input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1);
-
input_sync(dev);
return PSMOUSE_FULL_PACKET;
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 8ac9e03c05b45..19f7727555911 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -116,13 +116,30 @@ static DEFINE_MUTEX(psmouse_mutex);
static struct workqueue_struct *kpsmoused_wq;
-static void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
+void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
{
input_report_key(dev, BTN_LEFT, buttons & BIT(0));
input_report_key(dev, BTN_MIDDLE, buttons & BIT(2));
input_report_key(dev, BTN_RIGHT, buttons & BIT(1));
}
+void psmouse_report_standard_motion(struct input_dev *dev, u8 *packet)
+{
+ int x, y;
+
+ x = packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0;
+ y = packet[2] ? packet[2] - ((packet[0] << 3) & 0x100) : 0;
+
+ input_report_rel(dev, REL_X, x);
+ input_report_rel(dev, REL_Y, -y);
+}
+
+void psmouse_report_standard_packet(struct input_dev *dev, u8 *packet)
+{
+ psmouse_report_standard_buttons(dev, packet[0]);
+ psmouse_report_standard_motion(dev, packet);
+}
+
/*
* psmouse_process_byte() analyzes the PS/2 data stream and reports
* relevant events to the input module once full packet has arrived.
@@ -195,11 +212,8 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
}
/* Generic PS/2 Mouse */
- psmouse_report_standard_buttons(dev,
- packet[0] | psmouse->extra_buttons);
-
- input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0);
- input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
+ packet[0] |= psmouse->extra_buttons;
+ psmouse_report_standard_packet(dev, packet);
input_sync(dev);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 8cd453808cc7d..8bc99691494e9 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -140,6 +140,10 @@ int psmouse_activate(struct psmouse *psmouse);
int psmouse_deactivate(struct psmouse *psmouse);
bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]);
+void psmouse_report_standard_buttons(struct input_dev *, u8 buttons);
+void psmouse_report_standard_motion(struct input_dev *, u8 *packet);
+void psmouse_report_standard_packet(struct input_dev *, u8 *packet);
+
struct psmouse_attribute {
struct device_attribute dattr;
void *data;
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index 11c32ac8234b2..1d6010d463e2c 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -710,7 +710,6 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
unsigned char *packet = psmouse->packet;
unsigned char button_status = 0, lscroll = 0, rscroll = 0;
unsigned short abs_x, abs_y, fgrs = 0;
- int rel_x, rel_y;
if (psmouse->pktcnt < 4)
return PSMOUSE_GOOD_DATA;
@@ -840,15 +839,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
/*
* Standard PS/2 Mouse
*/
- input_report_key(dev, BTN_LEFT, packet[0] & 1);
- input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1);
- input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1);
-
- rel_x = packet[1] ? (int)packet[1] - (int)((packet[0] << 4) & 0x100) : 0;
- rel_y = packet[2] ? (int)((packet[0] << 3) & 0x100) - (int)packet[2] : 0;
-
- input_report_rel(dev, REL_X, rel_x);
- input_report_rel(dev, REL_Y, rel_y);
+ psmouse_report_standard_packet(dev, packet);
break;
}
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox