Linux Input/HID development
 help / color / mirror / Atom feed
* Re: About Dell Inspiron 3442 touchpad
From: Benjamin Tissoires @ 2014-10-29  1:40 UTC (permalink / raw)
  To: Luiz Carlos Ramos; +Cc: linux-input
In-Reply-To: <1414544444.169720.184461733.4C6DF47C@webmail.messagingengine.com>

Hi Luiz,

On Tue, Oct 28, 2014 at 9:00 PM, Luiz Carlos Ramos
<lramos.prof@yahoo.com.br> wrote:
> Hello,
>
> I'm trying to make a touchpad from a Dell Inspiron I14-3442 laptop work.
>
> Some details:
>
> - I'm using plain Slackware64 14.1, but raised the kernel to 3.16.3 for
> tests
>
> - xinput ignores the touchpad; it shows only a USB mouse/keyboard
> adapter and the laptop's keyboard:
>
> root@pace:/sys/bus/hid/devices# xinput
>  Virtual core pointer                            id=2    [master pointer
>   (3)]
>      Virtual core XTEST pointer                      id=4    [slave
>      pointer  (2)]
>      Generic USB K/B                                 id=12   [slave
>      pointer  (2)]
>   Virtual core keyboard                           id=3    [master
>   keyboard (2)]
>       Virtual core XTEST keyboard                     id=5    [slave
>       keyboard (3)]
>       Power Button                                    id=6    [slave
>       keyboard (3)]
>       Video Bus                                       id=7    [slave
>       keyboard (3)]
>       Power Button                                    id=9    [slave
>       keyboard (3)]
>       Sleep Button                                    id=10   [slave
>       keyboard (3)]
>       Integrated_Webcam_HD                            id=13   [slave
>       keyboard (3)]
>       AT Translated Set 2 keyboard                    id=14   [slave
>       keyboard (3)]
>       Dell WMI hotkeys                                id=15   [slave
>       keyboard (3)]
>       Video Bus                                       id=8    [slave
>       keyboard (3)]
>       Generic USB K/B                                 id=11   [slave
>       keyboard (3)]
>
> - it seems Ubuntu certified this machine (check
> http://www.ubuntu.com/certification/hardware/201402-14674/components/),
> but it assumes the touchpad is PS/2. I haven't found it as a PS/2 thing,
> even loading psmouse.ko, or doing other tricks
>
> - some articles lists some tips for making it work (like
> http://askubuntu.com/questions/134627/how-do-i-get-the-touchpad-settings-working-on-a-dell-xps-13-ultrabook,
> or https://bugzilla.redhat.com/show_bug.cgi?id=1048314#c2), but I read
> them carefully, made some tests, and they didn't work. One article says
> I could blacklist i2c_hid or like in order to make the bring up the
> touchpad in PS/2 mode, but I couldn't succeed doing so
>
> - at Dell's site, it is offered a driver for Ubuntu 12.04, but it's
> almost obsolete. It seems to be just merged into the kernel
>
> - from Windows 8.1, which runs in the same machine (dual boot), I
> concluded the proper way of making it work is to use HID over I2C. It
> seems that there are two components loaded; one I2CHID, and a Synaptics
> HID. This makes me hint it may be a Synaptics device

Well, if this is a Synaptics HID over I2C device, it should be handled
by hid-rmi in recent kernels (or hid-multitouch but I would say
hid-rmi in your case).
Is the hid-rmi module loaded? Can we get a dmesg output so we can see
if there is any problem?

>
> - it seems there are two I2C busses in the machine. One is related to
> the Intel video graphics subsystem (i801). The other seems to be linked
> to the touchpad (i2c_designware_platform). I'm not sure that latest kmod
> (i2c_designware_platform) is the right one to be used in this case, but
> it appears to be working:

Yeah, i2c_designware_platform is pretty common for Haswell processors.

>
> root@pace:/sys/bus/i2c/devices# ls -l /sys/bus/i2c/devices
> total 0
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-0 ->
> ../../../devices/pci0000:00/INT33C2:00/i2c-0
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-1 ->
> ../../../devices/pci0000:00/INT33C3:00/i2c-1
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-2 ->
> ../../../devices/pci0000:00/0000:00:02.0/i2c-2
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-3 ->
> ../../../devices/pci0000:00/0000:00:02.0/i2c-3
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-4 ->
> ../../../devices/pci0000:00/0000:00:02.0/i2c-4
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-5 ->
> ../../../devices/pci0000:00/0000:00:02.0/i2c-5
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-6 ->
> ../../../devices/pci0000:00/0000:00:02.0/i2c-6
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-7 ->
> ../../../devices/pci0000:00/0000:00:02.0/i2c-7
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-8 ->
> ../../../devices/pci0000:00/0000:00:02.0/i2c-8
> lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-DLL0652:00 ->
> ../../../devices/pci0000:00/INT33C3:00/i2c-1/i2c-DLL0652:00

This one is the touchpad.

>
> root@pace:/sys/bus/i2c/devices# lsmod | grep i2c
> i2c_hid                10682  0
> hid                    94632  3 i2c_hid,hid_generic,usbhid
> i2c_dev                 5739  0
> i2c_designware_platform     3189  0
> i2c_i801               13732  0
> i2c_designware_core     6045  1 i2c_designware_platform
> i2c_algo_bit            5351  1 i915
> i2c_core               35216  11
> drm,i915,i2c_i801,i2c_dev,i2c_hid,i2c_designware_platform,drm_kms_helper,i2c_algo_bit,v4l2_common,synaptics_i2c,videodev
>
> - in the HID /sys directory, there are three devices. Two are related to
> a keyboard/mouse USB adapter. The third seems to be the linked to the
> touchpad:
>
> root@pace:/sys/bus/hid/devices# ls -l /sys/bus/hid/devices
> total 0
> lrwxrwxrwx 1 root root 0 Out 28 22:40 0003:13BA:0017.004F ->
> ../../../devices/pci0000:00/0000:00:1d.0/usb3/3-1/3-1.3/3-1.3:1.0/0003:13BA:0017.004F
> lrwxrwxrwx 1 root root 0 Out 28 22:40 0003:13BA:0017.0050 ->
> ../../../devices/pci0000:00/0000:00:1d.0/usb3/3-1/3-1.3/3-1.3:1.1/0003:13BA:0017.0050
> lrwxrwxrwx 1 root root 0 Out 28 22:40 0018:06CB:2985.0052 ->
> ../../../devices/pci0000:00/INT33C3:00/i2c-1/i2c-DLL0652:00/0018:06CB:2985.0052

This is the HID over I2C touchpad.

>
> - when I load the kernel module i2c-hid.ko (with debug=1), I read this
> in dmesg:
>
> [146172.568787] i2c_hid i2c-DLL0652:00: Fetching the HID descriptor
> [146172.568791] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=20 00
> [146172.574806] i2c_hid i2c-DLL0652:00: HID Descriptor: 1e 00 00 01 85
> 00 21 00 24 00 20 00 25 00 17 00 22 00 23 00 cb 06 85 29 00 00 00 00 00
> 00
> [146172.574845] i2c_hid i2c-DLL0652:00: entering i2c_hid_parse
> [146172.574847] i2c_hid i2c-DLL0652:00: i2c_hid_hwreset
> [146172.574849] i2c_hid i2c-DLL0652:00: i2c_hid_set_power
> [146172.574850] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 00
> 08
> [146172.575436] i2c_hid i2c-DLL0652:00: resetting...
> [146172.575442] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 00
> 01
> [146172.576113] i2c_hid i2c-DLL0652:00: __i2c_hid_command: waiting...
> [146172.577414] i2c_hid i2c-DLL0652:00: __i2c_hid_command: finished.
> [146172.577417] i2c_hid i2c-DLL0652:00: asking HID report descriptor
> [146172.577419] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=21 00
> [146172.581072] i2c_hid i2c-DLL0652:00: Report Descriptor: 05 01 09 02
> a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02
> 95 06 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 06 00
> ff 09 01 a1 01 85 09 09 02 15 00 26
> [146172.581126] i2c_hid i2c-DLL0652:00: i2c_hid_set_power
> [146172.581129] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 01
> 08

Everything is fine, this is the normal behavior while connecting a
i2c_hid device.
Normally, we should have then hid-rmi asking for more things and then
it will eventually set up the input device.

>
> I am aware this information probably is not sufficient to draw any
> conclusions, but I'd appreciate to hear from someone who knows i2c_hid
> in detail what steps I should take next. For me the last command timed
> out or got stuck, but I haven't checked the code to see if it's the
> case. Anyway, if it was a timeout case, it should have something logged
> after the time expired.

There is no answer from the device when a SET_POWER is emitted. So
this is not a timeout problem.

If hid-rmi is compiled and is not taking the device, we have a big
problem, but for now, the symptoms look like you do not have this
driver compiled and hid-generic does not bind the device because it
waits for hid-rmi to handle it.

>
> I have some programming skills, and so if it's the case of applying any
> patches, or recompiling the kernel or any subsystem to make tests, I'm
> up to.

Cool, thanks.

Cheers,
Benjamin

^ permalink raw reply

* Re: [PATCH 11/15] sound: soc: poodle: make use of new locomo GPIO interface
From: Alexandre Courbot @ 2014-10-29  3:03 UTC (permalink / raw)
  To: Mark Brown
  Cc: Dmitry Eremin-Solenikov, linux-arm-kernel@lists.infradead.org,
	linux-gpio@vger.kernel.org, linux-input, linux-leds, linux-spi,
	linux-fbdev@vger.kernel.org, alsa-devel@alsa-project.org,
	Andrea Adami, Russell King, Daniel Mack, Haojian Zhuang,
	Robert Jarzmik, Linus Walleij, Dmitry Torokhov, Bryan Wu,
	Richard Purdie, Samuel Ortiz, Lee Jones, Jingoo Han,
	Liam Girdwood
In-Reply-To: <20141028145850.GU18557@sirena.org.uk>

On Tue, Oct 28, 2014 at 11:58 PM, Mark Brown <broonie@kernel.org> wrote:
> On Tue, Oct 28, 2014 at 03:02:04AM +0300, Dmitry Eremin-Solenikov wrote:
>> Since LoCoMo driver has been converted to provide proper gpiolib
>> interface, make poodle ASoC platform driver use gpiolib API.
>
> Please use subject lines matching the style for the subsystem.
>
>> +     ret = gpio_request_array(poodle_gpios, ARRAY_SIZE(poodle_gpios));
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "gpio_request_array() failed: %d\n",
>> +                             ret);
>> +             return ret;
>> +     }
>
> I sense a need for devm_gpio_request_array() here.  Otherwise this looks
> fine - ideally it'd move to gpiod but moving to gpiolib is a clear win
> so no need to block on this.

I wish Dmitry took the opportunity to move this driver to the gpiod
API, especially since doing so would be trivial for this driver. Not a
critical requirement though, the present patch is already an
improvement. But if you want to do that last step, please have a look
at Documentation/gpio/consumer.txt and the "Platform Data" section of
Documentation/gpio/board.txt.

^ permalink raw reply

* Re: [PATCH] Input: max77693-haptic - fix potential overflow
From: Jaewon Kim @ 2014-10-29  3:22 UTC (permalink / raw)
  To: Dmitry Torokhov, linux-input; +Cc: Chanwoo Choi, linux-kernel
In-Reply-To: <20141028164322.GA13234@dtor-ws>

Hi Dmitry,

2014년 10월 29일 01:43에 Dmitry Torokhov 이(가) 쓴 글:
> Expression haptic->pwm_dev->period * haptic->magnitude is of type 'unsigned
> int' and may overflow. We need to convert one of the operands to u64 before
> multiplying, instead of casting result (potentially overflown) to u64.
>
> Reported by Coverity: CID 1248753
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>   drivers/input/misc/max77693-haptic.c | 5 ++---
>   1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
> index 7b1fde9..ef6a9d6 100644
> --- a/drivers/input/misc/max77693-haptic.c
> +++ b/drivers/input/misc/max77693-haptic.c
> @@ -194,7 +194,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
>   				       struct ff_effect *effect)
>   {
>   	struct max77693_haptic *haptic = input_get_drvdata(dev);
> -	uint64_t period_mag_multi;
> +	u64 period_mag_multi;
>   
>   	haptic->magnitude = effect->u.rumble.strong_magnitude;
>   	if (!haptic->magnitude)
> @@ -205,8 +205,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
>   	 * The formula to convert magnitude to pwm_duty as follows:
>   	 * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
>   	 */
> -	period_mag_multi = (int64_t)(haptic->pwm_dev->period *
> -						haptic->magnitude);
> +	period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude;
>   	haptic->pwm_duty = (unsigned int)(period_mag_multi >>
>   						MAX_MAGNITUDE_SHIFT);
>   


There was casting miss in multiplying.
Thanks.

Acked-by : Jaewon Kim <jaewon02.kim@samsung.com>

^ permalink raw reply

* Re: [PATCH] Input: max77693-haptic - fix potential overflow
From: Chanwoo Choi @ 2014-10-29  4:34 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, Jaewon Kim, linux-kernel
In-Reply-To: <20141028164322.GA13234@dtor-ws>

On 10/29/2014 01:43 AM, Dmitry Torokhov wrote:
> Expression haptic->pwm_dev->period * haptic->magnitude is of type 'unsigned
> int' and may overflow. We need to convert one of the operands to u64 before
> multiplying, instead of casting result (potentially overflown) to u64.
> 
> Reported by Coverity: CID 1248753
> 
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>  drivers/input/misc/max77693-haptic.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
> index 7b1fde9..ef6a9d6 100644
> --- a/drivers/input/misc/max77693-haptic.c
> +++ b/drivers/input/misc/max77693-haptic.c
> @@ -194,7 +194,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
>  				       struct ff_effect *effect)
>  {
>  	struct max77693_haptic *haptic = input_get_drvdata(dev);
> -	uint64_t period_mag_multi;
> +	u64 period_mag_multi;
>  
>  	haptic->magnitude = effect->u.rumble.strong_magnitude;
>  	if (!haptic->magnitude)
> @@ -205,8 +205,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
>  	 * The formula to convert magnitude to pwm_duty as follows:
>  	 * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
>  	 */
> -	period_mag_multi = (int64_t)(haptic->pwm_dev->period *
> -						haptic->magnitude);
> +	period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude;
>  	haptic->pwm_duty = (unsigned int)(period_mag_multi >>
>  						MAX_MAGNITUDE_SHIFT);
>  
> 

Looks good to me.

Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>

Thanks,
Chanwoo Choi

^ permalink raw reply

* [PATCH 1/3] Input: misc - Use __maybe_unused instead of ifdef around suspend/resume
From: Jingoo Han @ 2014-10-29  5:18 UTC (permalink / raw)
  To: 'Dmitry Torokhov'; +Cc: linux-input, 'Jingoo Han'

Use __maybe_unused instead of ifdef guards around suspend/resume
functions, in order to increase build coverage and fix build warnings.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 drivers/input/misc/88pm860x_onkey.c   |    6 ++----
 drivers/input/misc/ad714x-i2c.c       |    6 ++----
 drivers/input/misc/ad714x-spi.c       |    6 ++----
 drivers/input/misc/adxl34x-i2c.c      |    6 ++----
 drivers/input/misc/adxl34x-spi.c      |    6 ++----
 drivers/input/misc/drv260x.c          |    6 ++----
 drivers/input/misc/drv2667.c          |    6 ++----
 drivers/input/misc/gp2ap002a00f.c     |    6 ++----
 drivers/input/misc/kxtj9.c            |    6 ++----
 drivers/input/misc/max77693-haptic.c  |    6 ++----
 drivers/input/misc/max8925_onkey.c    |    6 ++----
 drivers/input/misc/max8997_haptic.c   |    4 +---
 drivers/input/misc/palmas-pwrbutton.c |    6 ++----
 drivers/input/misc/pm8xxx-vibrator.c  |    4 +---
 drivers/input/misc/pmic8xxx-pwrkey.c  |    6 ++----
 drivers/input/misc/pwm-beeper.c       |    6 +++---
 drivers/input/misc/sirfsoc-onkey.c    |    4 +---
 drivers/input/misc/twl4030-vibra.c    |    6 ++----
 drivers/input/misc/twl6040-vibra.c    |    4 +---
 19 files changed, 35 insertions(+), 71 deletions(-)

diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
index 220ce0f..3cbd1b3 100644
--- a/drivers/input/misc/88pm860x_onkey.c
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -112,8 +112,7 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int pm860x_onkey_suspend(struct device *dev)
+static int __maybe_unused pm860x_onkey_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -122,7 +121,7 @@ static int pm860x_onkey_suspend(struct device *dev)
 		chip->wakeup_flag |= 1 << PM8607_IRQ_ONKEY;
 	return 0;
 }
-static int pm860x_onkey_resume(struct device *dev)
+static int __maybe_unused pm860x_onkey_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
@@ -131,7 +130,6 @@ static int pm860x_onkey_resume(struct device *dev)
 		chip->wakeup_flag &= ~(1 << PM8607_IRQ_ONKEY);
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(pm860x_onkey_pm_ops, pm860x_onkey_suspend, pm860x_onkey_resume);
 
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index e0f5225..189bdc8 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -13,17 +13,15 @@
 #include <linux/pm.h>
 #include "ad714x.h"
 
-#ifdef CONFIG_PM_SLEEP
-static int ad714x_i2c_suspend(struct device *dev)
+static int __maybe_unused ad714x_i2c_suspend(struct device *dev)
 {
 	return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev)));
 }
 
-static int ad714x_i2c_resume(struct device *dev)
+static int __maybe_unused ad714x_i2c_resume(struct device *dev)
 {
 	return ad714x_enable(i2c_get_clientdata(to_i2c_client(dev)));
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume);
 
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
index 3a90b71..a79e50b 100644
--- a/drivers/input/misc/ad714x-spi.c
+++ b/drivers/input/misc/ad714x-spi.c
@@ -16,17 +16,15 @@
 #define AD714x_SPI_CMD_PREFIX      0xE000   /* bits 15:11 */
 #define AD714x_SPI_READ            BIT(10)
 
-#ifdef CONFIG_PM_SLEEP
-static int ad714x_spi_suspend(struct device *dev)
+static int __maybe_unused ad714x_spi_suspend(struct device *dev)
 {
 	return ad714x_disable(spi_get_drvdata(to_spi_device(dev)));
 }
 
-static int ad714x_spi_resume(struct device *dev)
+static int __maybe_unused ad714x_spi_resume(struct device *dev)
 {
 	return ad714x_enable(spi_get_drvdata(to_spi_device(dev)));
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume);
 
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index 416f47d..470bfd6 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -105,8 +105,7 @@ static int adxl34x_i2c_remove(struct i2c_client *client)
 	return adxl34x_remove(ac);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int adxl34x_i2c_suspend(struct device *dev)
+static int __maybe_unused adxl34x_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adxl34x *ac = i2c_get_clientdata(client);
@@ -116,7 +115,7 @@ static int adxl34x_i2c_suspend(struct device *dev)
 	return 0;
 }
 
-static int adxl34x_i2c_resume(struct device *dev)
+static int __maybe_unused adxl34x_i2c_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adxl34x *ac = i2c_get_clientdata(client);
@@ -125,7 +124,6 @@ static int adxl34x_i2c_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend,
 			 adxl34x_i2c_resume);
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
index 76dc067..da6e76b 100644
--- a/drivers/input/misc/adxl34x-spi.c
+++ b/drivers/input/misc/adxl34x-spi.c
@@ -94,8 +94,7 @@ static int adxl34x_spi_remove(struct spi_device *spi)
 	return adxl34x_remove(ac);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int adxl34x_spi_suspend(struct device *dev)
+static int __maybe_unused adxl34x_spi_suspend(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct adxl34x *ac = spi_get_drvdata(spi);
@@ -105,7 +104,7 @@ static int adxl34x_spi_suspend(struct device *dev)
 	return 0;
 }
 
-static int adxl34x_spi_resume(struct device *dev)
+static int __maybe_unused adxl34x_spi_resume(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct adxl34x *ac = spi_get_drvdata(spi);
@@ -114,7 +113,6 @@ static int adxl34x_spi_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
 			 adxl34x_spi_resume);
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index cab87f5..a364e10 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -639,8 +639,7 @@ static int drv260x_probe(struct i2c_client *client,
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int drv260x_suspend(struct device *dev)
+static int __maybe_unused drv260x_suspend(struct device *dev)
 {
 	struct drv260x_data *haptics = dev_get_drvdata(dev);
 	int ret = 0;
@@ -672,7 +671,7 @@ out:
 	return ret;
 }
 
-static int drv260x_resume(struct device *dev)
+static int __maybe_unused drv260x_resume(struct device *dev)
 {
 	struct drv260x_data *haptics = dev_get_drvdata(dev);
 	int ret = 0;
@@ -702,7 +701,6 @@ out:
 	mutex_unlock(&haptics->input_dev->mutex);
 	return ret;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume);
 
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index 0f43758..a021744 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -406,8 +406,7 @@ static int drv2667_probe(struct i2c_client *client,
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int drv2667_suspend(struct device *dev)
+static int __maybe_unused drv2667_suspend(struct device *dev)
 {
 	struct drv2667_data *haptics = dev_get_drvdata(dev);
 	int ret = 0;
@@ -436,7 +435,7 @@ out:
 	return ret;
 }
 
-static int drv2667_resume(struct device *dev)
+static int __maybe_unused drv2667_resume(struct device *dev)
 {
 	struct drv2667_data *haptics = dev_get_drvdata(dev);
 	int ret = 0;
@@ -464,7 +463,6 @@ out:
 	mutex_unlock(&haptics->input_dev->mutex);
 	return ret;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
 
diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c
index de21e31..0ac176d 100644
--- a/drivers/input/misc/gp2ap002a00f.c
+++ b/drivers/input/misc/gp2ap002a00f.c
@@ -225,8 +225,7 @@ static int gp2a_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int gp2a_suspend(struct device *dev)
+static int __maybe_unused gp2a_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gp2a_data *dt = i2c_get_clientdata(client);
@@ -244,7 +243,7 @@ static int gp2a_suspend(struct device *dev)
 	return retval;
 }
 
-static int gp2a_resume(struct device *dev)
+static int __maybe_unused gp2a_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gp2a_data *dt = i2c_get_clientdata(client);
@@ -261,7 +260,6 @@ static int gp2a_resume(struct device *dev)
 
 	return retval;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(gp2a_pm, gp2a_suspend, gp2a_resume);
 
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index d708478..6e29349 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -615,8 +615,7 @@ static int kxtj9_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int kxtj9_suspend(struct device *dev)
+static int __maybe_unused kxtj9_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
@@ -631,7 +630,7 @@ static int kxtj9_suspend(struct device *dev)
 	return 0;
 }
 
-static int kxtj9_resume(struct device *dev)
+static int __maybe_unused kxtj9_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
@@ -646,7 +645,6 @@ static int kxtj9_resume(struct device *dev)
 	mutex_unlock(&input_dev->mutex);
 	return retval;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
 
diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c
index 7b1fde9..1b12d77 100644
--- a/drivers/input/misc/max77693-haptic.c
+++ b/drivers/input/misc/max77693-haptic.c
@@ -310,8 +310,7 @@ static int max77693_haptic_probe(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int max77693_haptic_suspend(struct device *dev)
+static int __maybe_unused max77693_haptic_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
@@ -324,7 +323,7 @@ static int max77693_haptic_suspend(struct device *dev)
 	return 0;
 }
 
-static int max77693_haptic_resume(struct device *dev)
+static int __maybe_unused max77693_haptic_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct max77693_haptic *haptic = platform_get_drvdata(pdev);
@@ -336,7 +335,6 @@ static int max77693_haptic_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops,
 			 max77693_haptic_suspend, max77693_haptic_resume);
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c
index 3809618..11d0d37 100644
--- a/drivers/input/misc/max8925_onkey.c
+++ b/drivers/input/misc/max8925_onkey.c
@@ -133,8 +133,7 @@ static int max8925_onkey_probe(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int max8925_onkey_suspend(struct device *dev)
+static int __maybe_unused max8925_onkey_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct max8925_onkey_info *info = platform_get_drvdata(pdev);
@@ -148,7 +147,7 @@ static int max8925_onkey_suspend(struct device *dev)
 	return 0;
 }
 
-static int max8925_onkey_resume(struct device *dev)
+static int __maybe_unused max8925_onkey_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct max8925_onkey_info *info = platform_get_drvdata(pdev);
@@ -161,7 +160,6 @@ static int max8925_onkey_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(max8925_onkey_pm_ops, max8925_onkey_suspend, max8925_onkey_resume);
 
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index a363ebb..980437a 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -378,8 +378,7 @@ static int max8997_haptic_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int max8997_haptic_suspend(struct device *dev)
+static int __maybe_unused max8997_haptic_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct max8997_haptic *chip = platform_get_drvdata(pdev);
@@ -388,7 +387,6 @@ static int max8997_haptic_suspend(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);
 
diff --git a/drivers/input/misc/palmas-pwrbutton.c b/drivers/input/misc/palmas-pwrbutton.c
index f505ac3..2c4d6ca 100644
--- a/drivers/input/misc/palmas-pwrbutton.c
+++ b/drivers/input/misc/palmas-pwrbutton.c
@@ -260,7 +260,6 @@ static int palmas_pwron_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
 /**
  * palmas_pwron_suspend() - suspend handler
  * @dev:	power button device
@@ -269,7 +268,7 @@ static int palmas_pwron_remove(struct platform_device *pdev)
  *
  * Return: 0
  */
-static int palmas_pwron_suspend(struct device *dev)
+static int __maybe_unused palmas_pwron_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct palmas_pwron *pwron = platform_get_drvdata(pdev);
@@ -290,7 +289,7 @@ static int palmas_pwron_suspend(struct device *dev)
  *
  * Return: 0
  */
-static int palmas_pwron_resume(struct device *dev)
+static int __maybe_unused palmas_pwron_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct palmas_pwron *pwron = platform_get_drvdata(pdev);
@@ -300,7 +299,6 @@ static int palmas_pwron_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(palmas_pwron_pm,
 			 palmas_pwron_suspend, palmas_pwron_resume);
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
index 6a915ba..e5266cd 100644
--- a/drivers/input/misc/pm8xxx-vibrator.c
+++ b/drivers/input/misc/pm8xxx-vibrator.c
@@ -199,8 +199,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int pm8xxx_vib_suspend(struct device *dev)
+static int __maybe_unused pm8xxx_vib_suspend(struct device *dev)
 {
 	struct pm8xxx_vib *vib = dev_get_drvdata(dev);
 
@@ -209,7 +208,6 @@ static int pm8xxx_vib_suspend(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
 
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index c91e3d3..2899945 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -53,8 +53,7 @@ static irqreturn_t pwrkey_release_irq(int irq, void *_pwr)
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int pmic8xxx_pwrkey_suspend(struct device *dev)
+static int __maybe_unused pmic8xxx_pwrkey_suspend(struct device *dev)
 {
 	struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
 
@@ -64,7 +63,7 @@ static int pmic8xxx_pwrkey_suspend(struct device *dev)
 	return 0;
 }
 
-static int pmic8xxx_pwrkey_resume(struct device *dev)
+static int __maybe_unused pmic8xxx_pwrkey_resume(struct device *dev)
 {
 	struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
 
@@ -73,7 +72,6 @@ static int pmic8xxx_pwrkey_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops,
 		pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume);
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index 8ef288e..93f640a 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -144,8 +144,7 @@ static int pwm_beeper_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int pwm_beeper_suspend(struct device *dev)
+static int __maybe_unused pwm_beeper_suspend(struct device *dev)
 {
 	struct pwm_beeper *beeper = dev_get_drvdata(dev);
 
@@ -155,7 +154,7 @@ static int pwm_beeper_suspend(struct device *dev)
 	return 0;
 }
 
-static int pwm_beeper_resume(struct device *dev)
+static int __maybe_unused pwm_beeper_resume(struct device *dev)
 {
 	struct pwm_beeper *beeper = dev_get_drvdata(dev);
 
@@ -170,6 +169,7 @@ static int pwm_beeper_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops,
 			 pwm_beeper_suspend, pwm_beeper_resume);
 
+#ifdef CONFIG_PM_SLEEP
 #define PWM_BEEPER_PM_OPS (&pwm_beeper_pm_ops)
 #else
 #define PWM_BEEPER_PM_OPS NULL
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index fed5102..151f169 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -179,8 +179,7 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int sirfsoc_pwrc_resume(struct device *dev)
+static int __maybe_unused sirfsoc_pwrc_resume(struct device *dev)
 {
 	struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev);
 	struct input_dev *input = pwrcdrv->input;
@@ -196,7 +195,6 @@ static int sirfsoc_pwrc_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume);
 
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 960ef2a..c802c4a 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -157,8 +157,7 @@ static void twl4030_vibra_close(struct input_dev *input)
 }
 
 /*** Module ***/
-#ifdef CONFIG_PM_SLEEP
-static int twl4030_vibra_suspend(struct device *dev)
+static int __maybe_unused twl4030_vibra_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct vibra_info *info = platform_get_drvdata(pdev);
@@ -169,12 +168,11 @@ static int twl4030_vibra_suspend(struct device *dev)
 	return 0;
 }
 
-static int twl4030_vibra_resume(struct device *dev)
+static int __maybe_unused twl4030_vibra_resume(struct device *dev)
 {
 	vibra_disable_leds();
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
 			 twl4030_vibra_suspend, twl4030_vibra_resume);
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 6d26eec..190fdef 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -236,8 +236,7 @@ static void twl6040_vibra_close(struct input_dev *input)
 	mutex_unlock(&info->mutex);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int twl6040_vibra_suspend(struct device *dev)
+static int __maybe_unused twl6040_vibra_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct vibra_info *info = platform_get_drvdata(pdev);
@@ -251,7 +250,6 @@ static int twl6040_vibra_suspend(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
 
-- 
1.7.9.5



^ permalink raw reply related

* [PATCH 2/3] Input: mouse - Use __maybe_unused instead of ifdef around suspend/resume
From: Jingoo Han @ 2014-10-29  5:19 UTC (permalink / raw)
  To: 'Dmitry Torokhov'; +Cc: linux-input, 'Jingoo Han'
In-Reply-To: <000501cff337$c5f23750$51d6a5f0$%han@samsung.com>

Use __maybe_unused instead of ifdef guards around suspend/resume
functions, in order to increase build coverage and fix build warnings.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 drivers/input/mouse/cyapa.c         |    6 ++----
 drivers/input/mouse/navpoint.c      |    6 ++----
 drivers/input/mouse/synaptics_i2c.c |    6 ++----
 3 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index b409c3d..1d978c7 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -905,8 +905,7 @@ static int cyapa_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int cyapa_suspend(struct device *dev)
+static int __maybe_unused cyapa_suspend(struct device *dev)
 {
 	int ret;
 	u8 power_mode;
@@ -929,7 +928,7 @@ static int cyapa_suspend(struct device *dev)
 	return 0;
 }
 
-static int cyapa_resume(struct device *dev)
+static int __maybe_unused cyapa_resume(struct device *dev)
 {
 	int ret;
 	struct cyapa *cyapa = dev_get_drvdata(dev);
@@ -944,7 +943,6 @@ static int cyapa_resume(struct device *dev)
 	enable_irq(cyapa->irq);
 	return 0;
 }
-#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(cyapa_pm_ops, cyapa_suspend, cyapa_resume);
 
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c
index 1ccc88a..6901727 100644
--- a/drivers/input/mouse/navpoint.c
+++ b/drivers/input/mouse/navpoint.c
@@ -318,8 +318,7 @@ static int navpoint_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int navpoint_suspend(struct device *dev)
+static int __maybe_unused navpoint_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct navpoint *navpoint = platform_get_drvdata(pdev);
@@ -333,7 +332,7 @@ static int navpoint_suspend(struct device *dev)
 	return 0;
 }
 
-static int navpoint_resume(struct device *dev)
+static int __maybe_unused navpoint_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct navpoint *navpoint = platform_get_drvdata(pdev);
@@ -346,7 +345,6 @@ static int navpoint_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume);
 
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index ad82260..878f184 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -614,8 +614,7 @@ static int synaptics_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int synaptics_i2c_suspend(struct device *dev)
+static int __maybe_unused synaptics_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct synaptics_i2c *touch = i2c_get_clientdata(client);
@@ -628,7 +627,7 @@ static int synaptics_i2c_suspend(struct device *dev)
 	return 0;
 }
 
-static int synaptics_i2c_resume(struct device *dev)
+static int __maybe_unused synaptics_i2c_resume(struct device *dev)
 {
 	int ret;
 	struct i2c_client *client = to_i2c_client(dev);
@@ -643,7 +642,6 @@ static int synaptics_i2c_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
 			 synaptics_i2c_resume);
-- 
1.7.9.5



^ permalink raw reply related

* [PATCH 3/3] Input: touchscreen - Use __maybe_unused instead of ifdef around suspend/resume
From: Jingoo Han @ 2014-10-29  5:19 UTC (permalink / raw)
  To: 'Dmitry Torokhov'; +Cc: linux-input, 'Jingoo Han'
In-Reply-To: <000501cff337$c5f23750$51d6a5f0$%han@samsung.com>

Use __maybe_unused instead of ifdef guards around suspend/resume
functions, in order to increase build coverage and fix build warnings.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
---
 drivers/input/touchscreen/ad7877.c        |    6 ++----
 drivers/input/touchscreen/ad7879.c        |    6 ++----
 drivers/input/touchscreen/ads7846.c       |    6 ++----
 drivers/input/touchscreen/atmel_mxt_ts.c  |    6 ++----
 drivers/input/touchscreen/auo-pixcir-ts.c |    6 ++----
 drivers/input/touchscreen/cy8ctmg110_ts.c |    6 ++----
 drivers/input/touchscreen/cyttsp_core.c   |    7 ++-----
 drivers/input/touchscreen/edt-ft5x06.c    |    6 ++----
 drivers/input/touchscreen/eeti_ts.c       |    6 ++----
 drivers/input/touchscreen/egalax_ts.c     |    6 ++----
 drivers/input/touchscreen/ili210x.c       |    6 ++----
 drivers/input/touchscreen/ipaq-micro-ts.c |    6 ++----
 drivers/input/touchscreen/mms114.c        |    6 ++----
 drivers/input/touchscreen/pixcir_i2c_ts.c |    6 ++----
 drivers/input/touchscreen/st1232.c        |    7 ++-----
 drivers/input/touchscreen/tsc2005.c       |    6 ++----
 drivers/input/touchscreen/ucb1400_ts.c    |    6 ++----
 drivers/input/touchscreen/wacom_i2c.c     |    6 ++----
 drivers/input/touchscreen/zforce_ts.c     |    6 ++----
 19 files changed, 38 insertions(+), 78 deletions(-)

diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 523865d..da4e5bb 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -820,8 +820,7 @@ static int ad7877_remove(struct spi_device *spi)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int ad7877_suspend(struct device *dev)
+static int __maybe_unused ad7877_suspend(struct device *dev)
 {
 	struct ad7877 *ts = dev_get_drvdata(dev);
 
@@ -830,7 +829,7 @@ static int ad7877_suspend(struct device *dev)
 	return 0;
 }
 
-static int ad7877_resume(struct device *dev)
+static int __maybe_unused ad7877_resume(struct device *dev)
 {
 	struct ad7877 *ts = dev_get_drvdata(dev);
 
@@ -838,7 +837,6 @@ static int ad7877_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);
 
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c
index 1eb9d3c..fec66ad 100644
--- a/drivers/input/touchscreen/ad7879.c
+++ b/drivers/input/touchscreen/ad7879.c
@@ -284,8 +284,7 @@ static void ad7879_close(struct input_dev* input)
 		__ad7879_disable(ts);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int ad7879_suspend(struct device *dev)
+static int __maybe_unused ad7879_suspend(struct device *dev)
 {
 	struct ad7879 *ts = dev_get_drvdata(dev);
 
@@ -301,7 +300,7 @@ static int ad7879_suspend(struct device *dev)
 	return 0;
 }
 
-static int ad7879_resume(struct device *dev)
+static int __maybe_unused ad7879_resume(struct device *dev)
 {
 	struct ad7879 *ts = dev_get_drvdata(dev);
 
@@ -316,7 +315,6 @@ static int ad7879_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume);
 EXPORT_SYMBOL(ad7879_pm_ops);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index e57ba52..e4eb8a6 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -883,8 +883,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int ads7846_suspend(struct device *dev)
+static int __maybe_unused ads7846_suspend(struct device *dev)
 {
 	struct ads7846 *ts = dev_get_drvdata(dev);
 
@@ -906,7 +905,7 @@ static int ads7846_suspend(struct device *dev)
 	return 0;
 }
 
-static int ads7846_resume(struct device *dev)
+static int __maybe_unused ads7846_resume(struct device *dev)
 {
 	struct ads7846 *ts = dev_get_drvdata(dev);
 
@@ -927,7 +926,6 @@ static int ads7846_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index aaacf8b..bb07020 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2244,8 +2244,7 @@ static int mxt_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int mxt_suspend(struct device *dev)
+static int __maybe_unused mxt_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mxt_data *data = i2c_get_clientdata(client);
@@ -2261,7 +2260,7 @@ static int mxt_suspend(struct device *dev)
 	return 0;
 }
 
-static int mxt_resume(struct device *dev)
+static int __maybe_unused mxt_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mxt_data *data = i2c_get_clientdata(client);
@@ -2276,7 +2275,6 @@ static int mxt_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
 
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 7f3c947..40e02dd 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -417,8 +417,7 @@ static void auo_pixcir_input_close(struct input_dev *dev)
 	return;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int auo_pixcir_suspend(struct device *dev)
+static int __maybe_unused auo_pixcir_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
@@ -450,7 +449,7 @@ unlock:
 	return ret;
 }
 
-static int auo_pixcir_resume(struct device *dev)
+static int __maybe_unused auo_pixcir_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
@@ -479,7 +478,6 @@ unlock:
 
 	return ret;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops,
 			 auo_pixcir_suspend, auo_pixcir_resume);
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index 5bf1aee..f2119ee 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -291,8 +291,7 @@ err_free_mem:
 	return err;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int cy8ctmg110_suspend(struct device *dev)
+static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
@@ -306,7 +305,7 @@ static int cy8ctmg110_suspend(struct device *dev)
 	return 0;
 }
 
-static int cy8ctmg110_resume(struct device *dev)
+static int __maybe_unused cy8ctmg110_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct cy8ctmg110 *ts = i2c_get_clientdata(client);
@@ -319,7 +318,6 @@ static int cy8ctmg110_resume(struct device *dev)
 	}
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
 
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index eee656f..5b74e8b 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -472,8 +472,7 @@ static int cyttsp_disable(struct cyttsp *ts)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int cyttsp_suspend(struct device *dev)
+static int __maybe_unused cyttsp_suspend(struct device *dev)
 {
 	struct cyttsp *ts = dev_get_drvdata(dev);
 	int retval = 0;
@@ -491,7 +490,7 @@ static int cyttsp_suspend(struct device *dev)
 	return retval;
 }
 
-static int cyttsp_resume(struct device *dev)
+static int __maybe_unused cyttsp_resume(struct device *dev)
 {
 	struct cyttsp *ts = dev_get_drvdata(dev);
 
@@ -507,8 +506,6 @@ static int cyttsp_resume(struct device *dev)
 	return 0;
 }
 
-#endif
-
 SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
 EXPORT_SYMBOL_GPL(cyttsp_pm_ops);
 
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index ee3434f..3793fcc 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -1092,8 +1092,7 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int edt_ft5x06_ts_suspend(struct device *dev)
+static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -1103,7 +1102,7 @@ static int edt_ft5x06_ts_suspend(struct device *dev)
 	return 0;
 }
 
-static int edt_ft5x06_ts_resume(struct device *dev)
+static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -1112,7 +1111,6 @@ static int edt_ft5x06_ts_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,
 			 edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index b1884dd..09be6ce 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -264,8 +264,7 @@ static int eeti_ts_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int eeti_ts_suspend(struct device *dev)
+static int __maybe_unused eeti_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
@@ -284,7 +283,7 @@ static int eeti_ts_suspend(struct device *dev)
 	return 0;
 }
 
-static int eeti_ts_resume(struct device *dev)
+static int __maybe_unused eeti_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct eeti_ts_priv *priv = i2c_get_clientdata(client);
@@ -302,7 +301,6 @@ static int eeti_ts_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume);
 
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index c805784..4c56299 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -239,8 +239,7 @@ static const struct i2c_device_id egalax_ts_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, egalax_ts_id);
 
-#ifdef CONFIG_PM_SLEEP
-static int egalax_ts_suspend(struct device *dev)
+static int __maybe_unused egalax_ts_suspend(struct device *dev)
 {
 	static const u8 suspend_cmd[MAX_I2C_DATA_LEN] = {
 		0x3, 0x6, 0xa, 0x3, 0x36, 0x3f, 0x2, 0, 0, 0
@@ -252,13 +251,12 @@ static int egalax_ts_suspend(struct device *dev)
 	return ret > 0 ? 0 : ret;
 }
 
-static int egalax_ts_resume(struct device *dev)
+static int __maybe_unused egalax_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
 	return egalax_wake_up_device(client);
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
 
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 2a50891..da6dc81 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -311,8 +311,7 @@ static int ili210x_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int ili210x_i2c_suspend(struct device *dev)
+static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -322,7 +321,7 @@ static int ili210x_i2c_suspend(struct device *dev)
 	return 0;
 }
 
-static int ili210x_i2c_resume(struct device *dev)
+static int __maybe_unused ili210x_i2c_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -331,7 +330,6 @@ static int ili210x_i2c_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
 			 ili210x_i2c_suspend, ili210x_i2c_resume);
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
index 62c8976..33c1348 100644
--- a/drivers/input/touchscreen/ipaq-micro-ts.c
+++ b/drivers/input/touchscreen/ipaq-micro-ts.c
@@ -122,8 +122,7 @@ static int micro_ts_probe(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int micro_ts_suspend(struct device *dev)
+static int __maybe_unused micro_ts_suspend(struct device *dev)
 {
 	struct touchscreen_data *ts = dev_get_drvdata(dev);
 
@@ -132,7 +131,7 @@ static int micro_ts_suspend(struct device *dev)
 	return 0;
 }
 
-static int micro_ts_resume(struct device *dev)
+static int __maybe_unused micro_ts_resume(struct device *dev)
 {
 	struct touchscreen_data *ts = dev_get_drvdata(dev);
 	struct input_dev *input = ts->input;
@@ -146,7 +145,6 @@ static int micro_ts_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static const struct dev_pm_ops micro_ts_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume)
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 372bbf7..67c0d31 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -515,8 +515,7 @@ static int mms114_probe(struct i2c_client *client,
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int mms114_suspend(struct device *dev)
+static int __maybe_unused mms114_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mms114_data *data = i2c_get_clientdata(client);
@@ -540,7 +539,7 @@ static int mms114_suspend(struct device *dev)
 	return 0;
 }
 
-static int mms114_resume(struct device *dev)
+static int __maybe_unused mms114_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mms114_data *data = i2c_get_clientdata(client);
@@ -559,7 +558,6 @@ static int mms114_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume);
 
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index fc49c75..4fb5537 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -347,8 +347,7 @@ static void pixcir_input_close(struct input_dev *dev)
 	pixcir_stop(ts);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int pixcir_i2c_ts_suspend(struct device *dev)
+static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
@@ -377,7 +376,7 @@ unlock:
 	return ret;
 }
 
-static int pixcir_i2c_ts_resume(struct device *dev)
+static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
@@ -405,7 +404,6 @@ unlock:
 
 	return ret;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
 			 pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 3c0f57e..697e26e 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -243,8 +243,7 @@ static int st1232_ts_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int st1232_ts_suspend(struct device *dev)
+static int __maybe_unused st1232_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct st1232_ts_data *ts = i2c_get_clientdata(client);
@@ -259,7 +258,7 @@ static int st1232_ts_suspend(struct device *dev)
 	return 0;
 }
 
-static int st1232_ts_resume(struct device *dev)
+static int __maybe_unused st1232_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct st1232_ts_data *ts = i2c_get_clientdata(client);
@@ -274,8 +273,6 @@ static int st1232_ts_resume(struct device *dev)
 	return 0;
 }
 
-#endif
-
 static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops,
 			 st1232_ts_suspend, st1232_ts_resume);
 
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
index 52380b6..72657c5 100644
--- a/drivers/input/touchscreen/tsc2005.c
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -773,8 +773,7 @@ static int tsc2005_remove(struct spi_device *spi)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int tsc2005_suspend(struct device *dev)
+static int __maybe_unused tsc2005_suspend(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct tsc2005 *ts = spi_get_drvdata(spi);
@@ -791,7 +790,7 @@ static int tsc2005_suspend(struct device *dev)
 	return 0;
 }
 
-static int tsc2005_resume(struct device *dev)
+static int __maybe_unused tsc2005_resume(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct tsc2005 *ts = spi_get_drvdata(spi);
@@ -807,7 +806,6 @@ static int tsc2005_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);
 
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index b46c55c..bf132c4 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -406,8 +406,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int ucb1400_ts_suspend(struct device *dev)
+static int __maybe_unused ucb1400_ts_suspend(struct device *dev)
 {
 	struct ucb1400_ts *ucb = dev_get_platdata(dev);
 	struct input_dev *idev = ucb->ts_idev;
@@ -421,7 +420,7 @@ static int ucb1400_ts_suspend(struct device *dev)
 	return 0;
 }
 
-static int ucb1400_ts_resume(struct device *dev)
+static int __maybe_unused ucb1400_ts_resume(struct device *dev)
 {
 	struct ucb1400_ts *ucb = dev_get_platdata(dev);
 	struct input_dev *idev = ucb->ts_idev;
@@ -434,7 +433,6 @@ static int ucb1400_ts_resume(struct device *dev)
 	mutex_unlock(&idev->mutex);
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops,
 			 ucb1400_ts_suspend, ucb1400_ts_resume);
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index 7ccaa1b..32f8ac0 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -242,8 +242,7 @@ static int wacom_i2c_remove(struct i2c_client *client)
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int wacom_i2c_suspend(struct device *dev)
+static int __maybe_unused wacom_i2c_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -252,7 +251,7 @@ static int wacom_i2c_suspend(struct device *dev)
 	return 0;
 }
 
-static int wacom_i2c_resume(struct device *dev)
+static int __maybe_unused wacom_i2c_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
@@ -260,7 +259,6 @@ static int wacom_i2c_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume);
 
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index 8ba48f5..19880c7 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -602,8 +602,7 @@ static void zforce_input_close(struct input_dev *dev)
 	return;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int zforce_suspend(struct device *dev)
+static int __maybe_unused zforce_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct zforce_ts *ts = i2c_get_clientdata(client);
@@ -648,7 +647,7 @@ unlock:
 	return ret;
 }
 
-static int zforce_resume(struct device *dev)
+static int __maybe_unused zforce_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct zforce_ts *ts = i2c_get_clientdata(client);
@@ -685,7 +684,6 @@ unlock:
 
 	return ret;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume);
 
-- 
1.7.9.5



^ permalink raw reply related

* Re: [PATCH 00/13] HID: add support of Logitech touchpads and special devices
From: Jiri Kosina @ 2014-10-29  9:49 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Andrew de los Reyes, Benjamin Tissoires, Nestor Lopez Casado,
	linux-kernel@vger.kernel.org, Linux Input
In-Reply-To: <CAN+gG=GET=FLmte9kQOtS+x=HPaTdgEu4HxuydHXBx1GZksNRw@mail.gmail.com>

On Tue, 28 Oct 2014, Benjamin Tissoires wrote:

> >> I've tested these patches successfully on a Chromebook Pixel with the
> >> following devices:
> >>
> >> - T650 touchpad
> >> - TK820 keyboard/touchpad
> >> - Original WTP touchpad
> >>
> >> I also tested a touch mouse and as expected it continued to function
> >> as a plain USB mouse. The TK820 was indeed broken into two devices,
> >> with autorepeat enabled for the keyboard only. The other two devices
> >> behaved as expected with no perceived regressions.
> >>
> >> In short, from a functionality perspective I'm happy with these
> >> patches. I will let others discuss code structure.
> >
> > Thank you. Can I use
> >
> >         Tested-by: Andrew de los Reyes <andrew-vger@gizmolabs.org>
> >
> > once / if I am merging this patchset?
> >
> 
> I am pretty sure this is not required too, but I am raising this one
> again in Jiri's pile of things to review.
> Sorry Jiri, I did not forget about it :)

It absolutely hasn't been forgotten, I've been just a bit busy during past 
weeks.

I am almost done with the review, expect to hear from me in a 1-2 days 
timeframe regarding this series.

Thanks for patience,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* Re: [PATCH 1/3] mfd: stmpe: add pull up/down register offsets for STMPE
From: Linus Walleij @ 2014-10-29  9:55 UTC (permalink / raw)
  To: Lee Jones
  Cc: Samuel Ortiz, Dmitry Torokhov, linux-kernel@vger.kernel.org,
	Linux Input
In-Reply-To: <20141020064605.GB25349@x1>

On Mon, Oct 20, 2014 at 8:46 AM, Lee Jones <lee.jones@linaro.org> wrote:
> On Sat, 18 Oct 2014, Linus Walleij wrote:
>
>> This adds the register offsets for pull up/down for the STMPE
>> 1601, 1801 and 24xx expanders. This is used to bias GPIO lines
>> and keypad lines.
>>
>> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>> ---
>> Hi Sam, Lee: I think you should just ACK this so Dmitry can take the
>> patch series through the input tree, where the registers need to be
>> used to enable the keypad on the STMPE2401.
>> ---
>>  drivers/mfd/stmpe.c       | 4 ++++
>>  drivers/mfd/stmpe.h       | 3 +++
>>  include/linux/mfd/stmpe.h | 2 ++
>>  3 files changed, 9 insertions(+)
>
> Does this need to go in with the other patches in the set?
>
> I'm _guessing_ that, as you've sent them separately, they can be
> applied separately?

No sorry if it was unclear, the series need to go in toghether.
So this patch adds some infrastructure to the MFD device which
is then utilized by the input driver in a later patch.

> This needs to go in via MFD, but for my own reference:
>
> Acked-by: Lee Jones <lee.jones@linaro.org>

Dmitry can you merge this & the rest with Lee's ACK?

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH] HID: input: Fix TransducerSerialNumber implementation
From: Jiri Kosina @ 2014-10-29 10:00 UTC (permalink / raw)
  To: Jason Gerecke
  Cc: Benjamin Tissoires, linux-input@vger.kernel.org,
	pinglinux@gmail.com, Jason Gerecke
In-Reply-To: <1411495768-5956-1-git-send-email-killertofu@gmail.com>

On Tue, 23 Sep 2014, Jason Gerecke wrote:

> The commit which introduced TransducerSerialNumber (368c966) is missing
> two crucial implementation details. Firstly, the commit does not set the
> type/code/bit/max fields as expected later down the code which can cause
> the driver to crash when a tablet with this usage is connected. Secondly,
> the call to 'set_bit' causes MSC_PULSELED to be sent instead of the
> expected MSC_SERIAL. This commit addreses both issues.
> 
> Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
> ---
>  drivers/hid/hid-input.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index 2619f7f..cb1b3fa 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -689,7 +689,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
>  			break;
>  
>  		case 0x5b: /* TransducerSerialNumber */
> -			set_bit(MSC_SERIAL, input->mscbit);
> +			usage->type = EV_MSC;
> +			usage->code = MSC_SERIAL;
> +			bit = input->mscbit;
> +			max = MSC_MAX;
>  			break;
>  

Apologizes for the delay. I have now queued this for 3.18 still.

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* Re: [PATCH] HID: usbhid: prevent unwanted events to be sent when re-opening the device
From: Jiri Kosina @ 2014-10-29 10:05 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Hans de Goede, Bastien Nocera, linux-kernel, linux-input
In-Reply-To: <1412101702-2752-1-git-send-email-benjamin.tissoires@redhat.com>

On Tue, 30 Sep 2014, Benjamin Tissoires wrote:

> When events occurs while no one is listening to the node (hid->open == 0
> and usb_kill_urb() called) some events are still stacked somewhere in
> the USB (kernel or device?) stack. When the node gets reopened, these
> events are drained, and this results in spurious touch down/up, or mouse
> button clicks.
> 
> The problem was spotted with touchscreens in fdo bug #81781 [1], but it
> actually occurs with any mouse using hid-generic or touchscreen.
> 
> A way to reproduce it is to call:
> 
> $ xinput disable 9 ; sleep 5 ; xinput enable 9
> 
> With 9 being the device ID for the touchscreen/mouse. During the "sleep",
> produce some touch events or click events. When "xinput enable" is called,
> at least one click is generated.
> 
> This patch tries to fix this by draining the queue for 50 msec and
> during this time frame, not forwarding these old events to the hid layer.
> 
> Hans completed the explanation:
> """
> Devices like mice (basically any hid device) will have a fifo
> on the device side, when we stop submitting urbs to get hid reports from
> it, that fifo will fill up, and when we resume we will get whatever
> is there in that fifo.
> """
> 
> [1] https://bugs.freedesktop.org/show_bug.cgi?id=81781
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
> 
> OK, I know this is uggly, but I could not find a better way :(

I have been thinking about this quite a lot, but unfortunately wasn't able 
to come up with anything better either, so I am queuing this now.

Thanks.

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* Re: hid: roccat: Fix code style issues
From: Jiri Kosina @ 2014-10-29 13:57 UTC (permalink / raw)
  To: Hans Duedal; +Cc: erazor_de, linux-input
In-Reply-To: <1413039709-37143-1-git-send-email-hans.duedal@gmail.com>

On Sat, 11 Oct 2014, hans.duedal@gmail.com wrote:

> From: Hans Duedal <hans.duedal@gmail.com>
> 
> Missing whitespace, semi-colon after macro, and a duplicated out of
> memory message.
> 
> Signed-off-by: Hans Duedal <hans.duedal@gmail.com>

Applied, thanks.

> ---
>  drivers/hid/hid-roccat-kone.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
> index 6101816..c292650 100644
> --- a/drivers/hid/hid-roccat-kone.c
> +++ b/drivers/hid/hid-roccat-kone.c
> @@ -46,6 +46,7 @@ static void kone_profile_activated(struct kone_device *kone, uint new_profile)
>  static void kone_profile_report(struct kone_device *kone, uint new_profile)
>  {
>  	struct kone_roccat_report roccat_report;
> +
>  	roccat_report.event = kone_mouse_event_switch_profile;
>  	roccat_report.value = new_profile;
>  	roccat_report.key = 0;
> @@ -163,6 +164,7 @@ static int kone_set_settings(struct usb_device *usb_dev,
>  		struct kone_settings const *settings)
>  {
>  	int retval;
> +
>  	retval = kone_send(usb_dev, kone_command_settings,
>  			settings, sizeof(struct kone_settings));
>  	if (retval)
> @@ -387,7 +389,7 @@ static struct bin_attribute bin_attr_profile##number = {	\
>  	.read = kone_sysfs_read_profilex,			\
>  	.write = kone_sysfs_write_profilex,			\
>  	.private = &profile_numbers[number-1],			\
> -};
> +}
>  PROFILE_ATTR(1);
>  PROFILE_ATTR(2);
>  PROFILE_ATTR(3);
> @@ -456,6 +458,7 @@ static ssize_t kone_sysfs_show_tcu(struct device *dev,
>  static int kone_tcu_command(struct usb_device *usb_dev, int number)
>  {
>  	unsigned char value;
> +
>  	value = number;
>  	return kone_send(usb_dev, kone_command_calibrate, &value, 1);
>  }
> @@ -697,10 +700,8 @@ static int kone_init_specials(struct hid_device *hdev)
>  			== USB_INTERFACE_PROTOCOL_MOUSE) {
> 
>  		kone = kzalloc(sizeof(*kone), GFP_KERNEL);
> -		if (!kone) {
> -			hid_err(hdev, "can't alloc device descriptor\n");
> +		if (!kone)
>  			return -ENOMEM;
> -		}
>  		hid_set_drvdata(hdev, kone);
> 
>  		retval = kone_init_kone_device_struct(usb_dev, kone);
> --
> 1.9.3 (Apple Git-50)
> 

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* Re: [PATCH 00/13] HID: add support of Logitech touchpads and special devices
From: Benjamin Tissoires @ 2014-10-29 14:41 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Andrew de los Reyes, Benjamin Tissoires, Nestor Lopez Casado,
	linux-kernel@vger.kernel.org, Linux Input
In-Reply-To: <alpine.LNX.2.00.1410291048320.20256@pobox.suse.cz>

On Wed, Oct 29, 2014 at 5:49 AM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Tue, 28 Oct 2014, Benjamin Tissoires wrote:
>
>> >> I've tested these patches successfully on a Chromebook Pixel with the
>> >> following devices:
>> >>
>> >> - T650 touchpad
>> >> - TK820 keyboard/touchpad
>> >> - Original WTP touchpad
>> >>
>> >> I also tested a touch mouse and as expected it continued to function
>> >> as a plain USB mouse. The TK820 was indeed broken into two devices,
>> >> with autorepeat enabled for the keyboard only. The other two devices
>> >> behaved as expected with no perceived regressions.
>> >>
>> >> In short, from a functionality perspective I'm happy with these
>> >> patches. I will let others discuss code structure.
>> >
>> > Thank you. Can I use
>> >
>> >         Tested-by: Andrew de los Reyes <andrew-vger@gizmolabs.org>
>> >
>> > once / if I am merging this patchset?
>> >
>>
>> I am pretty sure this is not required too, but I am raising this one
>> again in Jiri's pile of things to review.
>> Sorry Jiri, I did not forget about it :)
>
> It absolutely hasn't been forgotten, I've been just a bit busy during past
> weeks.

No worries. I definitively understand. Being close to the merge window
is never a good time to send you patches and I am sure SuSE asks you a
lot also :)

>
> I am almost done with the review, expect to hear from me in a 1-2 days
> timeframe regarding this series.

Cool, thanks. That is much appreciated.

Cheers,
Benjamin

^ permalink raw reply

* Re: [PATCH v3] Input: driver for the Goodix touchpanel
From: Benjamin Tissoires @ 2014-10-29 14:49 UTC (permalink / raw)
  To: Bastien Nocera; +Cc: linux-input, Henrik Rydberg, Dmitry Torokhov
In-Reply-To: <1414544056.2406.25.camel@hadess.net>

On Tue, Oct 28, 2014 at 8:54 PM, Bastien Nocera <hadess@hadess.net> wrote:
> Add a driver for the Goodix touchscreen panel found in Onda v975w
> tablets. The driver is based off the Android driver gt9xx.c found
> in some Android code dumps, but now bears no resemblance to the original
> driver.
>
> The driver was tested on the aforementioned tablet.
>
> Signed-off-by: Bastien Nocera <hadess@hadess.net>
> Tested-by: Bastien Nocera <hadess@hadess.net>
> ---

Seems good to me:
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Cheers,
Benjamin

>  MAINTAINERS                        |   6 +
>  drivers/input/touchscreen/Kconfig  |  13 ++
>  drivers/input/touchscreen/Makefile |   1 +
>  drivers/input/touchscreen/goodix.c | 395 +++++++++++++++++++++++++++++++++++++
>  4 files changed, 415 insertions(+)
>  create mode 100644 drivers/input/touchscreen/goodix.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index dab92a7..6886886 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4138,6 +4138,12 @@ L:       linux-media@vger.kernel.org
>  S:     Maintained
>  F:     drivers/media/usb/go7007/
>
> +GOODIX TOUCHSCREEN
> +M:     Bastien Nocera <hadess@hadess.net>
> +L:     linux-input@vger.kernel.org
> +S:     Maintained
> +F:     drivers/input/touchscreen/goodix.c
> +
>  GPIO SUBSYSTEM
>  M:     Linus Walleij <linus.walleij@linaro.org>
>  M:     Alexandre Courbot <gnurou@gmail.com>
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index e1d8003..568a020 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -295,6 +295,19 @@ config TOUCHSCREEN_FUJITSU
>           To compile this driver as a module, choose M here: the
>           module will be called fujitsu-ts.
>
> +config TOUCHSCREEN_GOODIX
> +       tristate "Goodix I2C touchscreen"
> +       depends on I2C && ACPI
> +       help
> +         Say Y here if you have the Goodix touchscreen (such as one
> +         installed in Onda v975w tablets) connected to your
> +         system.
> +
> +         If unsure, say N.
> +
> +         To compile this driver as a module, choose M here: the
> +         module will be called goodix.
> +
>  config TOUCHSCREEN_ILI210X
>         tristate "Ilitek ILI210X based touchscreen"
>         depends on I2C
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 090e61c..dab4a56 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI)                += eeti_ts.o
>  obj-$(CONFIG_TOUCHSCREEN_ELO)          += elo.o
>  obj-$(CONFIG_TOUCHSCREEN_EGALAX)       += egalax_ts.o
>  obj-$(CONFIG_TOUCHSCREEN_FUJITSU)      += fujitsu_ts.o
> +obj-$(CONFIG_TOUCHSCREEN_GOODIX)       += goodix.o
>  obj-$(CONFIG_TOUCHSCREEN_ILI210X)      += ili210x.o
>  obj-$(CONFIG_TOUCHSCREEN_INEXIO)       += inexio.o
>  obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)    += intel-mid-touch.o
> diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
> new file mode 100644
> index 0000000..5b10ced
> --- /dev/null
> +++ b/drivers/input/touchscreen/goodix.c
> @@ -0,0 +1,395 @@
> +/*
> + *  driver for Goodix Touchscreens
> + *
> + *  Copyright (c) 2014 Red Hat Inc.
> + *
> + *  This code is based on gt9xx.c authored by andrew@goodix.com:
> + *
> + *  2010 - 2012 Goodix Technology.
> + */
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; version 2 of the License.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/i2c.h>
> +#include <linux/input.h>
> +#include <linux/input/mt.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/slab.h>
> +#include <asm/unaligned.h>
> +
> +struct goodix_ts_data {
> +       struct i2c_client *client;
> +       struct input_dev *input_dev;
> +       int abs_x_max;
> +       int abs_y_max;
> +       unsigned int max_touch_num;
> +       unsigned int int_trigger_type;
> +};
> +
> +#define GOODIX_MAX_HEIGHT              4096
> +#define GOODIX_MAX_WIDTH               4096
> +#define GOODIX_INT_TRIGGER             1
> +#define GOODIX_CONTACT_SIZE            8
> +#define GOODIX_MAX_CONTACTS            10
> +
> +#define GOODIX_CONFIG_MAX_LENGTH       240
> +
> +/* Register defines */
> +#define GOODIX_READ_COOR_ADDR          0x814E
> +#define GOODIX_REG_CONFIG_DATA         0x8047
> +#define GOODIX_REG_VERSION             0x8140
> +
> +#define RESOLUTION_LOC         1
> +#define TRIGGER_LOC            6
> +
> +static const unsigned long goodix_irq_flags[] = {
> +       IRQ_TYPE_EDGE_RISING,
> +       IRQ_TYPE_EDGE_FALLING,
> +       IRQ_TYPE_LEVEL_LOW,
> +       IRQ_TYPE_LEVEL_HIGH,
> +};
> +
> +/**
> + * goodix_i2c_read - read data from a register of the i2c slave device.
> + *
> + * @client: i2c device.
> + * @reg: the register to read from.
> + * @buf: raw write data buffer.
> + * @len: length of the buffer to write
> + */
> +static int goodix_i2c_read(struct i2c_client *client,
> +                               u16 reg, u8 *buf, int len)
> +{
> +       struct i2c_msg msgs[2];
> +       u16 wbuf = cpu_to_be16(reg);
> +       int ret;
> +
> +       msgs[0].flags = 0;
> +       msgs[0].addr  = client->addr;
> +       msgs[0].len   = 2;
> +       msgs[0].buf   = (u8 *) &wbuf;
> +
> +       msgs[1].flags = I2C_M_RD;
> +       msgs[1].addr  = client->addr;
> +       msgs[1].len   = len;
> +       msgs[1].buf   = buf;
> +
> +       ret = i2c_transfer(client->adapter, msgs, 2);
> +       return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
> +}
> +
> +static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
> +{
> +       int touch_num;
> +       int error;
> +
> +       error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data,
> +                               GOODIX_CONTACT_SIZE + 1);
> +       if (error) {
> +               dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
> +               return error;
> +       }
> +
> +       touch_num = data[0] & 0x0f;
> +       if (touch_num > GOODIX_MAX_CONTACTS)
> +               return -EPROTO;
> +
> +       if (touch_num > 1) {
> +               data += 1 + GOODIX_CONTACT_SIZE;
> +               error = goodix_i2c_read(ts->client,
> +                                       GOODIX_READ_COOR_ADDR +
> +                                               1 + GOODIX_CONTACT_SIZE,
> +                                       data,
> +                                       GOODIX_CONTACT_SIZE * (touch_num - 1));
> +               if (error)
> +                       return error;
> +       }
> +
> +       return touch_num;
> +}
> +
> +static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
> +{
> +       int id = coor_data[0] & 0x0F;
> +       int input_x = get_unaligned_le16(&coor_data[1]);
> +       int input_y = get_unaligned_le16(&coor_data[3]);
> +       int input_w = get_unaligned_le16(&coor_data[5]);
> +
> +       input_mt_slot(ts->input_dev, id);
> +       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
> +       input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
> +       input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
> +       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
> +       input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
> +}
> +
> +/**
> + * goodix_process_events - Process incoming events
> + *
> + * @ts: our goodix_ts_data pointer
> + *
> + * Called when the IRQ is triggered. Read the current device state, and push
> + * the input events to the user space.
> + */
> +static void goodix_process_events(struct goodix_ts_data *ts)
> +{
> +       u8  point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
> +       int touch_num;
> +       int i;
> +
> +       touch_num = goodix_ts_read_input_report(ts, point_data);
> +       if (touch_num < 0)
> +               return;
> +
> +       for (i = 0; i < touch_num; i++)
> +               goodix_ts_report_touch(ts,
> +                               &point_data[1 + GOODIX_CONTACT_SIZE * i]);
> +
> +       input_mt_sync_frame(ts->input_dev);
> +       input_sync(ts->input_dev);
> +}
> +
> +/**
> + * goodix_ts_irq_handler - The IRQ handler
> + *
> + * @irq: interrupt number.
> + * @dev_id: private data pointer.
> + */
> +static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
> +{
> +       static const u8 end_cmd[] = {
> +               GOODIX_READ_COOR_ADDR >> 8,
> +               GOODIX_READ_COOR_ADDR & 0xff,
> +               0
> +       };
> +       struct goodix_ts_data *ts = dev_id;
> +
> +       goodix_process_events(ts);
> +
> +       if (i2c_master_send(ts->client, end_cmd, sizeof(end_cmd)) < 0)
> +               dev_err(&ts->client->dev, "I2C write end_cmd error\n");
> +
> +       return IRQ_HANDLED;
> +}
> +
> +/**
> + * goodix_read_config - Read the embedded configuration of the panel
> + *
> + * @ts: our goodix_ts_data pointer
> + *
> + * Must be called during probe
> + */
> +static void goodix_read_config(struct goodix_ts_data *ts)
> +{
> +       u8 config[GOODIX_CONFIG_MAX_LENGTH];
> +       int error;
> +
> +       error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA,
> +                             config,
> +                          GOODIX_CONFIG_MAX_LENGTH);
> +       if (error) {
> +               dev_warn(&ts->client->dev,
> +                        "Error reading config (%d), using defaults\n",
> +                        error);
> +               ts->abs_x_max = GOODIX_MAX_WIDTH;
> +               ts->abs_y_max = GOODIX_MAX_HEIGHT;
> +               ts->int_trigger_type = GOODIX_INT_TRIGGER;
> +               return;
> +       }
> +
> +       ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
> +       ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
> +       ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03;
> +       if (!ts->abs_x_max || !ts->abs_y_max) {
> +               dev_err(&ts->client->dev,
> +                       "Invalid config, using defaults\n");
> +               ts->abs_x_max = GOODIX_MAX_WIDTH;
> +               ts->abs_y_max = GOODIX_MAX_HEIGHT;
> +       }
> +}
> +
> +
> +/**
> + * goodix_read_version - Read goodix touchscreen version
> + *
> + * @client: the i2c client
> + * @version: output buffer containing the version on success
> + */
> +static int goodix_read_version(struct i2c_client *client, u16 *version)
> +{
> +       int error;
> +       u8 buf[6];
> +
> +       error = goodix_i2c_read(client, GOODIX_REG_VERSION, buf, sizeof(buf));
> +       if (error) {
> +               dev_err(&client->dev, "read version failed: %d\n", error);
> +               return error;
> +       }
> +
> +       if (version)
> +               *version = get_unaligned_le16(&buf[4]);
> +
> +       dev_info(&client->dev, "IC VERSION: %6ph\n", buf);
> +
> +       return 0;
> +}
> +
> +/**
> + * goodix_i2c_test - I2C test function to check if the device answers.
> + *
> + * @client: the i2c client
> + */
> +static int goodix_i2c_test(struct i2c_client *client)
> +{
> +       int retry = 0;
> +       int error;
> +       u8 test;
> +
> +       while (retry++ < 2) {
> +               error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA,
> +                                       &test, 1);
> +               if (!error)
> +                       return 0;
> +
> +               dev_err(&client->dev, "i2c test failed attempt %d: %d\n",
> +                       retry, error);
> +               msleep(20);
> +       }
> +
> +       return error;
> +}
> +
> +/**
> + * goodix_request_input_dev - Allocate, populate and register the input device
> + *
> + * @ts: our goodix_ts_data pointer
> + *
> + * Must be called during probe
> + */
> +static int goodix_request_input_dev(struct goodix_ts_data *ts)
> +{
> +       int error;
> +
> +       ts->input_dev = devm_input_allocate_device(&ts->client->dev);
> +       if (!ts->input_dev) {
> +               dev_err(&ts->client->dev, "Failed to allocate input device.");
> +               return -ENOMEM;
> +       }
> +
> +       ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) |
> +                                 BIT_MASK(EV_KEY) |
> +                                 BIT_MASK(EV_ABS);
> +
> +       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
> +                               ts->abs_x_max, 0, 0);
> +       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
> +                               ts->abs_y_max, 0, 0);
> +       input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
> +       input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
> +
> +       input_mt_init_slots(ts->input_dev, GOODIX_MAX_CONTACTS,
> +                           INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
> +
> +       ts->input_dev->name = "Goodix Capacitive TouchScreen";
> +       ts->input_dev->phys = "input/ts";
> +       ts->input_dev->id.bustype = BUS_I2C;
> +       ts->input_dev->id.vendor = 0x0416;
> +       ts->input_dev->id.product = 0x1001;
> +       ts->input_dev->id.version = 10427;
> +
> +       error = input_register_device(ts->input_dev);
> +       if (error) {
> +               dev_err(&ts->client->dev,
> +                       "Failed to register input device: %d", error);
> +               return error;
> +       }
> +
> +       return 0;
> +}
> +
> +static int goodix_ts_probe(struct i2c_client *client,
> +                          const struct i2c_device_id *id)
> +{
> +       struct goodix_ts_data *ts;
> +       unsigned long irq_flags;
> +       int error;
> +       u16 version_info;
> +
> +       dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr);
> +
> +       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> +               dev_err(&client->dev, "I2C check functionality failed.\n");
> +               return -ENXIO;
> +       }
> +
> +       ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
> +       if (!ts)
> +               return -ENOMEM;
> +
> +       ts->client = client;
> +       i2c_set_clientdata(client, ts);
> +
> +       error = goodix_i2c_test(client);
> +       if (error) {
> +               dev_err(&client->dev, "I2C communication failure: %d\n", error);
> +               return error;
> +       }
> +
> +       error = goodix_read_version(client, &version_info);
> +       if (error) {
> +               dev_err(&client->dev, "Read version failed.\n");
> +               return error;
> +       }
> +
> +       goodix_read_config(ts);
> +
> +       error = goodix_request_input_dev(ts);
> +       if (error)
> +               return error;
> +
> +       irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
> +       error = devm_request_threaded_irq(&ts->client->dev, client->irq,
> +                                         NULL, goodix_ts_irq_handler,
> +                                         irq_flags, client->name, ts);
> +       if (error) {
> +               dev_err(&client->dev, "request IRQ failed: %d.\n", error);
> +               return error;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct i2c_device_id goodix_ts_id[] = {
> +       { "GDIX1001:00", 0 },
> +       { }
> +};
> +
> +static const struct acpi_device_id goodix_acpi_match[] = {
> +       { "GDIX1001", 0 },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
> +
> +static struct i2c_driver goodix_ts_driver = {
> +       .probe = goodix_ts_probe,
> +       .id_table = goodix_ts_id,
> +       .driver = {
> +               .name = "Goodix-TS",
> +               .owner = THIS_MODULE,
> +               .acpi_match_table = goodix_acpi_match,
> +       },
> +};
> +module_i2c_driver(goodix_ts_driver);
> +
> +MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
> +MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
> +MODULE_DESCRIPTION("Goodix touchscreen driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.1.0
>
>

^ permalink raw reply

* Re: [PATCH 0/2] Qualcomm PM8941 power key driver
From: Ivan T. Ivanov @ 2014-10-29 16:07 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Dmitry Torokhov, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Grant Likely, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
	linux-arm-msm@vger.kernel.org
In-Reply-To: <20141024152350.GD28611@sonymobile.com>



Hi Bjorn,

On Fri, 2014-10-24 at 08:23 -0700, Bjorn Andersson wrote:
> On Wed 08 Oct 02:50 PDT 2014, Ivan T. Ivanov wrote:
> 
> > On Tue, 2014-10-07 at 11:46 -0700, Bjorn Andersson wrote:
> > > On Tue 07 Oct 02:01 PDT 2014, Ivan T. Ivanov wrote:
> > > 
> > > > Hi Bjorn,
> > > > 
> > > > On Mon, 2014-10-06 at 18:11 -0700, Bjorn Andersson wrote:
> [..]
> > > > >  create mode 100644 drivers/input/misc/pm8941-pwrkey.c
> > > > 
> > > > Any reason why we cannot reuse pm8xxx-pwrkey driver? It have been
> > > > converted to regmap already.
> > > > 
> > > 
> > > The boilerplate code is the same,
> > 
> > The boilerplate code is almost 100% :-)
> > 
> > >  but configuration registers have different
> > > layout and values written in them are different.
> > 
> > We talk about 3 registers and 2 bit defines. struct regmap_field
> > should be able to help here.
> > 
> 
> You're totally right, we could rewrite the driver to use regmap_field and make
> the rest of the differences conditional. In my eyes we end up with two drivers
> in one file - but it can be done.
> 
> A difference however is that in pm8941 the ps hold behavious (reboot vs power
> off) is controlled by this same block. So I have an additional patch that adds
> a restart handler here that sets the pmic in the right state before we pull
> pshold (but I haven't been able to test it properly).
> 
> In pm8xxx this is handled in the pmic misc block and does not belong in this
> driver.

Ok, Your plan is to bring up support for QPNP power-on PMIC sub function into this
driver. In this case, I agree, it will be cleaner to have separate driver for this.

Regards,
Ivan

^ permalink raw reply

* Re: [PATCH 00/13] HID: add support of Logitech touchpads and special devices
From: Jiri Kosina @ 2014-10-29 16:14 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Andrew de los Reyes, Benjamin Tissoires, Nestor Lopez Casado,
	linux-kernel@vger.kernel.org, Linux Input
In-Reply-To: <CAN+gG=GXHUFz7y1AFyPcV2YP6dYzd-CBStJf5UAENbrpnVuOJg@mail.gmail.com>

On Wed, 29 Oct 2014, Benjamin Tissoires wrote:

> No worries. I definitively understand. Being close to the merge window 
> is never a good time to send you patches and I am sure SuSE asks you a 
> lot also :)

Indeed, sometimes the flow of inbound things is just unstoppable :)

> > I am almost done with the review, expect to hear from me in a 1-2 days 
> > timeframe regarding this series.
> 
> Cool, thanks. That is much appreciated.

I have now applied the whole patchset and pushed out.

Thanks,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* Re: [PATCH 00/13] HID: add support of Logitech touchpads and special devices
From: Benjamin Tissoires @ 2014-10-29 18:14 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Andrew de los Reyes, Benjamin Tissoires, Nestor Lopez Casado,
	linux-kernel@vger.kernel.org, Linux Input
In-Reply-To: <alpine.LNX.2.00.1410291713520.20256@pobox.suse.cz>

On Wed, Oct 29, 2014 at 12:14 PM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Wed, 29 Oct 2014, Benjamin Tissoires wrote:
>
>> No worries. I definitively understand. Being close to the merge window
>> is never a good time to send you patches and I am sure SuSE asks you a
>> lot also :)
>
> Indeed, sometimes the flow of inbound things is just unstoppable :)
>
>> > I am almost done with the review, expect to hear from me in a 1-2 days
>> > timeframe regarding this series.
>>
>> Cool, thanks. That is much appreciated.
>
> I have now applied the whole patchset and pushed out.
>

That was much faster than expected!!! Thanks a lot.

Cheers,
Benjamin

^ permalink raw reply

* Re: [PATCH 1/3] mfd: stmpe: add pull up/down register offsets for STMPE
From: Dmitry Torokhov @ 2014-10-29 19:31 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Lee Jones, Samuel Ortiz, linux-kernel@vger.kernel.org,
	Linux Input
In-Reply-To: <CACRpkdbsswGBy69+EGJTbTpxD7j2FnruyGdyUZRBVtt-JaScfg@mail.gmail.com>

On Wednesday, October 29, 2014 10:55:14 AM Linus Walleij wrote:
> On Mon, Oct 20, 2014 at 8:46 AM, Lee Jones <lee.jones@linaro.org> wrote:
> > On Sat, 18 Oct 2014, Linus Walleij wrote:
> >> This adds the register offsets for pull up/down for the STMPE
> >> 1601, 1801 and 24xx expanders. This is used to bias GPIO lines
> >> and keypad lines.
> >> 
> >> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> >> ---
> >> Hi Sam, Lee: I think you should just ACK this so Dmitry can take the
> >> patch series through the input tree, where the registers need to be
> >> used to enable the keypad on the STMPE2401.
> >> ---
> >> 
> >>  drivers/mfd/stmpe.c       | 4 ++++
> >>  drivers/mfd/stmpe.h       | 3 +++
> >>  include/linux/mfd/stmpe.h | 2 ++
> >>  3 files changed, 9 insertions(+)
> > 
> > Does this need to go in with the other patches in the set?
> > 
> > I'm _guessing_ that, as you've sent them separately, they can be
> > applied separately?
> 
> No sorry if it was unclear, the series need to go in toghether.
> So this patch adds some infrastructure to the MFD device which
> is then utilized by the input driver in a later patch.
> 
> > This needs to go in via MFD, but for my own reference:
> > 
> > Acked-by: Lee Jones <lee.jones@linaro.org>
> 
> Dmitry can you merge this & the rest with Lee's ACK?

I'd be delighted, but it _sounded_ like Lee wanted it to go though MFD?

Thanks.

-- 
Dmitry

^ permalink raw reply

* Fix Penguin Penalty 17th October2014 ( mail-archive.com )
From: bargains04894 @ 2014-10-29 20:26 UTC (permalink / raw)
  To: linux-input

Dear Sir

Did your website get hit by Google Penguin update on October 17th 2014? What basically is Google Penguin Update? It is actually a code name for Google algorithm which aims at decreasing your websites search engine rankings that violate Google’s guidelines by using black hat SEO techniques to rank your webpage by giving number of spammy links to the page.
 
We are one of those few SEO companies that can help you avoid penalties from Google Updates like Penguin and Panda. Our clients have survived all the previous and present updates with ease. They have never been hit because we use 100% white hat SEO techniques to rank Webpages.  Simple thing that we do to keep websites away from any Penguin or Panda penalties is follow Google guidelines and we give Google users the best answers to their queries.

If you are looking to increase the quality of your websites and to get more targeted traffic or save your websites from these Google penalties email us back with your interest. 

We will be glad to serve you and help you grow your business.

Regards

Vince G

SEO Manager ( TOB )
B7 Green Avenue, Amritsar 143001 Punjab
____________________________
NO CLICK in the subject to STOP EMAILS
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] Input: synaptics - add support for ForcePads
From: Peter Hutterer @ 2014-10-30  0:38 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Andrew Duggan, Hans de Goede, linux-input, Benjamin Tissoires,
	Christopher Heiny, linux-kernel
In-Reply-To: <20140909225725.GA18901@core.coreip.homeip.net>

On Tue, Sep 09, 2014 at 03:57:25PM -0700, Dmitry Torokhov wrote:
> From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> 
> ForcePads are found on HP EliteBook 1040 laptops. They lack any kind of
> physical buttons, instead they generate primary button click when user
> presses somewhat hard on the surface of the touchpad. Unfortunately they
> also report primary button click whenever there are 2 or more contacts
> on the pad, messing up all multi-finger gestures (2-finger scrolling,
> multi-finger tapping, etc). To cope with this behavior we introduce a
> delay (currently 50 msecs) in reporting primary press in case more
> contacts appear.

can we assign INPUT_PROP_FORCEPAD to this? or PRESSUREPAD or something if
we're worried about trademarks. This is something I'd like to know in
userspace, we can then ignore clicks completely and do the rest ourselves. 

Cheers,
   Peter

> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>  drivers/input/mouse/synaptics.c |   68 ++++++++++++++++++++++++++++++---------
>  drivers/input/mouse/synaptics.h |   11 ++++++
>  2 files changed, 63 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> index e8573c6..fd23181 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -629,10 +629,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
>  			 ((buf[0] & 0x04) >> 1) |
>  			 ((buf[3] & 0x04) >> 2));
>  
> +		if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
> +			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
> +		    hw->w == 2) {
> +			synaptics_parse_agm(buf, priv, hw);
> +			return 1;
> +		}
> +
> +		hw->x = (((buf[3] & 0x10) << 8) |
> +			 ((buf[1] & 0x0f) << 8) |
> +			 buf[4]);
> +		hw->y = (((buf[3] & 0x20) << 7) |
> +			 ((buf[1] & 0xf0) << 4) |
> +			 buf[5]);
> +		hw->z = buf[2];
> +
>  		hw->left  = (buf[0] & 0x01) ? 1 : 0;
>  		hw->right = (buf[0] & 0x02) ? 1 : 0;
>  
> -		if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
> +		if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) {
> +			/*
> +			 * ForcePads, like Clickpads, use middle button
> +			 * bits to report primary button clicks.
> +			 * Unfortunately they report primary button not
> +			 * only when user presses on the pad above certain
> +			 * threshold, but also when there are more than one
> +			 * finger on the touchpad, which interferes with
> +			 * out multi-finger gestures.
> +			 */
> +			if (hw->z == 0) {
> +				/* No contacts */
> +				priv->press = priv->report_press = false;
> +			} else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) {
> +				/*
> +				 * Single-finger touch with pressure above
> +				 * the threshold. If pressure stays long
> +				 * enough, we'll start reporting primary
> +				 * button. We rely on the device continuing
> +				 * sending data even if finger does not
> +				 * move.
> +				 */
> +				if  (!priv->press) {
> +					priv->press_start = jiffies;
> +					priv->press = true;
> +				} else if (time_after(jiffies,
> +						priv->press_start +
> +							msecs_to_jiffies(50))) {
> +					priv->report_press = true;
> +				}
> +			} else {
> +				priv->press = false;
> +			}
> +
> +			hw->left = priv->report_press;
> +
> +		} else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
>  			/*
>  			 * Clickpad's button is transmitted as middle button,
>  			 * however, since it is primary button, we will report
> @@ -651,21 +702,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
>  			hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
>  		}
>  
> -		if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
> -			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
> -		    hw->w == 2) {
> -			synaptics_parse_agm(buf, priv, hw);
> -			return 1;
> -		}
> -
> -		hw->x = (((buf[3] & 0x10) << 8) |
> -			 ((buf[1] & 0x0f) << 8) |
> -			 buf[4]);
> -		hw->y = (((buf[3] & 0x20) << 7) |
> -			 ((buf[1] & 0xf0) << 4) |
> -			 buf[5]);
> -		hw->z = buf[2];
> -
>  		if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
>  		    ((buf[0] ^ buf[3]) & 0x02)) {
>  			switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
> diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
> index e594af0..fb2e076 100644
> --- a/drivers/input/mouse/synaptics.h
> +++ b/drivers/input/mouse/synaptics.h
> @@ -78,6 +78,11 @@
>   * 2	0x08	image sensor		image sensor tracks 5 fingers, but only
>   *					reports 2.
>   * 2	0x20	report min		query 0x0f gives min coord reported
> + * 2	0x80	forcepad		forcepad is a variant of clickpad that
> + *					does not have physical buttons but rather
> + *					uses pressure above certain threshold to
> + *					report primary clicks. Forcepads also have
> + *					clickpad bit set.
>   */
>  #define SYN_CAP_CLICKPAD(ex0c)		((ex0c) & 0x100000) /* 1-button ClickPad */
>  #define SYN_CAP_CLICKPAD2BTN(ex0c)	((ex0c) & 0x000100) /* 2-button ClickPad */
> @@ -86,6 +91,7 @@
>  #define SYN_CAP_ADV_GESTURE(ex0c)	((ex0c) & 0x080000)
>  #define SYN_CAP_REDUCED_FILTERING(ex0c)	((ex0c) & 0x000400)
>  #define SYN_CAP_IMAGE_SENSOR(ex0c)	((ex0c) & 0x000800)
> +#define SYN_CAP_FORCEPAD(ex0c)		((ex0c) & 0x008000)
>  
>  /* synaptics modes query bits */
>  #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
> @@ -177,6 +183,11 @@ struct synaptics_data {
>  	 */
>  	struct synaptics_hw_state agm;
>  	bool agm_pending;			/* new AGM packet received */
> +
> +	/* ForcePad handling */
> +	unsigned long				press_start;
> +	bool					press;
> +	bool					report_press;
>  };
>  
>  void synaptics_module_init(void);
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* Re: About Dell Inspiron 3442 touchpad
From: Luiz Carlos Ramos @ 2014-10-30 10:06 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: linux-input
In-Reply-To: <207925.414b376d6a6b514141424539564642466841415469444f48593549@popretr.messagingengine.com>

Hi Benjamin,

Thanks for the assistance and quick reply.

On Tue, Oct 28, 2014, at 23:40, Benjamin Tissoires wrote:
> Hi Luiz,
> 
> On Tue, Oct 28, 2014 at 9:00 PM, Luiz Carlos Ramos
> <lramos.prof@yahoo.com.br> wrote:
> > Hello,
> >
> > I'm trying to make a touchpad from a Dell Inspiron I14-3442 laptop work.
> >
> > Some details:
> >
> > - I'm using plain Slackware64 14.1, but raised the kernel to 3.16.3 for
> > tests
> >
> > - xinput ignores the touchpad; it shows only a USB mouse/keyboard
> > adapter and the laptop's keyboard:
> >
> > root@pace:/sys/bus/hid/devices# xinput
> >  Virtual core pointer                            id=2    [master pointer
> >   (3)]
> >      Virtual core XTEST pointer                      id=4    [slave
> >      pointer  (2)]
> >      Generic USB K/B                                 id=12   [slave
> >      pointer  (2)]
> >   Virtual core keyboard                           id=3    [master
> >   keyboard (2)]
> >       Virtual core XTEST keyboard                     id=5    [slave
> >       keyboard (3)]
> >       Power Button                                    id=6    [slave
> >       keyboard (3)]
> >       Video Bus                                       id=7    [slave
> >       keyboard (3)]
> >       Power Button                                    id=9    [slave
> >       keyboard (3)]
> >       Sleep Button                                    id=10   [slave
> >       keyboard (3)]
> >       Integrated_Webcam_HD                            id=13   [slave
> >       keyboard (3)]
> >       AT Translated Set 2 keyboard                    id=14   [slave
> >       keyboard (3)]
> >       Dell WMI hotkeys                                id=15   [slave
> >       keyboard (3)]
> >       Video Bus                                       id=8    [slave
> >       keyboard (3)]
> >       Generic USB K/B                                 id=11   [slave
> >       keyboard (3)]
> >
> > - it seems Ubuntu certified this machine (check
> > http://www.ubuntu.com/certification/hardware/201402-14674/components/),
> > but it assumes the touchpad is PS/2. I haven't found it as a PS/2 thing,
> > even loading psmouse.ko, or doing other tricks
> >
> > - some articles lists some tips for making it work (like
> > http://askubuntu.com/questions/134627/how-do-i-get-the-touchpad-settings-working-on-a-dell-xps-13-ultrabook,
> > or https://bugzilla.redhat.com/show_bug.cgi?id=1048314#c2), but I read
> > them carefully, made some tests, and they didn't work. One article says
> > I could blacklist i2c_hid or like in order to make the bring up the
> > touchpad in PS/2 mode, but I couldn't succeed doing so
> >
> > - at Dell's site, it is offered a driver for Ubuntu 12.04, but it's
> > almost obsolete. It seems to be just merged into the kernel
> >
> > - from Windows 8.1, which runs in the same machine (dual boot), I
> > concluded the proper way of making it work is to use HID over I2C. It
> > seems that there are two components loaded; one I2CHID, and a Synaptics
> > HID. This makes me hint it may be a Synaptics device
> 
> Well, if this is a Synaptics HID over I2C device, it should be handled
> by hid-rmi in recent kernels (or hid-multitouch but I would say
> hid-rmi in your case).
> Is the hid-rmi module loaded? Can we get a dmesg output so we can see
> if there is any problem?
> 
> >
> > - it seems there are two I2C busses in the machine. One is related to
> > the Intel video graphics subsystem (i801). The other seems to be linked
> > to the touchpad (i2c_designware_platform). I'm not sure that latest kmod
> > (i2c_designware_platform) is the right one to be used in this case, but
> > it appears to be working:
> 
> Yeah, i2c_designware_platform is pretty common for Haswell processors.
> 
> >
> > root@pace:/sys/bus/i2c/devices# ls -l /sys/bus/i2c/devices
> > total 0
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-0 ->
> > ../../../devices/pci0000:00/INT33C2:00/i2c-0
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-1 ->
> > ../../../devices/pci0000:00/INT33C3:00/i2c-1
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-2 ->
> > ../../../devices/pci0000:00/0000:00:02.0/i2c-2
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-3 ->
> > ../../../devices/pci0000:00/0000:00:02.0/i2c-3
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-4 ->
> > ../../../devices/pci0000:00/0000:00:02.0/i2c-4
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-5 ->
> > ../../../devices/pci0000:00/0000:00:02.0/i2c-5
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-6 ->
> > ../../../devices/pci0000:00/0000:00:02.0/i2c-6
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-7 ->
> > ../../../devices/pci0000:00/0000:00:02.0/i2c-7
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-8 ->
> > ../../../devices/pci0000:00/0000:00:02.0/i2c-8
> > lrwxrwxrwx 1 root root 0 Out 18 17:26 i2c-DLL0652:00 ->
> > ../../../devices/pci0000:00/INT33C3:00/i2c-1/i2c-DLL0652:00
> 
> This one is the touchpad.
> 
> >
> > root@pace:/sys/bus/i2c/devices# lsmod | grep i2c
> > i2c_hid                10682  0
> > hid                    94632  3 i2c_hid,hid_generic,usbhid
> > i2c_dev                 5739  0
> > i2c_designware_platform     3189  0
> > i2c_i801               13732  0
> > i2c_designware_core     6045  1 i2c_designware_platform
> > i2c_algo_bit            5351  1 i915
> > i2c_core               35216  11
> > drm,i915,i2c_i801,i2c_dev,i2c_hid,i2c_designware_platform,drm_kms_helper,i2c_algo_bit,v4l2_common,synaptics_i2c,videodev
> >
> > - in the HID /sys directory, there are three devices. Two are related to
> > a keyboard/mouse USB adapter. The third seems to be the linked to the
> > touchpad:
> >
> > root@pace:/sys/bus/hid/devices# ls -l /sys/bus/hid/devices
> > total 0
> > lrwxrwxrwx 1 root root 0 Out 28 22:40 0003:13BA:0017.004F ->
> > ../../../devices/pci0000:00/0000:00:1d.0/usb3/3-1/3-1.3/3-1.3:1.0/0003:13BA:0017.004F
> > lrwxrwxrwx 1 root root 0 Out 28 22:40 0003:13BA:0017.0050 ->
> > ../../../devices/pci0000:00/0000:00:1d.0/usb3/3-1/3-1.3/3-1.3:1.1/0003:13BA:0017.0050
> > lrwxrwxrwx 1 root root 0 Out 28 22:40 0018:06CB:2985.0052 ->
> > ../../../devices/pci0000:00/INT33C3:00/i2c-1/i2c-DLL0652:00/0018:06CB:2985.0052
> 
> This is the HID over I2C touchpad.
> 
> >
> > - when I load the kernel module i2c-hid.ko (with debug=1), I read this
> > in dmesg:
> >
> > [146172.568787] i2c_hid i2c-DLL0652:00: Fetching the HID descriptor
> > [146172.568791] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=20 00
> > [146172.574806] i2c_hid i2c-DLL0652:00: HID Descriptor: 1e 00 00 01 85
> > 00 21 00 24 00 20 00 25 00 17 00 22 00 23 00 cb 06 85 29 00 00 00 00 00
> > 00
> > [146172.574845] i2c_hid i2c-DLL0652:00: entering i2c_hid_parse
> > [146172.574847] i2c_hid i2c-DLL0652:00: i2c_hid_hwreset
> > [146172.574849] i2c_hid i2c-DLL0652:00: i2c_hid_set_power
> > [146172.574850] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 00
> > 08
> > [146172.575436] i2c_hid i2c-DLL0652:00: resetting...
> > [146172.575442] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 00
> > 01
> > [146172.576113] i2c_hid i2c-DLL0652:00: __i2c_hid_command: waiting...
> > [146172.577414] i2c_hid i2c-DLL0652:00: __i2c_hid_command: finished.
> > [146172.577417] i2c_hid i2c-DLL0652:00: asking HID report descriptor
> > [146172.577419] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=21 00
> > [146172.581072] i2c_hid i2c-DLL0652:00: Report Descriptor: 05 01 09 02
> > a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02
> > 95 06 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 06 00
> > ff 09 01 a1 01 85 09 09 02 15 00 26
> > [146172.581126] i2c_hid i2c-DLL0652:00: i2c_hid_set_power
> > [146172.581129] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 01
> > 08
> 
> Everything is fine, this is the normal behavior while connecting a
> i2c_hid device.
> Normally, we should have then hid-rmi asking for more things and then
> it will eventually set up the input device.
> 
> >
> > I am aware this information probably is not sufficient to draw any
> > conclusions, but I'd appreciate to hear from someone who knows i2c_hid
> > in detail what steps I should take next. For me the last command timed
> > out or got stuck, but I haven't checked the code to see if it's the
> > case. Anyway, if it was a timeout case, it should have something logged
> > after the time expired.
> 
> There is no answer from the device when a SET_POWER is emitted. So
> this is not a timeout problem.
> 
> If hid-rmi is compiled and is not taking the device, we have a big
> problem, but for now, the symptoms look like you do not have this
> driver compiled and hid-generic does not bind the device because it
> waits for hid-rmi to handle it.
> 

Well, I tried to insmod hid-rmi, and nothing special happened. Here is a
dmesg output (relevant lines):

[158885.774386] i2c_hid i2c-DLL0652:00: Fetching the HID descriptor
[158885.774391] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=20 00
[158885.785853] i2c_hid i2c-DLL0652:00: HID Descriptor: 1e 00 00 01 85
00 21 00 24 00 20 00 25 00 17 00 22 00 23 00 cb 06 85 29 00 00 00 00 00
00
[158885.785924] i2c_hid i2c-DLL0652:00: entering i2c_hid_parse
[158885.785926] i2c_hid i2c-DLL0652:00: i2c_hid_hwreset
[158885.785927] i2c_hid i2c-DLL0652:00: i2c_hid_set_power
[158885.785928] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 00
08
[158885.786494] i2c_hid i2c-DLL0652:00: resetting...
[158885.786497] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 00
01
[158885.787285] i2c_hid i2c-DLL0652:00: __i2c_hid_command: waiting...
[158885.788496] i2c_hid i2c-DLL0652:00: __i2c_hid_command: finished.
[158885.788499] i2c_hid i2c-DLL0652:00: asking HID report descriptor
[158885.788501] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=21 00
[158885.792194] i2c_hid i2c-DLL0652:00: Report Descriptor: 05 01 09 02
a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02
95 06 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 c0 c0 06 00
ff 09 01 a1 01 85 09 09 02 15 00 26
[158885.792252] i2c_hid i2c-DLL0652:00: i2c_hid_set_power
[158885.792254] i2c_hid i2c-DLL0652:00: __i2c_hid_command: cmd=22 00 01
08

I included lines like:

printk(KERN_ERR "hid_rmi_probe(): called\n");
printk(KERN_ERR "hid_rmi_probe(): ret=0\n");

in the beginning and at the end of the routine rmi_probe(). These lines
didn't 
appear in dmesg (those pictured above). I don't know if "probe" is to be
called 
in this case, or not. Is there any other condition to make hid-rmi be
"instantiated",
I mean, other kmod to be loaded, or a special ioctl() coming to the hid
from userland,
or even echoing something to the "bind" file at /sys/...?

Well, here's the "directory" /sys/bus/hid/drivers/hid-rmi:

root@pace:/sys/bus/hid/drivers/hid-rmi# ls -l
/sys/bus/hid/drivers/hid-rmi/
total 0
--w------- 1 root root 4096 Out 30 08:03 bind
lrwxrwxrwx 1 root root    0 Out 30 08:03 module ->
../../../../module/hid_rmi
--w------- 1 root root 4096 Out 30 08:03 new_id
--w------- 1 root root 4096 Out 30 07:48 uevent
--w------- 1 root root 4096 Out 30 08:03 unbind

One thing I didn't still did is to reboot the machine. I found it was
not the case,
but this type of action use to work a lot in IT/IS, right? :-) 

> >
> > I have some programming skills, and so if it's the case of applying any
> > patches, or recompiling the kernel or any subsystem to make tests, I'm
> > up to.
> 
> Cool, thanks.
> 
> Cheers,
> Benjamin

Many thanks, 

Luiz

^ permalink raw reply

* [PATCH v2] psmouse: Add some support for the FocalTech PS/2 protocol extensions.
From: Mathias Gottschlag @ 2014-10-30 12:42 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, Hans de Goede, Benjamin Tissoires

Most of the protocol for these touchpads has been reverse engineered. This
commit adds a basic multitouch-capable driver.

A lot of the protocol is still unknown. Especially, we don't know how to
identify the device yet apart from the PNP ID.

The previous workaround for these devices has been left in place in case
the driver is not compiled into the kernel or in case some other device
with the same PNP ID is not recognized by the driver yet still has the
same
problems with the device probing code.
---

Thanks for the first round of review, I hope I addressed all comments.
Changes compared to the last version:
- The detection code does not compare all registers anymore.
- The driver now reads the size of the touchpad during initialization.
This should add support for Asus X450JN, where the touchpad is a bit
wider.
- set_input_params has been simplified.
- fingers are now valid=0 when the touchpad reports a large object.

 drivers/input/mouse/Kconfig        |  10 ++
 drivers/input/mouse/focaltech.c    | 293
++++++++++++++++++++++++++++++++++++-
 drivers/input/mouse/focaltech.h    |  60 ++++++++
 drivers/input/mouse/psmouse-base.c |  32 ++--
 drivers/input/mouse/psmouse.h      |   1 +
 5 files changed, 379 insertions(+), 17 deletions(-)

diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 366fc7a..db973e5 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -146,6 +146,16 @@ config MOUSE_PS2_OLPC
  	  If unsure, say N.
 +config MOUSE_PS2_FOCALTECH
+	bool "FocalTech PS/2 mouse protocol extension" if EXPERT
+	default y
+	depends on MOUSE_PS2
+	help
+	  Say Y here if you have a FocalTech PS/2 TouchPad connected to
+	  your system.
+
+	  If unsure, say Y.
+
 config MOUSE_SERIAL
 	tristate "Serial mouse"
 	select SERIO
diff --git a/drivers/input/mouse/focaltech.c
b/drivers/input/mouse/focaltech.c
index f4d657e..974007e 100644
--- a/drivers/input/mouse/focaltech.c
+++ b/drivers/input/mouse/focaltech.c
@@ -2,6 +2,7 @@
  * Focaltech TouchPad PS/2 mouse driver
  *
  * Copyright (c) 2014 Red Hat Inc.
+ * Copyright (c) 2014 Mathias Gottschlag <mgottschlag@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -13,15 +14,14 @@
  * Hans de Goede <hdegoede@redhat.com>
  */
 -/*
- * The Focaltech PS/2 touchpad protocol is unknown. This drivers
deals with
- * detection only, to avoid further detection attempts confusing the
touchpad
- * this way it at least works in PS/2 mouse compatibility mode.
- */
  #include <linux/device.h>
 #include <linux/libps2.h>
+#include <linux/input/mt.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
 #include "psmouse.h"
+#include "focaltech.h"
  static const char * const focaltech_pnp_ids[] = {
 	"FLT0101",
@@ -30,6 +30,12 @@ static const char * const focaltech_pnp_ids[] = {
 	NULL
 };
 +/*
+ * Even if the kernel is built without support for Focaltech PS/2
touchpads (or
+ * when the real driver fails to recognize the device), we still have
to detect
+ * them in order to avoid further detection attempts confusing the
touchpad.
+ * This way it at least works in PS/2 mouse compatibility mode.
+ */
 int focaltech_detect(struct psmouse *psmouse, bool set_properties)
 {
 	if (!psmouse_matches_pnp_id(psmouse, focaltech_pnp_ids))
@@ -37,16 +43,289 @@ int focaltech_detect(struct psmouse *psmouse,
bool set_properties)
  	if (set_properties) {
 		psmouse->vendor = "FocalTech";
-		psmouse->name = "FocalTech Touchpad in mouse emulation mode";
+		psmouse->name = "FocalTech Touchpad";
 	}
  	return 0;
 }
 -int focaltech_init(struct psmouse *psmouse)
+static void focaltech_reset(struct psmouse *psmouse)
 {
 	ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
 	psmouse_reset(psmouse);
+}
+
+#ifdef CONFIG_MOUSE_PS2_FOCALTECH
+
+static void focaltech_report_state(struct psmouse *psmouse)
+{
+	int i;
+	struct focaltech_data *priv = psmouse->private;
+	struct focaltech_hw_state *state = &priv->state;
+	struct input_dev *dev = psmouse->dev;
+	int finger_count = 0;
+
+	for (i = 0; i < FOC_MAX_FINGERS; i++) {
+		struct focaltech_finger_state *finger = &state->fingers[i];
+		int active = finger->active && finger->valid;
+		input_mt_slot(dev, i);
+		input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
+		if (active) {
+			finger_count++;
+			input_report_abs(dev, ABS_MT_POSITION_X, finger->x);
+			input_report_abs(dev, ABS_MT_POSITION_Y,
+					focaltech_invert_y(finger->y));
+		}
+	}
+	input_mt_report_pointer_emulation(dev, finger_count);
+
+	input_report_key(psmouse->dev, BTN_LEFT, state->pressed);
+	input_sync(psmouse->dev);
+}
+
+static void process_touch_packet(struct focaltech_hw_state *state,
+		unsigned char *packet)
+{
+	int i;
+	unsigned char fingers = packet[1];
+
+	state->pressed = (packet[0] >> 4) & 1;
+	/* the second byte contains a bitmap of all fingers touching the pad */
+	for (i = 0; i < FOC_MAX_FINGERS; i++) {
+		if ((fingers & 0x1) && !state->fingers[i].active) {
+			/* we do not have a valid position for the finger yet */
+			state->fingers[i].valid = 0;
+		}
+		state->fingers[i].active = fingers & 0x1;
+		fingers >>= 1;
+	}
+}
+
+static void process_abs_packet(struct focaltech_hw_state *state,
+		unsigned char *packet)
+{
+	unsigned int finger = (packet[1] >> 4) - 1;
+
+	state->pressed = (packet[0] >> 4) & 1;
+	if (finger >= FOC_MAX_FINGERS)
+		return;
+	/*
+	 * packet[5] contains some kind of tool size in the most significant
+	 * nibble. 0xff is a special value (latching) that signals a large
+	 * contact area.
+	 */
+	if (packet[5] == 0xff) {
+		state->fingers[finger].valid = 0;
+		return;
+	}
+	state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2];
+	state->fingers[finger].y = (packet[3] << 8) | packet[4];
+	state->fingers[finger].valid = 1;
+}
+static void process_rel_packet(struct focaltech_hw_state *state,
+		unsigned char *packet)
+{
+	int finger1 = ((packet[0] >> 4) & 0x7) - 1;
+	int finger2 = ((packet[3] >> 4) & 0x7) - 1;
+
+	state->pressed = packet[0] >> 7;
+	if (finger1 < FOC_MAX_FINGERS) {
+		state->fingers[finger1].x += (char)packet[1];
+		state->fingers[finger1].y += (char)packet[2];
+	}
+	/*
+	 * If there is an odd number of fingers, the last relative packet only
+	 * contains one finger. In this case, the second finger index in the
+	 * packet is 0 (we subtract 1 in the lines above to create array
+	 * indices).
+	 */
+	if (finger2 != -1 && finger2 < FOC_MAX_FINGERS) {
+		state->fingers[finger2].x += (char)packet[4];
+		state->fingers[finger2].y += (char)packet[5];
+	}
+}
+
+static void focaltech_process_packet(struct psmouse *psmouse)
+{
+	struct focaltech_data *priv = psmouse->private;
+	unsigned char *packet = psmouse->packet;
+
+	switch (packet[0] & 0xf) {
+	case FOC_TOUCH:
+		process_touch_packet(&priv->state, packet);
+		break;
+	case FOC_ABS:
+		process_abs_packet(&priv->state, packet);
+		break;
+	case FOC_REL:
+		process_rel_packet(&priv->state, packet);
+		break;
+	default:
+		psmouse_err(psmouse, "Unknown packet type: %02x", packet[0]);
+		break;
+	}
+
+	focaltech_report_state(psmouse);
+}
+
+static psmouse_ret_t focaltech_process_byte(struct psmouse *psmouse)
+{
+	if (psmouse->pktcnt >= 6) { /* Full packet received */
+		focaltech_process_packet(psmouse);
+		return PSMOUSE_FULL_PACKET;
+	}
+	/*
+	 * we might want to do some validation of the data here, but we do not
+	 * know the protocoll well enough
+	 */
+	return PSMOUSE_GOOD_DATA;
+}
+
+static int focaltech_switch_protocol(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char param[3];
+
+	param[0] = 0;
+	if (ps2_command(ps2dev, param, 0x10f8))
+		return -EIO;
+	if (ps2_command(ps2dev, param, 0x10f8))
+		return -EIO;
+	if (ps2_command(ps2dev, param, 0x10f8))
+		return -EIO;
+	param[0] = 1;
+	if (ps2_command(ps2dev, param, 0x10f8))
+		return -EIO;
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11))
+		return -EIO;
+
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_ENABLE))
+		return -EIO;
  	return 0;
 }
+
+static void focaltech_disconnect(struct psmouse *psmouse)
+{
+	focaltech_reset(psmouse);
+	kfree(psmouse->private);
+	psmouse->private = NULL;
+}
+
+static int focaltech_reconnect(struct psmouse *psmouse)
+{
+	focaltech_reset(psmouse);
+	if (focaltech_switch_protocol(psmouse)) {
+		psmouse_err(psmouse,
+			    "Unable to initialize the device.");
+		return -1;
+	}
+	return 0;
+}
+
+static void set_input_params(struct psmouse *psmouse)
+{
+	struct input_dev *dev = psmouse->dev;
+	struct focaltech_data *priv = psmouse->private;
+
+	__set_bit(EV_ABS, dev->evbit);
+	input_set_abs_params(dev, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
+	input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
+	input_mt_init_slots(dev, 5, INPUT_MT_POINTER);
+	__clear_bit(EV_REL, dev->evbit);
+	__clear_bit(REL_X, dev->relbit);
+	__clear_bit(REL_Y, dev->relbit);
+	__clear_bit(BTN_RIGHT, dev->keybit);
+	__clear_bit(BTN_MIDDLE, dev->keybit);
+	__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
+}
+
+static int focaltech_read_register(struct ps2dev *ps2dev, int reg,
+		unsigned char *param)
+{
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11))
+		return -1;
+	param[0] = 0;
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
+		return -1;
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
+		return -1;
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
+		return -1;
+	param[0] = reg;
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
+		return -1;
+	if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
+		return -1;
+	return 0;
+}
+
+static int focaltech_read_size(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	struct focaltech_data *priv = psmouse->private;
+	char param[3];
+
+	if (focaltech_read_register(ps2dev, 2, param))
+		return -EIO;
+	/* not sure whether this is 100% correct */
+	priv->x_max = (unsigned char)param[1] * 128;
+	priv->y_max = (unsigned char)param[2] * 128;
+
+	return 0;
+}
+int focaltech_init(struct psmouse *psmouse)
+{
+	struct focaltech_data *priv;
+
+	focaltech_reset(psmouse);
+	if (focaltech_read_size(psmouse)) {
+		focaltech_reset(psmouse);
+		psmouse_err(psmouse,
+			    "Unable to read the size of the touchpad.");
+		return -ENOSYS;
+	}
+	if (focaltech_switch_protocol(psmouse)) {
+		focaltech_reset(psmouse);
+		psmouse_err(psmouse,
+			    "Unable to initialize the device.");
+		return -ENOSYS;
+	}
+
+	psmouse->private = priv = kzalloc(sizeof(struct focaltech_data),
GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	set_input_params(psmouse);
+
+	psmouse->protocol_handler = focaltech_process_byte;
+	psmouse->pktsize = 6;
+	psmouse->disconnect = focaltech_disconnect;
+	psmouse->reconnect = focaltech_reconnect;
+	psmouse->cleanup = focaltech_reset;
+	/* resync is not supported yet */
+	psmouse->resync_time = 0;
+
+	return 0;
+}
+
+bool focaltech_supported(void)
+{
+	return true;
+}
+
+#else /* CONFIG_MOUSE_PS2_FOCALTECH */
+
+int focaltech_init(struct psmouse *psmouse)
+{
+	focaltech_reset(psmouse);
+
+	return 0;
+}
+
+bool focaltech_supported(void)
+{
+	return false;
+}
+
+#endif /* CONFIG_MOUSE_PS2_FOCALTECH */
diff --git a/drivers/input/mouse/focaltech.h
b/drivers/input/mouse/focaltech.h
index 498650c..68c5cfc 100644
--- a/drivers/input/mouse/focaltech.h
+++ b/drivers/input/mouse/focaltech.h
@@ -2,6 +2,7 @@
  * Focaltech TouchPad PS/2 mouse driver
  *
  * Copyright (c) 2014 Red Hat Inc.
+ * Copyright (c) 2014 Mathias Gottschlag <mgottschlag@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -16,7 +17,66 @@
 #ifndef _FOCALTECH_H
 #define _FOCALTECH_H
 +/*
+ * Packet types - the numbers are not consecutive, so we might be missing
+ * something here.
+ */
+#define FOC_TOUCH 0x3 /* bitmap of active fingers */
+#define FOC_ABS 0x6 /* absolute position of one finger */
+#define FOC_REL 0x9 /* relative position of 1-2 fingers */
+
+#define FOC_MAX_FINGERS 5
+
+#define FOC_MAX_X 2431
+#define FOC_MAX_Y 1663
+
+static inline int focaltech_invert_y(int y)
+{
+	return FOC_MAX_Y - y;
+}
+
+/*
+ * Current state of a single finger on the touchpad.
+ */
+struct focaltech_finger_state {
+	/* the touchpad has generated a touch event for the finger */
+	bool active;
+	/*
+	 * The touchpad has sent position data for the finger. Touch event
+	 * packages reset this flag for new fingers, and there is a time
+	 * between the first touch event and the following absolute position
+	 * packet for the finger where the touchpad has declared the finger to
+	 * be valid, but we do not have any valid position yet.
+	 */
+	bool valid;
+	/* absolute position (from the bottom left corner) of the finger */
+	unsigned int x;
+	unsigned int y;
+};
+
+/*
+ * Description of the current state of the touchpad hardware.
+ */
+struct focaltech_hw_state {
+	/*
+	 * The touchpad tracks the positions of the fingers for us, the array
+	 * indices correspond to the finger indices returned in the report
+	 * packages.
+	 */
+	struct focaltech_finger_state fingers[FOC_MAX_FINGERS];
+	/*
+	 * True if the clickpad has been pressed.
+	 */
+	bool pressed;
+};
+
+struct focaltech_data {
+	unsigned int x_max, y_max;
+	struct focaltech_hw_state state;
+};
+
 int focaltech_detect(struct psmouse *psmouse, bool set_properties);
 int focaltech_init(struct psmouse *psmouse);
+bool focaltech_supported(void);
  #endif
diff --git a/drivers/input/mouse/psmouse-base.c
b/drivers/input/mouse/psmouse-base.c
index 26994f6..4a9de33 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -725,16 +725,19 @@ static int psmouse_extensions(struct psmouse
*psmouse,
  /* Always check for focaltech, this is safe as it uses pnp-id
matching */
 	if (psmouse_do_detect(focaltech_detect, psmouse, set_properties) == 0) {
-		if (!set_properties || focaltech_init(psmouse) == 0) {
-			/*
-			 * Not supported yet, use bare protocol.
-			 * Note that we need to also restrict
-			 * psmouse_max_proto so that psmouse_initialize()
-			 * does not try to reset rate and resolution,
-			 * because even that upsets the device.
-			 */
-			psmouse_max_proto = PSMOUSE_PS2;
-			return PSMOUSE_PS2;
+		if (max_proto > PSMOUSE_IMEX) {
+			if (!set_properties || focaltech_init(psmouse) == 0) {
+				if (focaltech_supported())
+					return PSMOUSE_FOCALTECH;
+				/*
+				 * Note that we need to also restrict
+				 * psmouse_max_proto so that psmouse_initialize()
+				 * does not try to reset rate and resolution,
+				 * because even that upsets the device.
+				 */
+				psmouse_max_proto = PSMOUSE_PS2;
+				return PSMOUSE_PS2;
+			}
 		}
 	}
 @@ -1063,6 +1066,15 @@ static const struct psmouse_protocol
psmouse_protocols[] = {
 		.alias		= "cortps",
 		.detect		= cortron_detect,
 	},
+#ifdef CONFIG_MOUSE_PS2_FOCALTECH
+	{
+		.type		= PSMOUSE_FOCALTECH,
+		.name		= "FocalTechPS/2",
+		.alias		= "focaltech",
+		.detect		= focaltech_detect,
+		.init		= focaltech_init,
+	},
+#endif
 	{
 		.type		= PSMOUSE_AUTO,
 		.name		= "auto",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index f4cf664..c2ff137 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -96,6 +96,7 @@ enum psmouse_type {
 	PSMOUSE_FSP,
 	PSMOUSE_SYNAPTICS_RELATIVE,
 	PSMOUSE_CYPRESS,
+	PSMOUSE_FOCALTECH,
 	PSMOUSE_AUTO		/* This one should always be last */
 };
 -- 1.9.1


^ permalink raw reply related

* Re: [PATCH] psmouse: Add some support for the FocalTech PS/2 protocol extensions.
From: Mathias Gottschlag @ 2014-10-30 12:48 UTC (permalink / raw)
  To: Hans de Goede, Dmitry Torokhov; +Cc: linux-input
In-Reply-To: <544E1304.2060006@redhat.com>

Two small comments below.

Am 27.10.2014 um 10:40 schrieb Hans de Goede:
> Hi Matthias,
>
> On 10/25/2014 02:01 PM, Mathias Gottschlag wrote:
>> Most of the protocol for these touchpads has been reverse engineered.
This
>> commit adds a basic multitouch-capable driver.
>>
>> A lot of the protocol is still unknown. Especially, we don't know how to
>> identify the device yet apart from the PNP ID. The code currently
compares
>> known good values with all data from the touchpad which could be
usable for
>> identification, so by design even minor variations will cause the driver
>> to fail to detect the device and fall back to compatibility mode.
>>
>> The previous workaround for these devices has been left in place in case
>> the driver is not compiled into the kernel or in case some other device
>> with the same PNP ID is not recognized by the driver yet still has
the same
>> problems with the device probing code.
>> ---
>>
>> Hi,
>>
>> this patch is related to the following bugs:
>> https://bugzilla.redhat.com/show_bug.cgi?id=1110011
>> https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1372609
>>
>> It has been tested on the Asus UX303LN, UX303LA and K750L laptops. The
>> latter is affected by bug 1110011 above and used to require additional
>> flags before the touchpad would work. This behaviour should have been
>> fixed by the previous FocalTech patch, but is still present after this
>> patch. I have not yet gotten any feedback yet, but my theory is that the
>> original patch failed to fix the kernel on that device. I have to admit
>> though that I haven't 100% understood that patch.
>>
>> When reviewing, keep in mind that this is my first linux patch. I am
>> using the code for quite some time now without issues, but I might have
>> overlooked quite some problems.
>
> First of all many thanks for working on this.
>
> First one overall comment on the patch, I don't really like the new
> detect function you are adding, and I don't see a need for it, pnp-id
> detection is what windows uses, and it should be 100% reliable (famous
last
> words). So I would prefer to stick with with only the pnp-id detection.
>
> I do agree that keeping the pnp-id detection (and falling back to
bare) even
> when focaltech support is not compiled in is something which we should do.
>
> Note that likewise specifying psmouse.proto=bare should runtime disable
> your new code if compiled in so the detection blurb in psmouse-base.c
should
> look something like this:
>
> /* Always check for focaltech, this is safe as it uses pnp-id matching */
>         if (psmouse_do_detect(focaltech_detect, psmouse,
set_properties) == 0) {
>         if (max_proto > PSMOUSE_IMEX) {
>                     if (!set_properties || focaltech_init(psmouse) == 0) {
>                 if (focaltech_supported())
>                     return PSMOUSE_FOCALTECH;
>                             /*
>                              * Note that we need to also restrict
>                              * psmouse_max_proto so that
psmouse_initialize()
>                              * does not try to reset rate and resolution,
>                              * because even that upsets the device.
>                              */
>                             psmouse_max_proto = PSMOUSE_PS2;
>                             return PSMOUSE_PS2;
>             }
>                 }
>         }
>
> Where focaltech_supported() is a simple:
>
> #ifdef CONFIG_MOUSE_PS2_FOCALTECH
> bool focaltech_supported(void) {
>     return true;
> }
> #else
> bool focaltech_supported(void) {
>     return false;
> }
> #endif
>
> in focaltech.c (see synaptics.c, which defines synaptics_supported()
in the
> same way.
>
>
>
>
>
>>
>> Regards,
>> Mathias
>>
>>  drivers/input/mouse/Kconfig        |  10 ++
>>  drivers/input/mouse/focaltech.c    | 326
>> ++++++++++++++++++++++++++++++++++++-
>>  drivers/input/mouse/focaltech.h    |  61 +++++++
>>  drivers/input/mouse/psmouse-base.c |  15 ++
>>  drivers/input/mouse/psmouse.h      |   1 +
>>  5 files changed, 406 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
>> index 366fc7a..db973e5 100644
>> --- a/drivers/input/mouse/Kconfig
>> +++ b/drivers/input/mouse/Kconfig
>> @@ -146,6 +146,16 @@ config MOUSE_PS2_OLPC
>>         If unsure, say N.
>>  +config MOUSE_PS2_FOCALTECH
>> +    bool "FocalTech PS/2 mouse protocol extension" if EXPERT
>> +    default y
>> +    depends on MOUSE_PS2
>> +    help
>> +      Say Y here if you have a FocalTech PS/2 TouchPad connected to
>> +      your system.
>> +
>> +      If unsure, say Y.
>> +
>>  config MOUSE_SERIAL
>>      tristate "Serial mouse"
>>      select SERIO
>> diff --git a/drivers/input/mouse/focaltech.c
>> b/drivers/input/mouse/focaltech.c
>> index f4d657e..ada97cc 100644
>> --- a/drivers/input/mouse/focaltech.c
>> +++ b/drivers/input/mouse/focaltech.c
>> @@ -2,6 +2,7 @@
>>   * Focaltech TouchPad PS/2 mouse driver
>>   *
>>   * Copyright (c) 2014 Red Hat Inc.
>> + * Copyright (c) 2014 Mathias Gottschlag <mgottschlag@gmail.com>
>>   *
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License as published by
>> @@ -13,15 +14,14 @@
>>   * Hans de Goede <hdegoede@redhat.com>
>>   */
>>  -/*
>> - * The Focaltech PS/2 touchpad protocol is unknown. This drivers
deals with
>> - * detection only, to avoid further detection attempts confusing the
>> touchpad
>> - * this way it at least works in PS/2 mouse compatibility mode.
>> - */
>>   #include <linux/device.h>
>>  #include <linux/libps2.h>
>> +#include <linux/input/mt.h>
>> +#include <linux/serio.h>
>> +#include <linux/slab.h>
>>  #include "psmouse.h"
>> +#include "focaltech.h"
>>   static const char * const focaltech_pnp_ids[] = {
>>      "FLT0101",
>> @@ -30,7 +30,14 @@ static const char * const focaltech_pnp_ids[] = {
>>      NULL
>>  };
>>  -int focaltech_detect(struct psmouse *psmouse, bool set_properties)
>> +/*
>> + * Even if the kernel is built without support for Focaltech PS/2
>> touchpads (or
>> + * when the real driver fails to recognize the device), we still have
>> to detect
>> + * them in order to avoid further detection attempts confusing the
>> touchpad.
>> + * This way it at least works in PS/2 mouse compatibility mode.
>> + */
>> +
>> +int focaltech_detect_fallback(struct psmouse *psmouse, bool
set_properties)
>>  {
>>      if (!psmouse_matches_pnp_id(psmouse, focaltech_pnp_ids))
>>          return -ENODEV;
>> @@ -43,10 +50,315 @@ int focaltech_detect(struct psmouse *psmouse, bool
>> set_properties)
>>      return 0;
>>  }
>>  -int focaltech_init(struct psmouse *psmouse)
>> +int focaltech_init_fallback(struct psmouse *psmouse)
>> +{
>> +    ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
>> +    psmouse_reset(psmouse);
>> +
>> +    return 0;
>> +}
>> +
>
> As discussed please keep this named focaltech_init, and make this version
> #ifndef CONFIG_MOUSE_PS2_FOCALTECH (or put it in the #else block.
>
> Also you may want to make this use the newly defined focaltech_reset()
> function (which would then be outside of #ifdef
CONFIG_MOUSE_PS2_FOCALTECH)
>
>> +#ifdef CONFIG_MOUSE_PS2_FOCALTECH
>> +
>> +static int focaltech_read_register(struct ps2dev *ps2dev, int reg,
>> +        unsigned char *param)
>> +{
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11))
>> +        return -1;
>> +    param[0] = 0;
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>> +        return -1;
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>> +        return -1;
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>> +        return -1;
>> +    param[0] = reg;
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
>> +        return -1;
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
>> +        return -1;
>> +    return 0;
>> +}
>> +
>
> If you drop the register contents check, you can drop this as well,
> may be useful for future reference though, so may make it #if 0 ...
#endif.
> Dmitry ?
I've left this one in, I think my comment about the touchpad size below
was correct.
>
>
>
>> +int focaltech_detect(struct psmouse *psmouse, bool set_properties)
>> +{
>> +    struct ps2dev *ps2dev = &psmouse->ps2dev;
>> +    unsigned char param[3];
>> +
>> +    if (!psmouse_matches_pnp_id(psmouse, focaltech_pnp_ids))
>> +        return -ENODEV;
>> +
>> +    /*
>> +     * We don't know how to identify the device, so we just check the
>> +     * content of all registers.
>> +     */
>> +    if (focaltech_read_register(ps2dev, 0, param))
>> +        return -EIO;
>> +    if (param[0] != 0x69 || param[1] != 0x80 || param[2] != 0x80)
>> +        return -ENODEV;
>> +    if (focaltech_read_register(ps2dev, 1, param))
>> +        return -EIO;
>> +    if (param[0] != 0x36 || param[1] != 0x53 || param[2] != 0x03)
>> +        return -ENODEV;
>> +    if (focaltech_read_register(ps2dev, 2, param))
>> +        return -EIO;
>> +    /* 0x13 and 0x0d might be the touchpad size? */
>> +    if (param[0] != 0x00 || param[1] != 0x13 || param[2] != 0x0d)
>> +        return -ENODEV;
>> +    if (focaltech_read_register(ps2dev, 5, param))
>> +        return -EIO;
>> +    if (param[0] != 0x0b || param[1] != 0x03 || param[2] != 0x00)
>> +        return -ENODEV;
>> +    if (focaltech_read_register(ps2dev, 6, param))
>> +        return -EIO;
>> +    if (param[0] != 0x23 || param[1] != 0xbd || param[2] != 0xf8)
>> +        return -ENODEV;
>> +
>> +    if (set_properties) {
>> +        psmouse->vendor = "FocalTech";
>> +        psmouse->name = "FocalTech Touchpad";
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static void focaltech_report_state(struct psmouse *psmouse)
>> +{
>> +    int i;
>> +    struct focaltech_data *priv = psmouse->private;
>> +    struct focaltech_hw_state *state = &priv->state;
>> +    struct input_dev *dev = psmouse->dev;
>> +    int finger_count = 0;
>> +
>> +    for (i = 0; i < FOC_MAX_FINGERS; i++) {
>> +        struct focaltech_finger_state *finger = &state->fingers[i];
>> +        int active = finger->active && finger->valid;
>> +        input_mt_slot(dev, i);
>> +        input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
>> +        if (active) {
>> +            finger_count++;
>> +            input_report_abs(dev, ABS_MT_POSITION_X, finger->x);
>> +            input_report_abs(dev, ABS_MT_POSITION_Y,
>> +                    focaltech_invert_y(finger->y));
>> +        }
>> +    }
>> +    input_mt_report_pointer_emulation(dev, false);
>> +    input_mt_report_finger_count(dev, finger_count);
>
> These 2 lines should be replace with:
>     input_mt_report_pointer_emulation(dev, finger_count);
>
> So that BTN_TOUCH properly gets set when at least one finger is down
(this is
> mandatory when not reporting pressure).
>
> Also I see that you are not using input_mt_assign_slots, so I take it that
> if put 2 fingers down and then lift the first finger down, the second
finger
> stays in slot->fingers[1] ? Because if it does not then you need to use
> input_mt_assign_slots.
Yes, the touchpad keeps track of which touch corresponds to which finger.
>
>
>> +
>> +    input_report_key(psmouse->dev, BTN_LEFT, state->pressed);
>> +    input_sync(psmouse->dev);
>> +}
>> +
>> +static void process_touch_packet(struct focaltech_hw_state *state,
>> +        unsigned char *packet)
>> +{
>> +    int i;
>> +    unsigned char fingers = packet[1];
>> +
>> +    state->pressed = (packet[0] >> 4) & 1;
>> +    /* the second byte contains a bitmap of all fingers touching the
pad */
>> +    for (i = 0; i < FOC_MAX_FINGERS; i++) {
>> +        if ((fingers & 0x1) && !state->fingers[i].active) {
>> +            /* we do not have a valid position for the finger yet */
>> +            state->fingers[i].valid = 0;
>> +        }
>> +        state->fingers[i].active = fingers & 0x1;
>> +        fingers >>= 1;
>> +    }
>> +}
>> +
>> +static void process_abs_packet(struct focaltech_hw_state *state,
>> +        unsigned char *packet)
>> +{
>> +    unsigned int finger = (packet[1] >> 4) - 1;
>> +
>> +    state->pressed = (packet[0] >> 4) & 1;
>> +    if (finger >= FOC_MAX_FINGERS)
>> +        return;
>> +    /*
>> +     * packet[5] contains some kind of tool size in the most significant
>> +     * nibble. 0xff is a special value (latching) that signals a large
>> +     * contact area.
>> +     */
>> +    if (packet[5] == 0xff)
>> +        return;
>
> Maybe set state->fingers[finger].valid = 0 here ?
>
>> +    state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2];
>> +    state->fingers[finger].y = (packet[3] << 8) | packet[4];
>> +    state->fingers[finger].valid = 1;
>> +}
>> +static void process_rel_packet(struct focaltech_hw_state *state,
>> +        unsigned char *packet)
>> +{
>> +    int finger1 = ((packet[0] >> 4) & 0x7) - 1;
>> +    int finger2 = ((packet[3] >> 4) & 0x7) - 1;
>> +
>> +    state->pressed = packet[0] >> 7;
>> +    if (finger1 < FOC_MAX_FINGERS) {
>> +        state->fingers[finger1].x += (char)packet[1];
>> +        state->fingers[finger1].y += (char)packet[2];
>> +    }
>> +    /*
>> +     * If there is an odd number of fingers, the last relative
packet only
>> +     * contains one finger. In this case, the second finger index in the
>> +     * packet is 0 (we subtract 1 in the lines above to create array
>> +     * indices).
>> +     */
>> +    if (finger2 != -1 && finger2 < FOC_MAX_FINGERS) {
>> +        state->fingers[finger2].x += (char)packet[4];
>> +        state->fingers[finger2].y += (char)packet[5];
>> +    }
>> +}
>> +
>> +static void focaltech_process_packet(struct psmouse *psmouse)
>> +{
>> +    struct focaltech_data *priv = psmouse->private;
>> +    unsigned char *packet = psmouse->packet;
>> +
>> +    switch (packet[0] & 0xf) {
>> +    case FOC_TOUCH:
>> +        process_touch_packet(&priv->state, packet);
>> +        break;
>> +    case FOC_ABS:
>> +        process_abs_packet(&priv->state, packet);
>> +        break;
>> +    case FOC_REL:
>> +        process_rel_packet(&priv->state, packet);
>> +        break;
>> +    default:
>> +        psmouse_err(psmouse, "Unknown packet type: %02x", packet[0]);
>> +        break;
>> +    }
>> +
>> +    focaltech_report_state(psmouse);
>> +}
>> +
>> +static psmouse_ret_t focaltech_process_byte(struct psmouse *psmouse)
>>  {
>> +    if (psmouse->pktcnt >= 6) { /* Full packet received */
>> +        focaltech_process_packet(psmouse);
>> +        return PSMOUSE_FULL_PACKET;
>> +    }
>> +    /*
>> +     * we might want to do some validation of the data here, but we
do not
>> +     * know the protocoll well enough
>> +     */
>> +    return PSMOUSE_GOOD_DATA;
>> +}
>> +
>> +static void focaltech_reset(struct psmouse *psmouse)
>> +{
>> +    psmouse_info(psmouse, "focaltech_reset");
>>      ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
>>      psmouse_reset(psmouse);
>> +}
>> +
>> +static int focaltech_switch_protocol(struct psmouse *psmouse)
>> +{
>> +    struct ps2dev *ps2dev = &psmouse->ps2dev;
>> +    unsigned char param[3];
>> +
>> +    param[0] = 0;
>> +    if (ps2_command(ps2dev, param, 0x10f8))
>> +        return -EIO;
>> +    if (ps2_command(ps2dev, param, 0x10f8))
>> +        return -EIO;
>> +    if (ps2_command(ps2dev, param, 0x10f8))
>> +        return -EIO;
>> +    param[0] = 1;
>> +    if (ps2_command(ps2dev, param, 0x10f8))
>> +        return -EIO;
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11))
>> +        return -EIO;
>> +
>> +    if (ps2_command(ps2dev, param, PSMOUSE_CMD_ENABLE))
>> +        return -EIO;
>>       return 0;
>>  }
>> +
>> +static void focaltech_disconnect(struct psmouse *psmouse)
>> +{
>> +    focaltech_reset(psmouse);
>> +    kfree(psmouse->private);
>> +    psmouse->private = NULL;
>> +}
>> +
>> +static int focaltech_reconnect(struct psmouse *psmouse)
>> +{
>> +    focaltech_reset(psmouse);
>> +    if (focaltech_switch_protocol(psmouse)) {
>> +        psmouse_err(psmouse,
>> +                "Unable to initialize the device.");
>> +        return -1;
>> +    }
>> +    return 0;
>> +}
>> +
>> +static void set_input_params(struct psmouse *psmouse)
>> +{
>> +    struct input_dev *dev = psmouse->dev;
>> +
>> +    __set_bit(EV_KEY, dev->evbit);
>> +    __set_bit(EV_ABS, dev->evbit);
>> +    input_set_abs_params(dev, ABS_X, 0, FOC_MAX_X, 0, 0);
>> +    input_set_abs_params(dev, ABS_Y, 0, FOC_MAX_Y, 0, 0);
>> +    input_mt_init_slots(dev, 5, INPUT_MT_POINTER);
>> +    input_set_abs_params(dev, ABS_MT_POSITION_X, 0, FOC_MAX_X, 0, 0);
>> +    input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, FOC_MAX_Y, 0, 0);
>> +    __set_bit(BTN_TOUCH, dev->keybit);
>> +    __set_bit(BTN_TOOL_FINGER, dev->keybit);
>> +    __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
>> +    __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
>> +    __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
>> +    __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
>> +    __clear_bit(EV_REL, dev->evbit);
>> +    __clear_bit(REL_X, dev->relbit);
>> +    __clear_bit(REL_Y, dev->relbit);
>> +    __set_bit(BTN_LEFT, dev->keybit);
>> +    __clear_bit(BTN_RIGHT, dev->keybit);
>> +    __clear_bit(BTN_MIDDLE, dev->keybit);
>> +    __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
>> +}
>> +
>> +int focaltech_init(struct psmouse *psmouse)
>> +{
>> +    struct focaltech_data *priv;
>> +
>> +    focaltech_reset(psmouse);
>> +    if (focaltech_switch_protocol(psmouse)) {
>> +        focaltech_reset(psmouse);
>> +        psmouse_info(psmouse,
>> +                 "Unable to initialize the device.");
>> +        return -ENOSYS;
>> +    }
>> +
>> +    psmouse->private = priv = kzalloc(sizeof(struct focaltech_data),
>> GFP_KERNEL);
>> +    if (!priv)
>> +        return -ENOMEM;
>> +
>> +    set_input_params(psmouse);
>> +
>> +    psmouse->protocol_handler = focaltech_process_byte;
>> +    psmouse->pktsize = 6;
>> +    psmouse->disconnect = focaltech_disconnect;
>> +    psmouse->reconnect = focaltech_reconnect;
>> +    psmouse->cleanup = focaltech_reset;
>> +    /* resync is not supported yet */
>> +    psmouse->resync_time = 0;
>> +
>> +    return 0;
>> +}
>> +
>> +#else /* CONFIG_MOUSE_PS2_FOCALTECH */
>> +
>> +int focaltech_detect(struct psmouse *psmouse, bool set_properties)
>> +{
>> +    return -ENOSYS;
>> +}
>> +
>> +int focaltech_init(struct psmouse *psmouse)
>> +{
>> +    return -ENOSYS;
>> +}
>> +
>> +#endif /* CONFIG_MOUSE_PS2_FOCALTECH */
>> diff --git a/drivers/input/mouse/focaltech.h
>> b/drivers/input/mouse/focaltech.h
>> index 498650c..3c553b2 100644
>> --- a/drivers/input/mouse/focaltech.h
>> +++ b/drivers/input/mouse/focaltech.h
>> @@ -2,6 +2,7 @@
>>   * Focaltech TouchPad PS/2 mouse driver
>>   *
>>   * Copyright (c) 2014 Red Hat Inc.
>> + * Copyright (c) 2014 Mathias Gottschlag <mgottschlag@gmail.com>
>>   *
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License as published by
>> @@ -16,7 +17,67 @@
>>  #ifndef _FOCALTECH_H
>>  #define _FOCALTECH_H
>>  +/*
>> + * Packet types - the numbers are not consecutive, so we might be
missing
>> + * something here.
>> + */
>> +#define FOC_TOUCH 0x3 /* bitmap of active fingers */
>> +#define FOC_ABS 0x6 /* absolute position of one finger */
>> +#define FOC_REL 0x9 /* relative position of 1-2 fingers */
>> +
>> +#define FOC_MAX_FINGERS 5
>> +
>> +#define FOC_MAX_X 2431
>> +#define FOC_MAX_Y 1663
>> +
>> +static inline int focaltech_invert_y(int y)
>> +{
>> +    return FOC_MAX_Y - y;
>> +}
>> +
>> +/*
>> + * Current state of a single finger on the touchpad.
>> + */
>> +struct focaltech_finger_state {
>> +    /* the touchpad has generated a touch event for the finger */
>> +    bool active;
>> +    /*
>> +     * The touchpad has sent position data for the finger. Touch event
>> +     * packages reset this flag for new fingers, and there is a time
>> +     * between the first touch event and the following absolute position
>> +     * packet for the finger where the touchpad has declared the
finger to
>> +     * be valid, but we do not have any valid position yet.
>> +     */
>> +    bool valid;
>> +    /* absolute position (from the bottom left corner) of the finger */
>> +    unsigned int x;
>> +    unsigned int y;
>> +};
>> +
>> +/*
>> + * Description of the current state of the touchpad hardware.
>> + */
>> +struct focaltech_hw_state {
>> +    /*
>> +     * The touchpad tracks the positions of the fingers for us, the
array
>> +     * indices correspond to the finger indices returned in the report
>> +     * packages.
>> +     */
>> +    struct focaltech_finger_state fingers[FOC_MAX_FINGERS];
>> +    /*
>> +     * True if the clickpad has been pressed.
>> +     */
>> +    bool pressed;
>> +};
>> +
>> +struct focaltech_data {
>> +    struct focaltech_hw_state state;
>> +};
>> +
>>  int focaltech_detect(struct psmouse *psmouse, bool set_properties);
>>  int focaltech_init(struct psmouse *psmouse);
>>  +int focaltech_detect_fallback(struct psmouse *psmouse, bool
>> set_properties);
>> +int focaltech_init_fallback(struct psmouse *psmouse);
>> +
>>  #endif
>> diff --git a/drivers/input/mouse/psmouse-base.c
>> b/drivers/input/mouse/psmouse-base.c
>> index 26994f6..2e2b98d 100644
>> --- a/drivers/input/mouse/psmouse-base.c
>> +++ b/drivers/input/mouse/psmouse-base.c
>> @@ -726,6 +726,12 @@ static int psmouse_extensions(struct psmouse
*psmouse,
>>  /* Always check for focaltech, this is safe as it uses pnp-id
matching */
>>      if (psmouse_do_detect(focaltech_detect, psmouse, set_properties)
== 0) {
>>          if (!set_properties || focaltech_init(psmouse) == 0) {
>> +            return PSMOUSE_FOCALTECH;
>> +        }
>> +    }
>> +    if (psmouse_do_detect(focaltech_detect_fallback,
>> +                  psmouse, set_properties) == 0) {
>> +        if (!set_properties || focaltech_init_fallback(psmouse) == 0) {
>>              /*
>>               * Not supported yet, use bare protocol.
>>               * Note that we need to also restrict
>> @@ -1063,6 +1069,15 @@ static const struct psmouse_protocol
>> psmouse_protocols[] = {
>>          .alias        = "cortps",
>>          .detect        = cortron_detect,
>>      },
>> +#ifdef CONFIG_MOUSE_PS2_FOCALTECH
>> +    {
>> +        .type        = PSMOUSE_FOCALTECH,
>> +        .name        = "FocalTechPS/2",
>> +        .alias        = "focaltech",
>> +        .detect        = focaltech_detect,
>> +        .init        = focaltech_init,
>> +    },
>> +#endif
>>      {
>>          .type        = PSMOUSE_AUTO,
>>          .name        = "auto",
>> diff --git a/drivers/input/mouse/psmouse.h
b/drivers/input/mouse/psmouse.h
>> index f4cf664..c2ff137 100644
>> --- a/drivers/input/mouse/psmouse.h
>> +++ b/drivers/input/mouse/psmouse.h
>> @@ -96,6 +96,7 @@ enum psmouse_type {
>>      PSMOUSE_FSP,
>>      PSMOUSE_SYNAPTICS_RELATIVE,
>>      PSMOUSE_CYPRESS,
>> +    PSMOUSE_FOCALTECH,
>>      PSMOUSE_AUTO        /* This one should always be last */
>>  };
>
> Overall this looks very good, many thanks for your work on this!
>
> Regards,
>
> Hans
>




^ permalink raw reply

* Problems with Elantech touchpad in 3.18-rc2
From: Roel Aaij @ 2014-10-30 17:14 UTC (permalink / raw)
  Cc: dmitry.torokhov, linux-input


[-- Attachment #1.1: Type: text/plain, Size: 2372 bytes --]

Dear kernel input developers,

While trying out 3.18-rc2, I noticed that the Elantech touchpad on my
laptop didn't work as intended anymore. Mouse movement and tapping one
finger worked, but scrolling and two finger tapping did not. X.org also
didn't recognise the touchpad as a synaptics touchpad anymore.

After googling around I found that i8042.nomux=0 brought it back to normal.

My laptop is a Clevo model W650SH with a keyboard and a touchpad attached,
and no touchschreen. Some output of dmesg is listed at the bottom, and the
result of dmidecode is attached.

Best regards,

Roel Aaij

Some dmesg output without i8042.nomux=0 (not fully functional touchpad)

[    1.221297] i8042: PNP: PS/2 Controller [PNP0303:PS2K,PNP0f13:ELNM] at 0x60,0x64 irq 1,12
[    1.226412] serio: i8042 KBD port at 0x60,0x64 irq 1
[    1.226414] serio: i8042 AUX port at 0x60,0x64 irq 12
[    1.229415] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input6
[    5.017142] psmouse serio1: elantech: assuming hardware version 3 (with firmware version 0x450f02)
[    5.018055] psmouse serio1: elantech: elantech_send_cmd query 0x02 failed.
[    5.018057] psmouse serio1: elantech: failed to query capabilities.
[    5.930158] input: PS/2 Elantech Touchpad as /devices/platform/i8042/serio1/input/input8


Some dmesg output with i8042.nomux=0 (fully functional touchpad)

[    1.361320] i8042: PNP: PS/2 Controller [PNP0303:PS2K,PNP0f13:ELNM] at 0x60,0x64 irq 1,12
[    1.366134] i8042: Detected active multiplexing controller, rev 1.1
[    1.367757] serio: i8042 KBD port at 0x60,0x64 irq 1
[    1.367759] serio: i8042 AUX0 port at 0x60,0x64 irq 12
[    1.367764] serio: i8042 AUX1 port at 0x60,0x64 irq 12
[    1.367765] serio: i8042 AUX2 port at 0x60,0x64 irq 12
[    1.367766] serio: i8042 AUX3 port at 0x60,0x64 irq 12
[    1.371243] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input6
[   99.389964] psmouse serio2: elantech: assuming hardware version 3 (with firmware version 0x450f02)
[   99.489797] psmouse serio2: elantech: Synaptics capabilities query result 0x79, 0x17, 0x0c.
[   99.819119] input: ETPS/2 Elantech Touchpad as /devices/platform/i8042/serio2/input/input22

P.S. The late timestamps in the last few lines are due to a "modprobe -r psmouse && modprobe psmouse"

[-- Attachment #1.2: dmi --]
[-- Type: text/plain, Size: 11352 bytes --]

# dmidecode 2.12
SMBIOS 2.7 present.
34 structures occupying 1874 bytes.
Table at 0x000EB500.

Handle 0x0000, DMI type 0, 24 bytes
BIOS Information
	Vendor: American Megatrends Inc.
	Version: 1.00.05
	Release Date: 08/07/2013
	Address: 0xF0000
	Runtime Size: 64 kB
	ROM Size: 4096 kB
	Characteristics:
		PCI is supported
		BIOS is upgradeable
		BIOS shadowing is allowed
		Boot from CD is supported
		Selectable boot is supported
		EDD is supported
		Print screen service is supported (int 5h)
		8042 keyboard services are supported (int 9h)
		Printer services are supported (int 17h)
		ACPI is supported
		USB legacy is supported
		BIOS boot specification is supported
		Targeted content distribution is supported
		UEFI is supported
	BIOS Revision: 4.6

Handle 0x0001, DMI type 1, 27 bytes
System Information
	Manufacturer: Notebook                        
	Product Name: W65_W670SH                      
	Version: Not Applicable                  
	Serial Number: Not Applicable                  
	UUID: ECF59000-47ED-0000-0000-000000000000
	Wake-up Type: Power Switch
	SKU Number: Not Applicable                  
	Family: Not Applicable                  

Handle 0x0002, DMI type 2, 15 bytes
Base Board Information
	Manufacturer: Notebook                        
	Product Name: W65_W670SH                      
	Version: Not Applicable                  
	Serial Number: Not Applicable                  
	Asset Tag: Tag 12345
	Features:
		Board is a hosting board
		Board is replaceable
	Location In Chassis: Not Applicable
	Chassis Handle: 0x0003
	Type: Motherboard
	Contained Object Handles: 0

Handle 0x0003, DMI type 3, 22 bytes
Chassis Information
	Manufacturer: Notebook                        
	Type: Laptop
	Lock: Not Present
	Version: N/A                             
	Serial Number: None                            
	Asset Tag: No Asset Tag
	Boot-up State: Safe
	Power Supply State: Safe
	Thermal State: Safe
	Security Status: None
	OEM Information: 0x00000000
	Height: Unspecified
	Number Of Power Cords: 1
	Contained Elements: 0
	SKU Number: To be filled by O.E.M.

Handle 0x0004, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J1A1
	Internal Connector Type: None
	External Reference Designator: PS2Mouse
	External Connector Type: PS/2
	Port Type: Mouse Port

Handle 0x0005, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J1A1
	Internal Connector Type: None
	External Reference Designator: Keyboard
	External Connector Type: PS/2
	Port Type: Keyboard Port

Handle 0x0006, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J2A1
	Internal Connector Type: None
	External Reference Designator: TV Out
	External Connector Type: Mini Centronics Type-14
	Port Type: Other

Handle 0x0007, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J2A2A
	Internal Connector Type: None
	External Reference Designator: COM A
	External Connector Type: DB-9 male
	Port Type: Serial Port 16550A Compatible

Handle 0x0008, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J2A2B
	Internal Connector Type: None
	External Reference Designator: Video
	External Connector Type: DB-15 female
	Port Type: Video Port

Handle 0x0009, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J3A1
	Internal Connector Type: None
	External Reference Designator: USB1
	External Connector Type: Access Bus (USB)
	Port Type: USB

Handle 0x000A, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J3A1
	Internal Connector Type: None
	External Reference Designator: USB2
	External Connector Type: Access Bus (USB)
	Port Type: USB

Handle 0x000B, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J3A1
	Internal Connector Type: None
	External Reference Designator: USB3
	External Connector Type: Access Bus (USB)
	Port Type: USB

Handle 0x000C, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J5A1
	Internal Connector Type: None
	External Reference Designator: LAN
	External Connector Type: RJ-45
	Port Type: Network Port

Handle 0x000D, DMI type 8, 9 bytes
Port Connector Information
	Internal Reference Designator: J5A1
	Internal Connector Type: None
	External Reference Designator: USB4
	External Connector Type: Access Bus (USB)
	Port Type: USB

Handle 0x000E, DMI type 9, 17 bytes
System Slot Information
	Designation: J6B2
	Type: x16 PCI Express
	Current Usage: In Use
	Length: Long
	ID: 0
	Characteristics:
		3.3 V is provided
		Opening is shared
		PME signal is supported
	Bus Address: 0000:00:01.0

Handle 0x000F, DMI type 10, 8 bytes
On Board Device 1 Information
	Type: Video
	Status: Enabled
	Description:    To Be Filled By O.E.M.
On Board Device 2 Information
	Type: Ethernet
	Status: Enabled
	Description: To Be Filled By O.E.M.

Handle 0x0010, DMI type 11, 5 bytes
OEM Strings
	String 1: 1558
	String 2: OEM String
	String 3: To Be Filled By O.E.M.
	String 4: To Be Filled By O.E.M.
	String 5: BIOS:1.00.05

Handle 0x0011, DMI type 12, 5 bytes
System Configuration Options
	Option 1: To Be Filled By O.E.M.

Handle 0x0012, DMI type 24, 5 bytes
Hardware Security
	Power-On Password Status: Disabled
	Keyboard Password Status: Disabled
	Administrator Password Status: Disabled
	Front Panel Reset Status: Disabled

Handle 0x0013, DMI type 32, 20 bytes
System Boot Information
	Status: No errors detected

Handle 0x0014, DMI type 4, 42 bytes
Processor Information
	Socket Designation: SOCKET 0
	Type: Central Processor
	Family: Core i7
	Manufacturer: Intel
	ID: C3 06 03 00 FF FB EB BF
	Signature: Type 0, Family 6, Model 60, Stepping 3
	Flags:
		FPU (Floating-point unit on-chip)
		VME (Virtual mode extension)
		DE (Debugging extension)
		PSE (Page size extension)
		TSC (Time stamp counter)
		MSR (Model specific registers)
		PAE (Physical address extension)
		MCE (Machine check exception)
		CX8 (CMPXCHG8 instruction supported)
		APIC (On-chip APIC hardware supported)
		SEP (Fast system call)
		MTRR (Memory type range registers)
		PGE (Page global enable)
		MCA (Machine check architecture)
		CMOV (Conditional move instruction supported)
		PAT (Page attribute table)
		PSE-36 (36-bit page size extension)
		CLFSH (CLFLUSH instruction supported)
		DS (Debug store)
		ACPI (ACPI supported)
		MMX (MMX technology supported)
		FXSR (FXSAVE and FXSTOR instructions supported)
		SSE (Streaming SIMD extensions)
		SSE2 (Streaming SIMD extensions 2)
		SS (Self-snoop)
		HTT (Multi-threading)
		TM (Thermal monitor supported)
		PBE (Pending break enabled)
	Version: Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
	Voltage: 1.2 V
	External Clock: 100 MHz
	Max Speed: 3800 MHz
	Current Speed: 2400 MHz
	Status: Populated, Enabled
	Upgrade: Socket rPGA988B
	L1 Cache Handle: 0x0016
	L2 Cache Handle: 0x0015
	L3 Cache Handle: 0x0017
	Serial Number: Not Specified
	Asset Tag: Fill By OEM
	Part Number: Fill By OEM
	Core Count: 4
	Core Enabled: 4
	Thread Count: 8
	Characteristics:
		64-bit capable

Handle 0x0015, DMI type 7, 19 bytes
Cache Information
	Socket Designation: CPU Internal L2
	Configuration: Enabled, Not Socketed, Level 2
	Operational Mode: Write Back
	Location: Internal
	Installed Size: 1024 kB
	Maximum Size: 1024 kB
	Supported SRAM Types:
		Unknown
	Installed SRAM Type: Unknown
	Speed: Unknown
	Error Correction Type: Single-bit ECC
	System Type: Unified
	Associativity: 8-way Set-associative

Handle 0x0016, DMI type 7, 19 bytes
Cache Information
	Socket Designation: CPU Internal L1
	Configuration: Enabled, Not Socketed, Level 1
	Operational Mode: Write Back
	Location: Internal
	Installed Size: 256 kB
	Maximum Size: 256 kB
	Supported SRAM Types:
		Unknown
	Installed SRAM Type: Unknown
	Speed: Unknown
	Error Correction Type: Single-bit ECC
	System Type: Other
	Associativity: 8-way Set-associative

Handle 0x0017, DMI type 7, 19 bytes
Cache Information
	Socket Designation: CPU Internal L3
	Configuration: Enabled, Not Socketed, Level 3
	Operational Mode: Write Back
	Location: Internal
	Installed Size: 6144 kB
	Maximum Size: 6144 kB
	Supported SRAM Types:
		Unknown
	Installed SRAM Type: Unknown
	Speed: Unknown
	Error Correction Type: Single-bit ECC
	System Type: Unified
	Associativity: 12-way Set-associative

Handle 0x0018, DMI type 16, 23 bytes
Physical Memory Array
	Location: System Board Or Motherboard
	Use: System Memory
	Error Correction Type: None
	Maximum Capacity: 32 GB
	Error Information Handle: Not Provided
	Number Of Devices: 4

Handle 0x0019, DMI type 17, 34 bytes
Memory Device
	Array Handle: 0x0018
	Error Information Handle: Not Provided
	Total Width: 64 bits
	Data Width: 64 bits
	Size: 8192 MB
	Form Factor: SODIMM
	Set: None
	Locator: ChannelA-DIMM0
	Bank Locator: BANK 0
	Type: DDR3
	Type Detail: Synchronous
	Speed: 1600 MHz
	Manufacturer: 1315
	Serial Number: 12230000
	Asset Tag: 9876543210
	Part Number: CT102464BF160B.C16
	Rank: 2
	Configured Clock Speed: 1600 MHz

Handle 0x001A, DMI type 20, 35 bytes
Memory Device Mapped Address
	Starting Address: 0x00000000000
	Ending Address: 0x001FFFFFFFF
	Range Size: 8 GB
	Physical Device Handle: 0x0019
	Memory Array Mapped Address Handle: 0x001E
	Partition Row Position: Unknown
	Interleave Position: Unknown
	Interleaved Data Depth: Unknown

Handle 0x001B, DMI type 17, 34 bytes
Memory Device
	Array Handle: 0x0018
	Error Information Handle: Not Provided
	Total Width: Unknown
	Data Width: Unknown
	Size: No Module Installed
	Form Factor: DIMM
	Set: None
	Locator: ChannelA-DIMM1
	Bank Locator: BANK 1
	Type: Unknown
	Type Detail: None
	Speed: Unknown
	Manufacturer: [Empty]
	Serial Number: [Empty]
	Asset Tag: 9876543210
	Part Number: [Empty]
	Rank: Unknown
	Configured Clock Speed: Unknown

Handle 0x001C, DMI type 17, 34 bytes
Memory Device
	Array Handle: 0x0018
	Error Information Handle: Not Provided
	Total Width: Unknown
	Data Width: Unknown
	Size: No Module Installed
	Form Factor: DIMM
	Set: None
	Locator: ChannelB-DIMM0
	Bank Locator: BANK 2
	Type: Unknown
	Type Detail: None
	Speed: Unknown
	Manufacturer: [Empty]
	Serial Number: [Empty]
	Asset Tag: 9876543210
	Part Number: [Empty]
	Rank: Unknown
	Configured Clock Speed: Unknown

Handle 0x001D, DMI type 17, 34 bytes
Memory Device
	Array Handle: 0x0018
	Error Information Handle: Not Provided
	Total Width: Unknown
	Data Width: Unknown
	Size: No Module Installed
	Form Factor: DIMM
	Set: None
	Locator: ChannelB-DIMM1
	Bank Locator: BANK 3
	Type: Unknown
	Type Detail: None
	Speed: Unknown
	Manufacturer: [Empty]
	Serial Number: [Empty]
	Asset Tag: 9876543210
	Part Number: [Empty]
	Rank: Unknown
	Configured Clock Speed: Unknown

Handle 0x001E, DMI type 19, 31 bytes
Memory Array Mapped Address
	Starting Address: 0x00000000000
	Ending Address: 0x001FFFFFFFF
	Range Size: 8 GB
	Physical Array Handle: 0x0018
	Partition Width: 4

Handle 0x0022, DMI type 131, 64 bytes
OEM-specific Type
	Header and Data:
		83 40 22 00 31 00 00 00 00 00 00 00 00 00 00 00
		F8 00 49 8C 00 00 00 00 01 20 00 00 00 00 09 00
		7A 05 0D 00 00 00 00 00 C8 00 FF FF 00 00 00 00
		00 00 00 00 66 00 00 00 76 50 72 6F 00 00 00 00

Handle 0x0023, DMI type 13, 22 bytes
BIOS Language Information
	Language Description Format: Long
	Installable Languages: 1
		en|US|iso8859-1
	Currently Installed Language: en|US|iso8859-1

Handle 0x0025, DMI type 127, 4 bytes
End Of Table


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply

* Re: [PATCH] Input: synaptics - add support for ForcePads
From: Dmitry Torokhov @ 2014-10-30 17:35 UTC (permalink / raw)
  To: Peter Hutterer
  Cc: Andrew Duggan, Hans de Goede, linux-input, Benjamin Tissoires,
	Christopher Heiny, linux-kernel
In-Reply-To: <20141030003855.GA15677@jelly.redhat.com>

On Thu, Oct 30, 2014 at 10:38:55AM +1000, Peter Hutterer wrote:
> On Tue, Sep 09, 2014 at 03:57:25PM -0700, Dmitry Torokhov wrote:
> > From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > 
> > ForcePads are found on HP EliteBook 1040 laptops. They lack any kind of
> > physical buttons, instead they generate primary button click when user
> > presses somewhat hard on the surface of the touchpad. Unfortunately they
> > also report primary button click whenever there are 2 or more contacts
> > on the pad, messing up all multi-finger gestures (2-finger scrolling,
> > multi-finger tapping, etc). To cope with this behavior we introduce a
> > delay (currently 50 msecs) in reporting primary press in case more
> > contacts appear.
> 
> can we assign INPUT_PROP_FORCEPAD to this? or PRESSUREPAD or something if
> we're worried about trademarks. This is something I'd like to know in
> userspace, we can then ignore clicks completely and do the rest ourselves. 

Hmm, I think we can, but I'd like to wait to see if there are more
models with such touchpads (I sure hope there isn't; lack of tactile
feedback on presses is not the best user experience so I hope this
initiative dies a quick death).

Thanks.

-- 
Dmitry

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox