Re: [PATCH] HID: rmi: use HID_QUIRK_NO_INPUT_SYNC

2018-05-28 Thread Benjamin Tissoires
On Fri, May 25, 2018 at 2:51 PM, Benjamin Tissoires
<benjamin.tissoi...@redhat.com> wrote:
> When we receive a RMI4 report, we should not unconditionally send an
> input_sync event. Instead, we should let the rmi4 transport layer do it
> for us.
>
> This fixes a situation where we might receive X in a report and the rest
> in a subsequent one. And this messes up user space.
>
> Link: https://bugs.freedesktop.org/show_bug.cgi?id=100436
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
> ---
>
> Hi,
>
> Oscar, do you mind if we add your "Tested-by: Oscar Morante <your@email>"?

As mentioned in comment 25 of the bug above
(https://bugs.freedesktop.org/show_bug.cgi?id=100436#c25), oscar is
fine adding his tested-by line.

Cheers,
Benjamin

>
> Andrew, can you check for any sides effects please?
>
> Cheers,
> Benjamin
>
>  drivers/hid/hid-rmi.c | 20 
>  1 file changed, 20 insertions(+)
>
> diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
> index 9c9362149641..9e33165250a3 100644
> --- a/drivers/hid/hid-rmi.c
> +++ b/drivers/hid/hid-rmi.c
> @@ -413,6 +413,24 @@ static int rmi_event(struct hid_device *hdev, struct 
> hid_field *field,
> return 0;
>  }
>
> +static void rmi_report(struct hid_device *hid, struct hid_report *report)
> +{
> +   struct hid_field *field = report->field[0];
> +
> +   if (!(hid->claimed & HID_CLAIMED_INPUT))
> +   return;
> +
> +   switch (report->id) {
> +   case RMI_READ_DATA_REPORT_ID:
> +   /* fall-through */
> +   case RMI_ATTN_REPORT_ID:
> +   return;
> +   }
> +
> +   if (field && field->hidinput && field->hidinput->input)
> +   input_sync(field->hidinput->input);
> +}
> +
>  #ifdef CONFIG_PM
>  static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
>  {
> @@ -637,6 +655,7 @@ static int rmi_probe(struct hid_device *hdev, const 
> struct hid_device_id *id)
> hid_set_drvdata(hdev, data);
>
> hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
> +   hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
>
> ret = hid_parse(hdev);
> if (ret) {
> @@ -744,6 +763,7 @@ static struct hid_driver rmi_driver = {
> .remove = rmi_remove,
> .event  = rmi_event,
> .raw_event  = rmi_raw_event,
> +   .report = rmi_report,
> .input_mapping  = rmi_input_mapping,
> .input_configured   = rmi_input_configured,
>  #ifdef CONFIG_PM
> --
> 2.14.3
>


Re: [PATCH] HID: rmi: use HID_QUIRK_NO_INPUT_SYNC

2018-05-28 Thread Benjamin Tissoires
On Fri, May 25, 2018 at 2:51 PM, Benjamin Tissoires
 wrote:
> When we receive a RMI4 report, we should not unconditionally send an
> input_sync event. Instead, we should let the rmi4 transport layer do it
> for us.
>
> This fixes a situation where we might receive X in a report and the rest
> in a subsequent one. And this messes up user space.
>
> Link: https://bugs.freedesktop.org/show_bug.cgi?id=100436
>
> Signed-off-by: Benjamin Tissoires 
> ---
>
> Hi,
>
> Oscar, do you mind if we add your "Tested-by: Oscar Morante "?

As mentioned in comment 25 of the bug above
(https://bugs.freedesktop.org/show_bug.cgi?id=100436#c25), oscar is
fine adding his tested-by line.

Cheers,
Benjamin

>
> Andrew, can you check for any sides effects please?
>
> Cheers,
> Benjamin
>
>  drivers/hid/hid-rmi.c | 20 
>  1 file changed, 20 insertions(+)
>
> diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
> index 9c9362149641..9e33165250a3 100644
> --- a/drivers/hid/hid-rmi.c
> +++ b/drivers/hid/hid-rmi.c
> @@ -413,6 +413,24 @@ static int rmi_event(struct hid_device *hdev, struct 
> hid_field *field,
> return 0;
>  }
>
> +static void rmi_report(struct hid_device *hid, struct hid_report *report)
> +{
> +   struct hid_field *field = report->field[0];
> +
> +   if (!(hid->claimed & HID_CLAIMED_INPUT))
> +   return;
> +
> +   switch (report->id) {
> +   case RMI_READ_DATA_REPORT_ID:
> +   /* fall-through */
> +   case RMI_ATTN_REPORT_ID:
> +   return;
> +   }
> +
> +   if (field && field->hidinput && field->hidinput->input)
> +   input_sync(field->hidinput->input);
> +}
> +
>  #ifdef CONFIG_PM
>  static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
>  {
> @@ -637,6 +655,7 @@ static int rmi_probe(struct hid_device *hdev, const 
> struct hid_device_id *id)
> hid_set_drvdata(hdev, data);
>
> hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
> +   hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
>
> ret = hid_parse(hdev);
> if (ret) {
> @@ -744,6 +763,7 @@ static struct hid_driver rmi_driver = {
> .remove = rmi_remove,
> .event  = rmi_event,
> .raw_event  = rmi_raw_event,
> +   .report = rmi_report,
> .input_mapping  = rmi_input_mapping,
> .input_configured   = rmi_input_configured,
>  #ifdef CONFIG_PM
> --
> 2.14.3
>


Re: [PATCH] HID: steam: select CONFIG_POWER_SUPPLY

2018-05-25 Thread Benjamin Tissoires
On Fri, May 25, 2018 at 5:30 PM, Arnd Bergmann <a...@arndb.de> wrote:
> Using the power supply APIs requires selecting the appropriate
> Kconfig symbol, otherwise we get this build failure:
>
> drivers/hid/hid-steam.o: In function `steam_unregister':
> hid-steam.c:(.text+0x1cc): undefined reference to `power_supply_unregister'
> drivers/hid/hid-steam.o: In function `steam_battery_get_property':
> hid-steam.c:(.text+0x2d2): undefined reference to `power_supply_get_drvdata'
> drivers/hid/hid-steam.o: In function `steam_raw_event':
> hid-steam.c:(.text+0xcba): undefined reference to `power_supply_changed'
> drivers/hid/hid-steam.o: In function `steam_register':
> hid-steam.c:(.text+0x13e3): undefined reference to `power_supply_register'
> hid-steam.c:(.text+0x13fe): undefined reference to `power_supply_powers'
>
> Fixes: f82719790751 ("HID: steam: add battery device.")
> Signed-off-by: Arnd Bergmann <a...@arndb.de>

Looks good:
Reviewed-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

> ---
>  drivers/hid/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 8a865e3ccea6..a49a10437c40 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -848,6 +848,7 @@ config HID_SPEEDLINK
>  config HID_STEAM
> tristate "Steam Controller support"
> depends on HID
> +   select POWER_SUPPLY
> ---help---
> Say Y here if you have a Steam Controller if you want to use it
> without running the Steam Client. It supports both the wired and
> --
> 2.9.0
>


Re: [PATCH] HID: steam: select CONFIG_POWER_SUPPLY

2018-05-25 Thread Benjamin Tissoires
On Fri, May 25, 2018 at 5:30 PM, Arnd Bergmann  wrote:
> Using the power supply APIs requires selecting the appropriate
> Kconfig symbol, otherwise we get this build failure:
>
> drivers/hid/hid-steam.o: In function `steam_unregister':
> hid-steam.c:(.text+0x1cc): undefined reference to `power_supply_unregister'
> drivers/hid/hid-steam.o: In function `steam_battery_get_property':
> hid-steam.c:(.text+0x2d2): undefined reference to `power_supply_get_drvdata'
> drivers/hid/hid-steam.o: In function `steam_raw_event':
> hid-steam.c:(.text+0xcba): undefined reference to `power_supply_changed'
> drivers/hid/hid-steam.o: In function `steam_register':
> hid-steam.c:(.text+0x13e3): undefined reference to `power_supply_register'
> hid-steam.c:(.text+0x13fe): undefined reference to `power_supply_powers'
>
> Fixes: f82719790751 ("HID: steam: add battery device.")
> Signed-off-by: Arnd Bergmann 

Looks good:
Reviewed-by: Benjamin Tissoires 

> ---
>  drivers/hid/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 8a865e3ccea6..a49a10437c40 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -848,6 +848,7 @@ config HID_SPEEDLINK
>  config HID_STEAM
> tristate "Steam Controller support"
> depends on HID
> +   select POWER_SUPPLY
> ---help---
> Say Y here if you have a Steam Controller if you want to use it
> without running the Steam Client. It supports both the wired and
> --
> 2.9.0
>


[PATCH] HID: rmi: use HID_QUIRK_NO_INPUT_SYNC

2018-05-25 Thread Benjamin Tissoires
When we receive a RMI4 report, we should not unconditionally send an
input_sync event. Instead, we should let the rmi4 transport layer do it
for us.

This fixes a situation where we might receive X in a report and the rest
in a subsequent one. And this messes up user space.

Link: https://bugs.freedesktop.org/show_bug.cgi?id=100436

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---

Hi,

Oscar, do you mind if we add your "Tested-by: Oscar Morante <your@email>"?

Andrew, can you check for any sides effects please?

Cheers,
Benjamin

 drivers/hid/hid-rmi.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 9c9362149641..9e33165250a3 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -413,6 +413,24 @@ static int rmi_event(struct hid_device *hdev, struct 
hid_field *field,
return 0;
 }
 
+static void rmi_report(struct hid_device *hid, struct hid_report *report)
+{
+   struct hid_field *field = report->field[0];
+
+   if (!(hid->claimed & HID_CLAIMED_INPUT))
+   return;
+
+   switch (report->id) {
+   case RMI_READ_DATA_REPORT_ID:
+   /* fall-through */
+   case RMI_ATTN_REPORT_ID:
+   return;
+   }
+
+   if (field && field->hidinput && field->hidinput->input)
+   input_sync(field->hidinput->input);
+}
+
 #ifdef CONFIG_PM
 static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
 {
@@ -637,6 +655,7 @@ static int rmi_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
hid_set_drvdata(hdev, data);
 
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+   hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
 
ret = hid_parse(hdev);
if (ret) {
@@ -744,6 +763,7 @@ static struct hid_driver rmi_driver = {
.remove = rmi_remove,
.event  = rmi_event,
.raw_event  = rmi_raw_event,
+   .report = rmi_report,
.input_mapping  = rmi_input_mapping,
.input_configured   = rmi_input_configured,
 #ifdef CONFIG_PM
-- 
2.14.3



[PATCH] HID: rmi: use HID_QUIRK_NO_INPUT_SYNC

2018-05-25 Thread Benjamin Tissoires
When we receive a RMI4 report, we should not unconditionally send an
input_sync event. Instead, we should let the rmi4 transport layer do it
for us.

This fixes a situation where we might receive X in a report and the rest
in a subsequent one. And this messes up user space.

Link: https://bugs.freedesktop.org/show_bug.cgi?id=100436

Signed-off-by: Benjamin Tissoires 
---

Hi,

Oscar, do you mind if we add your "Tested-by: Oscar Morante "?

Andrew, can you check for any sides effects please?

Cheers,
Benjamin

 drivers/hid/hid-rmi.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 9c9362149641..9e33165250a3 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -413,6 +413,24 @@ static int rmi_event(struct hid_device *hdev, struct 
hid_field *field,
return 0;
 }
 
+static void rmi_report(struct hid_device *hid, struct hid_report *report)
+{
+   struct hid_field *field = report->field[0];
+
+   if (!(hid->claimed & HID_CLAIMED_INPUT))
+   return;
+
+   switch (report->id) {
+   case RMI_READ_DATA_REPORT_ID:
+   /* fall-through */
+   case RMI_ATTN_REPORT_ID:
+   return;
+   }
+
+   if (field && field->hidinput && field->hidinput->input)
+   input_sync(field->hidinput->input);
+}
+
 #ifdef CONFIG_PM
 static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
 {
@@ -637,6 +655,7 @@ static int rmi_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
hid_set_drvdata(hdev, data);
 
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+   hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
 
ret = hid_parse(hdev);
if (ret) {
@@ -744,6 +763,7 @@ static struct hid_driver rmi_driver = {
.remove = rmi_remove,
.event  = rmi_event,
.raw_event  = rmi_raw_event,
+   .report = rmi_report,
.input_mapping  = rmi_input_mapping,
.input_configured   = rmi_input_configured,
 #ifdef CONFIG_PM
-- 
2.14.3



Re: Sometimes unusable i2c-hid devices in 4.17-rcX

2018-05-24 Thread Benjamin Tissoires
Hi Mario,

On Tue, May 22, 2018 at 6:15 PM,  <mario.limoncie...@dell.com> wrote:
> Benjamin,
>
>> -Original Message-
>> From: Benjamin Tissoires [mailto:benjamin.tissoi...@gmail.com]
>> Sent: Friday, May 18, 2018 1:18 PM
>> To: Limonciello, Mario
>> Cc: linux-input; linux-kernel@vger.kernel.org
>> Subject: Re: Sometimes unusable i2c-hid devices in 4.17-rcX
>>
>> On Thu, May 17, 2018 at 4:44 PM,  <mario.limoncie...@dell.com> wrote:
>> >> -Original Message-
>> >> From: Benjamin Tissoires [mailto:benjamin.tissoi...@gmail.com]
>> >> Sent: Thursday, May 17, 2018 9:28 AM
>> >> To: Limonciello, Mario
>> >> Cc: linux-input; linux-kernel@vger.kernel.org
>> >> Subject: Re: Sometimes unusable i2c-hid devices in 4.17-rcX
>> >>
>> >> Hi Mario,
>> >>
>> >> On Wed, May 16, 2018 at 10:00 PM,  <mario.limoncie...@dell.com> wrote:
>> >> > Hi All,
>> >> >
>> >> > I've been running 4.16-rc7 on an XPS 9365 for some time and recently 
>> >> > moved
>> up
>> >> to 4.17-rc5.
>> >> > Immediately I noticed that i2c-hid devices (both touchscreen and 
>> >> > touchpad)
>> were
>> >> not working.
>> >> > Also when shutting the system down or rebooting it would just hang. 
>> >> > (magic
>> sysrq
>> >> still worked).
>> >> >
>> >> > I figured it was an easy to identify regression so I started a bisect 
>> >> > but it came
>> up
>> >> with garbage
>> >> > that ended in selftests shortly after 4.17-rc2.  I realized that's 
>> >> > because is still
>> will
>> >> fail on 4.17-rc2
>> >> > occasionally, seemingly after trying something newer and warm rebooting.
>> >> > So it seems like it's "worse" after 4.17-rc2 (doesn't work at all) but 
>> >> > semi
>> >> reproducible on 4.17-rc2.
>> >> >
>> >> > Not sure if I'm chasing some initialization race, but wanted to see if 
>> >> > anyone
>> else
>> >> was running into this
>> >> > or has some ideas?
>> >>
>> >> I am reliably running a v4.17-rc3 with a merge on Jiri's tree on the 9360.
>> >>
>> >> I doubt it's related to the event processing as I am not encountering
>> >> those issues.
>> >>
>> >> It *could* be related to the interrupts not being properly raised.
>> >>
>> >> Could you monitor /proc/interrupts and check if the ones associated
>> >> with your i2c-hid devices are increasing when you are using them?
>> >> Also, does the device emits raw HID events? (you can use hid-recorder
>> >> to check on the hidraw nodes.)
>> >
>>
>> Sorry, I couldn't get to it today. Monday is a public holiday here, so
>> I'll check on this Tuesday.
>>
>> > I checked both, /proc/interrupts isn't incrementing at all with the 
>> > DLL077A:01
>> device.
>> > Hid-recorder is showing output from the raw HID node.
>>
>> I don't really understand how the hidraw node can send data while the
>> interrupts are not raised.
>>
>> Could you share the output of hid-recorder?
> Sure attached.
> Note that I had a dock connected at the same time since I needed power.  This 
> was
> different than my previous tests.
> That dock has 2 HID endpoints (so that might muddy this, I can re-capture if 
> you need me to)

According to the file, this is the touchpad, and you draw a quick
circle on it. It's surprising the interrupts are not incrementing
because it clearly works fine.

>
>>
>> >
>> > Same thing for the touchscreen, no incrementing for it on the 
>> > i2c_designware.0
>> device.
>> >
>> > Something notable however;
>> > When in this bad state hid-recorder didn't show /dev/hidraw1 for the
>> touchscreen (which
>> > Happens to be a Wacom touch screen).
>> > It only showed /dev/hidraw0 for the touchpad.
>>
>> This explains why the touchscreen doesn't increment the interrupts.
>> Something I missed in the first email is that the hidraw0 node
>> disappear for the wacom device as the touchpad gets the hidraw0 name.
>>
>> Could you provide the output  of a working kernel configuration of:
>> sudo hid-recorder /dev/hidraw*
>>
>> This should provide me the whole logs at the same time of all the
>> hi

Re: Sometimes unusable i2c-hid devices in 4.17-rcX

2018-05-24 Thread Benjamin Tissoires
Hi Mario,

On Tue, May 22, 2018 at 6:15 PM,   wrote:
> Benjamin,
>
>> -Original Message-----
>> From: Benjamin Tissoires [mailto:benjamin.tissoi...@gmail.com]
>> Sent: Friday, May 18, 2018 1:18 PM
>> To: Limonciello, Mario
>> Cc: linux-input; linux-kernel@vger.kernel.org
>> Subject: Re: Sometimes unusable i2c-hid devices in 4.17-rcX
>>
>> On Thu, May 17, 2018 at 4:44 PM,   wrote:
>> >> -Original Message-
>> >> From: Benjamin Tissoires [mailto:benjamin.tissoi...@gmail.com]
>> >> Sent: Thursday, May 17, 2018 9:28 AM
>> >> To: Limonciello, Mario
>> >> Cc: linux-input; linux-kernel@vger.kernel.org
>> >> Subject: Re: Sometimes unusable i2c-hid devices in 4.17-rcX
>> >>
>> >> Hi Mario,
>> >>
>> >> On Wed, May 16, 2018 at 10:00 PM,   wrote:
>> >> > Hi All,
>> >> >
>> >> > I've been running 4.16-rc7 on an XPS 9365 for some time and recently 
>> >> > moved
>> up
>> >> to 4.17-rc5.
>> >> > Immediately I noticed that i2c-hid devices (both touchscreen and 
>> >> > touchpad)
>> were
>> >> not working.
>> >> > Also when shutting the system down or rebooting it would just hang. 
>> >> > (magic
>> sysrq
>> >> still worked).
>> >> >
>> >> > I figured it was an easy to identify regression so I started a bisect 
>> >> > but it came
>> up
>> >> with garbage
>> >> > that ended in selftests shortly after 4.17-rc2.  I realized that's 
>> >> > because is still
>> will
>> >> fail on 4.17-rc2
>> >> > occasionally, seemingly after trying something newer and warm rebooting.
>> >> > So it seems like it's "worse" after 4.17-rc2 (doesn't work at all) but 
>> >> > semi
>> >> reproducible on 4.17-rc2.
>> >> >
>> >> > Not sure if I'm chasing some initialization race, but wanted to see if 
>> >> > anyone
>> else
>> >> was running into this
>> >> > or has some ideas?
>> >>
>> >> I am reliably running a v4.17-rc3 with a merge on Jiri's tree on the 9360.
>> >>
>> >> I doubt it's related to the event processing as I am not encountering
>> >> those issues.
>> >>
>> >> It *could* be related to the interrupts not being properly raised.
>> >>
>> >> Could you monitor /proc/interrupts and check if the ones associated
>> >> with your i2c-hid devices are increasing when you are using them?
>> >> Also, does the device emits raw HID events? (you can use hid-recorder
>> >> to check on the hidraw nodes.)
>> >
>>
>> Sorry, I couldn't get to it today. Monday is a public holiday here, so
>> I'll check on this Tuesday.
>>
>> > I checked both, /proc/interrupts isn't incrementing at all with the 
>> > DLL077A:01
>> device.
>> > Hid-recorder is showing output from the raw HID node.
>>
>> I don't really understand how the hidraw node can send data while the
>> interrupts are not raised.
>>
>> Could you share the output of hid-recorder?
> Sure attached.
> Note that I had a dock connected at the same time since I needed power.  This 
> was
> different than my previous tests.
> That dock has 2 HID endpoints (so that might muddy this, I can re-capture if 
> you need me to)

According to the file, this is the touchpad, and you draw a quick
circle on it. It's surprising the interrupts are not incrementing
because it clearly works fine.

>
>>
>> >
>> > Same thing for the touchscreen, no incrementing for it on the 
>> > i2c_designware.0
>> device.
>> >
>> > Something notable however;
>> > When in this bad state hid-recorder didn't show /dev/hidraw1 for the
>> touchscreen (which
>> > Happens to be a Wacom touch screen).
>> > It only showed /dev/hidraw0 for the touchpad.
>>
>> This explains why the touchscreen doesn't increment the interrupts.
>> Something I missed in the first email is that the hidraw0 node
>> disappear for the wacom device as the touchpad gets the hidraw0 name.
>>
>> Could you provide the output  of a working kernel configuration of:
>> sudo hid-recorder /dev/hidraw*
>>
>> This should provide me the whole logs at the same time of all the
>> hidraw nodes, and will allow me to reproduce the combination of
>> wacom/hid-multit

Re: Sometimes unusable i2c-hid devices in 4.17-rcX

2018-05-18 Thread Benjamin Tissoires
On Thu, May 17, 2018 at 4:44 PM,  <mario.limoncie...@dell.com> wrote:
>> -Original Message-----
>> From: Benjamin Tissoires [mailto:benjamin.tissoi...@gmail.com]
>> Sent: Thursday, May 17, 2018 9:28 AM
>> To: Limonciello, Mario
>> Cc: linux-input; linux-kernel@vger.kernel.org
>> Subject: Re: Sometimes unusable i2c-hid devices in 4.17-rcX
>>
>> Hi Mario,
>>
>> On Wed, May 16, 2018 at 10:00 PM,  <mario.limoncie...@dell.com> wrote:
>> > Hi All,
>> >
>> > I've been running 4.16-rc7 on an XPS 9365 for some time and recently moved 
>> > up
>> to 4.17-rc5.
>> > Immediately I noticed that i2c-hid devices (both touchscreen and touchpad) 
>> > were
>> not working.
>> > Also when shutting the system down or rebooting it would just hang. (magic 
>> > sysrq
>> still worked).
>> >
>> > I figured it was an easy to identify regression so I started a bisect but 
>> > it came up
>> with garbage
>> > that ended in selftests shortly after 4.17-rc2.  I realized that's because 
>> > is still will
>> fail on 4.17-rc2
>> > occasionally, seemingly after trying something newer and warm rebooting.
>> > So it seems like it's "worse" after 4.17-rc2 (doesn't work at all) but semi
>> reproducible on 4.17-rc2.
>> >
>> > Not sure if I'm chasing some initialization race, but wanted to see if 
>> > anyone else
>> was running into this
>> > or has some ideas?
>>
>> I am reliably running a v4.17-rc3 with a merge on Jiri's tree on the 9360.
>>
>> I doubt it's related to the event processing as I am not encountering
>> those issues.
>>
>> It *could* be related to the interrupts not being properly raised.
>>
>> Could you monitor /proc/interrupts and check if the ones associated
>> with your i2c-hid devices are increasing when you are using them?
>> Also, does the device emits raw HID events? (you can use hid-recorder
>> to check on the hidraw nodes.)
>

Sorry, I couldn't get to it today. Monday is a public holiday here, so
I'll check on this Tuesday.

> I checked both, /proc/interrupts isn't incrementing at all with the 
> DLL077A:01 device.
> Hid-recorder is showing output from the raw HID node.

I don't really understand how the hidraw node can send data while the
interrupts are not raised.

Could you share the output of hid-recorder?

>
> Same thing for the touchscreen, no incrementing for it on the 
> i2c_designware.0 device.
>
> Something notable however;
> When in this bad state hid-recorder didn't show /dev/hidraw1 for the 
> touchscreen (which
> Happens to be a Wacom touch screen).
> It only showed /dev/hidraw0 for the touchpad.

This explains why the touchscreen doesn't increment the interrupts.
Something I missed in the first email is that the hidraw0 node
disappear for the wacom device as the touchpad gets the hidraw0 name.

Could you provide the output  of a working kernel configuration of:
sudo hid-recorder /dev/hidraw*

This should provide me the whole logs at the same time of all the
hidraw nodes, and will allow me to reproduce the combination of
wacom/hid-multitouch you are experiencing.

Cheers,
Benjamin

>
>
>>
>> Cheers,
>> Benjamin
>>
>> >
>> > #dmesg | grep 'i2c\|hid' doesn't show any obvious errors when in this 
>> > state of
>> non functional hid stuff.
>> > [2.398649] i2c /dev entries driver
>> > [2.881651] hidraw: raw HID events driver (C) Jiri Kosina
>> > [3.683583] ish-hid {33AECD58-B679-4E54-9BD9-A04D34F0C226}: [hid-ish]:
>> enum_devices_done OK, num_hid_devices=5
>> > [3.701259] hid-generic 001F:8086:22D8.0001: hidraw0:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.702204] hid-generic 001F:8086:22D8.0002: hidraw1:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.703063] hid-generic 001F:8086:22D8.0003: hidraw2:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.704276] hid-generic 001F:8086:22D8.0004: hidraw3:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.704557] hid-generic 001F:8086:22D8.0005: hidraw4:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.750710] psmouse serio1: synaptics: Your touchpad (PNP: DLL077a 
>> > PNP0f13)
>> says it can support a different bus. If i2c-hid and hid-rmi are not used, 
>> you might
>> want to try setting psmouse.synaptics_intertouch to 1 and report this to 
>> linux-
>> in...@vger.kernel.org.
>> > [7.030446] acpi INT33D5:00: intel-hid: created platform device
>> > [7.19

Re: Sometimes unusable i2c-hid devices in 4.17-rcX

2018-05-18 Thread Benjamin Tissoires
On Thu, May 17, 2018 at 4:44 PM,   wrote:
>> -Original Message-
>> From: Benjamin Tissoires [mailto:benjamin.tissoi...@gmail.com]
>> Sent: Thursday, May 17, 2018 9:28 AM
>> To: Limonciello, Mario
>> Cc: linux-input; linux-kernel@vger.kernel.org
>> Subject: Re: Sometimes unusable i2c-hid devices in 4.17-rcX
>>
>> Hi Mario,
>>
>> On Wed, May 16, 2018 at 10:00 PM,   wrote:
>> > Hi All,
>> >
>> > I've been running 4.16-rc7 on an XPS 9365 for some time and recently moved 
>> > up
>> to 4.17-rc5.
>> > Immediately I noticed that i2c-hid devices (both touchscreen and touchpad) 
>> > were
>> not working.
>> > Also when shutting the system down or rebooting it would just hang. (magic 
>> > sysrq
>> still worked).
>> >
>> > I figured it was an easy to identify regression so I started a bisect but 
>> > it came up
>> with garbage
>> > that ended in selftests shortly after 4.17-rc2.  I realized that's because 
>> > is still will
>> fail on 4.17-rc2
>> > occasionally, seemingly after trying something newer and warm rebooting.
>> > So it seems like it's "worse" after 4.17-rc2 (doesn't work at all) but semi
>> reproducible on 4.17-rc2.
>> >
>> > Not sure if I'm chasing some initialization race, but wanted to see if 
>> > anyone else
>> was running into this
>> > or has some ideas?
>>
>> I am reliably running a v4.17-rc3 with a merge on Jiri's tree on the 9360.
>>
>> I doubt it's related to the event processing as I am not encountering
>> those issues.
>>
>> It *could* be related to the interrupts not being properly raised.
>>
>> Could you monitor /proc/interrupts and check if the ones associated
>> with your i2c-hid devices are increasing when you are using them?
>> Also, does the device emits raw HID events? (you can use hid-recorder
>> to check on the hidraw nodes.)
>

Sorry, I couldn't get to it today. Monday is a public holiday here, so
I'll check on this Tuesday.

> I checked both, /proc/interrupts isn't incrementing at all with the 
> DLL077A:01 device.
> Hid-recorder is showing output from the raw HID node.

I don't really understand how the hidraw node can send data while the
interrupts are not raised.

Could you share the output of hid-recorder?

>
> Same thing for the touchscreen, no incrementing for it on the 
> i2c_designware.0 device.
>
> Something notable however;
> When in this bad state hid-recorder didn't show /dev/hidraw1 for the 
> touchscreen (which
> Happens to be a Wacom touch screen).
> It only showed /dev/hidraw0 for the touchpad.

This explains why the touchscreen doesn't increment the interrupts.
Something I missed in the first email is that the hidraw0 node
disappear for the wacom device as the touchpad gets the hidraw0 name.

Could you provide the output  of a working kernel configuration of:
sudo hid-recorder /dev/hidraw*

This should provide me the whole logs at the same time of all the
hidraw nodes, and will allow me to reproduce the combination of
wacom/hid-multitouch you are experiencing.

Cheers,
Benjamin

>
>
>>
>> Cheers,
>> Benjamin
>>
>> >
>> > #dmesg | grep 'i2c\|hid' doesn't show any obvious errors when in this 
>> > state of
>> non functional hid stuff.
>> > [2.398649] i2c /dev entries driver
>> > [2.881651] hidraw: raw HID events driver (C) Jiri Kosina
>> > [3.683583] ish-hid {33AECD58-B679-4E54-9BD9-A04D34F0C226}: [hid-ish]:
>> enum_devices_done OK, num_hid_devices=5
>> > [3.701259] hid-generic 001F:8086:22D8.0001: hidraw0:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.702204] hid-generic 001F:8086:22D8.0002: hidraw1:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.703063] hid-generic 001F:8086:22D8.0003: hidraw2:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.704276] hid-generic 001F:8086:22D8.0004: hidraw3:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.704557] hid-generic 001F:8086:22D8.0005: hidraw4:  HID
>> v2.00 Device [hid-ishtp 8086:22D8] on
>> > [3.750710] psmouse serio1: synaptics: Your touchpad (PNP: DLL077a 
>> > PNP0f13)
>> says it can support a different bus. If i2c-hid and hid-rmi are not used, 
>> you might
>> want to try setting psmouse.synaptics_intertouch to 1 and report this to 
>> linux-
>> in...@vger.kernel.org.
>> > [7.030446] acpi INT33D5:00: intel-hid: created platform device
>> > [7.199178] i2c_hid i2c-WCOM482F:00: i2c-WCOM482F:00 supply vdd not
>&g

Re: Sometimes unusable i2c-hid devices in 4.17-rcX

2018-05-17 Thread Benjamin Tissoires
Hi Mario,

On Wed, May 16, 2018 at 10:00 PM,   wrote:
> Hi All,
>
> I've been running 4.16-rc7 on an XPS 9365 for some time and recently moved up 
> to 4.17-rc5.
> Immediately I noticed that i2c-hid devices (both touchscreen and touchpad) 
> were not working.
> Also when shutting the system down or rebooting it would just hang. (magic 
> sysrq still worked).
>
> I figured it was an easy to identify regression so I started a bisect but it 
> came up with garbage
> that ended in selftests shortly after 4.17-rc2.  I realized that's because is 
> still will fail on 4.17-rc2
> occasionally, seemingly after trying something newer and warm rebooting.
> So it seems like it's "worse" after 4.17-rc2 (doesn't work at all) but semi 
> reproducible on 4.17-rc2.
>
> Not sure if I'm chasing some initialization race, but wanted to see if anyone 
> else was running into this
> or has some ideas?

I am reliably running a v4.17-rc3 with a merge on Jiri's tree on the 9360.

I doubt it's related to the event processing as I am not encountering
those issues.

It *could* be related to the interrupts not being properly raised.

Could you monitor /proc/interrupts and check if the ones associated
with your i2c-hid devices are increasing when you are using them?
Also, does the device emits raw HID events? (you can use hid-recorder
to check on the hidraw nodes.)

Cheers,
Benjamin

>
> #dmesg | grep 'i2c\|hid' doesn't show any obvious errors when in this state 
> of non functional hid stuff.
> [2.398649] i2c /dev entries driver
> [2.881651] hidraw: raw HID events driver (C) Jiri Kosina
> [3.683583] ish-hid {33AECD58-B679-4E54-9BD9-A04D34F0C226}: [hid-ish]: 
> enum_devices_done OK, num_hid_devices=5
> [3.701259] hid-generic 001F:8086:22D8.0001: hidraw0:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.702204] hid-generic 001F:8086:22D8.0002: hidraw1:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.703063] hid-generic 001F:8086:22D8.0003: hidraw2:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.704276] hid-generic 001F:8086:22D8.0004: hidraw3:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.704557] hid-generic 001F:8086:22D8.0005: hidraw4:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.750710] psmouse serio1: synaptics: Your touchpad (PNP: DLL077a 
> PNP0f13) says it can support a different bus. If i2c-hid and hid-rmi are not 
> used, you might want to try setting psmouse.synaptics_intertouch to 1 and 
> report this to linux-in...@vger.kernel.org.
> [7.030446] acpi INT33D5:00: intel-hid: created platform device
> [7.199178] i2c_hid i2c-WCOM482F:00: i2c-WCOM482F:00 supply vdd not found, 
> using dummy regulator
> [7.246638] input: WCOM482F:00 056A:482F as 
> /devices/pci:00/:00:15.0/i2c_designware.0/i2c-6/i2c-WCOM482F:00/0018:056A:482F.0006/input/input11
> [7.246873] hid-generic 0018:056A:482F.0006: input,hidraw0: I2C HID v1.00 
> Mouse [WCOM482F:00 056A:482F] on i2c-WCOM482F:00
> [7.275279] i2c_hid i2c-DLL077A:01: i2c-DLL077A:01 supply vdd not found, 
> using dummy regulator
> [7.304107] input: DLL077A:01 06CB:76AF as 
> /devices/pci:00/:00:15.1/i2c_designware.1/i2c-7/i2c-DLL077A:01/0018:06CB:76AF.0007/input/input14
> [7.304212] hid-generic 0018:06CB:76AF.0007: input,hidraw1: I2C HID v1.00 
> Mouse [DLL077A:01 06CB:76AF] on i2c-DLL077A:01
> [7.657123] usbcore: registered new interface driver usbhid
> [7.657124] usbhid: USB HID core driver
> [7.722876] input: Wacom HID 482F Pen as 
> /devices/pci:00/:00:15.0/i2c_designware.0/i2c-6/i2c-WCOM482F:00/0018:056A:482F.0006/input/input15
> [7.723148] input: Wacom HID 482F Finger as 
> /devices/pci:00/:00:15.0/i2c_designware.0/i2c-6/i2c-WCOM482F:00/0018:056A:482F.0006/input/input16
> [7.723611] wacom 0018:056A:482F.0006: hidraw0: I2C HID v1.00 Mouse 
> [WCOM482F:00 056A:482F] on i2c-WCOM482F:00
> [7.768275] input: DLL077A:01 06CB:76AF Touchpad as 
> /devices/pci:00/:00:15.1/i2c_designware.1/i2c-7/i2c-DLL077A:01/0018:06CB:76AF.0007/input/input19
> [7.864201] hid-multitouch 0018:06CB:76AF.0007: input,hidraw0: I2C HID 
> v1.00 Mouse [DLL077A:01 06CB:76AF] on i2c-DLL077A:01
>
> However in this state, I can't rmmod i2c-hid.  It just hangs the system with 
> this trace:
> [  243.033779] INFO: task kworker/u8:0:6 blocked for more than 120 seconds.
> [  243.033793]   Not tainted 4.17.0-rc1+ #37
> [  243.033798] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables 
> this message.
> [  243.033804] kworker/u8:0D0 6  2 0x8000
> [  243.033826] Workqueue: events_power_efficient 
> power_supply_deferred_register_work
> [  243.033832] Call Trace:
> [  243.033850]  __schedule+0x3c2/0x890
> [  243.033861]  ? __switch_to_asm+0x40/0x70
> [  243.033868]  schedule+0x36/0x80
> [  243.033875]  schedule_preempt_disabled+0xe/0x10
> [  243.033882]  __mutex_lock.isra.4+0x2ae/0x4e0
> [  243.033890]  ? 

Re: Sometimes unusable i2c-hid devices in 4.17-rcX

2018-05-17 Thread Benjamin Tissoires
Hi Mario,

On Wed, May 16, 2018 at 10:00 PM,   wrote:
> Hi All,
>
> I've been running 4.16-rc7 on an XPS 9365 for some time and recently moved up 
> to 4.17-rc5.
> Immediately I noticed that i2c-hid devices (both touchscreen and touchpad) 
> were not working.
> Also when shutting the system down or rebooting it would just hang. (magic 
> sysrq still worked).
>
> I figured it was an easy to identify regression so I started a bisect but it 
> came up with garbage
> that ended in selftests shortly after 4.17-rc2.  I realized that's because is 
> still will fail on 4.17-rc2
> occasionally, seemingly after trying something newer and warm rebooting.
> So it seems like it's "worse" after 4.17-rc2 (doesn't work at all) but semi 
> reproducible on 4.17-rc2.
>
> Not sure if I'm chasing some initialization race, but wanted to see if anyone 
> else was running into this
> or has some ideas?

I am reliably running a v4.17-rc3 with a merge on Jiri's tree on the 9360.

I doubt it's related to the event processing as I am not encountering
those issues.

It *could* be related to the interrupts not being properly raised.

Could you monitor /proc/interrupts and check if the ones associated
with your i2c-hid devices are increasing when you are using them?
Also, does the device emits raw HID events? (you can use hid-recorder
to check on the hidraw nodes.)

Cheers,
Benjamin

>
> #dmesg | grep 'i2c\|hid' doesn't show any obvious errors when in this state 
> of non functional hid stuff.
> [2.398649] i2c /dev entries driver
> [2.881651] hidraw: raw HID events driver (C) Jiri Kosina
> [3.683583] ish-hid {33AECD58-B679-4E54-9BD9-A04D34F0C226}: [hid-ish]: 
> enum_devices_done OK, num_hid_devices=5
> [3.701259] hid-generic 001F:8086:22D8.0001: hidraw0:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.702204] hid-generic 001F:8086:22D8.0002: hidraw1:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.703063] hid-generic 001F:8086:22D8.0003: hidraw2:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.704276] hid-generic 001F:8086:22D8.0004: hidraw3:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.704557] hid-generic 001F:8086:22D8.0005: hidraw4:  HID v2.00 
> Device [hid-ishtp 8086:22D8] on
> [3.750710] psmouse serio1: synaptics: Your touchpad (PNP: DLL077a 
> PNP0f13) says it can support a different bus. If i2c-hid and hid-rmi are not 
> used, you might want to try setting psmouse.synaptics_intertouch to 1 and 
> report this to linux-in...@vger.kernel.org.
> [7.030446] acpi INT33D5:00: intel-hid: created platform device
> [7.199178] i2c_hid i2c-WCOM482F:00: i2c-WCOM482F:00 supply vdd not found, 
> using dummy regulator
> [7.246638] input: WCOM482F:00 056A:482F as 
> /devices/pci:00/:00:15.0/i2c_designware.0/i2c-6/i2c-WCOM482F:00/0018:056A:482F.0006/input/input11
> [7.246873] hid-generic 0018:056A:482F.0006: input,hidraw0: I2C HID v1.00 
> Mouse [WCOM482F:00 056A:482F] on i2c-WCOM482F:00
> [7.275279] i2c_hid i2c-DLL077A:01: i2c-DLL077A:01 supply vdd not found, 
> using dummy regulator
> [7.304107] input: DLL077A:01 06CB:76AF as 
> /devices/pci:00/:00:15.1/i2c_designware.1/i2c-7/i2c-DLL077A:01/0018:06CB:76AF.0007/input/input14
> [7.304212] hid-generic 0018:06CB:76AF.0007: input,hidraw1: I2C HID v1.00 
> Mouse [DLL077A:01 06CB:76AF] on i2c-DLL077A:01
> [7.657123] usbcore: registered new interface driver usbhid
> [7.657124] usbhid: USB HID core driver
> [7.722876] input: Wacom HID 482F Pen as 
> /devices/pci:00/:00:15.0/i2c_designware.0/i2c-6/i2c-WCOM482F:00/0018:056A:482F.0006/input/input15
> [7.723148] input: Wacom HID 482F Finger as 
> /devices/pci:00/:00:15.0/i2c_designware.0/i2c-6/i2c-WCOM482F:00/0018:056A:482F.0006/input/input16
> [7.723611] wacom 0018:056A:482F.0006: hidraw0: I2C HID v1.00 Mouse 
> [WCOM482F:00 056A:482F] on i2c-WCOM482F:00
> [7.768275] input: DLL077A:01 06CB:76AF Touchpad as 
> /devices/pci:00/:00:15.1/i2c_designware.1/i2c-7/i2c-DLL077A:01/0018:06CB:76AF.0007/input/input19
> [7.864201] hid-multitouch 0018:06CB:76AF.0007: input,hidraw0: I2C HID 
> v1.00 Mouse [DLL077A:01 06CB:76AF] on i2c-DLL077A:01
>
> However in this state, I can't rmmod i2c-hid.  It just hangs the system with 
> this trace:
> [  243.033779] INFO: task kworker/u8:0:6 blocked for more than 120 seconds.
> [  243.033793]   Not tainted 4.17.0-rc1+ #37
> [  243.033798] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables 
> this message.
> [  243.033804] kworker/u8:0D0 6  2 0x8000
> [  243.033826] Workqueue: events_power_efficient 
> power_supply_deferred_register_work
> [  243.033832] Call Trace:
> [  243.033850]  __schedule+0x3c2/0x890
> [  243.033861]  ? __switch_to_asm+0x40/0x70
> [  243.033868]  schedule+0x36/0x80
> [  243.033875]  schedule_preempt_disabled+0xe/0x10
> [  243.033882]  __mutex_lock.isra.4+0x2ae/0x4e0
> [  243.033890]  ? __switch_to_asm+0x34/0x70
> [  243.033899]  ? 

Re: [PATCH] HID: i2c-hid: check if device is there before really probing

2018-05-14 Thread Benjamin Tissoires
On Wed, May 9, 2018 at 9:12 PM, Dmitry Torokhov <d...@google.com> wrote:
> From: Dmitry Torokhov <d...@chromium.org>
>
> On many Chromebooks touch devices are multi-sourced; the components are
> electrically compatible and one can be freely swapped for another without
> changing the OS image or firmware.
>
> To avoid bunch of scary messages when device is not actually present in the
> system let's try testing basic communication with it and if there is no
> response terminate probe early with -ENXIO.
>
> Signed-off-by: Dmitry Torokhov <d...@chromium.org>
> ---

Looks good. Tested on a Dell XPS with an i2c-hid touchpad:
Reviewed-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

Cheers,
Benjamin

>  drivers/hid/i2c-hid/i2c-hid.c | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
> index 7230243b94d30..a59d483ff316a 100644
> --- a/drivers/hid/i2c-hid/i2c-hid.c
> +++ b/drivers/hid/i2c-hid/i2c-hid.c
> @@ -1048,6 +1048,14 @@ static int i2c_hid_probe(struct i2c_client *client,
> pm_runtime_enable(>dev);
> device_enable_async_suspend(>dev);
>
> +   /* Make sure there is something at this address */
> +   ret = i2c_smbus_read_byte(client);
> +   if (ret < 0) {
> +   dev_dbg(>dev, "nothing at this address: %d\n", ret);
> +   ret = -ENXIO;
> +   goto err_pm;
> +   }
> +
> ret = i2c_hid_fetch_hid_descriptor(ihid);
> if (ret < 0)
> goto err_pm;
> --
> 2.17.0.441.gb46fe60e1d-goog
>


Re: [PATCH] HID: i2c-hid: check if device is there before really probing

2018-05-14 Thread Benjamin Tissoires
On Wed, May 9, 2018 at 9:12 PM, Dmitry Torokhov  wrote:
> From: Dmitry Torokhov 
>
> On many Chromebooks touch devices are multi-sourced; the components are
> electrically compatible and one can be freely swapped for another without
> changing the OS image or firmware.
>
> To avoid bunch of scary messages when device is not actually present in the
> system let's try testing basic communication with it and if there is no
> response terminate probe early with -ENXIO.
>
> Signed-off-by: Dmitry Torokhov 
> ---

Looks good. Tested on a Dell XPS with an i2c-hid touchpad:
Reviewed-by: Benjamin Tissoires 

Cheers,
Benjamin

>  drivers/hid/i2c-hid/i2c-hid.c | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
> index 7230243b94d30..a59d483ff316a 100644
> --- a/drivers/hid/i2c-hid/i2c-hid.c
> +++ b/drivers/hid/i2c-hid/i2c-hid.c
> @@ -1048,6 +1048,14 @@ static int i2c_hid_probe(struct i2c_client *client,
> pm_runtime_enable(>dev);
> device_enable_async_suspend(>dev);
>
> +   /* Make sure there is something at this address */
> +   ret = i2c_smbus_read_byte(client);
> +   if (ret < 0) {
> +   dev_dbg(>dev, "nothing at this address: %d\n", ret);
> +   ret = -ENXIO;
> +   goto err_pm;
> +   }
> +
> ret = i2c_hid_fetch_hid_descriptor(ihid);
> if (ret < 0)
> goto err_pm;
> --
> 2.17.0.441.gb46fe60e1d-goog
>


Re: [PATCH v2 0/9] Input: support for latest Lenovo thinkpads (series 80)

2018-05-14 Thread Benjamin Tissoires
Hi Dmitry,

This is your monthly reminder of the Lenov 80 pending series :)
Could you consider taking this series and Aaron's patch?

Cheers,
Benjamin

On Tue, Apr 17, 2018 at 1:42 PM, Aaron Ma  wrote:
> Hi Dmitry and Benjamin:
>
> Could you apply my patch too?
>
> It add LEN0096 that Benjamin's patch doesn't include.
>
> +   "LEN0096", /* X280 */
>
> Regards,
> Aaron


Re: [PATCH v2 0/9] Input: support for latest Lenovo thinkpads (series 80)

2018-05-14 Thread Benjamin Tissoires
Hi Dmitry,

This is your monthly reminder of the Lenov 80 pending series :)
Could you consider taking this series and Aaron's patch?

Cheers,
Benjamin

On Tue, Apr 17, 2018 at 1:42 PM, Aaron Ma  wrote:
> Hi Dmitry and Benjamin:
>
> Could you apply my patch too?
>
> It add LEN0096 that Benjamin's patch doesn't include.
>
> +   "LEN0096", /* X280 */
>
> Regards,
> Aaron


Re: [PATCH] HID: wacom: Release device resource data obtained by devres_alloc()

2018-04-24 Thread Benjamin Tissoires
On Tue, Apr 24, 2018 at 10:03 AM, Arvind Yadav
<arvind.yadav...@gmail.com> wrote:
> Free device resource data, if __wacom_devm_sysfs_create_group
> is not successful.
>
> Signed-off-by: Arvind Yadav <arvind.yadav...@gmail.com>
> ---

Looks good to me:
Reviewed-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

Cheers,
Benjamin

>  drivers/hid/wacom_sys.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
> index b54ef1f..ee7a37e 100644
> --- a/drivers/hid/wacom_sys.c
> +++ b/drivers/hid/wacom_sys.c
> @@ -1213,8 +1213,10 @@ static int __wacom_devm_sysfs_create_group(struct 
> wacom *wacom,
> devres->root = root;
>
> error = sysfs_create_group(devres->root, group);
> -   if (error)
> +   if (error) {
> +   devres_free(devres);
> return error;
> +   }
>
> devres_add(>hdev->dev, devres);
>
> --
> 1.9.1
>


Re: [PATCH] HID: wacom: Release device resource data obtained by devres_alloc()

2018-04-24 Thread Benjamin Tissoires
On Tue, Apr 24, 2018 at 10:03 AM, Arvind Yadav
 wrote:
> Free device resource data, if __wacom_devm_sysfs_create_group
> is not successful.
>
> Signed-off-by: Arvind Yadav 
> ---

Looks good to me:
Reviewed-by: Benjamin Tissoires 

Cheers,
Benjamin

>  drivers/hid/wacom_sys.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
> index b54ef1f..ee7a37e 100644
> --- a/drivers/hid/wacom_sys.c
> +++ b/drivers/hid/wacom_sys.c
> @@ -1213,8 +1213,10 @@ static int __wacom_devm_sysfs_create_group(struct 
> wacom *wacom,
> devres->root = root;
>
> error = sysfs_create_group(devres->root, group);
> -   if (error)
> +   if (error) {
> +   devres_free(devres);
> return error;
> +   }
>
> devres_add(>hdev->dev, devres);
>
> --
> 1.9.1
>


[PATCH v2 5/6] HID: multitouch: simplify the settings of the various features

2018-04-24 Thread Benjamin Tissoires
The Win8 spec also declare other features we want to support:
latency and surface and button switches.

Though it doesn't seem we need to activate those by default, we have been
proved in the past that manufacturers rely on the Windows driver behavior
so we better mimic it to prevent further issues.

The current way of setting the features is cumbersome. It avoids iterating
over the list of features, but the way we store/retrieve the data just
doesn't scale with more than two values.

So iterate over the features when we decide to switch on the device and
make it simpler to extend.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-multitouch.c | 131 ---
 1 file changed, 60 insertions(+), 71 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 43784d31a1a3..8878de9eedba 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -127,11 +127,7 @@ struct mt_device {
int left_button_state;  /* left button state */
unsigned last_slot_field;   /* the last field of a slot */
unsigned mt_report_id;  /* the report ID of the multitouch device */
-   __s16 inputmode;/* InputMode HID feature, -1 if non-existent */
-   __s16 inputmode_index;  /* InputMode HID feature index in the report */
-   __s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
-  -1 if non-existent */
-   __u8 inputmode_value;  /* InputMode HID feature value */
+   __u8 inputmode_value;   /* InputMode HID feature value */
__u8 num_received;  /* how many contacts we received */
__u8 num_expected;  /* expected last contact index */
__u8 maxcontacts;
@@ -415,32 +411,9 @@ static void mt_feature_mapping(struct hid_device *hdev,
struct mt_device *td = hid_get_drvdata(hdev);
 
switch (usage->hid) {
-   case HID_DG_INPUTMODE:
-   /* Ignore if value index is out of bounds. */
-   if (usage->usage_index >= field->report_count) {
-   dev_err(>dev, "HID_DG_INPUTMODE out of range\n");
-   break;
-   }
-
-   if (td->inputmode < 0) {
-   td->inputmode = field->report->id;
-   td->inputmode_index = usage->usage_index;
-   } else {
-   /*
-* Some elan panels wrongly declare 2 input mode
-* features, and silently ignore when we set the
-* value in the second field. Skip the second feature
-* and hope for the best.
-*/
-   dev_info(>dev,
-"Ignoring the extra HID_DG_INPUTMODE\n");
-   }
-
-   break;
case HID_DG_CONTACTMAX:
mt_get_feature(hdev, field->report);
 
-   td->maxcontact_report_id = field->report->id;
td->maxcontacts = field->value[0];
if (!td->maxcontacts &&
field->logical_maximum <= MT_MAX_MAXCONTACT)
@@ -1181,61 +1154,81 @@ static void mt_report(struct hid_device *hid, struct 
hid_report *report)
input_sync(field->hidinput->input);
 }
 
-static void mt_set_input_mode(struct hid_device *hdev)
+static bool mt_need_to_apply_feature(struct hid_device *hdev,
+struct hid_field *field,
+struct hid_usage *usage)
 {
struct mt_device *td = hid_get_drvdata(hdev);
-   struct hid_report *r;
-   struct hid_report_enum *re;
struct mt_class *cls = >mtclass;
+   struct hid_report *report = field->report;
+   unsigned int index = usage->usage_index;
char *buf;
u32 report_len;
+   int max;
 
-   if (td->inputmode < 0)
-   return;
-
-   re = &(hdev->report_enum[HID_FEATURE_REPORT]);
-   r = re->report_id_hash[td->inputmode];
-   if (r) {
+   switch (usage->hid) {
+   case HID_DG_INPUTMODE:
if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
-   report_len = hid_report_len(r);
-   buf = hid_alloc_report_buf(r, GFP_KERNEL);
+   report_len = hid_report_len(report);
+   buf = hid_alloc_report_buf(report, GFP_KERNEL);
if (!buf) {
-   hid_err(hdev, "failed to allocate buffer for 
report\n");
-   return;
+   hid_err(hdev,
+   "failed to allocate buffer for 
report\n");
+  

[PATCH v2 4/6] HID: multitouch: make use of HID_QUIRK_INPUT_PER_APP

2018-04-24 Thread Benjamin Tissoires
We now have HID_QUIRK_INPUT_PER_APPLICATION that splits the devices
into several devices. This helps us as we can now rely on hid-input
to set the names for us.

Also, this helps removing some magical numbers '0' when calling
.input_configured().

The only thing to take care of is that the field .report in struct
hid_input is now null. We need to iterate over the full list of
reports attached to a hid_input.

This is required for some Advanced Silicon touchscreen to correctly apply
the HID_QUIRK_INPUT_PER_APPLICATION as they have 2 reports associated
with the hidinput node. One contains the Input data, the other one
contains the Output data.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-multitouch.c | 72 
 1 file changed, 33 insertions(+), 39 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index dad2fbb0e3f8..43784d31a1a3 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1274,54 +1274,48 @@ static int mt_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
struct mt_device *td = hid_get_drvdata(hdev);
char *name;
const char *suffix = NULL;
-   struct hid_field *field = hi->report->field[0];
+   unsigned int application = 0;
+   struct hid_report *report;
int ret;
 
-   if (hi->report->id == td->mt_report_id) {
-   ret = mt_touch_input_configured(hdev, hi);
-   if (ret)
-   return ret;
+   list_for_each_entry(report, >reports, hidinput_list) {
+   application = report->application;
+   if (report->id == td->mt_report_id) {
+   ret = mt_touch_input_configured(hdev, hi);
+   if (ret)
+   return ret;
+   }
+
+   /*
+* some egalax touchscreens have "application == DG_TOUCHSCREEN"
+* for the stylus. Check this first, and then rely on
+* the application field.
+*/
+   if (report->field[0]->physical == HID_DG_STYLUS) {
+   suffix = "Pen";
+   /* force BTN_STYLUS to allow tablet matching in udev */
+   __set_bit(BTN_STYLUS, hi->input->keybit);
+   }
}
 
-   /*
-* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
-* for the stylus. Check this first, and then rely on the application
-* field.
-*/
-   if (hi->report->field[0]->physical == HID_DG_STYLUS) {
-   suffix = "Pen";
-   /* force BTN_STYLUS to allow tablet matching in udev */
-   __set_bit(BTN_STYLUS, hi->input->keybit);
-   } else {
-   switch (field->application) {
+   if (!suffix) {
+   switch (application) {
case HID_GD_KEYBOARD:
-   suffix = "Keyboard";
-   break;
case HID_GD_KEYPAD:
-   suffix = "Keypad";
-   break;
case HID_GD_MOUSE:
-   suffix = "Mouse";
-   break;
-   case HID_DG_STYLUS:
-   suffix = "Pen";
-   /* force BTN_STYLUS to allow tablet matching in udev */
-   __set_bit(BTN_STYLUS, hi->input->keybit);
-   break;
-   case HID_DG_TOUCHSCREEN:
-   /* we do not set suffix = "Touchscreen" */
-   break;
case HID_DG_TOUCHPAD:
-   suffix = "Touchpad";
-   break;
case HID_GD_SYSTEM_CONTROL:
-   suffix = "System Control";
-   break;
case HID_CP_CONSUMER_CONTROL:
-   suffix = "Consumer Control";
-   break;
case HID_GD_WIRELESS_RADIO_CTLS:
-   suffix = "Wireless Radio Control";
+   /* already handled by hid core */
+   break;
+   case HID_DG_TOUCHSCREEN:
+   /* we do not set suffix = "Touchscreen" */
+   hi->input->name = hdev->name;
+   break;
+   case HID_DG_STYLUS:
+   /* force BTN_STYLUS to allow tablet matching in udev */
+   __set_bit(BTN_STYLUS, hi->input->keybit);
break;
case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
suffix = "Custom Media Keys&qu

[PATCH v2 5/6] HID: multitouch: simplify the settings of the various features

2018-04-24 Thread Benjamin Tissoires
The Win8 spec also declare other features we want to support:
latency and surface and button switches.

Though it doesn't seem we need to activate those by default, we have been
proved in the past that manufacturers rely on the Windows driver behavior
so we better mimic it to prevent further issues.

The current way of setting the features is cumbersome. It avoids iterating
over the list of features, but the way we store/retrieve the data just
doesn't scale with more than two values.

So iterate over the features when we decide to switch on the device and
make it simpler to extend.

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-multitouch.c | 131 ---
 1 file changed, 60 insertions(+), 71 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 43784d31a1a3..8878de9eedba 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -127,11 +127,7 @@ struct mt_device {
int left_button_state;  /* left button state */
unsigned last_slot_field;   /* the last field of a slot */
unsigned mt_report_id;  /* the report ID of the multitouch device */
-   __s16 inputmode;/* InputMode HID feature, -1 if non-existent */
-   __s16 inputmode_index;  /* InputMode HID feature index in the report */
-   __s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
-  -1 if non-existent */
-   __u8 inputmode_value;  /* InputMode HID feature value */
+   __u8 inputmode_value;   /* InputMode HID feature value */
__u8 num_received;  /* how many contacts we received */
__u8 num_expected;  /* expected last contact index */
__u8 maxcontacts;
@@ -415,32 +411,9 @@ static void mt_feature_mapping(struct hid_device *hdev,
struct mt_device *td = hid_get_drvdata(hdev);
 
switch (usage->hid) {
-   case HID_DG_INPUTMODE:
-   /* Ignore if value index is out of bounds. */
-   if (usage->usage_index >= field->report_count) {
-   dev_err(>dev, "HID_DG_INPUTMODE out of range\n");
-   break;
-   }
-
-   if (td->inputmode < 0) {
-   td->inputmode = field->report->id;
-   td->inputmode_index = usage->usage_index;
-   } else {
-   /*
-* Some elan panels wrongly declare 2 input mode
-* features, and silently ignore when we set the
-* value in the second field. Skip the second feature
-* and hope for the best.
-*/
-   dev_info(>dev,
-"Ignoring the extra HID_DG_INPUTMODE\n");
-   }
-
-   break;
case HID_DG_CONTACTMAX:
mt_get_feature(hdev, field->report);
 
-   td->maxcontact_report_id = field->report->id;
td->maxcontacts = field->value[0];
if (!td->maxcontacts &&
field->logical_maximum <= MT_MAX_MAXCONTACT)
@@ -1181,61 +1154,81 @@ static void mt_report(struct hid_device *hid, struct 
hid_report *report)
input_sync(field->hidinput->input);
 }
 
-static void mt_set_input_mode(struct hid_device *hdev)
+static bool mt_need_to_apply_feature(struct hid_device *hdev,
+struct hid_field *field,
+struct hid_usage *usage)
 {
struct mt_device *td = hid_get_drvdata(hdev);
-   struct hid_report *r;
-   struct hid_report_enum *re;
struct mt_class *cls = >mtclass;
+   struct hid_report *report = field->report;
+   unsigned int index = usage->usage_index;
char *buf;
u32 report_len;
+   int max;
 
-   if (td->inputmode < 0)
-   return;
-
-   re = &(hdev->report_enum[HID_FEATURE_REPORT]);
-   r = re->report_id_hash[td->inputmode];
-   if (r) {
+   switch (usage->hid) {
+   case HID_DG_INPUTMODE:
if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
-   report_len = hid_report_len(r);
-   buf = hid_alloc_report_buf(r, GFP_KERNEL);
+   report_len = hid_report_len(report);
+   buf = hid_alloc_report_buf(report, GFP_KERNEL);
if (!buf) {
-   hid_err(hdev, "failed to allocate buffer for 
report\n");
-   return;
+   hid_err(hdev,
+   "failed to allocate buffer for 
report\n");
+   return false;
 

[PATCH v2 4/6] HID: multitouch: make use of HID_QUIRK_INPUT_PER_APP

2018-04-24 Thread Benjamin Tissoires
We now have HID_QUIRK_INPUT_PER_APPLICATION that splits the devices
into several devices. This helps us as we can now rely on hid-input
to set the names for us.

Also, this helps removing some magical numbers '0' when calling
.input_configured().

The only thing to take care of is that the field .report in struct
hid_input is now null. We need to iterate over the full list of
reports attached to a hid_input.

This is required for some Advanced Silicon touchscreen to correctly apply
the HID_QUIRK_INPUT_PER_APPLICATION as they have 2 reports associated
with the hidinput node. One contains the Input data, the other one
contains the Output data.

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-multitouch.c | 72 
 1 file changed, 33 insertions(+), 39 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index dad2fbb0e3f8..43784d31a1a3 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1274,54 +1274,48 @@ static int mt_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
struct mt_device *td = hid_get_drvdata(hdev);
char *name;
const char *suffix = NULL;
-   struct hid_field *field = hi->report->field[0];
+   unsigned int application = 0;
+   struct hid_report *report;
int ret;
 
-   if (hi->report->id == td->mt_report_id) {
-   ret = mt_touch_input_configured(hdev, hi);
-   if (ret)
-   return ret;
+   list_for_each_entry(report, >reports, hidinput_list) {
+   application = report->application;
+   if (report->id == td->mt_report_id) {
+   ret = mt_touch_input_configured(hdev, hi);
+   if (ret)
+   return ret;
+   }
+
+   /*
+* some egalax touchscreens have "application == DG_TOUCHSCREEN"
+* for the stylus. Check this first, and then rely on
+* the application field.
+*/
+   if (report->field[0]->physical == HID_DG_STYLUS) {
+   suffix = "Pen";
+   /* force BTN_STYLUS to allow tablet matching in udev */
+   __set_bit(BTN_STYLUS, hi->input->keybit);
+   }
}
 
-   /*
-* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
-* for the stylus. Check this first, and then rely on the application
-* field.
-*/
-   if (hi->report->field[0]->physical == HID_DG_STYLUS) {
-   suffix = "Pen";
-   /* force BTN_STYLUS to allow tablet matching in udev */
-   __set_bit(BTN_STYLUS, hi->input->keybit);
-   } else {
-   switch (field->application) {
+   if (!suffix) {
+   switch (application) {
case HID_GD_KEYBOARD:
-   suffix = "Keyboard";
-   break;
case HID_GD_KEYPAD:
-   suffix = "Keypad";
-   break;
case HID_GD_MOUSE:
-   suffix = "Mouse";
-   break;
-   case HID_DG_STYLUS:
-   suffix = "Pen";
-   /* force BTN_STYLUS to allow tablet matching in udev */
-   __set_bit(BTN_STYLUS, hi->input->keybit);
-   break;
-   case HID_DG_TOUCHSCREEN:
-   /* we do not set suffix = "Touchscreen" */
-   break;
case HID_DG_TOUCHPAD:
-   suffix = "Touchpad";
-   break;
case HID_GD_SYSTEM_CONTROL:
-   suffix = "System Control";
-   break;
case HID_CP_CONSUMER_CONTROL:
-   suffix = "Consumer Control";
-   break;
case HID_GD_WIRELESS_RADIO_CTLS:
-   suffix = "Wireless Radio Control";
+   /* already handled by hid core */
+   break;
+   case HID_DG_TOUCHSCREEN:
+   /* we do not set suffix = "Touchscreen" */
+   hi->input->name = hdev->name;
+   break;
+   case HID_DG_STYLUS:
+   /* force BTN_STYLUS to allow tablet matching in udev */
+   __set_bit(BTN_STYLUS, hi->input->keybit);
break;
case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
suffix = "Custom Media Keys";
@@ -1459,10 +1453,10 @@ s

[PATCH v2 3/6] HID: input: append a suffix matching the application

2018-04-24 Thread Benjamin Tissoires
Given that we create one input node per application, we should name
the input node accordingly to not lose userspace.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-input.c | 67 +++--
 include/linux/hid.h |  1 +
 2 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 361643683c08..ab93dd5927c3 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1510,15 +1510,56 @@ static void report_features(struct hid_device *hid)
}
 }
 
-static struct hid_input *hidinput_allocate(struct hid_device *hid)
+static struct hid_input *hidinput_allocate(struct hid_device *hid,
+  unsigned int application)
 {
struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
struct input_dev *input_dev = input_allocate_device();
-   if (!hidinput || !input_dev) {
-   kfree(hidinput);
-   input_free_device(input_dev);
-   hid_err(hid, "Out of memory during hid input probe\n");
-   return NULL;
+   const char *suffix = NULL;
+
+   if (!hidinput || !input_dev)
+   goto fail;
+
+   if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) &&
+   hid->maxapplication > 1) {
+   switch (application) {
+   case HID_GD_KEYBOARD:
+   suffix = "Keyboard";
+   break;
+   case HID_GD_KEYPAD:
+   suffix = "Keypad";
+   break;
+   case HID_GD_MOUSE:
+   suffix = "Mouse";
+   break;
+   case HID_DG_STYLUS:
+   suffix = "Pen";
+   break;
+   case HID_DG_TOUCHSCREEN:
+   suffix = "Touchscreen";
+   break;
+   case HID_DG_TOUCHPAD:
+   suffix = "Touchpad";
+   break;
+   case HID_GD_SYSTEM_CONTROL:
+   suffix = "System Control";
+   break;
+   case HID_CP_CONSUMER_CONTROL:
+   suffix = "Consumer Control";
+   break;
+   case HID_GD_WIRELESS_RADIO_CTLS:
+   suffix = "Wireless Radio Control";
+   break;
+   default:
+   break;
+   }
+   }
+
+   if (suffix) {
+   hidinput->name = kasprintf(GFP_KERNEL, "%s %s",
+  hid->name, suffix);
+   if (!hidinput->name)
+   goto fail;
}
 
input_set_drvdata(input_dev, hid);
@@ -1528,7 +1569,7 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
input_dev->setkeycode = hidinput_setkeycode;
input_dev->getkeycode = hidinput_getkeycode;
 
-   input_dev->name = hid->name;
+   input_dev->name = hidinput->name ? hidinput->name : hid->name;
input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq;
input_dev->id.bustype = hid->bus;
@@ -1543,6 +1584,12 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
INIT_LIST_HEAD(>reports);
 
return hidinput;
+
+fail:
+   kfree(hidinput);
+   input_free_device(input_dev);
+   hid_err(hid, "Out of memory during hid input probe\n");
+   return NULL;
 }
 
 static bool hidinput_has_been_populated(struct hid_input *hidinput)
@@ -1588,6 +1635,7 @@ static void hidinput_cleanup_hidinput(struct hid_device 
*hid,
 
list_del(>list);
input_free_device(hidinput->input);
+   kfree(hidinput->name);
 
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
if (k == HID_OUTPUT_REPORT &&
@@ -1656,6 +1704,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
struct hid_driver *drv = hid->driver;
struct hid_report *report;
struct hid_input *next, *hidinput = NULL;
+   unsigned int application;
int i, k;
 
INIT_LIST_HEAD(>inputs);
@@ -1688,6 +1737,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
if (!report->maxfield)
continue;
 
+   application = report->application;
+
/*
 * Find the previous hidinput report attached
 * to this report id.
@@ -1699,7 +1750,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
h

[PATCH v2 2/6] HID: generic: create one input report per application type

2018-04-24 Thread Benjamin Tissoires
It is not a good idea to try to fit all types of applications in the
same input report. There are a lot of devices that are needing
the quirk HID_MULTI_INPUT but this quirk doesn't match the actual HID
description as it is based on the report ID.

Given that most devices with MULTI_INPUT I can think of split nicely
the devices inputs into application, it is a good thing to split the
devices by default based on this assumption.

Also make hid-multitouch following this rule, to not have to deal
with too many input created.

While we are at it, fix some checkpatch complaints about converting
'unsigned' to 'unsigned int'.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-core.c   | 19 +--
 drivers/hid/hid-generic.c| 15 +++
 drivers/hid/hid-gfrm.c   |  2 +-
 drivers/hid/hid-input.c  | 17 +
 drivers/hid/hid-magicmouse.c |  6 +++---
 include/linux/hid.h  | 10 +++---
 6 files changed, 56 insertions(+), 13 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5d7cc6bbbac6..68819106f4fc 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -57,7 +57,9 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special 
drivers and handle
  * Register a new report for a device.
  */
 
-struct hid_report *hid_register_report(struct hid_device *device, unsigned 
type, unsigned id)
+struct hid_report *hid_register_report(struct hid_device *device,
+  unsigned int type, unsigned int id,
+  unsigned int application)
 {
struct hid_report_enum *report_enum = device->report_enum + type;
struct hid_report *report;
@@ -78,6 +80,7 @@ struct hid_report *hid_register_report(struct hid_device 
*device, unsigned type,
report->type = type;
report->size = 0;
report->device = device;
+   report->application = application;
report_enum->report_id_hash[id] = report;
 
list_add_tail(>list, _enum->report_list);
@@ -221,11 +224,15 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
 {
struct hid_report *report;
struct hid_field *field;
-   unsigned usages;
-   unsigned offset;
-   unsigned i;
+   unsigned int usages;
+   unsigned int offset;
+   unsigned int i;
+   unsigned int application;
+
+   application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
-   report = hid_register_report(parser->device, report_type, 
parser->global.report_id);
+   report = hid_register_report(parser->device, report_type,
+parser->global.report_id, application);
if (!report) {
hid_err(parser->device, "hid_register_report failed\n");
return -1;
@@ -259,7 +266,7 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
 
field->physical = hid_lookup_collection(parser, 
HID_COLLECTION_PHYSICAL);
field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
-   field->application = hid_lookup_collection(parser, 
HID_COLLECTION_APPLICATION);
+   field->application = application;
 
for (i = 0; i < usages; i++) {
unsigned j = i;
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c
index c25b4718de44..3b6eccbc2519 100644
--- a/drivers/hid/hid-generic.c
+++ b/drivers/hid/hid-generic.c
@@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev,
return true;
 }
 
+static int hid_generic_probe(struct hid_device *hdev,
+const struct hid_device_id *id)
+{
+   int ret;
+
+   hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
+   ret = hid_parse(hdev);
+   if (ret)
+   return ret;
+
+   return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
 static const struct hid_device_id hid_table[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
{ }
@@ -66,6 +80,7 @@ static struct hid_driver hid_generic = {
.name = "hid-generic",
.id_table = hid_table,
.match = hid_generic_match,
+   .probe = hid_generic_probe,
 };
 module_hid_driver(hid_generic);
 
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
index 075b1c020846..cf477f8c8f4c 100644
--- a/drivers/hid/hid-gfrm.c
+++ b/drivers/hid/hid-gfrm.c
@@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 * those reports reach gfrm_raw_event() from hid_input_report().
 */
if (!hid_register_report(hdev, HID_INPUT_REPORT,
-GFRM100_SEARCH_KEY_REPORT_ID)) {
+GFRM100_SEARCH_KEY_R

[PATCH v2 3/6] HID: input: append a suffix matching the application

2018-04-24 Thread Benjamin Tissoires
Given that we create one input node per application, we should name
the input node accordingly to not lose userspace.

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-input.c | 67 +++--
 include/linux/hid.h |  1 +
 2 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 361643683c08..ab93dd5927c3 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1510,15 +1510,56 @@ static void report_features(struct hid_device *hid)
}
 }
 
-static struct hid_input *hidinput_allocate(struct hid_device *hid)
+static struct hid_input *hidinput_allocate(struct hid_device *hid,
+  unsigned int application)
 {
struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
struct input_dev *input_dev = input_allocate_device();
-   if (!hidinput || !input_dev) {
-   kfree(hidinput);
-   input_free_device(input_dev);
-   hid_err(hid, "Out of memory during hid input probe\n");
-   return NULL;
+   const char *suffix = NULL;
+
+   if (!hidinput || !input_dev)
+   goto fail;
+
+   if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) &&
+   hid->maxapplication > 1) {
+   switch (application) {
+   case HID_GD_KEYBOARD:
+   suffix = "Keyboard";
+   break;
+   case HID_GD_KEYPAD:
+   suffix = "Keypad";
+   break;
+   case HID_GD_MOUSE:
+   suffix = "Mouse";
+   break;
+   case HID_DG_STYLUS:
+   suffix = "Pen";
+   break;
+   case HID_DG_TOUCHSCREEN:
+   suffix = "Touchscreen";
+   break;
+   case HID_DG_TOUCHPAD:
+   suffix = "Touchpad";
+   break;
+   case HID_GD_SYSTEM_CONTROL:
+   suffix = "System Control";
+   break;
+   case HID_CP_CONSUMER_CONTROL:
+   suffix = "Consumer Control";
+   break;
+   case HID_GD_WIRELESS_RADIO_CTLS:
+   suffix = "Wireless Radio Control";
+   break;
+   default:
+   break;
+   }
+   }
+
+   if (suffix) {
+   hidinput->name = kasprintf(GFP_KERNEL, "%s %s",
+  hid->name, suffix);
+   if (!hidinput->name)
+   goto fail;
}
 
input_set_drvdata(input_dev, hid);
@@ -1528,7 +1569,7 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
input_dev->setkeycode = hidinput_setkeycode;
input_dev->getkeycode = hidinput_getkeycode;
 
-   input_dev->name = hid->name;
+   input_dev->name = hidinput->name ? hidinput->name : hid->name;
input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq;
input_dev->id.bustype = hid->bus;
@@ -1543,6 +1584,12 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
INIT_LIST_HEAD(>reports);
 
return hidinput;
+
+fail:
+   kfree(hidinput);
+   input_free_device(input_dev);
+   hid_err(hid, "Out of memory during hid input probe\n");
+   return NULL;
 }
 
 static bool hidinput_has_been_populated(struct hid_input *hidinput)
@@ -1588,6 +1635,7 @@ static void hidinput_cleanup_hidinput(struct hid_device 
*hid,
 
list_del(>list);
input_free_device(hidinput->input);
+   kfree(hidinput->name);
 
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
if (k == HID_OUTPUT_REPORT &&
@@ -1656,6 +1704,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
struct hid_driver *drv = hid->driver;
struct hid_report *report;
struct hid_input *next, *hidinput = NULL;
+   unsigned int application;
int i, k;
 
INIT_LIST_HEAD(>inputs);
@@ -1688,6 +1737,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
if (!report->maxfield)
continue;
 
+   application = report->application;
+
/*
 * Find the previous hidinput report attached
 * to this report id.
@@ -1699,7 +1750,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
hidinpu

[PATCH v2 2/6] HID: generic: create one input report per application type

2018-04-24 Thread Benjamin Tissoires
It is not a good idea to try to fit all types of applications in the
same input report. There are a lot of devices that are needing
the quirk HID_MULTI_INPUT but this quirk doesn't match the actual HID
description as it is based on the report ID.

Given that most devices with MULTI_INPUT I can think of split nicely
the devices inputs into application, it is a good thing to split the
devices by default based on this assumption.

Also make hid-multitouch following this rule, to not have to deal
with too many input created.

While we are at it, fix some checkpatch complaints about converting
'unsigned' to 'unsigned int'.

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-core.c   | 19 +--
 drivers/hid/hid-generic.c| 15 +++
 drivers/hid/hid-gfrm.c   |  2 +-
 drivers/hid/hid-input.c  | 17 +
 drivers/hid/hid-magicmouse.c |  6 +++---
 include/linux/hid.h  | 10 +++---
 6 files changed, 56 insertions(+), 13 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5d7cc6bbbac6..68819106f4fc 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -57,7 +57,9 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special 
drivers and handle
  * Register a new report for a device.
  */
 
-struct hid_report *hid_register_report(struct hid_device *device, unsigned 
type, unsigned id)
+struct hid_report *hid_register_report(struct hid_device *device,
+  unsigned int type, unsigned int id,
+  unsigned int application)
 {
struct hid_report_enum *report_enum = device->report_enum + type;
struct hid_report *report;
@@ -78,6 +80,7 @@ struct hid_report *hid_register_report(struct hid_device 
*device, unsigned type,
report->type = type;
report->size = 0;
report->device = device;
+   report->application = application;
report_enum->report_id_hash[id] = report;
 
list_add_tail(>list, _enum->report_list);
@@ -221,11 +224,15 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
 {
struct hid_report *report;
struct hid_field *field;
-   unsigned usages;
-   unsigned offset;
-   unsigned i;
+   unsigned int usages;
+   unsigned int offset;
+   unsigned int i;
+   unsigned int application;
+
+   application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
-   report = hid_register_report(parser->device, report_type, 
parser->global.report_id);
+   report = hid_register_report(parser->device, report_type,
+parser->global.report_id, application);
if (!report) {
hid_err(parser->device, "hid_register_report failed\n");
return -1;
@@ -259,7 +266,7 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
 
field->physical = hid_lookup_collection(parser, 
HID_COLLECTION_PHYSICAL);
field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
-   field->application = hid_lookup_collection(parser, 
HID_COLLECTION_APPLICATION);
+   field->application = application;
 
for (i = 0; i < usages; i++) {
unsigned j = i;
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c
index c25b4718de44..3b6eccbc2519 100644
--- a/drivers/hid/hid-generic.c
+++ b/drivers/hid/hid-generic.c
@@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev,
return true;
 }
 
+static int hid_generic_probe(struct hid_device *hdev,
+const struct hid_device_id *id)
+{
+   int ret;
+
+   hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
+   ret = hid_parse(hdev);
+   if (ret)
+   return ret;
+
+   return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
 static const struct hid_device_id hid_table[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
{ }
@@ -66,6 +80,7 @@ static struct hid_driver hid_generic = {
.name = "hid-generic",
.id_table = hid_table,
.match = hid_generic_match,
+   .probe = hid_generic_probe,
 };
 module_hid_driver(hid_generic);
 
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
index 075b1c020846..cf477f8c8f4c 100644
--- a/drivers/hid/hid-gfrm.c
+++ b/drivers/hid/hid-gfrm.c
@@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 * those reports reach gfrm_raw_event() from hid_input_report().
 */
if (!hid_register_report(hdev, HID_INPUT_REPORT,
-GFRM100_SEARCH_KEY_REPORT_ID)) {
+GFRM100_SEARCH_KEY_REPORT_ID, 0)) {
ret = -ENO

[PATCH v2 6/6] HID: multitouch: implement precision touchpad latency and switches

2018-04-24 Thread Benjamin Tissoires
The Win 8.1 precision touchpad spec introduce new modes for touchpads
that can come in handy[1].

Implement the settings of these modes, so we are not taken off-guard if
a firmware decides to enforce them.

[1] 
https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-precision-touchpad-required-hid-top-level-collections

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-multitouch.c | 34 +-
 include/linux/hid.h  |  3 +++
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 8878de9eedba..82c98bf14d60 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -81,6 +81,11 @@ MODULE_LICENSE("GPL");
 
 #define MT_BUTTONTYPE_CLICKPAD 0
 
+enum latency_mode {
+   HID_LATENCY_NORMAL = 0,
+   HID_LATENCY_HIGH = 1,
+};
+
 #define MT_IO_FLAGS_RUNNING0
 #define MT_IO_FLAGS_ACTIVE_SLOTS   1
 #define MT_IO_FLAGS_PENDING_SLOTS  2
@@ -1156,7 +1161,10 @@ static void mt_report(struct hid_device *hid, struct 
hid_report *report)
 
 static bool mt_need_to_apply_feature(struct hid_device *hdev,
 struct hid_field *field,
-struct hid_usage *usage)
+struct hid_usage *usage,
+enum latency_mode latency,
+bool surface_switch,
+bool button_switch)
 {
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = >mtclass;
@@ -1195,12 +1203,25 @@ static bool mt_need_to_apply_feature(struct hid_device 
*hdev,
}
}
break;
+
+   case HID_DG_LATENCYMODE:
+   field->value[index] = latency;
+   return 1;
+
+   case HID_DG_SURFACESWITCH:
+   field->value[index] = surface_switch;
+   return 1;
+
+   case HID_DG_BUTTONSWITCH:
+   field->value[index] = button_switch;
+   return 1;
}
 
return false; /* no need to update the report */
 }
 
-static void mt_set_modes(struct hid_device *hdev)
+static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
+bool surface_switch, bool button_switch)
 {
struct hid_report_enum *rep_enum;
struct hid_report *rep;
@@ -1222,7 +1243,10 @@ static void mt_set_modes(struct hid_device *hdev)
 
if (mt_need_to_apply_feature(hdev,
 rep->field[i],
-usage))
+usage,
+latency,
+surface_switch,
+button_switch))
update_report = true;
}
}
@@ -1467,7 +1491,7 @@ static int mt_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
dev_warn(>dev, "Cannot allocate sysfs group for %s\n",
hdev->name);
 
-   mt_set_modes(hdev);
+   mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
 
/* release .fields memory as it is not used anymore */
devm_kfree(>dev, td->fields);
@@ -1480,7 +1504,7 @@ static int mt_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 static int mt_reset_resume(struct hid_device *hdev)
 {
mt_release_contacts(hdev);
-   mt_set_modes(hdev);
+   mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
return 0;
 }
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d3bd83d9127f..d65ce4ab82d6 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -292,9 +292,12 @@ struct hid_item {
 #define HID_DG_CONTACTCOUNT0x000d0054
 #define HID_DG_CONTACTMAX  0x000d0055
 #define HID_DG_SCANTIME0x000d0056
+#define HID_DG_SURFACESWITCH   0x000d0057
+#define HID_DG_BUTTONSWITCH0x000d0058
 #define HID_DG_BUTTONTYPE  0x000d0059
 #define HID_DG_BARRELSWITCH2   0x000d005a
 #define HID_DG_TOOLSERIALNUMBER0x000d005b
+#define HID_DG_LATENCYMODE 0x000d0060
 
 #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS  0xff310076
 /*
-- 
2.14.3



[PATCH v2 6/6] HID: multitouch: implement precision touchpad latency and switches

2018-04-24 Thread Benjamin Tissoires
The Win 8.1 precision touchpad spec introduce new modes for touchpads
that can come in handy[1].

Implement the settings of these modes, so we are not taken off-guard if
a firmware decides to enforce them.

[1] 
https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-precision-touchpad-required-hid-top-level-collections

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-multitouch.c | 34 +-
 include/linux/hid.h  |  3 +++
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 8878de9eedba..82c98bf14d60 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -81,6 +81,11 @@ MODULE_LICENSE("GPL");
 
 #define MT_BUTTONTYPE_CLICKPAD 0
 
+enum latency_mode {
+   HID_LATENCY_NORMAL = 0,
+   HID_LATENCY_HIGH = 1,
+};
+
 #define MT_IO_FLAGS_RUNNING0
 #define MT_IO_FLAGS_ACTIVE_SLOTS   1
 #define MT_IO_FLAGS_PENDING_SLOTS  2
@@ -1156,7 +1161,10 @@ static void mt_report(struct hid_device *hid, struct 
hid_report *report)
 
 static bool mt_need_to_apply_feature(struct hid_device *hdev,
 struct hid_field *field,
-struct hid_usage *usage)
+struct hid_usage *usage,
+enum latency_mode latency,
+bool surface_switch,
+bool button_switch)
 {
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = >mtclass;
@@ -1195,12 +1203,25 @@ static bool mt_need_to_apply_feature(struct hid_device 
*hdev,
}
}
break;
+
+   case HID_DG_LATENCYMODE:
+   field->value[index] = latency;
+   return 1;
+
+   case HID_DG_SURFACESWITCH:
+   field->value[index] = surface_switch;
+   return 1;
+
+   case HID_DG_BUTTONSWITCH:
+   field->value[index] = button_switch;
+   return 1;
}
 
return false; /* no need to update the report */
 }
 
-static void mt_set_modes(struct hid_device *hdev)
+static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
+bool surface_switch, bool button_switch)
 {
struct hid_report_enum *rep_enum;
struct hid_report *rep;
@@ -1222,7 +1243,10 @@ static void mt_set_modes(struct hid_device *hdev)
 
if (mt_need_to_apply_feature(hdev,
 rep->field[i],
-usage))
+usage,
+latency,
+surface_switch,
+button_switch))
update_report = true;
}
}
@@ -1467,7 +1491,7 @@ static int mt_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
dev_warn(>dev, "Cannot allocate sysfs group for %s\n",
hdev->name);
 
-   mt_set_modes(hdev);
+   mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
 
/* release .fields memory as it is not used anymore */
devm_kfree(>dev, td->fields);
@@ -1480,7 +1504,7 @@ static int mt_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 static int mt_reset_resume(struct hid_device *hdev)
 {
mt_release_contacts(hdev);
-   mt_set_modes(hdev);
+   mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
return 0;
 }
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d3bd83d9127f..d65ce4ab82d6 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -292,9 +292,12 @@ struct hid_item {
 #define HID_DG_CONTACTCOUNT0x000d0054
 #define HID_DG_CONTACTMAX  0x000d0055
 #define HID_DG_SCANTIME0x000d0056
+#define HID_DG_SURFACESWITCH   0x000d0057
+#define HID_DG_BUTTONSWITCH0x000d0058
 #define HID_DG_BUTTONTYPE  0x000d0059
 #define HID_DG_BARRELSWITCH2   0x000d005a
 #define HID_DG_TOOLSERIALNUMBER0x000d005b
+#define HID_DG_LATENCYMODE 0x000d0060
 
 #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS  0xff310076
 /*
-- 
2.14.3



[PATCH v2 0/6] HID: input cleanups and mt additions

2018-04-24 Thread Benjamin Tissoires
Hi Jiri,

following the thread about the 'not incrementing ABS_MISC', here is the
actual submission of the series.

Compared to the 2 patches I sent last week, there are a few more:
- patch 1 needed to be added or some (all?) Advanced Silicon touchscreen
  would fail the tests with HID_QUIRK_INPUT_PER_APPLICATION
- patch 3 is extracted from v1-2/2, as it has grown significantly, still
  because of the same issue with Advanced Silicon panels
- patch 4 is something I had in mind while debugging some other
  not-so-talkative touchpads, because of patch 5
- patch 5 should put us at the same level than the Windows driver now.
  Note that we could unset the features (button/surface reporting, and
  latency during suspend, but not sure it helps that much. We should probably
  test the current consumption with and without)

The series has been tested against regressions thanks to my new hid test suite
https://github.com/bentiss/hid-tools (I rewrote hid-replay in python and hook
up python tests). I also used the loaner from Dell (thanks Mario!), and XPS
9360 that has both touchscreen and touchpad, and on which the touchpad has the
new features I implemented here.

Cheers,
Benjamin


Benjamin Tissoires (6):
  HID: store the full list of reports in the hidinput
  HID: generic: create one input report per application type
  HID: input: append a suffix matching the application
  HID: multitouch: make use of HID_QUIRK_INPUT_PER_APP
  HID: multitouch: simplify the settings of the various features
  HID: multitouch: implement precision touchpad latency and switches

 drivers/hid/hid-core.c   |  19 ++--
 drivers/hid/hid-generic.c|  15 +++
 drivers/hid/hid-gfrm.c   |   2 +-
 drivers/hid/hid-input.c  |  90 +++--
 drivers/hid/hid-magicmouse.c |   6 +-
 drivers/hid/hid-multitouch.c | 227 ++-
 include/linux/hid.h  |  16 ++-
 7 files changed, 244 insertions(+), 131 deletions(-)

-- 
2.14.3



[PATCH v2 1/6] HID: store the full list of reports in the hidinput

2018-04-24 Thread Benjamin Tissoires
We were only storing the report in case of QUIRK_MULTI_INPUT.
It is interesting for the upcoming  HID_QUIRK_INPUT_PER_APP to also
store the full list of reports that are attached to it.

We need the full list because a device (Advanced Silicon has some)
might want to use a different report ID for the Input reports and
the Output reports. Storing the full list allows the drivers to
have all the data.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-input.c | 6 ++
 include/linux/hid.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index a8a33e56b43e..62e42664955e 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1536,9 +1536,12 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
input_dev->dev.parent = >dev;
+
hidinput->input = input_dev;
list_add_tail(>list, >inputs);
 
+   INIT_LIST_HEAD(>reports);
+
return hidinput;
 }
 
@@ -1688,6 +1691,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
 
if (hid->quirks & HID_QUIRK_MULTI_INPUT)
hidinput->report = report;
+
+   list_add_tail(>hidinput_list,
+ >reports);
}
}
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 0a8d5c320b6c..e1ec7f91f926 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -464,6 +464,7 @@ struct hid_field {
 
 struct hid_report {
struct list_head list;
+   struct list_head hidinput_list;
unsigned id;/* id of this report */
unsigned type;  /* report type */
struct hid_field *field[HID_MAX_FIELDS];/* fields of the report 
*/
@@ -510,6 +511,7 @@ struct hid_input {
struct hid_report *report;
struct input_dev *input;
bool registered;
+   struct list_head reports;   /* the list of reports */
 };
 
 enum hid_type {
-- 
2.14.3



[PATCH v2 0/6] HID: input cleanups and mt additions

2018-04-24 Thread Benjamin Tissoires
Hi Jiri,

following the thread about the 'not incrementing ABS_MISC', here is the
actual submission of the series.

Compared to the 2 patches I sent last week, there are a few more:
- patch 1 needed to be added or some (all?) Advanced Silicon touchscreen
  would fail the tests with HID_QUIRK_INPUT_PER_APPLICATION
- patch 3 is extracted from v1-2/2, as it has grown significantly, still
  because of the same issue with Advanced Silicon panels
- patch 4 is something I had in mind while debugging some other
  not-so-talkative touchpads, because of patch 5
- patch 5 should put us at the same level than the Windows driver now.
  Note that we could unset the features (button/surface reporting, and
  latency during suspend, but not sure it helps that much. We should probably
  test the current consumption with and without)

The series has been tested against regressions thanks to my new hid test suite
https://github.com/bentiss/hid-tools (I rewrote hid-replay in python and hook
up python tests). I also used the loaner from Dell (thanks Mario!), and XPS
9360 that has both touchscreen and touchpad, and on which the touchpad has the
new features I implemented here.

Cheers,
Benjamin


Benjamin Tissoires (6):
  HID: store the full list of reports in the hidinput
  HID: generic: create one input report per application type
  HID: input: append a suffix matching the application
  HID: multitouch: make use of HID_QUIRK_INPUT_PER_APP
  HID: multitouch: simplify the settings of the various features
  HID: multitouch: implement precision touchpad latency and switches

 drivers/hid/hid-core.c   |  19 ++--
 drivers/hid/hid-generic.c|  15 +++
 drivers/hid/hid-gfrm.c   |   2 +-
 drivers/hid/hid-input.c  |  90 +++--
 drivers/hid/hid-magicmouse.c |   6 +-
 drivers/hid/hid-multitouch.c | 227 ++-
 include/linux/hid.h  |  16 ++-
 7 files changed, 244 insertions(+), 131 deletions(-)

-- 
2.14.3



[PATCH v2 1/6] HID: store the full list of reports in the hidinput

2018-04-24 Thread Benjamin Tissoires
We were only storing the report in case of QUIRK_MULTI_INPUT.
It is interesting for the upcoming  HID_QUIRK_INPUT_PER_APP to also
store the full list of reports that are attached to it.

We need the full list because a device (Advanced Silicon has some)
might want to use a different report ID for the Input reports and
the Output reports. Storing the full list allows the drivers to
have all the data.

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-input.c | 6 ++
 include/linux/hid.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index a8a33e56b43e..62e42664955e 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1536,9 +1536,12 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
input_dev->dev.parent = >dev;
+
hidinput->input = input_dev;
list_add_tail(>list, >inputs);
 
+   INIT_LIST_HEAD(>reports);
+
return hidinput;
 }
 
@@ -1688,6 +1691,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
 
if (hid->quirks & HID_QUIRK_MULTI_INPUT)
hidinput->report = report;
+
+   list_add_tail(>hidinput_list,
+ >reports);
}
}
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 0a8d5c320b6c..e1ec7f91f926 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -464,6 +464,7 @@ struct hid_field {
 
 struct hid_report {
struct list_head list;
+   struct list_head hidinput_list;
unsigned id;/* id of this report */
unsigned type;  /* report type */
struct hid_field *field[HID_MAX_FIELDS];/* fields of the report 
*/
@@ -510,6 +511,7 @@ struct hid_input {
struct hid_report *report;
struct input_dev *input;
bool registered;
+   struct list_head reports;   /* the list of reports */
 };
 
 enum hid_type {
-- 
2.14.3



Re: [PATCH v2 2/2] HID: input: do not increment usages when a duplicate is found

2018-04-17 Thread Benjamin Tissoires
FYI, these are the two patches I mentioned earlier.

checkpatch.pl still complains about them so do not merge them right away, but
this should give you a better idea.
Also, this is the tip of my local tree, so there is a high chance it doesn't
apply cleanly on your for-next branch.

Cheers,
Benjamin

Benjamin Tissoires (2):
  HID: generic: create one input report per application type
  HID: input: append a suffix matching the application

 drivers/hid/hid-core.c   | 10 --
 drivers/hid/hid-generic.c| 15 
 drivers/hid/hid-gfrm.c   |  2 +-
 drivers/hid/hid-input.c  | 84 +++-
 drivers/hid/hid-magicmouse.c |  6 ++--
 drivers/hid/hid-multitouch.c | 34 ++
 include/linux/hid.h  |  6 +++-
 7 files changed, 117 insertions(+), 40 deletions(-)

-- 
2.14.3



Re: [PATCH v2 2/2] HID: input: do not increment usages when a duplicate is found

2018-04-17 Thread Benjamin Tissoires
FYI, these are the two patches I mentioned earlier.

checkpatch.pl still complains about them so do not merge them right away, but
this should give you a better idea.
Also, this is the tip of my local tree, so there is a high chance it doesn't
apply cleanly on your for-next branch.

Cheers,
Benjamin

Benjamin Tissoires (2):
  HID: generic: create one input report per application type
  HID: input: append a suffix matching the application

 drivers/hid/hid-core.c   | 10 --
 drivers/hid/hid-generic.c| 15 
 drivers/hid/hid-gfrm.c   |  2 +-
 drivers/hid/hid-input.c  | 84 +++-
 drivers/hid/hid-magicmouse.c |  6 ++--
 drivers/hid/hid-multitouch.c | 34 ++
 include/linux/hid.h  |  6 +++-
 7 files changed, 117 insertions(+), 40 deletions(-)

-- 
2.14.3



[PATCH 2/2] HID: input: append a suffix matching the application

2018-04-17 Thread Benjamin Tissoires
Given that we create one input node per application, we should name
the input node accordingly to not lose userspace.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-input.c  | 64 ++--
 drivers/hid/hid-multitouch.c | 30 +++--
 include/linux/hid.h  |  1 +
 3 files changed, 66 insertions(+), 29 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 0803d5adefa7..886d81df50d4 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1500,15 +1500,56 @@ static void report_features(struct hid_device *hid)
}
 }
 
-static struct hid_input *hidinput_allocate(struct hid_device *hid)
+static struct hid_input *hidinput_allocate(struct hid_device *hid,
+  unsigned application)
 {
struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
struct input_dev *input_dev = input_allocate_device();
-   if (!hidinput || !input_dev) {
-   kfree(hidinput);
-   input_free_device(input_dev);
-   hid_err(hid, "Out of memory during hid input probe\n");
-   return NULL;
+   const char *suffix = NULL;
+
+   if (!hidinput || !input_dev)
+   goto fail;
+
+   if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) &&
+   hid->maxapplication > 1) {
+   switch (application) {
+   case HID_GD_KEYBOARD:
+   suffix = "Keyboard";
+   break;
+   case HID_GD_KEYPAD:
+   suffix = "Keypad";
+   break;
+   case HID_GD_MOUSE:
+   suffix = "Mouse";
+   break;
+   case HID_DG_STYLUS:
+   suffix = "Pen";
+   break;
+   case HID_DG_TOUCHSCREEN:
+   suffix = "Touchscreen";
+   break;
+   case HID_DG_TOUCHPAD:
+   suffix = "Touchpad";
+   break;
+   case HID_GD_SYSTEM_CONTROL:
+   suffix = "System Control";
+   break;
+   case HID_CP_CONSUMER_CONTROL:
+   suffix = "Consumer Control";
+   break;
+   case HID_GD_WIRELESS_RADIO_CTLS:
+   suffix = "Wireless Radio Control";
+   break;
+   default:
+   break;
+   }
+   }
+
+   if (suffix) {
+   hidinput->name = kasprintf(GFP_KERNEL, "%s %s",
+  hid->name, suffix);
+   if (!hidinput->name)
+   goto fail;
}
 
input_set_drvdata(input_dev, hid);
@@ -1518,7 +1559,7 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
input_dev->setkeycode = hidinput_setkeycode;
input_dev->getkeycode = hidinput_getkeycode;
 
-   input_dev->name = hid->name;
+   input_dev->name = hidinput->name ? hidinput->name : hid->name;
input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq;
input_dev->id.bustype = hid->bus;
@@ -1530,6 +1571,12 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
list_add_tail(>list, >inputs);
 
return hidinput;
+
+fail:
+   kfree(hidinput);
+   input_free_device(input_dev);
+   hid_err(hid, "Out of memory during hid input probe\n");
+   return NULL;
 }
 
 static bool hidinput_has_been_populated(struct hid_input *hidinput)
@@ -1575,6 +1622,7 @@ static void hidinput_cleanup_hidinput(struct hid_device 
*hid,
 
list_del(>list);
input_free_device(hidinput->input);
+   kfree(hidinput->name);
 
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
if (k == HID_OUTPUT_REPORT &&
@@ -1686,7 +1734,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
hidinput = hidinput_match_application(report);
 
if (!hidinput) {
-   hidinput = hidinput_allocate(hid);
+   hidinput = hidinput_allocate(hid, 
report->application);
if (!hidinput)
goto out_unwind;
}
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 2a0caf2e24ce..cfbaedc55e02 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1294,33 +1294,21 @@ static int mt_input_configured(struct hid_device 

[PATCH 2/2] HID: input: append a suffix matching the application

2018-04-17 Thread Benjamin Tissoires
Given that we create one input node per application, we should name
the input node accordingly to not lose userspace.

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-input.c  | 64 ++--
 drivers/hid/hid-multitouch.c | 30 +++--
 include/linux/hid.h  |  1 +
 3 files changed, 66 insertions(+), 29 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 0803d5adefa7..886d81df50d4 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1500,15 +1500,56 @@ static void report_features(struct hid_device *hid)
}
 }
 
-static struct hid_input *hidinput_allocate(struct hid_device *hid)
+static struct hid_input *hidinput_allocate(struct hid_device *hid,
+  unsigned application)
 {
struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
struct input_dev *input_dev = input_allocate_device();
-   if (!hidinput || !input_dev) {
-   kfree(hidinput);
-   input_free_device(input_dev);
-   hid_err(hid, "Out of memory during hid input probe\n");
-   return NULL;
+   const char *suffix = NULL;
+
+   if (!hidinput || !input_dev)
+   goto fail;
+
+   if ((hid->quirks & HID_QUIRK_INPUT_PER_APP) &&
+   hid->maxapplication > 1) {
+   switch (application) {
+   case HID_GD_KEYBOARD:
+   suffix = "Keyboard";
+   break;
+   case HID_GD_KEYPAD:
+   suffix = "Keypad";
+   break;
+   case HID_GD_MOUSE:
+   suffix = "Mouse";
+   break;
+   case HID_DG_STYLUS:
+   suffix = "Pen";
+   break;
+   case HID_DG_TOUCHSCREEN:
+   suffix = "Touchscreen";
+   break;
+   case HID_DG_TOUCHPAD:
+   suffix = "Touchpad";
+   break;
+   case HID_GD_SYSTEM_CONTROL:
+   suffix = "System Control";
+   break;
+   case HID_CP_CONSUMER_CONTROL:
+   suffix = "Consumer Control";
+   break;
+   case HID_GD_WIRELESS_RADIO_CTLS:
+   suffix = "Wireless Radio Control";
+   break;
+   default:
+   break;
+   }
+   }
+
+   if (suffix) {
+   hidinput->name = kasprintf(GFP_KERNEL, "%s %s",
+  hid->name, suffix);
+   if (!hidinput->name)
+   goto fail;
}
 
input_set_drvdata(input_dev, hid);
@@ -1518,7 +1559,7 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
input_dev->setkeycode = hidinput_setkeycode;
input_dev->getkeycode = hidinput_getkeycode;
 
-   input_dev->name = hid->name;
+   input_dev->name = hidinput->name ? hidinput->name : hid->name;
input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq;
input_dev->id.bustype = hid->bus;
@@ -1530,6 +1571,12 @@ static struct hid_input *hidinput_allocate(struct 
hid_device *hid)
list_add_tail(>list, >inputs);
 
return hidinput;
+
+fail:
+   kfree(hidinput);
+   input_free_device(input_dev);
+   hid_err(hid, "Out of memory during hid input probe\n");
+   return NULL;
 }
 
 static bool hidinput_has_been_populated(struct hid_input *hidinput)
@@ -1575,6 +1622,7 @@ static void hidinput_cleanup_hidinput(struct hid_device 
*hid,
 
list_del(>list);
input_free_device(hidinput->input);
+   kfree(hidinput->name);
 
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
if (k == HID_OUTPUT_REPORT &&
@@ -1686,7 +1734,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int 
force)
hidinput = hidinput_match_application(report);
 
if (!hidinput) {
-   hidinput = hidinput_allocate(hid);
+   hidinput = hidinput_allocate(hid, 
report->application);
if (!hidinput)
goto out_unwind;
}
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 2a0caf2e24ce..cfbaedc55e02 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1294,33 +1294,21 @@ static int mt_input_configured(struct hid_device *hdev, 
struct hid_i

[PATCH 1/2] HID: generic: create one input report per application type

2018-04-17 Thread Benjamin Tissoires
It is not a good idea to try to fit all types of applications in the
same input report. There are a lot of devices that are needing
the quirk HID_MULTI_INPUT but this quirk doesn't match the actual HID
description as it is based on the report ID.

Given that most devices with MULTI_INPUT I can think of split nicely
the devices inputs into application, it is a good thing to split the
devices by default based on this assumption.

Also make hid-multitouch following this rule, to not have to deal
with too many input created

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/hid/hid-core.c   | 10 +++---
 drivers/hid/hid-generic.c| 15 +++
 drivers/hid/hid-gfrm.c   |  2 +-
 drivers/hid/hid-input.c  | 20 +++-
 drivers/hid/hid-magicmouse.c |  6 +++---
 drivers/hid/hid-multitouch.c |  4 ++--
 include/linux/hid.h  |  5 -
 7 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5d7cc6bbbac6..ac4799abcc4d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -57,7 +57,8 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special 
drivers and handle
  * Register a new report for a device.
  */
 
-struct hid_report *hid_register_report(struct hid_device *device, unsigned 
type, unsigned id)
+struct hid_report *hid_register_report(struct hid_device *device, unsigned 
type,
+  unsigned id, unsigned application)
 {
struct hid_report_enum *report_enum = device->report_enum + type;
struct hid_report *report;
@@ -78,6 +79,7 @@ struct hid_report *hid_register_report(struct hid_device 
*device, unsigned type,
report->type = type;
report->size = 0;
report->device = device;
+   report->application = application;
report_enum->report_id_hash[id] = report;
 
list_add_tail(>list, _enum->report_list);
@@ -224,8 +226,10 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
unsigned usages;
unsigned offset;
unsigned i;
+   unsigned application = hid_lookup_collection(parser, 
HID_COLLECTION_APPLICATION);
 
-   report = hid_register_report(parser->device, report_type, 
parser->global.report_id);
+   report = hid_register_report(parser->device, report_type,
+parser->global.report_id, application);
if (!report) {
hid_err(parser->device, "hid_register_report failed\n");
return -1;
@@ -259,7 +263,7 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
 
field->physical = hid_lookup_collection(parser, 
HID_COLLECTION_PHYSICAL);
field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
-   field->application = hid_lookup_collection(parser, 
HID_COLLECTION_APPLICATION);
+   field->application = application;
 
for (i = 0; i < usages; i++) {
unsigned j = i;
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c
index c25b4718de44..3b6eccbc2519 100644
--- a/drivers/hid/hid-generic.c
+++ b/drivers/hid/hid-generic.c
@@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev,
return true;
 }
 
+static int hid_generic_probe(struct hid_device *hdev,
+const struct hid_device_id *id)
+{
+   int ret;
+
+   hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
+   ret = hid_parse(hdev);
+   if (ret)
+   return ret;
+
+   return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
 static const struct hid_device_id hid_table[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
{ }
@@ -66,6 +80,7 @@ static struct hid_driver hid_generic = {
.name = "hid-generic",
.id_table = hid_table,
.match = hid_generic_match,
+   .probe = hid_generic_probe,
 };
 module_hid_driver(hid_generic);
 
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
index 075b1c020846..cf477f8c8f4c 100644
--- a/drivers/hid/hid-gfrm.c
+++ b/drivers/hid/hid-gfrm.c
@@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 * those reports reach gfrm_raw_event() from hid_input_report().
 */
if (!hid_register_report(hdev, HID_INPUT_REPORT,
-GFRM100_SEARCH_KEY_REPORT_ID)) {
+GFRM100_SEARCH_KEY_REPORT_ID, 0)) {
ret = -ENOMEM;
goto done;
}
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 04056773102e..0803d5adefa7 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1607,6 +1607,20 @@ static struct hid_in

[PATCH 1/2] HID: generic: create one input report per application type

2018-04-17 Thread Benjamin Tissoires
It is not a good idea to try to fit all types of applications in the
same input report. There are a lot of devices that are needing
the quirk HID_MULTI_INPUT but this quirk doesn't match the actual HID
description as it is based on the report ID.

Given that most devices with MULTI_INPUT I can think of split nicely
the devices inputs into application, it is a good thing to split the
devices by default based on this assumption.

Also make hid-multitouch following this rule, to not have to deal
with too many input created

Signed-off-by: Benjamin Tissoires 
---
 drivers/hid/hid-core.c   | 10 +++---
 drivers/hid/hid-generic.c| 15 +++
 drivers/hid/hid-gfrm.c   |  2 +-
 drivers/hid/hid-input.c  | 20 +++-
 drivers/hid/hid-magicmouse.c |  6 +++---
 drivers/hid/hid-multitouch.c |  4 ++--
 include/linux/hid.h  |  5 -
 7 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5d7cc6bbbac6..ac4799abcc4d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -57,7 +57,8 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special 
drivers and handle
  * Register a new report for a device.
  */
 
-struct hid_report *hid_register_report(struct hid_device *device, unsigned 
type, unsigned id)
+struct hid_report *hid_register_report(struct hid_device *device, unsigned 
type,
+  unsigned id, unsigned application)
 {
struct hid_report_enum *report_enum = device->report_enum + type;
struct hid_report *report;
@@ -78,6 +79,7 @@ struct hid_report *hid_register_report(struct hid_device 
*device, unsigned type,
report->type = type;
report->size = 0;
report->device = device;
+   report->application = application;
report_enum->report_id_hash[id] = report;
 
list_add_tail(>list, _enum->report_list);
@@ -224,8 +226,10 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
unsigned usages;
unsigned offset;
unsigned i;
+   unsigned application = hid_lookup_collection(parser, 
HID_COLLECTION_APPLICATION);
 
-   report = hid_register_report(parser->device, report_type, 
parser->global.report_id);
+   report = hid_register_report(parser->device, report_type,
+parser->global.report_id, application);
if (!report) {
hid_err(parser->device, "hid_register_report failed\n");
return -1;
@@ -259,7 +263,7 @@ static int hid_add_field(struct hid_parser *parser, 
unsigned report_type, unsign
 
field->physical = hid_lookup_collection(parser, 
HID_COLLECTION_PHYSICAL);
field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
-   field->application = hid_lookup_collection(parser, 
HID_COLLECTION_APPLICATION);
+   field->application = application;
 
for (i = 0; i < usages; i++) {
unsigned j = i;
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c
index c25b4718de44..3b6eccbc2519 100644
--- a/drivers/hid/hid-generic.c
+++ b/drivers/hid/hid-generic.c
@@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev,
return true;
 }
 
+static int hid_generic_probe(struct hid_device *hdev,
+const struct hid_device_id *id)
+{
+   int ret;
+
+   hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
+   ret = hid_parse(hdev);
+   if (ret)
+   return ret;
+
+   return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
 static const struct hid_device_id hid_table[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
{ }
@@ -66,6 +80,7 @@ static struct hid_driver hid_generic = {
.name = "hid-generic",
.id_table = hid_table,
.match = hid_generic_match,
+   .probe = hid_generic_probe,
 };
 module_hid_driver(hid_generic);
 
diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
index 075b1c020846..cf477f8c8f4c 100644
--- a/drivers/hid/hid-gfrm.c
+++ b/drivers/hid/hid-gfrm.c
@@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 * those reports reach gfrm_raw_event() from hid_input_report().
 */
if (!hid_register_report(hdev, HID_INPUT_REPORT,
-GFRM100_SEARCH_KEY_REPORT_ID)) {
+GFRM100_SEARCH_KEY_REPORT_ID, 0)) {
ret = -ENOMEM;
goto done;
}
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 04056773102e..0803d5adefa7 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1607,6 +1607,20 @@ static struct hid_input *hidinput_ma

Re: [PATCH v2 2/2] HID: input: do not increment usages when a duplicate is found

2018-04-17 Thread Benjamin Tissoires
On Tue, Apr 17, 2018 at 2:11 PM, Jiri Kosina  wrote:
> On Mon, 16 Apr 2018, Dmitry Torokhov wrote:
>
>> So what is happening with this series? I think we should get it them
>> in; there is really no reason for bumping ABS_MISC till it gets into
>> ABS_MT_* range on some devices that are out there.
>>
>> FWIW
>>
>> Acked-by: Dmitry Torokhov 
>
> Sorry, I somehow lost this one. Now queued for 4.18.

Thanks Jiri, and thanks Dmitry for the reminder.

Jiri, BTW, I have 2 patch locally that should mitigate the negative
impact from this patch if there is any,

While trying to merging hid-multitouch into hid-core, I came to
realize that hid-generic should probably split the HID collections by
applications. If a device has a joystick and a mouse collection, there
is no point merging these two collections together. This is the most
common use case for reusing the same ABS_X value in one device.

I'll try to post the patches today, though I have some internal deadline :(

Cheers,
Benjamin


Re: [PATCH v2 2/2] HID: input: do not increment usages when a duplicate is found

2018-04-17 Thread Benjamin Tissoires
On Tue, Apr 17, 2018 at 2:11 PM, Jiri Kosina  wrote:
> On Mon, 16 Apr 2018, Dmitry Torokhov wrote:
>
>> So what is happening with this series? I think we should get it them
>> in; there is really no reason for bumping ABS_MISC till it gets into
>> ABS_MT_* range on some devices that are out there.
>>
>> FWIW
>>
>> Acked-by: Dmitry Torokhov 
>
> Sorry, I somehow lost this one. Now queued for 4.18.

Thanks Jiri, and thanks Dmitry for the reminder.

Jiri, BTW, I have 2 patch locally that should mitigate the negative
impact from this patch if there is any,

While trying to merging hid-multitouch into hid-core, I came to
realize that hid-generic should probably split the HID collections by
applications. If a device has a joystick and a mouse collection, there
is no point merging these two collections together. This is the most
common use case for reusing the same ABS_X value in one device.

I'll try to post the patches today, though I have some internal deadline :(

Cheers,
Benjamin


Re: [PATCH v6] Fix modifier keys for Redragon Asura Keyboard

2018-04-17 Thread Benjamin Tissoires
On Mon, Apr 16, 2018 at 11:38 PM, Robert Munteanu <romb...@apache.org> wrote:
> This adds a new driver for the Redragon Asura keyboard. The Asura
> keyboard contains an error in the HID descriptor which causes all
> modifier keys to be mapped to left shift. Additionally, we suppress
> the creation of a second, not working, keyboard device.
>
> Signed-off-by: Robert Munteanu <romb...@apache.org>
> ---

Looks good to me now:
Reviewed-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

Thanks Robert for respinning the series!

Cheers,
Benjamin

>  drivers/hid/Kconfig|  7 
>  drivers/hid/Makefile   |  1 +
>  drivers/hid/hid-ids.h  |  1 +
>  drivers/hid/hid-redragon.c | 86 
> ++
>  4 files changed, 95 insertions(+)
>  create mode 100644 drivers/hid/hid-redragon.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 19c499f5623d..1125e4813716 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -560,6 +560,13 @@ config HID_MAYFLASH
> Say Y here if you have HJZ Mayflash PS3 game controller adapters
> and want to enable force feedback support.
>
> +config HID_REDRAGON
> +   tristate "Redragon keyboards"
> +   depends on HID
> +   default !EXPERT
> +   ---help---
> +Support for Redragon keyboards that need fix-ups to work properly.
> +
>  config HID_MICROSOFT
> tristate "Microsoft non-fully HID-compliant devices"
> depends on HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index eb13b9e92d85..a36f3f40ba63 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -84,6 +84,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS)+= 
> hid-picolcd_debugfs.o
>
>  obj-$(CONFIG_HID_PLANTRONICS)  += hid-plantronics.o
>  obj-$(CONFIG_HID_PRIMAX)   += hid-primax.o
> +obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
>  obj-$(CONFIG_HID_RETRODE)  += hid-retrode.o
>  obj-$(CONFIG_HID_ROCCAT)   += hid-roccat.o hid-roccat-common.o \
> hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 9454ac134ce2..41a64d0e91f9 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -599,6 +599,7 @@
>  #define USB_VENDOR_ID_JESS 0x0c45
>  #define USB_DEVICE_ID_JESS_YUREX   0x1010
>  #define USB_DEVICE_ID_ASUS_MD_5112 0x5112
> +#define USB_DEVICE_ID_REDRAGON_ASURA   0x760b
>
>  #define USB_VENDOR_ID_JESS20x0f30
>  #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
> diff --git a/drivers/hid/hid-redragon.c b/drivers/hid/hid-redragon.c
> new file mode 100644
> index ..daf59578bf93
> --- /dev/null
> +++ b/drivers/hid/hid-redragon.c
> @@ -0,0 +1,86 @@
> +/*
> + *  HID driver for Redragon keyboards
> + *
> + *  Copyright (c) 2017 Robert Munteanu
> + *  SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +/*
> + * 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; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +#include "hid-ids.h"
> +
> +
> +/*
> + * The Redragon Asura keyboard sends an incorrect HID descriptor.
> + * At byte 100 it contains
> + *
> + *   0x81, 0x00
> + *
> + * which is Input (Data, Arr, Abs), but it should be
> + *
> + *   0x81, 0x02
> + *
> + * which is Input (Data, Var, Abs), which is consistent with the way
> + * key codes are generated.
> + */
> +
> +static __u8 *redragon_report_fixup(struct hid_device *hdev, __u8 *rdesc,
> +   unsigned int *rsize)
> +{
> +   if (*rsize >= 102 && rdesc[100] == 0x81 && rdesc[101] == 0x00) {
> +   dev_info(>dev, "Fixing Redragon ASURA report 
> descriptor.\n");
> +   rdesc[101] = 0x02;
> +   }
> +
> +   return rdesc;
> +}
> +
> +static int redragon_probe(struct hid_device *dev,
> +   const struct hid_device_id *id)
> +{
> +   int ret;
> +
> +   ret = hid_parse(dev);
> +   if (ret) {
> +   hid_err(dev, "parse failed\n");
> +   return ret;
> +   }
> +
> +   /* do not register unused input device */
> +   if (dev->maxapplication == 1)
> +   return 0;
> +
> +   ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
> +   if (ret) {
> +   hid_err(dev, "hw start failed\n&q

Re: [PATCH v6] Fix modifier keys for Redragon Asura Keyboard

2018-04-17 Thread Benjamin Tissoires
On Mon, Apr 16, 2018 at 11:38 PM, Robert Munteanu  wrote:
> This adds a new driver for the Redragon Asura keyboard. The Asura
> keyboard contains an error in the HID descriptor which causes all
> modifier keys to be mapped to left shift. Additionally, we suppress
> the creation of a second, not working, keyboard device.
>
> Signed-off-by: Robert Munteanu 
> ---

Looks good to me now:
Reviewed-by: Benjamin Tissoires 

Thanks Robert for respinning the series!

Cheers,
Benjamin

>  drivers/hid/Kconfig|  7 
>  drivers/hid/Makefile   |  1 +
>  drivers/hid/hid-ids.h  |  1 +
>  drivers/hid/hid-redragon.c | 86 
> ++
>  4 files changed, 95 insertions(+)
>  create mode 100644 drivers/hid/hid-redragon.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 19c499f5623d..1125e4813716 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -560,6 +560,13 @@ config HID_MAYFLASH
> Say Y here if you have HJZ Mayflash PS3 game controller adapters
> and want to enable force feedback support.
>
> +config HID_REDRAGON
> +   tristate "Redragon keyboards"
> +   depends on HID
> +   default !EXPERT
> +   ---help---
> +Support for Redragon keyboards that need fix-ups to work properly.
> +
>  config HID_MICROSOFT
> tristate "Microsoft non-fully HID-compliant devices"
> depends on HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index eb13b9e92d85..a36f3f40ba63 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -84,6 +84,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS)+= 
> hid-picolcd_debugfs.o
>
>  obj-$(CONFIG_HID_PLANTRONICS)  += hid-plantronics.o
>  obj-$(CONFIG_HID_PRIMAX)   += hid-primax.o
> +obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
>  obj-$(CONFIG_HID_RETRODE)  += hid-retrode.o
>  obj-$(CONFIG_HID_ROCCAT)   += hid-roccat.o hid-roccat-common.o \
> hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 9454ac134ce2..41a64d0e91f9 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -599,6 +599,7 @@
>  #define USB_VENDOR_ID_JESS 0x0c45
>  #define USB_DEVICE_ID_JESS_YUREX   0x1010
>  #define USB_DEVICE_ID_ASUS_MD_5112 0x5112
> +#define USB_DEVICE_ID_REDRAGON_ASURA   0x760b
>
>  #define USB_VENDOR_ID_JESS20x0f30
>  #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
> diff --git a/drivers/hid/hid-redragon.c b/drivers/hid/hid-redragon.c
> new file mode 100644
> index ..daf59578bf93
> --- /dev/null
> +++ b/drivers/hid/hid-redragon.c
> @@ -0,0 +1,86 @@
> +/*
> + *  HID driver for Redragon keyboards
> + *
> + *  Copyright (c) 2017 Robert Munteanu
> + *  SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +/*
> + * 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; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +#include "hid-ids.h"
> +
> +
> +/*
> + * The Redragon Asura keyboard sends an incorrect HID descriptor.
> + * At byte 100 it contains
> + *
> + *   0x81, 0x00
> + *
> + * which is Input (Data, Arr, Abs), but it should be
> + *
> + *   0x81, 0x02
> + *
> + * which is Input (Data, Var, Abs), which is consistent with the way
> + * key codes are generated.
> + */
> +
> +static __u8 *redragon_report_fixup(struct hid_device *hdev, __u8 *rdesc,
> +   unsigned int *rsize)
> +{
> +   if (*rsize >= 102 && rdesc[100] == 0x81 && rdesc[101] == 0x00) {
> +   dev_info(>dev, "Fixing Redragon ASURA report 
> descriptor.\n");
> +   rdesc[101] = 0x02;
> +   }
> +
> +   return rdesc;
> +}
> +
> +static int redragon_probe(struct hid_device *dev,
> +   const struct hid_device_id *id)
> +{
> +   int ret;
> +
> +   ret = hid_parse(dev);
> +   if (ret) {
> +   hid_err(dev, "parse failed\n");
> +   return ret;
> +   }
> +
> +   /* do not register unused input device */
> +   if (dev->maxapplication == 1)
> +   return 0;
> +
> +   ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
> +   if (ret) {
> +   hid_err(dev, "hw start failed\n");
> +   return ret;
> +   }
> +
> +   return 0;
> +}
&

Re: [PATCH v2 0/9] Input: support for latest Lenovo thinkpads (series 80)

2018-04-17 Thread Benjamin Tissoires
Hi KT,

gentle ping :)

Could you ACK/NACK this series?

Dmitry, the first patch could go without KT's approval. Also I
realized that Aaron submitted a similar patch for the X1 Carbon last
October: https://patchwork.kernel.org/patch/10008513/
So I think the first one should go ASAP now that the laptops are
shipping from Lenovo.

Cheers,
Benjamin

On Mon, Apr 9, 2018 at 11:10 AM, Benjamin Tissoires
<benjamin.tissoi...@redhat.com> wrote:
> Hi Dmitry,
>
> Here is the v2 of the Lenovo 80 series.
> Changes from v1:
> - included patch to convert a function to static from build bot
> - use of device property instead of platform data (thus the new device tree
>   binding)
>
> BTW, KT, if you want to add your Signed-off-by on the patches, feel free to
> do so. You were of tremendous help :)
>
> Cheers,
> Benjamin
>
> Benjamin Tissoires (9):
>   Input: synaptics - add Lenovo 80 series ids to SMBus
>   input: elan_i2c_smbus - fix corrupted stack
>   Input: elan_i2c - add trackstick report
>   Input: elantech - split device info into a separate structure
>   Input: elantech_query_info() can be static
>   Input: elantech - query the resolution in query_info
>   Input: elantech - add support for SMBus devices
>   Input: elantech - detect new ICs and setup Host Notify for them
>   input: psmouse-smbus: allow to control psmouse_deactivate
>
>  .../devicetree/bindings/input/elan_i2c.txt |   1 +
>  drivers/input/mouse/Kconfig|  12 +
>  drivers/input/mouse/elan_i2c_core.c|  90 +++-
>  drivers/input/mouse/elan_i2c_smbus.c   |  22 +-
>  drivers/input/mouse/elantech.c | 479 
> +++--
>  drivers/input/mouse/elantech.h |  69 ++-
>  drivers/input/mouse/psmouse-base.c |  21 +-
>  drivers/input/mouse/psmouse-smbus.c|  24 +-
>  drivers/input/mouse/psmouse.h  |   2 +
>  drivers/input/mouse/synaptics.c|   5 +-
>  10 files changed, 565 insertions(+), 160 deletions(-)
>
> --
> 2.14.3
>


Re: [PATCH v2 0/9] Input: support for latest Lenovo thinkpads (series 80)

2018-04-17 Thread Benjamin Tissoires
Hi KT,

gentle ping :)

Could you ACK/NACK this series?

Dmitry, the first patch could go without KT's approval. Also I
realized that Aaron submitted a similar patch for the X1 Carbon last
October: https://patchwork.kernel.org/patch/10008513/
So I think the first one should go ASAP now that the laptops are
shipping from Lenovo.

Cheers,
Benjamin

On Mon, Apr 9, 2018 at 11:10 AM, Benjamin Tissoires
 wrote:
> Hi Dmitry,
>
> Here is the v2 of the Lenovo 80 series.
> Changes from v1:
> - included patch to convert a function to static from build bot
> - use of device property instead of platform data (thus the new device tree
>   binding)
>
> BTW, KT, if you want to add your Signed-off-by on the patches, feel free to
> do so. You were of tremendous help :)
>
> Cheers,
> Benjamin
>
> Benjamin Tissoires (9):
>   Input: synaptics - add Lenovo 80 series ids to SMBus
>   input: elan_i2c_smbus - fix corrupted stack
>   Input: elan_i2c - add trackstick report
>   Input: elantech - split device info into a separate structure
>   Input: elantech_query_info() can be static
>   Input: elantech - query the resolution in query_info
>   Input: elantech - add support for SMBus devices
>   Input: elantech - detect new ICs and setup Host Notify for them
>   input: psmouse-smbus: allow to control psmouse_deactivate
>
>  .../devicetree/bindings/input/elan_i2c.txt |   1 +
>  drivers/input/mouse/Kconfig|  12 +
>  drivers/input/mouse/elan_i2c_core.c|  90 +++-
>  drivers/input/mouse/elan_i2c_smbus.c   |  22 +-
>  drivers/input/mouse/elantech.c | 479 
> +++--
>  drivers/input/mouse/elantech.h |  69 ++-
>  drivers/input/mouse/psmouse-base.c |  21 +-
>  drivers/input/mouse/psmouse-smbus.c|  24 +-
>  drivers/input/mouse/psmouse.h  |   2 +
>  drivers/input/mouse/synaptics.c|   5 +-
>  10 files changed, 565 insertions(+), 160 deletions(-)
>
> --
> 2.14.3
>


Re: [PATCH v5] Fix modifier keys for Redragon Asura Keyboard

2018-04-16 Thread Benjamin Tissoires
On Mon, Apr 16, 2018 at 12:14 PM, Robert Munteanu <romb...@apache.org> wrote:
> Hi Benjamin and Jiri,
>
> On Mon, 2018-04-16 at 12:02 +0200, Benjamin Tissoires wrote:
>> Hi Robert,
>>
>> On Wed, Apr 11, 2018 at 11:49 AM, Robert Munteanu <romb...@apache.org
>> > wrote:
>> > Changelog:
>> >
>> > - v2: modifier keys work, some combinations are still troublesome
>> > - v3: style cleanup, rebase on top of 4.14
>> > - v4: remove most debugging calls, make init info useful for user,
>> >   rebased on top of 4.15
>> > - v5: fix the HID descriptor as suggested by Benjamin Tissoires,
>> >   use existing USB vendor id, update comment style, add SPDX
>> >   license identifier, rename to hid-redragon, stop registering
>> >   two input devices, rebased on top of 4.16
>>
>> As Jiri said, please provide a correct commit message.
>
> Will do.
>
>>
>> I have a few nitpicks in the driver, v6 should be fine:
>>
>> >
>> > Signed-off-by: Robert Munteanu <romb...@apache.org>
>> > ---
>> >  drivers/hid/Kconfig|  7 
>> >  drivers/hid/Makefile   |  1 +
>> >  drivers/hid/hid-ids.h  |  1 +
>> >  drivers/hid/hid-quirks.c   |  3 ++
>> >  drivers/hid/hid-redragon.c | 89
>> > ++
>> >  5 files changed, 101 insertions(+)
>> >  create mode 100644 drivers/hid/hid-redragon.c
>> >
>> > diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
>> > index 19c499f5623d..1125e4813716 100644
>> > --- a/drivers/hid/Kconfig
>> > +++ b/drivers/hid/Kconfig
>> > @@ -560,6 +560,13 @@ config HID_MAYFLASH
>> > Say Y here if you have HJZ Mayflash PS3 game controller
>> > adapters
>> > and want to enable force feedback support.
>> >
>> > +config HID_REDRAGON
>> > +   tristate "Redragon keyboards"
>> > +   depends on HID
>> > +   default !EXPERT
>> > +   ---help---
>> > +Support for Redragon keyboards that need fix-ups to work
>> > properly.
>> > +
>> >  config HID_MICROSOFT
>> > tristate "Microsoft non-fully HID-compliant devices"
>> > depends on HID
>> > diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
>> > index eb13b9e92d85..a36f3f40ba63 100644
>> > --- a/drivers/hid/Makefile
>> > +++ b/drivers/hid/Makefile
>> > @@ -84,6 +84,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS)+=
>> > hid-picolcd_debugfs.o
>> >
>> >  obj-$(CONFIG_HID_PLANTRONICS)  += hid-plantronics.o
>> >  obj-$(CONFIG_HID_PRIMAX)   += hid-primax.o
>> > +obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
>> >  obj-$(CONFIG_HID_RETRODE)  += hid-retrode.o
>> >  obj-$(CONFIG_HID_ROCCAT)   += hid-roccat.o hid-roccat-common.o
>> > \
>> > hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
>> > diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
>> > index 9454ac134ce2..41a64d0e91f9 100644
>> > --- a/drivers/hid/hid-ids.h
>> > +++ b/drivers/hid/hid-ids.h
>> > @@ -599,6 +599,7 @@
>> >  #define USB_VENDOR_ID_JESS 0x0c45
>> >  #define USB_DEVICE_ID_JESS_YUREX   0x1010
>> >  #define USB_DEVICE_ID_ASUS_MD_5112 0x5112
>> > +#define USB_DEVICE_ID_REDRAGON_ASURA   0x760b
>> >
>> >  #define USB_VENDOR_ID_JESS20x0f30
>> >  #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
>> > diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
>> > index e92b77fa574a..5f1253f1739a 100644
>> > --- a/drivers/hid/hid-quirks.c
>> > +++ b/drivers/hid/hid-quirks.c
>> > @@ -557,6 +557,9 @@ static const struct hid_device_id
>> > hid_have_special_driver[] = {
>> >  #if IS_ENABLED(CONFIG_HID_PRODIKEYS)
>> > { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS,
>> > USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
>> >  #endif
>> > +#if IS_ENABLED(CONFIG_HID_REDRAGON)
>> > +   {
>> > HID_USB_DEVICE(USB_VENDOR_ID_JESS,  USB_DEVICE_ID_REDRAGON_ASURA)
>> > },
>> > +#endif
>>
>> Please drop this hunk. v4.16 should work without changing
>> hid_have_special_driver. This way, you will be sure that an initramfs
>> that doesn't include hid-redragon.ko will allo people to type their
>> LUKS password.
>
> I recall testing without this change resulted in the driver not being
&g

Re: [PATCH v5] Fix modifier keys for Redragon Asura Keyboard

2018-04-16 Thread Benjamin Tissoires
On Mon, Apr 16, 2018 at 12:14 PM, Robert Munteanu  wrote:
> Hi Benjamin and Jiri,
>
> On Mon, 2018-04-16 at 12:02 +0200, Benjamin Tissoires wrote:
>> Hi Robert,
>>
>> On Wed, Apr 11, 2018 at 11:49 AM, Robert Munteanu > > wrote:
>> > Changelog:
>> >
>> > - v2: modifier keys work, some combinations are still troublesome
>> > - v3: style cleanup, rebase on top of 4.14
>> > - v4: remove most debugging calls, make init info useful for user,
>> >   rebased on top of 4.15
>> > - v5: fix the HID descriptor as suggested by Benjamin Tissoires,
>> >   use existing USB vendor id, update comment style, add SPDX
>> >   license identifier, rename to hid-redragon, stop registering
>> >   two input devices, rebased on top of 4.16
>>
>> As Jiri said, please provide a correct commit message.
>
> Will do.
>
>>
>> I have a few nitpicks in the driver, v6 should be fine:
>>
>> >
>> > Signed-off-by: Robert Munteanu 
>> > ---
>> >  drivers/hid/Kconfig|  7 
>> >  drivers/hid/Makefile   |  1 +
>> >  drivers/hid/hid-ids.h  |  1 +
>> >  drivers/hid/hid-quirks.c   |  3 ++
>> >  drivers/hid/hid-redragon.c | 89
>> > ++
>> >  5 files changed, 101 insertions(+)
>> >  create mode 100644 drivers/hid/hid-redragon.c
>> >
>> > diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
>> > index 19c499f5623d..1125e4813716 100644
>> > --- a/drivers/hid/Kconfig
>> > +++ b/drivers/hid/Kconfig
>> > @@ -560,6 +560,13 @@ config HID_MAYFLASH
>> > Say Y here if you have HJZ Mayflash PS3 game controller
>> > adapters
>> > and want to enable force feedback support.
>> >
>> > +config HID_REDRAGON
>> > +   tristate "Redragon keyboards"
>> > +   depends on HID
>> > +   default !EXPERT
>> > +   ---help---
>> > +Support for Redragon keyboards that need fix-ups to work
>> > properly.
>> > +
>> >  config HID_MICROSOFT
>> > tristate "Microsoft non-fully HID-compliant devices"
>> > depends on HID
>> > diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
>> > index eb13b9e92d85..a36f3f40ba63 100644
>> > --- a/drivers/hid/Makefile
>> > +++ b/drivers/hid/Makefile
>> > @@ -84,6 +84,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS)+=
>> > hid-picolcd_debugfs.o
>> >
>> >  obj-$(CONFIG_HID_PLANTRONICS)  += hid-plantronics.o
>> >  obj-$(CONFIG_HID_PRIMAX)   += hid-primax.o
>> > +obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
>> >  obj-$(CONFIG_HID_RETRODE)  += hid-retrode.o
>> >  obj-$(CONFIG_HID_ROCCAT)   += hid-roccat.o hid-roccat-common.o
>> > \
>> > hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
>> > diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
>> > index 9454ac134ce2..41a64d0e91f9 100644
>> > --- a/drivers/hid/hid-ids.h
>> > +++ b/drivers/hid/hid-ids.h
>> > @@ -599,6 +599,7 @@
>> >  #define USB_VENDOR_ID_JESS 0x0c45
>> >  #define USB_DEVICE_ID_JESS_YUREX   0x1010
>> >  #define USB_DEVICE_ID_ASUS_MD_5112 0x5112
>> > +#define USB_DEVICE_ID_REDRAGON_ASURA   0x760b
>> >
>> >  #define USB_VENDOR_ID_JESS20x0f30
>> >  #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
>> > diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
>> > index e92b77fa574a..5f1253f1739a 100644
>> > --- a/drivers/hid/hid-quirks.c
>> > +++ b/drivers/hid/hid-quirks.c
>> > @@ -557,6 +557,9 @@ static const struct hid_device_id
>> > hid_have_special_driver[] = {
>> >  #if IS_ENABLED(CONFIG_HID_PRODIKEYS)
>> > { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS,
>> > USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
>> >  #endif
>> > +#if IS_ENABLED(CONFIG_HID_REDRAGON)
>> > +   {
>> > HID_USB_DEVICE(USB_VENDOR_ID_JESS,  USB_DEVICE_ID_REDRAGON_ASURA)
>> > },
>> > +#endif
>>
>> Please drop this hunk. v4.16 should work without changing
>> hid_have_special_driver. This way, you will be sure that an initramfs
>> that doesn't include hid-redragon.ko will allo people to type their
>> LUKS password.
>
> I recall testing without this change resulted in the driver not being
> picked up. I will retest ( running 4.16.0 here, can update to 4.16.1
> soo

Re: [PATCH v5] Fix modifier keys for Redragon Asura Keyboard

2018-04-16 Thread Benjamin Tissoires
Hi Robert,

On Wed, Apr 11, 2018 at 11:49 AM, Robert Munteanu <romb...@apache.org> wrote:
> Changelog:
>
> - v2: modifier keys work, some combinations are still troublesome
> - v3: style cleanup, rebase on top of 4.14
> - v4: remove most debugging calls, make init info useful for user,
>   rebased on top of 4.15
> - v5: fix the HID descriptor as suggested by Benjamin Tissoires,
>   use existing USB vendor id, update comment style, add SPDX
>   license identifier, rename to hid-redragon, stop registering
>   two input devices, rebased on top of 4.16

As Jiri said, please provide a correct commit message.

I have a few nitpicks in the driver, v6 should be fine:

>
> Signed-off-by: Robert Munteanu <romb...@apache.org>
> ---
>  drivers/hid/Kconfig|  7 
>  drivers/hid/Makefile   |  1 +
>  drivers/hid/hid-ids.h  |  1 +
>  drivers/hid/hid-quirks.c   |  3 ++
>  drivers/hid/hid-redragon.c | 89 
> ++
>  5 files changed, 101 insertions(+)
>  create mode 100644 drivers/hid/hid-redragon.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 19c499f5623d..1125e4813716 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -560,6 +560,13 @@ config HID_MAYFLASH
> Say Y here if you have HJZ Mayflash PS3 game controller adapters
> and want to enable force feedback support.
>
> +config HID_REDRAGON
> +   tristate "Redragon keyboards"
> +   depends on HID
> +   default !EXPERT
> +   ---help---
> +Support for Redragon keyboards that need fix-ups to work properly.
> +
>  config HID_MICROSOFT
> tristate "Microsoft non-fully HID-compliant devices"
> depends on HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index eb13b9e92d85..a36f3f40ba63 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -84,6 +84,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS)+= 
> hid-picolcd_debugfs.o
>
>  obj-$(CONFIG_HID_PLANTRONICS)  += hid-plantronics.o
>  obj-$(CONFIG_HID_PRIMAX)   += hid-primax.o
> +obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
>  obj-$(CONFIG_HID_RETRODE)  += hid-retrode.o
>  obj-$(CONFIG_HID_ROCCAT)   += hid-roccat.o hid-roccat-common.o \
> hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 9454ac134ce2..41a64d0e91f9 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -599,6 +599,7 @@
>  #define USB_VENDOR_ID_JESS 0x0c45
>  #define USB_DEVICE_ID_JESS_YUREX   0x1010
>  #define USB_DEVICE_ID_ASUS_MD_5112 0x5112
> +#define USB_DEVICE_ID_REDRAGON_ASURA   0x760b
>
>  #define USB_VENDOR_ID_JESS20x0f30
>  #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
> diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
> index e92b77fa574a..5f1253f1739a 100644
> --- a/drivers/hid/hid-quirks.c
> +++ b/drivers/hid/hid-quirks.c
> @@ -557,6 +557,9 @@ static const struct hid_device_id 
> hid_have_special_driver[] = {
>  #if IS_ENABLED(CONFIG_HID_PRODIKEYS)
> { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, 
> USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
>  #endif
> +#if IS_ENABLED(CONFIG_HID_REDRAGON)
> +   { HID_USB_DEVICE(USB_VENDOR_ID_JESS,  USB_DEVICE_ID_REDRAGON_ASURA) },
> +#endif

Please drop this hunk. v4.16 should work without changing
hid_have_special_driver. This way, you will be sure that an initramfs
that doesn't include hid-redragon.ko will allo people to type their
LUKS password.

>  #if IS_ENABLED(CONFIG_HID_RETRODE)
> { HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, 
> USB_DEVICE_ID_RETRODE2) },
>  #endif
> diff --git a/drivers/hid/hid-redragon.c b/drivers/hid/hid-redragon.c
> new file mode 100644
> index ..ff98a5dbb8e2
> --- /dev/null
> +++ b/drivers/hid/hid-redragon.c
> @@ -0,0 +1,89 @@
> +/*
> + *  HID driver for Redragon keyboards
> + *
> + *  Copyright (c) 2017 Robert Munteanu
> + *  SPDX-License-Identifier: GPL-2.0
> + */
> +
> +/*
> + * 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; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +
> +#include 
> +#include 

you probably don't need input.h

> +#include 
> +#include 
> +#include 

log2.h? I am not sure you need it either

> +#include 

probably drop this one too.

> +
> +#include "hid-ids.h"
> +
> +
> +/*
> + * The Redragon Asura keyboard sends an incorrect

Re: [PATCH v5] Fix modifier keys for Redragon Asura Keyboard

2018-04-16 Thread Benjamin Tissoires
Hi Robert,

On Wed, Apr 11, 2018 at 11:49 AM, Robert Munteanu  wrote:
> Changelog:
>
> - v2: modifier keys work, some combinations are still troublesome
> - v3: style cleanup, rebase on top of 4.14
> - v4: remove most debugging calls, make init info useful for user,
>   rebased on top of 4.15
> - v5: fix the HID descriptor as suggested by Benjamin Tissoires,
>   use existing USB vendor id, update comment style, add SPDX
>   license identifier, rename to hid-redragon, stop registering
>   two input devices, rebased on top of 4.16

As Jiri said, please provide a correct commit message.

I have a few nitpicks in the driver, v6 should be fine:

>
> Signed-off-by: Robert Munteanu 
> ---
>  drivers/hid/Kconfig|  7 
>  drivers/hid/Makefile   |  1 +
>  drivers/hid/hid-ids.h  |  1 +
>  drivers/hid/hid-quirks.c   |  3 ++
>  drivers/hid/hid-redragon.c | 89 
> ++
>  5 files changed, 101 insertions(+)
>  create mode 100644 drivers/hid/hid-redragon.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 19c499f5623d..1125e4813716 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -560,6 +560,13 @@ config HID_MAYFLASH
> Say Y here if you have HJZ Mayflash PS3 game controller adapters
> and want to enable force feedback support.
>
> +config HID_REDRAGON
> +   tristate "Redragon keyboards"
> +   depends on HID
> +   default !EXPERT
> +   ---help---
> +Support for Redragon keyboards that need fix-ups to work properly.
> +
>  config HID_MICROSOFT
> tristate "Microsoft non-fully HID-compliant devices"
> depends on HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index eb13b9e92d85..a36f3f40ba63 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -84,6 +84,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS)+= 
> hid-picolcd_debugfs.o
>
>  obj-$(CONFIG_HID_PLANTRONICS)  += hid-plantronics.o
>  obj-$(CONFIG_HID_PRIMAX)   += hid-primax.o
> +obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
>  obj-$(CONFIG_HID_RETRODE)  += hid-retrode.o
>  obj-$(CONFIG_HID_ROCCAT)   += hid-roccat.o hid-roccat-common.o \
> hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 9454ac134ce2..41a64d0e91f9 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -599,6 +599,7 @@
>  #define USB_VENDOR_ID_JESS 0x0c45
>  #define USB_DEVICE_ID_JESS_YUREX   0x1010
>  #define USB_DEVICE_ID_ASUS_MD_5112 0x5112
> +#define USB_DEVICE_ID_REDRAGON_ASURA   0x760b
>
>  #define USB_VENDOR_ID_JESS20x0f30
>  #define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
> diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
> index e92b77fa574a..5f1253f1739a 100644
> --- a/drivers/hid/hid-quirks.c
> +++ b/drivers/hid/hid-quirks.c
> @@ -557,6 +557,9 @@ static const struct hid_device_id 
> hid_have_special_driver[] = {
>  #if IS_ENABLED(CONFIG_HID_PRODIKEYS)
> { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, 
> USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
>  #endif
> +#if IS_ENABLED(CONFIG_HID_REDRAGON)
> +   { HID_USB_DEVICE(USB_VENDOR_ID_JESS,  USB_DEVICE_ID_REDRAGON_ASURA) },
> +#endif

Please drop this hunk. v4.16 should work without changing
hid_have_special_driver. This way, you will be sure that an initramfs
that doesn't include hid-redragon.ko will allo people to type their
LUKS password.

>  #if IS_ENABLED(CONFIG_HID_RETRODE)
> { HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY, 
> USB_DEVICE_ID_RETRODE2) },
>  #endif
> diff --git a/drivers/hid/hid-redragon.c b/drivers/hid/hid-redragon.c
> new file mode 100644
> index ..ff98a5dbb8e2
> --- /dev/null
> +++ b/drivers/hid/hid-redragon.c
> @@ -0,0 +1,89 @@
> +/*
> + *  HID driver for Redragon keyboards
> + *
> + *  Copyright (c) 2017 Robert Munteanu
> + *  SPDX-License-Identifier: GPL-2.0
> + */
> +
> +/*
> + * 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; either version 2 of the License, or (at your option)
> + * any later version.
> + */
> +
> +#include 
> +#include 

you probably don't need input.h

> +#include 
> +#include 
> +#include 

log2.h? I am not sure you need it either

> +#include 

probably drop this one too.

> +
> +#include "hid-ids.h"
> +
> +
> +/*
> + * The Redragon Asura keyboard sends an incorrect HID descriptor.
> + * At byte 100 it contains
> + *
> + * 

Re: [PATCH v5] Fix modifier keys for Redragon Asura Keyboard

2018-04-16 Thread Benjamin Tissoires
On Mon, Apr 16, 2018 at 11:49 AM, Jiri Kosina <ji...@kernel.org> wrote:
> On Wed, 11 Apr 2018, Robert Munteanu wrote:
>
>> Changelog:
>>
>> - v2: modifier keys work, some combinations are still troublesome
>> - v3: style cleanup, rebase on top of 4.14
>> - v4: remove most debugging calls, make init info useful for user,
>>   rebased on top of 4.15
>> - v5: fix the HID descriptor as suggested by Benjamin Tissoires,
>>   use existing USB vendor id, update comment style, add SPDX
>>   license identifier, rename to hid-redragon, stop registering
>>   two input devices, rebased on top of 4.16
>
> This should contain the text that goes directly into the git commit
> changelog, therefore should instead contain something like "This adds a
> news driver for HW XX, that needs a specialized driver bacuse  and
> things to specifically point out in implementation are ".
>
> Could you please provide that, so that I can commit it?

Jiri, please hold off, I have a few comments while quickly reviewing the patch.

Cheers,
Benjamin

>
> Thanks.
>
> --
> Jiri Kosina
> SUSE Labs
>


Re: [PATCH v5] Fix modifier keys for Redragon Asura Keyboard

2018-04-16 Thread Benjamin Tissoires
On Mon, Apr 16, 2018 at 11:49 AM, Jiri Kosina  wrote:
> On Wed, 11 Apr 2018, Robert Munteanu wrote:
>
>> Changelog:
>>
>> - v2: modifier keys work, some combinations are still troublesome
>> - v3: style cleanup, rebase on top of 4.14
>> - v4: remove most debugging calls, make init info useful for user,
>>   rebased on top of 4.15
>> - v5: fix the HID descriptor as suggested by Benjamin Tissoires,
>>   use existing USB vendor id, update comment style, add SPDX
>>   license identifier, rename to hid-redragon, stop registering
>>   two input devices, rebased on top of 4.16
>
> This should contain the text that goes directly into the git commit
> changelog, therefore should instead contain something like "This adds a
> news driver for HW XX, that needs a specialized driver bacuse  and
> things to specifically point out in implementation are ".
>
> Could you please provide that, so that I can commit it?

Jiri, please hold off, I have a few comments while quickly reviewing the patch.

Cheers,
Benjamin

>
> Thanks.
>
> --
> Jiri Kosina
> SUSE Labs
>


Re: [PATCH 0/8] Input: support for latest Lenovo thinkpads (series 80)

2018-04-10 Thread Benjamin Tissoires
Hi KT,

On Tue, Apr 10, 2018 at 7:45 AM, 廖崇榮 <kt.l...@emc.com.tw> wrote:
> Hi Benjamin,
>
> Thanks so much for your patch.
>
> I have tested them for Elan Gen5/Gen6(new) touchpad with SMbus/PS2.
> It works fine in my thinkpad so far but I find an issue today after 
> lid-close/open.
>
> I am not sure if you can see it in T480S , I "guess" it may be relative to 
> i2c_i801.
>
> The lid-close will enter deep sleep and cut touchpad power.
> I can see the resume flow after lid-open and SMbus-initial try to request 
> hello package but fail.
> Strangely, I can't see any SMbus host signal on LA scope after power-on.

That's weird. I do not see this, by either closing the lid or directly
calling 'systemctl suspend'.
On my system, i2c-i801 is also compiled as a module but psmouse is not
(directly in vmlinuz).

>
> I can't switch to SMbus after rmmod/modprobe psmouse because error happen in 
> elantech_create_smbus.

If the SMBus adapter is failing, it is somewhat expected. Reloading
psmouse will force a re-trigger of the SMBus probe function, but if
the underlying communication fails, there is no way for psmouse to
know it failed, so the PS/2 node will disappear. And the SMBus device
will not be there.

> It will be recovered only if I rmmod/modprobe i2c_i801 first.

Just to be sure, what happens if you rmmod/modprobe elan_i2c instead
of i2c_i801?

And which kernel are you running? On a vanilla 4.16 + Dmitry's next
branch I do not see such issues.

>
> Do you have any idea about it?

If reloading elan_i2c doesn't fix the situation, it must be in
i2c_i801. But this is weird that this happens on your platform but not
on my t480s going into S3.

Cheers,
Benjamin

>
> Thanks
> KT
> -Original Message-
> From: Benjamin Tissoires [mailto:benjamin.tissoi...@redhat.com]
> Sent: Friday, April 06, 2018 2:51 PM
> To: Dmitry Torokhov
> Cc: 廖崇榮; Oliver Haessler; Benjamin Berg; open list:HID CORE LAYER; lkml
> Subject: Re: [PATCH 0/8] Input: support for latest Lenovo thinkpads (series 
> 80)
>
> Hi Dmitry,
>
> On Fri, Apr 6, 2018 at 1:51 AM, Dmitry Torokhov <dmitry.torok...@gmail.com> 
> wrote:
>> Hi Benjamin,
>>
>> On Thu, Apr 05, 2018 at 03:25:29PM +0200, Benjamin Tissoires wrote:
>>> Hi Dmitry,
>>>
>>> well, this year, Lenovo gave us a surprise and decided to not use the
>>> same touchpad/trackstick in all its model. And by default, the
>>> support under Linux is less than ideal.
>>>
>>> Please find a series that should fix those issues. Compared to the 60
>>> series, there do not seem to e BIOS table issues this time, and
>>> suspend/resume works fine thanks to your latest trackstick fixes.
>>>
>>> The T480s is a different beast, as it uses an Elan touchpad.
>>> I have been carrying the patches 3-6 for a while and tested previous
>>> versions on various Elan PS/2 hardware without an issue as far as I
>>> could tell. I was lacking tests from users with SMBus as all the
>>> laptops I tried where puer PS/2.
>>>
>>> Anyway, it would be cool if you could have a look at the series.
>>
>> I am mostly happy with the series, but I would love to hear KT's take
>> on it.
>
> thanks for the quick review.
> I worked closely with KT for this series. He helped me a lot for the tiny 
> firmware changes that were required. However, quoting his email from Tuesday:
> "There will be a spring vacation in Taiwan from tomorrow." I guess we won't 
> hear from him until the end of next week as we always have a backlog of 
> urgent things to do after holidays...
>
> Cheers,
> Benjamin
>


Re: [PATCH 0/8] Input: support for latest Lenovo thinkpads (series 80)

2018-04-10 Thread Benjamin Tissoires
Hi KT,

On Tue, Apr 10, 2018 at 7:45 AM, 廖崇榮  wrote:
> Hi Benjamin,
>
> Thanks so much for your patch.
>
> I have tested them for Elan Gen5/Gen6(new) touchpad with SMbus/PS2.
> It works fine in my thinkpad so far but I find an issue today after 
> lid-close/open.
>
> I am not sure if you can see it in T480S , I "guess" it may be relative to 
> i2c_i801.
>
> The lid-close will enter deep sleep and cut touchpad power.
> I can see the resume flow after lid-open and SMbus-initial try to request 
> hello package but fail.
> Strangely, I can't see any SMbus host signal on LA scope after power-on.

That's weird. I do not see this, by either closing the lid or directly
calling 'systemctl suspend'.
On my system, i2c-i801 is also compiled as a module but psmouse is not
(directly in vmlinuz).

>
> I can't switch to SMbus after rmmod/modprobe psmouse because error happen in 
> elantech_create_smbus.

If the SMBus adapter is failing, it is somewhat expected. Reloading
psmouse will force a re-trigger of the SMBus probe function, but if
the underlying communication fails, there is no way for psmouse to
know it failed, so the PS/2 node will disappear. And the SMBus device
will not be there.

> It will be recovered only if I rmmod/modprobe i2c_i801 first.

Just to be sure, what happens if you rmmod/modprobe elan_i2c instead
of i2c_i801?

And which kernel are you running? On a vanilla 4.16 + Dmitry's next
branch I do not see such issues.

>
> Do you have any idea about it?

If reloading elan_i2c doesn't fix the situation, it must be in
i2c_i801. But this is weird that this happens on your platform but not
on my t480s going into S3.

Cheers,
Benjamin

>
> Thanks
> KT
> -Original Message-
> From: Benjamin Tissoires [mailto:benjamin.tissoi...@redhat.com]
> Sent: Friday, April 06, 2018 2:51 PM
> To: Dmitry Torokhov
> Cc: 廖崇榮; Oliver Haessler; Benjamin Berg; open list:HID CORE LAYER; lkml
> Subject: Re: [PATCH 0/8] Input: support for latest Lenovo thinkpads (series 
> 80)
>
> Hi Dmitry,
>
> On Fri, Apr 6, 2018 at 1:51 AM, Dmitry Torokhov  
> wrote:
>> Hi Benjamin,
>>
>> On Thu, Apr 05, 2018 at 03:25:29PM +0200, Benjamin Tissoires wrote:
>>> Hi Dmitry,
>>>
>>> well, this year, Lenovo gave us a surprise and decided to not use the
>>> same touchpad/trackstick in all its model. And by default, the
>>> support under Linux is less than ideal.
>>>
>>> Please find a series that should fix those issues. Compared to the 60
>>> series, there do not seem to e BIOS table issues this time, and
>>> suspend/resume works fine thanks to your latest trackstick fixes.
>>>
>>> The T480s is a different beast, as it uses an Elan touchpad.
>>> I have been carrying the patches 3-6 for a while and tested previous
>>> versions on various Elan PS/2 hardware without an issue as far as I
>>> could tell. I was lacking tests from users with SMBus as all the
>>> laptops I tried where puer PS/2.
>>>
>>> Anyway, it would be cool if you could have a look at the series.
>>
>> I am mostly happy with the series, but I would love to hear KT's take
>> on it.
>
> thanks for the quick review.
> I worked closely with KT for this series. He helped me a lot for the tiny 
> firmware changes that were required. However, quoting his email from Tuesday:
> "There will be a spring vacation in Taiwan from tomorrow." I guess we won't 
> hear from him until the end of next week as we always have a backlog of 
> urgent things to do after holidays...
>
> Cheers,
> Benjamin
>


[PATCH v2 0/9] Input: support for latest Lenovo thinkpads (series 80)

2018-04-09 Thread Benjamin Tissoires
Hi Dmitry,

Here is the v2 of the Lenovo 80 series.
Changes from v1:
- included patch to convert a function to static from build bot
- use of device property instead of platform data (thus the new device tree
  binding)

BTW, KT, if you want to add your Signed-off-by on the patches, feel free to
do so. You were of tremendous help :)

Cheers,
Benjamin

Benjamin Tissoires (9):
  Input: synaptics - add Lenovo 80 series ids to SMBus
  input: elan_i2c_smbus - fix corrupted stack
  Input: elan_i2c - add trackstick report
  Input: elantech - split device info into a separate structure
  Input: elantech_query_info() can be static
  Input: elantech - query the resolution in query_info
  Input: elantech - add support for SMBus devices
  Input: elantech - detect new ICs and setup Host Notify for them
  input: psmouse-smbus: allow to control psmouse_deactivate

 .../devicetree/bindings/input/elan_i2c.txt |   1 +
 drivers/input/mouse/Kconfig|  12 +
 drivers/input/mouse/elan_i2c_core.c|  90 +++-
 drivers/input/mouse/elan_i2c_smbus.c   |  22 +-
 drivers/input/mouse/elantech.c | 479 +++--
 drivers/input/mouse/elantech.h |  69 ++-
 drivers/input/mouse/psmouse-base.c |  21 +-
 drivers/input/mouse/psmouse-smbus.c|  24 +-
 drivers/input/mouse/psmouse.h  |   2 +
 drivers/input/mouse/synaptics.c|   5 +-
 10 files changed, 565 insertions(+), 160 deletions(-)

-- 
2.14.3



[PATCH v2 2/9] input: elan_i2c_smbus - fix corrupted stack

2018-04-09 Thread Benjamin Tissoires
New ICs (like the one on the Lenovo T480s) answer to
ETP_SMBUS_IAP_VERSION_CMD 4 bytes instead of 3. This corrupts the stack
as i2c_smbus_read_block_data() uses the values returned by the i2c
device to know how many data it need to return.

i2c_smbus_read_block_data() can read up to 32 bytes (I2C_SMBUS_BLOCK_MAX)
and there is no safeguard on how many bytes are provided in the return
value. Ensure we always have enough space for any future firmware.
Also 0-initialize the values to prevent any access to uninitialized memory.

Cc: <sta...@vger.kernel.org> # v4.4.x, v4.9.x, v4.14.x, v4.15.x, v4.16.x
Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
no changes in v2

 drivers/input/mouse/elan_i2c_smbus.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/input/mouse/elan_i2c_smbus.c 
b/drivers/input/mouse/elan_i2c_smbus.c
index 29f99529b187..cfcb32559925 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -130,7 +130,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client 
*client,
bool max_baseline, u8 *value)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  max_baseline ?
@@ -149,7 +149,7 @@ static int elan_smbus_get_version(struct i2c_client *client,
  bool iap, u8 *version)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_IAP_VERSION_CMD :
@@ -170,7 +170,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 u8 *clickpad)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_SM_VERSION_CMD, val);
@@ -188,7 +188,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_UNIQUEID_CMD, val);
@@ -205,7 +205,7 @@ static int elan_smbus_get_checksum(struct i2c_client 
*client,
   bool iap, u16 *csum)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_FW_CHECKSUM_CMD :
@@ -226,7 +226,7 @@ static int elan_smbus_get_max(struct i2c_client *client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val);
if (ret != 3) {
@@ -246,7 +246,7 @@ static int elan_smbus_get_resolution(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val);
if (ret != 3) {
@@ -267,7 +267,7 @@ static int elan_smbus_get_num_traces(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val);
if (ret != 3) {
@@ -294,7 +294,7 @@ static int elan_smbus_iap_get_mode(struct i2c_client 
*client,
 {
int error;
u16 constant;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val);
if (error < 0) {
@@ -345,7 +345,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client 
*client)
int len;
int error;
enum tp_mode mode;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06};
u16 password;
 
@@ -419,7 +419,7 @@ static int elan_smbus_write_fw_block(struct i2c_client 
*client,
struct device *dev = >dev;
int error;
u16 result;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
/*
 * Due to the limitation of smbus protocol limiting
-- 
2.14.3



[PATCH v2 0/9] Input: support for latest Lenovo thinkpads (series 80)

2018-04-09 Thread Benjamin Tissoires
Hi Dmitry,

Here is the v2 of the Lenovo 80 series.
Changes from v1:
- included patch to convert a function to static from build bot
- use of device property instead of platform data (thus the new device tree
  binding)

BTW, KT, if you want to add your Signed-off-by on the patches, feel free to
do so. You were of tremendous help :)

Cheers,
Benjamin

Benjamin Tissoires (9):
  Input: synaptics - add Lenovo 80 series ids to SMBus
  input: elan_i2c_smbus - fix corrupted stack
  Input: elan_i2c - add trackstick report
  Input: elantech - split device info into a separate structure
  Input: elantech_query_info() can be static
  Input: elantech - query the resolution in query_info
  Input: elantech - add support for SMBus devices
  Input: elantech - detect new ICs and setup Host Notify for them
  input: psmouse-smbus: allow to control psmouse_deactivate

 .../devicetree/bindings/input/elan_i2c.txt |   1 +
 drivers/input/mouse/Kconfig|  12 +
 drivers/input/mouse/elan_i2c_core.c|  90 +++-
 drivers/input/mouse/elan_i2c_smbus.c   |  22 +-
 drivers/input/mouse/elantech.c | 479 +++--
 drivers/input/mouse/elantech.h |  69 ++-
 drivers/input/mouse/psmouse-base.c |  21 +-
 drivers/input/mouse/psmouse-smbus.c|  24 +-
 drivers/input/mouse/psmouse.h  |   2 +
 drivers/input/mouse/synaptics.c|   5 +-
 10 files changed, 565 insertions(+), 160 deletions(-)

-- 
2.14.3



[PATCH v2 2/9] input: elan_i2c_smbus - fix corrupted stack

2018-04-09 Thread Benjamin Tissoires
New ICs (like the one on the Lenovo T480s) answer to
ETP_SMBUS_IAP_VERSION_CMD 4 bytes instead of 3. This corrupts the stack
as i2c_smbus_read_block_data() uses the values returned by the i2c
device to know how many data it need to return.

i2c_smbus_read_block_data() can read up to 32 bytes (I2C_SMBUS_BLOCK_MAX)
and there is no safeguard on how many bytes are provided in the return
value. Ensure we always have enough space for any future firmware.
Also 0-initialize the values to prevent any access to uninitialized memory.

Cc:  # v4.4.x, v4.9.x, v4.14.x, v4.15.x, v4.16.x
Signed-off-by: Benjamin Tissoires 
---
no changes in v2

 drivers/input/mouse/elan_i2c_smbus.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/input/mouse/elan_i2c_smbus.c 
b/drivers/input/mouse/elan_i2c_smbus.c
index 29f99529b187..cfcb32559925 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -130,7 +130,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client 
*client,
bool max_baseline, u8 *value)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  max_baseline ?
@@ -149,7 +149,7 @@ static int elan_smbus_get_version(struct i2c_client *client,
  bool iap, u8 *version)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_IAP_VERSION_CMD :
@@ -170,7 +170,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 u8 *clickpad)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_SM_VERSION_CMD, val);
@@ -188,7 +188,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_UNIQUEID_CMD, val);
@@ -205,7 +205,7 @@ static int elan_smbus_get_checksum(struct i2c_client 
*client,
   bool iap, u16 *csum)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_FW_CHECKSUM_CMD :
@@ -226,7 +226,7 @@ static int elan_smbus_get_max(struct i2c_client *client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val);
if (ret != 3) {
@@ -246,7 +246,7 @@ static int elan_smbus_get_resolution(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val);
if (ret != 3) {
@@ -267,7 +267,7 @@ static int elan_smbus_get_num_traces(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val);
if (ret != 3) {
@@ -294,7 +294,7 @@ static int elan_smbus_iap_get_mode(struct i2c_client 
*client,
 {
int error;
u16 constant;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val);
if (error < 0) {
@@ -345,7 +345,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client 
*client)
int len;
int error;
enum tp_mode mode;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06};
u16 password;
 
@@ -419,7 +419,7 @@ static int elan_smbus_write_fw_block(struct i2c_client 
*client,
struct device *dev = >dev;
int error;
u16 result;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
/*
 * Due to the limitation of smbus protocol limiting
-- 
2.14.3



[PATCH v2 5/9] Input: elantech_query_info() can be static

2018-04-09 Thread Benjamin Tissoires
Signed-off-by: Fengguang Wu <fengguang...@intel.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

---
new in v2, raised by kbuild test robot
---
 drivers/input/mouse/elantech.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index d485664f1563..980dfd7e861e 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1662,8 +1662,8 @@ static int elantech_set_properties(struct 
elantech_device_info *info)
return 0;
 }
 
-int elantech_query_info(struct psmouse *psmouse,
-   struct elantech_device_info *info)
+static int elantech_query_info(struct psmouse *psmouse,
+  struct elantech_device_info *info)
 {
unsigned char param[3];
 
-- 
2.14.3



[PATCH v2 5/9] Input: elantech_query_info() can be static

2018-04-09 Thread Benjamin Tissoires
Signed-off-by: Fengguang Wu 
Signed-off-by: Benjamin Tissoires 

---
new in v2, raised by kbuild test robot
---
 drivers/input/mouse/elantech.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index d485664f1563..980dfd7e861e 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1662,8 +1662,8 @@ static int elantech_set_properties(struct 
elantech_device_info *info)
return 0;
 }
 
-int elantech_query_info(struct psmouse *psmouse,
-   struct elantech_device_info *info)
+static int elantech_query_info(struct psmouse *psmouse,
+  struct elantech_device_info *info)
 {
unsigned char param[3];
 
-- 
2.14.3



[PATCH v2 4/9] Input: elantech - split device info into a separate structure

2018-04-09 Thread Benjamin Tissoires
In preparation for SMBus device support, move static device
information that we query form the touchpad upon initialization into
separate structure. This will allow us to query the device without
allocating memory first.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
no changes in v2

 drivers/input/mouse/elantech.c | 271 -
 drivers/input/mouse/elantech.h |  28 +++--
 2 files changed, 175 insertions(+), 124 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index db47a5e1d114..d485664f1563 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -24,7 +24,7 @@
 
 #define elantech_debug(fmt, ...)   \
do {\
-   if (etd->debug) \
+   if (etd->info.debug)\
psmouse_printk(KERN_DEBUG, psmouse, \
fmt, ##__VA_ARGS__);\
} while (0)
@@ -105,7 +105,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_READ) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -137,7 +137,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
 
if (rc)
psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
-   else if (etd->hw_version != 4)
+   else if (etd->info.hw_version != 4)
*val = param[0];
else
*val = param[1];
@@ -160,7 +160,7 @@ static int elantech_write_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_WRITE) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -237,7 +237,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
unsigned char *packet = psmouse->packet;
int fingers;
 
-   if (etd->fw_version < 0x02) {
+   if (etd->info.fw_version < 0x02) {
/*
 * byte 0:  D   U  p1  p2   1  p3   R   L
 * byte 1:  f   0  th  tw  x9  x8  y9  y8
@@ -252,7 +252,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
fingers = (packet[0] & 0xc0) >> 6;
}
 
-   if (etd->jumpy_cursor) {
+   if (etd->info.jumpy_cursor) {
if (fingers != 1) {
etd->single_finger_reports = 0;
} else if (etd->single_finger_reports < 2) {
@@ -282,8 +282,8 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
 
psmouse_report_standard_buttons(dev, packet[0]);
 
-   if (etd->fw_version < 0x02 &&
-   (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
+   if (etd->info.fw_version < 0x02 &&
+   (etd->info.capabilities[0] & ETP_CAP_HAS_ROCKER)) {
/* rocker up */
input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
/* rocker down */
@@ -391,7 +391,7 @@ static void elantech_report_absolute_v2(struct psmouse 
*psmouse)
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
psmouse_report_standard_buttons(dev, packet[0]);
-   if (etd->reports_pressure) {
+   if (etd->info.reports_pressure) {
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
}
@@ -444,7 +444,7 @@ static void elantech_report_trackpoint(struct psmouse 
*psmouse,
 
default:
/* Dump unexpected packet sequences if debug=1 (default) */
-   if (etd->debug == 1)
+   if (etd->info.debug == 1)
elantech_packet_dump(psmouse);
 
break;
@@ -523,7 +523,7 @@ static void elantech_report_absolute_v3(struct psmouse 
*psmouse,
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
 
/* For clickpads map both buttons to BTN_LEFT */
-   if (etd->fw_version & 0x001000)
+   if (etd->info.fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
else
psmouse_report_standard_buttons(dev, packet[0]);
@@ -541

[PATCH v2 4/9] Input: elantech - split device info into a separate structure

2018-04-09 Thread Benjamin Tissoires
In preparation for SMBus device support, move static device
information that we query form the touchpad upon initialization into
separate structure. This will allow us to query the device without
allocating memory first.

Signed-off-by: Benjamin Tissoires 
---
no changes in v2

 drivers/input/mouse/elantech.c | 271 -
 drivers/input/mouse/elantech.h |  28 +++--
 2 files changed, 175 insertions(+), 124 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index db47a5e1d114..d485664f1563 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -24,7 +24,7 @@
 
 #define elantech_debug(fmt, ...)   \
do {\
-   if (etd->debug) \
+   if (etd->info.debug)\
psmouse_printk(KERN_DEBUG, psmouse, \
fmt, ##__VA_ARGS__);\
} while (0)
@@ -105,7 +105,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_READ) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -137,7 +137,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
 
if (rc)
psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
-   else if (etd->hw_version != 4)
+   else if (etd->info.hw_version != 4)
*val = param[0];
else
*val = param[1];
@@ -160,7 +160,7 @@ static int elantech_write_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_WRITE) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -237,7 +237,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
unsigned char *packet = psmouse->packet;
int fingers;
 
-   if (etd->fw_version < 0x02) {
+   if (etd->info.fw_version < 0x02) {
/*
 * byte 0:  D   U  p1  p2   1  p3   R   L
 * byte 1:  f   0  th  tw  x9  x8  y9  y8
@@ -252,7 +252,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
fingers = (packet[0] & 0xc0) >> 6;
}
 
-   if (etd->jumpy_cursor) {
+   if (etd->info.jumpy_cursor) {
if (fingers != 1) {
etd->single_finger_reports = 0;
} else if (etd->single_finger_reports < 2) {
@@ -282,8 +282,8 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
 
psmouse_report_standard_buttons(dev, packet[0]);
 
-   if (etd->fw_version < 0x02 &&
-   (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
+   if (etd->info.fw_version < 0x02 &&
+   (etd->info.capabilities[0] & ETP_CAP_HAS_ROCKER)) {
/* rocker up */
input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
/* rocker down */
@@ -391,7 +391,7 @@ static void elantech_report_absolute_v2(struct psmouse 
*psmouse)
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
psmouse_report_standard_buttons(dev, packet[0]);
-   if (etd->reports_pressure) {
+   if (etd->info.reports_pressure) {
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
}
@@ -444,7 +444,7 @@ static void elantech_report_trackpoint(struct psmouse 
*psmouse,
 
default:
/* Dump unexpected packet sequences if debug=1 (default) */
-   if (etd->debug == 1)
+   if (etd->info.debug == 1)
elantech_packet_dump(psmouse);
 
break;
@@ -523,7 +523,7 @@ static void elantech_report_absolute_v3(struct psmouse 
*psmouse,
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
 
/* For clickpads map both buttons to BTN_LEFT */
-   if (etd->fw_version & 0x001000)
+   if (etd->info.fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
else
psmouse_report_standard_buttons(dev, packet[0]);
@@ -541,7 +541,7 @@ static void elantech_input_sync_v

[PATCH v2 7/9] Input: elantech - add support for SMBus devices

2018-04-09 Thread Benjamin Tissoires
Many of the Elantech devices are connected through PS/2 and a different
bus (SMBus or plain I2C).

To not break any existing device, we only enable SMBus based
on a module parameter. If some laptops require the quirk to
be set, we will have to rely on a list of PNPIds or MDI matching
to individually expose those hardware over SMBus.
the parameter mentioned above is elantech_smbus from the psmouse
module.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

---
changes in v2:
- use of device property instead of platform data
---
 drivers/input/mouse/Kconfig |  12 +++
 drivers/input/mouse/elantech.c  | 188 +++-
 drivers/input/mouse/elantech.h  |  24 +
 drivers/input/mouse/psmouse-base.c  |  21 +++-
 drivers/input/mouse/psmouse-smbus.c |  11 ++-
 drivers/input/mouse/psmouse.h   |   1 +
 6 files changed, 246 insertions(+), 11 deletions(-)

diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 89ebb8f39fee..f27f23f2d99a 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -133,6 +133,18 @@ config MOUSE_PS2_ELANTECH
 
  If unsure, say N.
 
+config MOUSE_PS2_ELANTECH_SMBUS
+   bool "Elantech PS/2 SMbus companion" if EXPERT
+   default y
+   depends on MOUSE_PS2 && MOUSE_PS2_ELANTECH
+   depends on I2C=y || I2C=MOUSE_PS2
+   select MOUSE_PS2_SMBUS
+   help
+ Say Y here if you have a Elantech touchpad connected to
+ to an SMBus, but enumerated through PS/2.
+
+ If unsure, say Y.
+
 config MOUSE_PS2_SENTELIC
bool "Sentelic Finger Sensing Pad PS/2 protocol extension"
depends on MOUSE_PS2
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index a2a14a31edb5..510e7c0622d3 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -14,13 +14,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include "psmouse.h"
 #include "elantech.h"
+#include "elan_i2c.h"
 
 #define elantech_debug(fmt, ...)   \
do {\
@@ -1084,7 +1087,8 @@ static unsigned int elantech_convert_res(unsigned int val)
 
 static int elantech_get_resolution_v4(struct psmouse *psmouse,
  unsigned int *x_res,
- unsigned int *y_res)
+ unsigned int *y_res,
+ unsigned int *bus)
 {
unsigned char param[3];
 
@@ -1093,6 +1097,7 @@ static int elantech_get_resolution_v4(struct psmouse 
*psmouse,
 
*x_res = elantech_convert_res(param[1] & 0x0f);
*y_res = elantech_convert_res((param[1] & 0xf0) >> 4);
+   *bus = param[2];
 
return 0;
 }
@@ -1474,6 +1479,12 @@ static void elantech_disconnect(struct psmouse *psmouse)
 {
struct elantech_data *etd = psmouse->private;
 
+   /*
+* We might have left a breadcrumb when trying to
+* set up SMbus companion.
+*/
+   psmouse_smbus_cleanup(psmouse);
+
if (etd->tp_dev)
input_unregister_device(etd->tp_dev);
sysfs_remove_group(>ps2dev.serio->dev.kobj,
@@ -1659,6 +1670,8 @@ static int elantech_query_info(struct psmouse *psmouse,
 {
unsigned char param[3];
 
+   memset(info, 0, sizeof(*info));
+
/*
 * Do the version query again so we can store the result
 */
@@ -1717,7 +1730,8 @@ static int elantech_query_info(struct psmouse *psmouse,
if (info->hw_version == 4) {
if (elantech_get_resolution_v4(psmouse,
   >x_res,
-  >y_res)) {
+  >y_res,
+  >bus)) {
psmouse_warn(psmouse,
 "failed to query resolution data.\n");
}
@@ -1726,6 +1740,129 @@ static int elantech_query_info(struct psmouse *psmouse,
return 0;
 }
 
+#if defined(CONFIG_MOUSE_PS2_ELANTECH_SMBUS)
+
+/*
+ * The newest Elantech device can use a secondary bus (over SMBus) which
+ * provides a better bandwidth and allow a better control of the touchpads.
+ * This is used to decide if we need to use this bus or not.
+ */
+enum {
+   ELANTECH_SMBUS_NOT_SET = -1,
+   ELANTECH_SMBUS_OFF,
+   ELANTECH_SMBUS_ON,
+};
+
+static int elantech_smbus = IS_ENABLED(CONFIG_MOUSE_ELAN_I2C_SMBUS) ?
+   ELANTECH_SMBUS_NOT_SET : ELANTECH_SMBUS_OFF;
+module_param_named(elantech_smbus, elantech_smbus, int, 0644);
+MODULE_PARM_DESC(elantech_smbus, "Use a secondary bus for the Elantech 
device.&q

[PATCH v2 7/9] Input: elantech - add support for SMBus devices

2018-04-09 Thread Benjamin Tissoires
Many of the Elantech devices are connected through PS/2 and a different
bus (SMBus or plain I2C).

To not break any existing device, we only enable SMBus based
on a module parameter. If some laptops require the quirk to
be set, we will have to rely on a list of PNPIds or MDI matching
to individually expose those hardware over SMBus.
the parameter mentioned above is elantech_smbus from the psmouse
module.

Signed-off-by: Benjamin Tissoires 

---
changes in v2:
- use of device property instead of platform data
---
 drivers/input/mouse/Kconfig |  12 +++
 drivers/input/mouse/elantech.c  | 188 +++-
 drivers/input/mouse/elantech.h  |  24 +
 drivers/input/mouse/psmouse-base.c  |  21 +++-
 drivers/input/mouse/psmouse-smbus.c |  11 ++-
 drivers/input/mouse/psmouse.h   |   1 +
 6 files changed, 246 insertions(+), 11 deletions(-)

diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 89ebb8f39fee..f27f23f2d99a 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -133,6 +133,18 @@ config MOUSE_PS2_ELANTECH
 
  If unsure, say N.
 
+config MOUSE_PS2_ELANTECH_SMBUS
+   bool "Elantech PS/2 SMbus companion" if EXPERT
+   default y
+   depends on MOUSE_PS2 && MOUSE_PS2_ELANTECH
+   depends on I2C=y || I2C=MOUSE_PS2
+   select MOUSE_PS2_SMBUS
+   help
+ Say Y here if you have a Elantech touchpad connected to
+ to an SMBus, but enumerated through PS/2.
+
+ If unsure, say Y.
+
 config MOUSE_PS2_SENTELIC
bool "Sentelic Finger Sensing Pad PS/2 protocol extension"
depends on MOUSE_PS2
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index a2a14a31edb5..510e7c0622d3 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -14,13 +14,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include "psmouse.h"
 #include "elantech.h"
+#include "elan_i2c.h"
 
 #define elantech_debug(fmt, ...)   \
do {\
@@ -1084,7 +1087,8 @@ static unsigned int elantech_convert_res(unsigned int val)
 
 static int elantech_get_resolution_v4(struct psmouse *psmouse,
  unsigned int *x_res,
- unsigned int *y_res)
+ unsigned int *y_res,
+ unsigned int *bus)
 {
unsigned char param[3];
 
@@ -1093,6 +1097,7 @@ static int elantech_get_resolution_v4(struct psmouse 
*psmouse,
 
*x_res = elantech_convert_res(param[1] & 0x0f);
*y_res = elantech_convert_res((param[1] & 0xf0) >> 4);
+   *bus = param[2];
 
return 0;
 }
@@ -1474,6 +1479,12 @@ static void elantech_disconnect(struct psmouse *psmouse)
 {
struct elantech_data *etd = psmouse->private;
 
+   /*
+* We might have left a breadcrumb when trying to
+* set up SMbus companion.
+*/
+   psmouse_smbus_cleanup(psmouse);
+
if (etd->tp_dev)
input_unregister_device(etd->tp_dev);
sysfs_remove_group(>ps2dev.serio->dev.kobj,
@@ -1659,6 +1670,8 @@ static int elantech_query_info(struct psmouse *psmouse,
 {
unsigned char param[3];
 
+   memset(info, 0, sizeof(*info));
+
/*
 * Do the version query again so we can store the result
 */
@@ -1717,7 +1730,8 @@ static int elantech_query_info(struct psmouse *psmouse,
if (info->hw_version == 4) {
if (elantech_get_resolution_v4(psmouse,
   >x_res,
-  >y_res)) {
+  >y_res,
+  >bus)) {
psmouse_warn(psmouse,
 "failed to query resolution data.\n");
}
@@ -1726,6 +1740,129 @@ static int elantech_query_info(struct psmouse *psmouse,
return 0;
 }
 
+#if defined(CONFIG_MOUSE_PS2_ELANTECH_SMBUS)
+
+/*
+ * The newest Elantech device can use a secondary bus (over SMBus) which
+ * provides a better bandwidth and allow a better control of the touchpads.
+ * This is used to decide if we need to use this bus or not.
+ */
+enum {
+   ELANTECH_SMBUS_NOT_SET = -1,
+   ELANTECH_SMBUS_OFF,
+   ELANTECH_SMBUS_ON,
+};
+
+static int elantech_smbus = IS_ENABLED(CONFIG_MOUSE_ELAN_I2C_SMBUS) ?
+   ELANTECH_SMBUS_NOT_SET : ELANTECH_SMBUS_OFF;
+module_param_named(elantech_smbus, elantech_smbus, int, 0644);
+MODULE_PARM_DESC(elantech_smbus, "Use a secondary bus for the Elantech 
device.");
+
+st

[PATCH v2 8/9] Input: elantech - detect new ICs and setup Host Notify for them

2018-04-09 Thread Benjamin Tissoires
New ICs are using a different scheme for the alternate bus parameter.
Given that they are new and are only using either PS2 only or PS2 + SMBus
Host Notify, we force those new ICs to use the SMBus solution for enhanced
reporting.

This allows the touchpad found on the Lenovo T480s to report 5 fingers
every 8 ms, instead of having a limit of 2 every 8 ms.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
no changes in v2

 drivers/input/mouse/elantech.c | 11 +++
 drivers/input/mouse/elantech.h | 15 +++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 510e7c0622d3..07e40a58e66c 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1793,11 +1793,11 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 
if (elantech_smbus == ELANTECH_SMBUS_NOT_SET) {
/*
-* FIXME:
-* constraint the I2C capable devices by using FW version,
-* board version, or by using DMI matching
+* New ICs are enabled by default.
+* Old ICs are up to the user to decide.
 */
-   return -ENXIO;
+   if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return -ENXIO;
}
 
psmouse_info(psmouse, "Trying to set up SMBus access\n");
@@ -1818,6 +1818,9 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 static bool elantech_use_host_notify(struct psmouse *psmouse,
 struct elantech_device_info *info)
 {
+   if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return true;
+
switch (info->bus) {
case ETP_BUS_PS2_ONLY:
/* expected case */
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index f9b1c485e8d9..119727085a60 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -115,6 +115,21 @@
 #define ETP_BUS_PS2_SMB_ALERT  3
 #define ETP_BUS_PS2_SMB_HST_NTFY   4
 
+/*
+ * New ICs are either using SMBus Host Notify or just plain PS2.
+ *
+ * ETP_FW_VERSION_QUERY is:
+ * Byte 1:
+ *  - bit 0..3: IC BODY
+ * Byte 2:
+ *  - bit 4: HiddenButton
+ *  - bit 5: PS2_SMBUS_NOTIFY
+ *  - bit 6: PS2CRCCheck
+ */
+#define ETP_NEW_IC_SMBUS_HOST_NOTIFY(fw_version)   \
+   fw_version) & 0x0f2000) == 0x0f2000) && \
+((fw_version) & 0xff) > 0)
+
 /*
  * The base position for one finger, v4 hardware
  */
-- 
2.14.3



[PATCH v2 8/9] Input: elantech - detect new ICs and setup Host Notify for them

2018-04-09 Thread Benjamin Tissoires
New ICs are using a different scheme for the alternate bus parameter.
Given that they are new and are only using either PS2 only or PS2 + SMBus
Host Notify, we force those new ICs to use the SMBus solution for enhanced
reporting.

This allows the touchpad found on the Lenovo T480s to report 5 fingers
every 8 ms, instead of having a limit of 2 every 8 ms.

Signed-off-by: Benjamin Tissoires 
---
no changes in v2

 drivers/input/mouse/elantech.c | 11 +++
 drivers/input/mouse/elantech.h | 15 +++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 510e7c0622d3..07e40a58e66c 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1793,11 +1793,11 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 
if (elantech_smbus == ELANTECH_SMBUS_NOT_SET) {
/*
-* FIXME:
-* constraint the I2C capable devices by using FW version,
-* board version, or by using DMI matching
+* New ICs are enabled by default.
+* Old ICs are up to the user to decide.
 */
-   return -ENXIO;
+   if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return -ENXIO;
}
 
psmouse_info(psmouse, "Trying to set up SMBus access\n");
@@ -1818,6 +1818,9 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 static bool elantech_use_host_notify(struct psmouse *psmouse,
 struct elantech_device_info *info)
 {
+   if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return true;
+
switch (info->bus) {
case ETP_BUS_PS2_ONLY:
/* expected case */
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index f9b1c485e8d9..119727085a60 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -115,6 +115,21 @@
 #define ETP_BUS_PS2_SMB_ALERT  3
 #define ETP_BUS_PS2_SMB_HST_NTFY   4
 
+/*
+ * New ICs are either using SMBus Host Notify or just plain PS2.
+ *
+ * ETP_FW_VERSION_QUERY is:
+ * Byte 1:
+ *  - bit 0..3: IC BODY
+ * Byte 2:
+ *  - bit 4: HiddenButton
+ *  - bit 5: PS2_SMBUS_NOTIFY
+ *  - bit 6: PS2CRCCheck
+ */
+#define ETP_NEW_IC_SMBUS_HOST_NOTIFY(fw_version)   \
+   fw_version) & 0x0f2000) == 0x0f2000) && \
+((fw_version) & 0xff) > 0)
+
 /*
  * The base position for one finger, v4 hardware
  */
-- 
2.14.3



[PATCH v2 9/9] input: psmouse-smbus: allow to control psmouse_deactivate

2018-04-09 Thread Benjamin Tissoires
This seems to be Synaptics specific, as some Elan touchpads are not
correctly switching to SMBus if we call deactivate before switching to
SMBus on cold boot and on resume.

Tested with the T480s

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

---
changes in v2:
- rebased on top of previous
---
 drivers/input/mouse/elantech.c  |  2 +-
 drivers/input/mouse/psmouse-smbus.c | 13 ++---
 drivers/input/mouse/psmouse.h   |  1 +
 drivers/input/mouse/synaptics.c |  2 +-
 4 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 07e40a58e66c..fb4d902c4403 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1774,7 +1774,7 @@ static int elantech_create_smbus(struct psmouse *psmouse,
if (info->has_trackpoint)
smbus_board.properties = i2c_properties;
 
-   return psmouse_smbus_init(psmouse, _board, NULL, 0,
+   return psmouse_smbus_init(psmouse, _board, NULL, 0, false,
  leave_breadcrumbs);
 }
 
diff --git a/drivers/input/mouse/psmouse-smbus.c 
b/drivers/input/mouse/psmouse-smbus.c
index c8a3b1f35ce3..852d4b486ddb 100644
--- a/drivers/input/mouse/psmouse-smbus.c
+++ b/drivers/input/mouse/psmouse-smbus.c
@@ -23,6 +23,7 @@ struct psmouse_smbus_dev {
struct i2c_client *client;
struct list_head node;
bool dead;
+   bool need_deactivate;
 };
 
 static LIST_HEAD(psmouse_smbus_list);
@@ -118,7 +119,10 @@ static psmouse_ret_t psmouse_smbus_process_byte(struct 
psmouse *psmouse)
 
 static int psmouse_smbus_reconnect(struct psmouse *psmouse)
 {
-   psmouse_deactivate(psmouse);
+   struct psmouse_smbus_dev *smbdev = psmouse->private;
+
+   if (smbdev->need_deactivate)
+   psmouse_deactivate(psmouse);
 
return 0;
 }
@@ -225,6 +229,7 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse)
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs)
 {
struct psmouse_smbus_dev *smbdev;
@@ -236,6 +241,7 @@ int psmouse_smbus_init(struct psmouse *psmouse,
 
smbdev->psmouse = psmouse;
smbdev->board = *board;
+   smbdev->need_deactivate = need_deactivate;
 
if (pdata) {
smbdev->board.platform_data = kmemdup(pdata, pdata_size,
@@ -246,6 +252,9 @@ int psmouse_smbus_init(struct psmouse *psmouse,
}
}
 
+   if (need_deactivate)
+   psmouse_deactivate(psmouse);
+
psmouse->private = smbdev;
psmouse->protocol_handler = psmouse_smbus_process_byte;
psmouse->reconnect = psmouse_smbus_reconnect;
@@ -253,8 +262,6 @@ int psmouse_smbus_init(struct psmouse *psmouse,
psmouse->disconnect = psmouse_smbus_disconnect;
psmouse->resync_time = 0;
 
-   psmouse_deactivate(psmouse);
-
mutex_lock(_smbus_mutex);
list_add_tail(>node, _smbus_list);
mutex_unlock(_smbus_mutex);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index dd4ec1f602d7..64c3a5d3fb3e 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -225,6 +225,7 @@ struct i2c_board_info;
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs);
 void psmouse_smbus_cleanup(struct psmouse *psmouse);
 
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 14a1188561aa..6b1ed53a8b03 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1751,7 +1751,7 @@ static int synaptics_create_intertouch(struct psmouse 
*psmouse,
};
 
return psmouse_smbus_init(psmouse, _board,
- , sizeof(pdata),
+ , sizeof(pdata), true,
  leave_breadcrumbs);
 }
 
-- 
2.14.3



[PATCH v2 9/9] input: psmouse-smbus: allow to control psmouse_deactivate

2018-04-09 Thread Benjamin Tissoires
This seems to be Synaptics specific, as some Elan touchpads are not
correctly switching to SMBus if we call deactivate before switching to
SMBus on cold boot and on resume.

Tested with the T480s

Signed-off-by: Benjamin Tissoires 

---
changes in v2:
- rebased on top of previous
---
 drivers/input/mouse/elantech.c  |  2 +-
 drivers/input/mouse/psmouse-smbus.c | 13 ++---
 drivers/input/mouse/psmouse.h   |  1 +
 drivers/input/mouse/synaptics.c |  2 +-
 4 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 07e40a58e66c..fb4d902c4403 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1774,7 +1774,7 @@ static int elantech_create_smbus(struct psmouse *psmouse,
if (info->has_trackpoint)
smbus_board.properties = i2c_properties;
 
-   return psmouse_smbus_init(psmouse, _board, NULL, 0,
+   return psmouse_smbus_init(psmouse, _board, NULL, 0, false,
  leave_breadcrumbs);
 }
 
diff --git a/drivers/input/mouse/psmouse-smbus.c 
b/drivers/input/mouse/psmouse-smbus.c
index c8a3b1f35ce3..852d4b486ddb 100644
--- a/drivers/input/mouse/psmouse-smbus.c
+++ b/drivers/input/mouse/psmouse-smbus.c
@@ -23,6 +23,7 @@ struct psmouse_smbus_dev {
struct i2c_client *client;
struct list_head node;
bool dead;
+   bool need_deactivate;
 };
 
 static LIST_HEAD(psmouse_smbus_list);
@@ -118,7 +119,10 @@ static psmouse_ret_t psmouse_smbus_process_byte(struct 
psmouse *psmouse)
 
 static int psmouse_smbus_reconnect(struct psmouse *psmouse)
 {
-   psmouse_deactivate(psmouse);
+   struct psmouse_smbus_dev *smbdev = psmouse->private;
+
+   if (smbdev->need_deactivate)
+   psmouse_deactivate(psmouse);
 
return 0;
 }
@@ -225,6 +229,7 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse)
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs)
 {
struct psmouse_smbus_dev *smbdev;
@@ -236,6 +241,7 @@ int psmouse_smbus_init(struct psmouse *psmouse,
 
smbdev->psmouse = psmouse;
smbdev->board = *board;
+   smbdev->need_deactivate = need_deactivate;
 
if (pdata) {
smbdev->board.platform_data = kmemdup(pdata, pdata_size,
@@ -246,6 +252,9 @@ int psmouse_smbus_init(struct psmouse *psmouse,
}
}
 
+   if (need_deactivate)
+   psmouse_deactivate(psmouse);
+
psmouse->private = smbdev;
psmouse->protocol_handler = psmouse_smbus_process_byte;
psmouse->reconnect = psmouse_smbus_reconnect;
@@ -253,8 +262,6 @@ int psmouse_smbus_init(struct psmouse *psmouse,
psmouse->disconnect = psmouse_smbus_disconnect;
psmouse->resync_time = 0;
 
-   psmouse_deactivate(psmouse);
-
mutex_lock(_smbus_mutex);
list_add_tail(>node, _smbus_list);
mutex_unlock(_smbus_mutex);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index dd4ec1f602d7..64c3a5d3fb3e 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -225,6 +225,7 @@ struct i2c_board_info;
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs);
 void psmouse_smbus_cleanup(struct psmouse *psmouse);
 
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 14a1188561aa..6b1ed53a8b03 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1751,7 +1751,7 @@ static int synaptics_create_intertouch(struct psmouse 
*psmouse,
};
 
return psmouse_smbus_init(psmouse, _board,
- , sizeof(pdata),
+ , sizeof(pdata), true,
  leave_breadcrumbs);
 }
 
-- 
2.14.3



[PATCH v2 6/9] Input: elantech - query the resolution in query_info

2018-04-09 Thread Benjamin Tissoires
The command ETP_RESOLUTION_QUERY also contains the bus information.
It is better to fetch it once, while we are querying for device
information.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
no changes in v2

 drivers/input/mouse/elantech.c | 27 +++
 drivers/input/mouse/elantech.h |  2 ++
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 980dfd7e861e..a2a14a31edb5 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1179,7 +1179,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
struct elantech_data *etd = psmouse->private;
struct elantech_device_info *info = >info;
unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
-   unsigned int x_res = 31, y_res = 31;
 
if (elantech_set_range(psmouse, _min, _min, _max, _max, ))
return -1;
@@ -1232,13 +1231,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
 
case 4:
-   if (elantech_get_resolution_v4(psmouse, _res, _res)) {
-   /*
-* if query failed, print a warning and leave the values
-* zero to resemble synaptics.c behavior.
-*/
-   psmouse_warn(psmouse, "couldn't query resolution 
data.\n");
-   }
elantech_set_buttonpad_prop(psmouse);
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
/* For X to recognize me as touchpad. */
@@ -1267,11 +1259,11 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
}
 
-   input_abs_set_res(dev, ABS_X, x_res);
-   input_abs_set_res(dev, ABS_Y, y_res);
+   input_abs_set_res(dev, ABS_X, info->x_res);
+   input_abs_set_res(dev, ABS_Y, info->y_res);
if (info->hw_version > 1) {
-   input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
-   input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_X, info->x_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_Y, info->y_res);
}
 
etd->y_max = y_max;
@@ -1720,6 +1712,17 @@ static int elantech_query_info(struct psmouse *psmouse,
/* The MSB indicates the presence of the trackpoint */
info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
 
+   info->x_res = 31;
+   info->y_res = 31;
+   if (info->hw_version == 4) {
+   if (elantech_get_resolution_v4(psmouse,
+  >x_res,
+  >y_res)) {
+   psmouse_warn(psmouse,
+"failed to query resolution data.\n");
+   }
+   }
+
return 0;
 }
 
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index d8ac27fe4597..851df4ce6232 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -120,6 +120,8 @@ struct elantech_device_info {
unsigned char debug;
unsigned char hw_version;
unsigned int fw_version;
+   unsigned int x_res;
+   unsigned int y_res;
bool paritycheck;
bool jumpy_cursor;
bool reports_pressure;
-- 
2.14.3



[PATCH v2 3/9] Input: elan_i2c - add trackstick report

2018-04-09 Thread Benjamin Tissoires
The Elan touchpads over I2C/SMBus also can handle a
trackstick. Unfortunately, nothing tells us if the
device supports trackstick (the information lies in
the PS/2 node), so rely on a platform data to enable
or not the trackstick node.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=1313939

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

---

changes in v2:
- use of generic device property instead of platform data so
  device tree can also make use of it
---
 .../devicetree/bindings/input/elan_i2c.txt |  1 +
 drivers/input/mouse/elan_i2c_core.c| 90 +-
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/elan_i2c.txt 
b/Documentation/devicetree/bindings/input/elan_i2c.txt
index ee3242c4ba67..d80a83583238 100644
--- a/Documentation/devicetree/bindings/input/elan_i2c.txt
+++ b/Documentation/devicetree/bindings/input/elan_i2c.txt
@@ -14,6 +14,7 @@ Optional properties:
 - pinctrl-0: a phandle pointing to the pin settings for the device (see
   pinctrl binding [1]).
 - vcc-supply: a phandle for the regulator supplying 3.3V power.
+- elan,trackpoint: touchpad can support a trackpoint (boolean)
 
 [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 [1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
diff --git a/drivers/input/mouse/elan_i2c_core.c 
b/drivers/input/mouse/elan_i2c_core.c
index 75e757520ef0..44e970931926 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -51,6 +52,7 @@
 #define ETP_MAX_FINGERS5
 #define ETP_FINGER_DATA_LEN5
 #define ETP_REPORT_ID  0x5D
+#define ETP_TP_REPORT_ID   0x5E
 #define ETP_REPORT_ID_OFFSET   2
 #define ETP_TOUCH_INFO_OFFSET  3
 #define ETP_FINGER_DATA_OFFSET 4
@@ -61,6 +63,7 @@
 struct elan_tp_data {
struct i2c_client   *client;
struct input_dev*input;
+   struct input_dev*tp_input; /* trackpoint input node */
struct regulator*vcc;
 
const struct elan_transport_ops *ops;
@@ -930,6 +933,34 @@ static void elan_report_absolute(struct elan_tp_data 
*data, u8 *packet)
input_sync(input);
 }
 
+static void elan_report_trackpoint(struct elan_tp_data *data, u8 *report)
+{
+   struct input_dev *input = data->tp_input;
+   u8 *packet = [ETP_REPORT_ID_OFFSET + 1];
+   int x, y;
+
+   if (!data->tp_input) {
+   dev_warn_once(>client->dev,
+ "received a trackpoint report while no trackpoint 
device has been created.\n"
+ "Please report upstream.\n");
+   return;
+   }
+
+   input_report_key(input, BTN_LEFT, packet[0] & 0x01);
+   input_report_key(input, BTN_RIGHT, packet[0] & 0x02);
+   input_report_key(input, BTN_MIDDLE, packet[0] & 0x04);
+
+   if ((packet[3] & 0x0F) == 0x06) {
+   x = packet[4] - (int)((packet[1]^0x80) << 1);
+   y = (int)((packet[2]^0x80) << 1) - packet[5];
+
+   input_report_rel(input, REL_X, x);
+   input_report_rel(input, REL_Y, y);
+   }
+
+   input_sync(input);
+}
+
 static irqreturn_t elan_isr(int irq, void *dev_id)
 {
struct elan_tp_data *data = dev_id;
@@ -951,11 +982,17 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
if (error)
goto out;
 
-   if (report[ETP_REPORT_ID_OFFSET] != ETP_REPORT_ID)
+   switch (report[ETP_REPORT_ID_OFFSET]) {
+   case ETP_REPORT_ID:
+   elan_report_absolute(data, report);
+   break;
+   case ETP_TP_REPORT_ID:
+   elan_report_trackpoint(data, report);
+   break;
+   default:
dev_err(dev, "invalid report id data (%x)\n",
report[ETP_REPORT_ID_OFFSET]);
-   else
-   elan_report_absolute(data, report);
+   }
 
 out:
return IRQ_HANDLED;
@@ -966,6 +1003,37 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
  * Elan initialization functions
  **
  */
+
+static int elan_setup_trackpoint_input_device(struct elan_tp_data *data)
+{
+   struct device *dev = >client->dev;
+   struct input_dev *input;
+
+   input = devm_input_allocate_device(dev);
+   if (!input)
+   return -ENOMEM;
+
+   input->name = "Elan TrackPoint";
+   input->id.bustype = BUS_I2C;
+   input->id.vendor = ELAN_VENDOR_ID;
+   input->id.product = data->product_id;
+   input_set_drvdata(input, data);
+
+   input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+   input->relbit[BIT_WORD(REL_X)] =
+   BIT_MASK(RE

[PATCH v2 3/9] Input: elan_i2c - add trackstick report

2018-04-09 Thread Benjamin Tissoires
The Elan touchpads over I2C/SMBus also can handle a
trackstick. Unfortunately, nothing tells us if the
device supports trackstick (the information lies in
the PS/2 node), so rely on a platform data to enable
or not the trackstick node.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=1313939

Signed-off-by: Benjamin Tissoires 

---

changes in v2:
- use of generic device property instead of platform data so
  device tree can also make use of it
---
 .../devicetree/bindings/input/elan_i2c.txt |  1 +
 drivers/input/mouse/elan_i2c_core.c| 90 +-
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/elan_i2c.txt 
b/Documentation/devicetree/bindings/input/elan_i2c.txt
index ee3242c4ba67..d80a83583238 100644
--- a/Documentation/devicetree/bindings/input/elan_i2c.txt
+++ b/Documentation/devicetree/bindings/input/elan_i2c.txt
@@ -14,6 +14,7 @@ Optional properties:
 - pinctrl-0: a phandle pointing to the pin settings for the device (see
   pinctrl binding [1]).
 - vcc-supply: a phandle for the regulator supplying 3.3V power.
+- elan,trackpoint: touchpad can support a trackpoint (boolean)
 
 [0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
 [1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
diff --git a/drivers/input/mouse/elan_i2c_core.c 
b/drivers/input/mouse/elan_i2c_core.c
index 75e757520ef0..44e970931926 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -51,6 +52,7 @@
 #define ETP_MAX_FINGERS5
 #define ETP_FINGER_DATA_LEN5
 #define ETP_REPORT_ID  0x5D
+#define ETP_TP_REPORT_ID   0x5E
 #define ETP_REPORT_ID_OFFSET   2
 #define ETP_TOUCH_INFO_OFFSET  3
 #define ETP_FINGER_DATA_OFFSET 4
@@ -61,6 +63,7 @@
 struct elan_tp_data {
struct i2c_client   *client;
struct input_dev*input;
+   struct input_dev*tp_input; /* trackpoint input node */
struct regulator*vcc;
 
const struct elan_transport_ops *ops;
@@ -930,6 +933,34 @@ static void elan_report_absolute(struct elan_tp_data 
*data, u8 *packet)
input_sync(input);
 }
 
+static void elan_report_trackpoint(struct elan_tp_data *data, u8 *report)
+{
+   struct input_dev *input = data->tp_input;
+   u8 *packet = [ETP_REPORT_ID_OFFSET + 1];
+   int x, y;
+
+   if (!data->tp_input) {
+   dev_warn_once(>client->dev,
+ "received a trackpoint report while no trackpoint 
device has been created.\n"
+ "Please report upstream.\n");
+   return;
+   }
+
+   input_report_key(input, BTN_LEFT, packet[0] & 0x01);
+   input_report_key(input, BTN_RIGHT, packet[0] & 0x02);
+   input_report_key(input, BTN_MIDDLE, packet[0] & 0x04);
+
+   if ((packet[3] & 0x0F) == 0x06) {
+   x = packet[4] - (int)((packet[1]^0x80) << 1);
+   y = (int)((packet[2]^0x80) << 1) - packet[5];
+
+   input_report_rel(input, REL_X, x);
+   input_report_rel(input, REL_Y, y);
+   }
+
+   input_sync(input);
+}
+
 static irqreturn_t elan_isr(int irq, void *dev_id)
 {
struct elan_tp_data *data = dev_id;
@@ -951,11 +982,17 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
if (error)
goto out;
 
-   if (report[ETP_REPORT_ID_OFFSET] != ETP_REPORT_ID)
+   switch (report[ETP_REPORT_ID_OFFSET]) {
+   case ETP_REPORT_ID:
+   elan_report_absolute(data, report);
+   break;
+   case ETP_TP_REPORT_ID:
+   elan_report_trackpoint(data, report);
+   break;
+   default:
dev_err(dev, "invalid report id data (%x)\n",
report[ETP_REPORT_ID_OFFSET]);
-   else
-   elan_report_absolute(data, report);
+   }
 
 out:
return IRQ_HANDLED;
@@ -966,6 +1003,37 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
  * Elan initialization functions
  **
  */
+
+static int elan_setup_trackpoint_input_device(struct elan_tp_data *data)
+{
+   struct device *dev = >client->dev;
+   struct input_dev *input;
+
+   input = devm_input_allocate_device(dev);
+   if (!input)
+   return -ENOMEM;
+
+   input->name = "Elan TrackPoint";
+   input->id.bustype = BUS_I2C;
+   input->id.vendor = ELAN_VENDOR_ID;
+   input->id.product = data->product_id;
+   input_set_drvdata(input, data);
+
+   input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+   input->relbit[BIT_WORD(REL_X)] =
+   BIT_MASK(REL_X) | BIT_MASK(R

[PATCH v2 6/9] Input: elantech - query the resolution in query_info

2018-04-09 Thread Benjamin Tissoires
The command ETP_RESOLUTION_QUERY also contains the bus information.
It is better to fetch it once, while we are querying for device
information.

Signed-off-by: Benjamin Tissoires 
---
no changes in v2

 drivers/input/mouse/elantech.c | 27 +++
 drivers/input/mouse/elantech.h |  2 ++
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 980dfd7e861e..a2a14a31edb5 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1179,7 +1179,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
struct elantech_data *etd = psmouse->private;
struct elantech_device_info *info = >info;
unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
-   unsigned int x_res = 31, y_res = 31;
 
if (elantech_set_range(psmouse, _min, _min, _max, _max, ))
return -1;
@@ -1232,13 +1231,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
 
case 4:
-   if (elantech_get_resolution_v4(psmouse, _res, _res)) {
-   /*
-* if query failed, print a warning and leave the values
-* zero to resemble synaptics.c behavior.
-*/
-   psmouse_warn(psmouse, "couldn't query resolution 
data.\n");
-   }
elantech_set_buttonpad_prop(psmouse);
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
/* For X to recognize me as touchpad. */
@@ -1267,11 +1259,11 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
}
 
-   input_abs_set_res(dev, ABS_X, x_res);
-   input_abs_set_res(dev, ABS_Y, y_res);
+   input_abs_set_res(dev, ABS_X, info->x_res);
+   input_abs_set_res(dev, ABS_Y, info->y_res);
if (info->hw_version > 1) {
-   input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
-   input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_X, info->x_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_Y, info->y_res);
}
 
etd->y_max = y_max;
@@ -1720,6 +1712,17 @@ static int elantech_query_info(struct psmouse *psmouse,
/* The MSB indicates the presence of the trackpoint */
info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
 
+   info->x_res = 31;
+   info->y_res = 31;
+   if (info->hw_version == 4) {
+   if (elantech_get_resolution_v4(psmouse,
+  >x_res,
+  >y_res)) {
+   psmouse_warn(psmouse,
+"failed to query resolution data.\n");
+   }
+   }
+
return 0;
 }
 
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index d8ac27fe4597..851df4ce6232 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -120,6 +120,8 @@ struct elantech_device_info {
unsigned char debug;
unsigned char hw_version;
unsigned int fw_version;
+   unsigned int x_res;
+   unsigned int y_res;
bool paritycheck;
bool jumpy_cursor;
bool reports_pressure;
-- 
2.14.3



[PATCH v2 1/9] Input: synaptics - add Lenovo 80 series ids to SMBus

2018-04-09 Thread Benjamin Tissoires
This time, Lenovo decided to go with different pieces in its latest series
of Thinkpads.

For those we have been able to test:
- the T480 is using Synaptics with an IBM trackpoint
   -> it behaves properly with or without intertouch, there is no point
  not using RMI4
- the X1 Carbon 6th gen is using Synaptics with an IBM trackpoint
   -> the touchpad doesn't behave properly under PS/2 so we have to
  switch it to RMI4 if we do not want to have disappointed users
- the X280 is using Synaptics with an ALPS trackpoint
   -> the recent fixes in the trackpoint handling fixed it so upstream
  now works fine with or without RMI4, and there is no point not
  using RMI4
- the T480s is using an Elan touchpad, so that's a different story

Cc: <sta...@vger.kernel.org> # v4.14.x, v4.15.x, v4.16.x
Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
no changes in v2

 drivers/input/mouse/synaptics.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 60f2c463d1cc..14a1188561aa 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -173,6 +173,9 @@ static const char * const smbus_pnp_ids[] = {
"LEN0046", /* X250 */
"LEN004a", /* W541 */
"LEN200f", /* T450s */
+   "LEN0071", /* T480 */
+   "LEN0092", /* X1 Carbon 6th gen */
+   "LEN0097", /* X280 -> ALPS trackpoint */
NULL
 };
 
-- 
2.14.3



[PATCH v2 1/9] Input: synaptics - add Lenovo 80 series ids to SMBus

2018-04-09 Thread Benjamin Tissoires
This time, Lenovo decided to go with different pieces in its latest series
of Thinkpads.

For those we have been able to test:
- the T480 is using Synaptics with an IBM trackpoint
   -> it behaves properly with or without intertouch, there is no point
  not using RMI4
- the X1 Carbon 6th gen is using Synaptics with an IBM trackpoint
   -> the touchpad doesn't behave properly under PS/2 so we have to
  switch it to RMI4 if we do not want to have disappointed users
- the X280 is using Synaptics with an ALPS trackpoint
   -> the recent fixes in the trackpoint handling fixed it so upstream
  now works fine with or without RMI4, and there is no point not
  using RMI4
- the T480s is using an Elan touchpad, so that's a different story

Cc:  # v4.14.x, v4.15.x, v4.16.x
Signed-off-by: Benjamin Tissoires 
---
no changes in v2

 drivers/input/mouse/synaptics.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 60f2c463d1cc..14a1188561aa 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -173,6 +173,9 @@ static const char * const smbus_pnp_ids[] = {
"LEN0046", /* X250 */
"LEN004a", /* W541 */
"LEN200f", /* T450s */
+   "LEN0071", /* T480 */
+   "LEN0092", /* X1 Carbon 6th gen */
+   "LEN0097", /* X280 -> ALPS trackpoint */
NULL
 };
 
-- 
2.14.3



Re: [PATCH 3/8] Input: elan_i2c - add trackstick report

2018-04-06 Thread Benjamin Tissoires
On Fri, Apr 6, 2018 at 1:46 AM, Dmitry Torokhov
<dmitry.torok...@gmail.com> wrote:
> Hi Benjamin,
>
> On Thu, Apr 05, 2018 at 03:25:32PM +0200, Benjamin Tissoires wrote:
>> The Elan touchpads over I2C/SMBus also can handle a
>> trackstick. Unfortunately, nothing tells us if the
>> device supports trackstick (the information lies in
>> the PS/2 node), so rely on a platform data to enable
>> or not the trackstick node.
>
> Hmm, I'd prefer if we did not add more platform data but rather user
> generic device properties.
>

Fair enough, I'll work on it for v2.

Cheers,
Benjamin


Re: [PATCH 3/8] Input: elan_i2c - add trackstick report

2018-04-06 Thread Benjamin Tissoires
On Fri, Apr 6, 2018 at 1:46 AM, Dmitry Torokhov
 wrote:
> Hi Benjamin,
>
> On Thu, Apr 05, 2018 at 03:25:32PM +0200, Benjamin Tissoires wrote:
>> The Elan touchpads over I2C/SMBus also can handle a
>> trackstick. Unfortunately, nothing tells us if the
>> device supports trackstick (the information lies in
>> the PS/2 node), so rely on a platform data to enable
>> or not the trackstick node.
>
> Hmm, I'd prefer if we did not add more platform data but rather user
> generic device properties.
>

Fair enough, I'll work on it for v2.

Cheers,
Benjamin


Re: [PATCH 0/8] Input: support for latest Lenovo thinkpads (series 80)

2018-04-06 Thread Benjamin Tissoires
Hi Dmitry,

On Fri, Apr 6, 2018 at 1:51 AM, Dmitry Torokhov
<dmitry.torok...@gmail.com> wrote:
> Hi Benjamin,
>
> On Thu, Apr 05, 2018 at 03:25:29PM +0200, Benjamin Tissoires wrote:
>> Hi Dmitry,
>>
>> well, this year, Lenovo gave us a surprise and decided to not use
>> the same touchpad/trackstick in all its model. And by default, the
>> support under Linux is less than ideal.
>>
>> Please find a series that should fix those issues. Compared to the 60
>> series, there do not seem to e BIOS table issues this time, and 
>> suspend/resume
>> works fine thanks to your latest trackstick fixes.
>>
>> The T480s is a different beast, as it uses an Elan touchpad.
>> I have been carrying the patches 3-6 for a while and tested previous
>> versions on various Elan PS/2 hardware without an issue as far as I
>> could tell. I was lacking tests from users with SMBus as all the laptops
>> I tried where puer PS/2.
>>
>> Anyway, it would be cool if you could have a look at the series.
>
> I am mostly happy with the series, but I would love to hear KT's take on
> it.

thanks for the quick review.
I worked closely with KT for this series. He helped me a lot for the
tiny firmware changes that were required. However, quoting his email
from Tuesday:
"There will be a spring vacation in Taiwan from tomorrow." I guess we
won't hear from him until the end of next week as we always have a
backlog of urgent things to do after holidays...

Cheers,
Benjamin


Re: [PATCH 0/8] Input: support for latest Lenovo thinkpads (series 80)

2018-04-06 Thread Benjamin Tissoires
Hi Dmitry,

On Fri, Apr 6, 2018 at 1:51 AM, Dmitry Torokhov
 wrote:
> Hi Benjamin,
>
> On Thu, Apr 05, 2018 at 03:25:29PM +0200, Benjamin Tissoires wrote:
>> Hi Dmitry,
>>
>> well, this year, Lenovo gave us a surprise and decided to not use
>> the same touchpad/trackstick in all its model. And by default, the
>> support under Linux is less than ideal.
>>
>> Please find a series that should fix those issues. Compared to the 60
>> series, there do not seem to e BIOS table issues this time, and 
>> suspend/resume
>> works fine thanks to your latest trackstick fixes.
>>
>> The T480s is a different beast, as it uses an Elan touchpad.
>> I have been carrying the patches 3-6 for a while and tested previous
>> versions on various Elan PS/2 hardware without an issue as far as I
>> could tell. I was lacking tests from users with SMBus as all the laptops
>> I tried where puer PS/2.
>>
>> Anyway, it would be cool if you could have a look at the series.
>
> I am mostly happy with the series, but I would love to hear KT's take on
> it.

thanks for the quick review.
I worked closely with KT for this series. He helped me a lot for the
tiny firmware changes that were required. However, quoting his email
from Tuesday:
"There will be a spring vacation in Taiwan from tomorrow." I guess we
won't hear from him until the end of next week as we always have a
backlog of urgent things to do after holidays...

Cheers,
Benjamin


[PATCH 0/8] Input: support for latest Lenovo thinkpads (series 80)

2018-04-05 Thread Benjamin Tissoires
Hi Dmitry,

well, this year, Lenovo gave us a surprise and decided to not use
the same touchpad/trackstick in all its model. And by default, the
support under Linux is less than ideal.

Please find a series that should fix those issues. Compared to the 60
series, there do not seem to e BIOS table issues this time, and suspend/resume
works fine thanks to your latest trackstick fixes.

The T480s is a different beast, as it uses an Elan touchpad.
I have been carrying the patches 3-6 for a while and tested previous
versions on various Elan PS/2 hardware without an issue as far as I
could tell. I was lacking tests from users with SMBus as all the laptops
I tried where puer PS/2.

Anyway, it would be cool if you could have a look at the series.

Cheers,
Benjamin

Benjamin Tissoires (8):
  Input: synaptics - add Lenovo 80 series ids to SMBus
  input: elan_i2c_smbus - fix corrupted stack
  Input: elan_i2c - add trackstick report
  Input: elantech - split device info into a separate structure
  Input: elantech - query the resolution in query_info
  Input: elantech - add support for SMBus devices
  Input: elantech - detect new ICs and setup Host Notify for them
  input: psmouse-smbus: allow to control psmouse_deactivate

 drivers/input/mouse/Kconfig  |  12 +
 drivers/input/mouse/elan_i2c.h   |  10 +
 drivers/input/mouse/elan_i2c_core.c  |  91 ++-
 drivers/input/mouse/elan_i2c_smbus.c |  22 +-
 drivers/input/mouse/elantech.c   | 475 ++-
 drivers/input/mouse/elantech.h   |  69 -
 drivers/input/mouse/psmouse-base.c   |  21 +-
 drivers/input/mouse/psmouse-smbus.c  |  13 +-
 drivers/input/mouse/psmouse.h|   2 +
 drivers/input/mouse/synaptics.c  |   5 +-
 10 files changed, 564 insertions(+), 156 deletions(-)

-- 
2.14.3



[PATCH 0/8] Input: support for latest Lenovo thinkpads (series 80)

2018-04-05 Thread Benjamin Tissoires
Hi Dmitry,

well, this year, Lenovo gave us a surprise and decided to not use
the same touchpad/trackstick in all its model. And by default, the
support under Linux is less than ideal.

Please find a series that should fix those issues. Compared to the 60
series, there do not seem to e BIOS table issues this time, and suspend/resume
works fine thanks to your latest trackstick fixes.

The T480s is a different beast, as it uses an Elan touchpad.
I have been carrying the patches 3-6 for a while and tested previous
versions on various Elan PS/2 hardware without an issue as far as I
could tell. I was lacking tests from users with SMBus as all the laptops
I tried where puer PS/2.

Anyway, it would be cool if you could have a look at the series.

Cheers,
Benjamin

Benjamin Tissoires (8):
  Input: synaptics - add Lenovo 80 series ids to SMBus
  input: elan_i2c_smbus - fix corrupted stack
  Input: elan_i2c - add trackstick report
  Input: elantech - split device info into a separate structure
  Input: elantech - query the resolution in query_info
  Input: elantech - add support for SMBus devices
  Input: elantech - detect new ICs and setup Host Notify for them
  input: psmouse-smbus: allow to control psmouse_deactivate

 drivers/input/mouse/Kconfig  |  12 +
 drivers/input/mouse/elan_i2c.h   |  10 +
 drivers/input/mouse/elan_i2c_core.c  |  91 ++-
 drivers/input/mouse/elan_i2c_smbus.c |  22 +-
 drivers/input/mouse/elantech.c   | 475 ++-
 drivers/input/mouse/elantech.h   |  69 -
 drivers/input/mouse/psmouse-base.c   |  21 +-
 drivers/input/mouse/psmouse-smbus.c  |  13 +-
 drivers/input/mouse/psmouse.h|   2 +
 drivers/input/mouse/synaptics.c  |   5 +-
 10 files changed, 564 insertions(+), 156 deletions(-)

-- 
2.14.3



[PATCH 2/8] input: elan_i2c_smbus - fix corrupted stack

2018-04-05 Thread Benjamin Tissoires
New ICs (like the one on the Lenovo T480s) answer to
ETP_SMBUS_IAP_VERSION_CMD 4 bytes instead of 3. This corrupts the stack
as i2c_smbus_read_block_data() uses the values returned by the i2c
device to know how many data it need to return.

i2c_smbus_read_block_data() can read up to 32 bytes (I2C_SMBUS_BLOCK_MAX)
and there is no safeguard on how many bytes are provided in the return
value. Ensure we always have enough space for any future firmware.
Also 0-initialize the values to prevent any access to uninitialized memory.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/input/mouse/elan_i2c_smbus.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/input/mouse/elan_i2c_smbus.c 
b/drivers/input/mouse/elan_i2c_smbus.c
index 29f99529b187..cfcb32559925 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -130,7 +130,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client 
*client,
bool max_baseline, u8 *value)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  max_baseline ?
@@ -149,7 +149,7 @@ static int elan_smbus_get_version(struct i2c_client *client,
  bool iap, u8 *version)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_IAP_VERSION_CMD :
@@ -170,7 +170,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 u8 *clickpad)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_SM_VERSION_CMD, val);
@@ -188,7 +188,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_UNIQUEID_CMD, val);
@@ -205,7 +205,7 @@ static int elan_smbus_get_checksum(struct i2c_client 
*client,
   bool iap, u16 *csum)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_FW_CHECKSUM_CMD :
@@ -226,7 +226,7 @@ static int elan_smbus_get_max(struct i2c_client *client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val);
if (ret != 3) {
@@ -246,7 +246,7 @@ static int elan_smbus_get_resolution(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val);
if (ret != 3) {
@@ -267,7 +267,7 @@ static int elan_smbus_get_num_traces(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val);
if (ret != 3) {
@@ -294,7 +294,7 @@ static int elan_smbus_iap_get_mode(struct i2c_client 
*client,
 {
int error;
u16 constant;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val);
if (error < 0) {
@@ -345,7 +345,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client 
*client)
int len;
int error;
enum tp_mode mode;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06};
u16 password;
 
@@ -419,7 +419,7 @@ static int elan_smbus_write_fw_block(struct i2c_client 
*client,
struct device *dev = >dev;
int error;
u16 result;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
/*
 * Due to the limitation of smbus protocol limiting
-- 
2.14.3



[PATCH 2/8] input: elan_i2c_smbus - fix corrupted stack

2018-04-05 Thread Benjamin Tissoires
New ICs (like the one on the Lenovo T480s) answer to
ETP_SMBUS_IAP_VERSION_CMD 4 bytes instead of 3. This corrupts the stack
as i2c_smbus_read_block_data() uses the values returned by the i2c
device to know how many data it need to return.

i2c_smbus_read_block_data() can read up to 32 bytes (I2C_SMBUS_BLOCK_MAX)
and there is no safeguard on how many bytes are provided in the return
value. Ensure we always have enough space for any future firmware.
Also 0-initialize the values to prevent any access to uninitialized memory.

Signed-off-by: Benjamin Tissoires 
---
 drivers/input/mouse/elan_i2c_smbus.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/input/mouse/elan_i2c_smbus.c 
b/drivers/input/mouse/elan_i2c_smbus.c
index 29f99529b187..cfcb32559925 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -130,7 +130,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client 
*client,
bool max_baseline, u8 *value)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  max_baseline ?
@@ -149,7 +149,7 @@ static int elan_smbus_get_version(struct i2c_client *client,
  bool iap, u8 *version)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_IAP_VERSION_CMD :
@@ -170,7 +170,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 u8 *clickpad)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_SM_VERSION_CMD, val);
@@ -188,7 +188,7 @@ static int elan_smbus_get_sm_version(struct i2c_client 
*client,
 static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  ETP_SMBUS_UNIQUEID_CMD, val);
@@ -205,7 +205,7 @@ static int elan_smbus_get_checksum(struct i2c_client 
*client,
   bool iap, u16 *csum)
 {
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client,
  iap ? ETP_SMBUS_FW_CHECKSUM_CMD :
@@ -226,7 +226,7 @@ static int elan_smbus_get_max(struct i2c_client *client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val);
if (ret != 3) {
@@ -246,7 +246,7 @@ static int elan_smbus_get_resolution(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val);
if (ret != 3) {
@@ -267,7 +267,7 @@ static int elan_smbus_get_num_traces(struct i2c_client 
*client,
 {
int ret;
int error;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val);
if (ret != 3) {
@@ -294,7 +294,7 @@ static int elan_smbus_iap_get_mode(struct i2c_client 
*client,
 {
int error;
u16 constant;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val);
if (error < 0) {
@@ -345,7 +345,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client 
*client)
int len;
int error;
enum tp_mode mode;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06};
u16 password;
 
@@ -419,7 +419,7 @@ static int elan_smbus_write_fw_block(struct i2c_client 
*client,
struct device *dev = >dev;
int error;
u16 result;
-   u8 val[3];
+   u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
 
/*
 * Due to the limitation of smbus protocol limiting
-- 
2.14.3



[PATCH 1/8] Input: synaptics - add Lenovo 80 series ids to SMBus

2018-04-05 Thread Benjamin Tissoires
This time, Lenovo decided to go with different pieces in its latest series
of Thinkpads.

For those we have been able to test:
- the T480 is using Synaptics with an IBM trackpoint
   -> it behaves properly with or without intertouch, there is no point
  not using RMI4
- the X1 Carbon 6th gen is using Synaptics with an IBM trackpoint
   -> the touchpad doesn't behave properly under PS/2 so we have to
  switch it to RMI4 if we do not want to have disappointed users
- the X280 is using Synaptics with an ALPS trackpoint
   -> the recent fixes in the trackpoint handling fixed it so upstream
  now works fine with or without RMI4, and there is no point not
  using RMI4
- the T480s is using an Elan touchpad, so that's a different story

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/input/mouse/synaptics.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 60f2c463d1cc..14a1188561aa 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -173,6 +173,9 @@ static const char * const smbus_pnp_ids[] = {
"LEN0046", /* X250 */
"LEN004a", /* W541 */
"LEN200f", /* T450s */
+   "LEN0071", /* T480 */
+   "LEN0092", /* X1 Carbon 6th gen */
+   "LEN0097", /* X280 -> ALPS trackpoint */
NULL
 };
 
-- 
2.14.3



[PATCH 1/8] Input: synaptics - add Lenovo 80 series ids to SMBus

2018-04-05 Thread Benjamin Tissoires
This time, Lenovo decided to go with different pieces in its latest series
of Thinkpads.

For those we have been able to test:
- the T480 is using Synaptics with an IBM trackpoint
   -> it behaves properly with or without intertouch, there is no point
  not using RMI4
- the X1 Carbon 6th gen is using Synaptics with an IBM trackpoint
   -> the touchpad doesn't behave properly under PS/2 so we have to
  switch it to RMI4 if we do not want to have disappointed users
- the X280 is using Synaptics with an ALPS trackpoint
   -> the recent fixes in the trackpoint handling fixed it so upstream
  now works fine with or without RMI4, and there is no point not
  using RMI4
- the T480s is using an Elan touchpad, so that's a different story

Signed-off-by: Benjamin Tissoires 
---
 drivers/input/mouse/synaptics.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 60f2c463d1cc..14a1188561aa 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -173,6 +173,9 @@ static const char * const smbus_pnp_ids[] = {
"LEN0046", /* X250 */
"LEN004a", /* W541 */
"LEN200f", /* T450s */
+   "LEN0071", /* T480 */
+   "LEN0092", /* X1 Carbon 6th gen */
+   "LEN0097", /* X280 -> ALPS trackpoint */
NULL
 };
 
-- 
2.14.3



[PATCH 4/8] Input: elantech - split device info into a separate structure

2018-04-05 Thread Benjamin Tissoires
In preparation for SMBus device support, move static device
information that we query form the touchpad upon initialization into
separate structure. This will allow us to query the device without
allocating memory first.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/input/mouse/elantech.c | 271 -
 drivers/input/mouse/elantech.h |  28 +++--
 2 files changed, 175 insertions(+), 124 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index db47a5e1d114..d485664f1563 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -24,7 +24,7 @@
 
 #define elantech_debug(fmt, ...)   \
do {\
-   if (etd->debug) \
+   if (etd->info.debug)\
psmouse_printk(KERN_DEBUG, psmouse, \
fmt, ##__VA_ARGS__);\
} while (0)
@@ -105,7 +105,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_READ) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -137,7 +137,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
 
if (rc)
psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
-   else if (etd->hw_version != 4)
+   else if (etd->info.hw_version != 4)
*val = param[0];
else
*val = param[1];
@@ -160,7 +160,7 @@ static int elantech_write_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_WRITE) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -237,7 +237,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
unsigned char *packet = psmouse->packet;
int fingers;
 
-   if (etd->fw_version < 0x02) {
+   if (etd->info.fw_version < 0x02) {
/*
 * byte 0:  D   U  p1  p2   1  p3   R   L
 * byte 1:  f   0  th  tw  x9  x8  y9  y8
@@ -252,7 +252,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
fingers = (packet[0] & 0xc0) >> 6;
}
 
-   if (etd->jumpy_cursor) {
+   if (etd->info.jumpy_cursor) {
if (fingers != 1) {
etd->single_finger_reports = 0;
} else if (etd->single_finger_reports < 2) {
@@ -282,8 +282,8 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
 
psmouse_report_standard_buttons(dev, packet[0]);
 
-   if (etd->fw_version < 0x02 &&
-   (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
+   if (etd->info.fw_version < 0x02 &&
+   (etd->info.capabilities[0] & ETP_CAP_HAS_ROCKER)) {
/* rocker up */
input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
/* rocker down */
@@ -391,7 +391,7 @@ static void elantech_report_absolute_v2(struct psmouse 
*psmouse)
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
psmouse_report_standard_buttons(dev, packet[0]);
-   if (etd->reports_pressure) {
+   if (etd->info.reports_pressure) {
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
}
@@ -444,7 +444,7 @@ static void elantech_report_trackpoint(struct psmouse 
*psmouse,
 
default:
/* Dump unexpected packet sequences if debug=1 (default) */
-   if (etd->debug == 1)
+   if (etd->info.debug == 1)
elantech_packet_dump(psmouse);
 
break;
@@ -523,7 +523,7 @@ static void elantech_report_absolute_v3(struct psmouse 
*psmouse,
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
 
/* For clickpads map both buttons to BTN_LEFT */
-   if (etd->fw_version & 0x001000)
+   if (etd->info.fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
else
psmouse_report_standard_buttons(dev, packet[0]);
@@ -541,7 +541,7 @@ static voi

[PATCH 4/8] Input: elantech - split device info into a separate structure

2018-04-05 Thread Benjamin Tissoires
In preparation for SMBus device support, move static device
information that we query form the touchpad upon initialization into
separate structure. This will allow us to query the device without
allocating memory first.

Signed-off-by: Benjamin Tissoires 
---
 drivers/input/mouse/elantech.c | 271 -
 drivers/input/mouse/elantech.h |  28 +++--
 2 files changed, 175 insertions(+), 124 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index db47a5e1d114..d485664f1563 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -24,7 +24,7 @@
 
 #define elantech_debug(fmt, ...)   \
do {\
-   if (etd->debug) \
+   if (etd->info.debug)\
psmouse_printk(KERN_DEBUG, psmouse, \
fmt, ##__VA_ARGS__);\
} while (0)
@@ -105,7 +105,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_READ) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -137,7 +137,7 @@ static int elantech_read_reg(struct psmouse *psmouse, 
unsigned char reg,
 
if (rc)
psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg);
-   else if (etd->hw_version != 4)
+   else if (etd->info.hw_version != 4)
*val = param[0];
else
*val = param[1];
@@ -160,7 +160,7 @@ static int elantech_write_reg(struct psmouse *psmouse, 
unsigned char reg,
if (reg > 0x11 && reg < 0x20)
return -1;
 
-   switch (etd->hw_version) {
+   switch (etd->info.hw_version) {
case 1:
if (ps2_sliced_command(>ps2dev, ETP_REGISTER_WRITE) ||
ps2_sliced_command(>ps2dev, reg) ||
@@ -237,7 +237,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
unsigned char *packet = psmouse->packet;
int fingers;
 
-   if (etd->fw_version < 0x02) {
+   if (etd->info.fw_version < 0x02) {
/*
 * byte 0:  D   U  p1  p2   1  p3   R   L
 * byte 1:  f   0  th  tw  x9  x8  y9  y8
@@ -252,7 +252,7 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
fingers = (packet[0] & 0xc0) >> 6;
}
 
-   if (etd->jumpy_cursor) {
+   if (etd->info.jumpy_cursor) {
if (fingers != 1) {
etd->single_finger_reports = 0;
} else if (etd->single_finger_reports < 2) {
@@ -282,8 +282,8 @@ static void elantech_report_absolute_v1(struct psmouse 
*psmouse)
 
psmouse_report_standard_buttons(dev, packet[0]);
 
-   if (etd->fw_version < 0x02 &&
-   (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) {
+   if (etd->info.fw_version < 0x02 &&
+   (etd->info.capabilities[0] & ETP_CAP_HAS_ROCKER)) {
/* rocker up */
input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
/* rocker down */
@@ -391,7 +391,7 @@ static void elantech_report_absolute_v2(struct psmouse 
*psmouse)
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4);
psmouse_report_standard_buttons(dev, packet[0]);
-   if (etd->reports_pressure) {
+   if (etd->info.reports_pressure) {
input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width);
}
@@ -444,7 +444,7 @@ static void elantech_report_trackpoint(struct psmouse 
*psmouse,
 
default:
/* Dump unexpected packet sequences if debug=1 (default) */
-   if (etd->debug == 1)
+   if (etd->info.debug == 1)
elantech_packet_dump(psmouse);
 
break;
@@ -523,7 +523,7 @@ static void elantech_report_absolute_v3(struct psmouse 
*psmouse,
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
 
/* For clickpads map both buttons to BTN_LEFT */
-   if (etd->fw_version & 0x001000)
+   if (etd->info.fw_version & 0x001000)
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
else
psmouse_report_standard_buttons(dev, packet[0]);
@@ -541,7 +541,7 @@ static void elantech_input_sync_v4(struct psmouse 

[PATCH 3/8] Input: elan_i2c - add trackstick report

2018-04-05 Thread Benjamin Tissoires
The Elan touchpads over I2C/SMBus also can handle a
trackstick. Unfortunately, nothing tells us if the
device supports trackstick (the information lies in
the PS/2 node), so rely on a platform data to enable
or not the trackstick node.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=1313939

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>

---

changes in v2:
- renamed ETP_PT_REPORT_ID into ETP_TP_REPORT_ID (pass-through to track-point)
  to stay more in line with the rest
- removed Host Notify support so amended to match parent
---
 drivers/input/mouse/elan_i2c.h  | 10 
 drivers/input/mouse/elan_i2c_core.c | 91 +++--
 2 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index 599544c1a91c..8f9c97267bc9 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -87,4 +87,14 @@ struct elan_transport_ops {
 
 extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops;
 
+/**
+ * struct elan_platform_data - system specific configuration info.
+ *
+ * @trackpoint - specify whether or not you want the trackstick input node to
+ * be created and handled by the driver.
+ */
+struct elan_platform_data {
+   bool trackpoint;
+};
+
 #endif /* _ELAN_I2C_H */
diff --git a/drivers/input/mouse/elan_i2c_core.c 
b/drivers/input/mouse/elan_i2c_core.c
index 75e757520ef0..8ed1e2a8a4dd 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -51,6 +51,7 @@
 #define ETP_MAX_FINGERS5
 #define ETP_FINGER_DATA_LEN5
 #define ETP_REPORT_ID  0x5D
+#define ETP_TP_REPORT_ID   0x5E
 #define ETP_REPORT_ID_OFFSET   2
 #define ETP_TOUCH_INFO_OFFSET  3
 #define ETP_FINGER_DATA_OFFSET 4
@@ -61,6 +62,7 @@
 struct elan_tp_data {
struct i2c_client   *client;
struct input_dev*input;
+   struct input_dev*tp_input; /* trackpoint input node */
struct regulator*vcc;
 
const struct elan_transport_ops *ops;
@@ -930,6 +932,34 @@ static void elan_report_absolute(struct elan_tp_data 
*data, u8 *packet)
input_sync(input);
 }
 
+static void elan_report_trackpoint(struct elan_tp_data *data, u8 *report)
+{
+   struct input_dev *input = data->tp_input;
+   u8 *packet = [ETP_REPORT_ID_OFFSET + 1];
+   int x, y;
+
+   if (!data->tp_input) {
+   dev_warn_once(>client->dev,
+ "received a trackpoint report while no trackpoint 
device has been created.\n"
+ "Please report upstream.\n");
+   return;
+   }
+
+   input_report_key(input, BTN_LEFT, packet[0] & 0x01);
+   input_report_key(input, BTN_RIGHT, packet[0] & 0x02);
+   input_report_key(input, BTN_MIDDLE, packet[0] & 0x04);
+
+   if ((packet[3] & 0x0F) == 0x06) {
+   x = packet[4] - (int)((packet[1]^0x80) << 1);
+   y = (int)((packet[2]^0x80) << 1) - packet[5];
+
+   input_report_rel(input, REL_X, x);
+   input_report_rel(input, REL_Y, y);
+   }
+
+   input_sync(input);
+}
+
 static irqreturn_t elan_isr(int irq, void *dev_id)
 {
struct elan_tp_data *data = dev_id;
@@ -951,11 +981,17 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
if (error)
goto out;
 
-   if (report[ETP_REPORT_ID_OFFSET] != ETP_REPORT_ID)
+   switch (report[ETP_REPORT_ID_OFFSET]) {
+   case ETP_REPORT_ID:
+   elan_report_absolute(data, report);
+   break;
+   case ETP_TP_REPORT_ID:
+   elan_report_trackpoint(data, report);
+   break;
+   default:
dev_err(dev, "invalid report id data (%x)\n",
report[ETP_REPORT_ID_OFFSET]);
-   else
-   elan_report_absolute(data, report);
+   }
 
 out:
return IRQ_HANDLED;
@@ -966,6 +1002,37 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
  * Elan initialization functions
  **
  */
+
+static int elan_setup_trackpoint_input_device(struct elan_tp_data *data)
+{
+   struct device *dev = >client->dev;
+   struct input_dev *input;
+
+   input = devm_input_allocate_device(dev);
+   if (!input)
+   return -ENOMEM;
+
+   input->name = "Elan TrackPoint";
+   input->id.bustype = BUS_I2C;
+   input->id.vendor = ELAN_VENDOR_ID;
+   input->id.product = data->product_id;
+   input_set_drvdata(input, data);
+
+   input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+   input->relbit[BIT_WORD(REL_X)] =
+   BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+   input->keybit[BIT_WORD(BTN_LEFT)] =
+   BIT_MASK(BTN_LEFT) 

[PATCH 3/8] Input: elan_i2c - add trackstick report

2018-04-05 Thread Benjamin Tissoires
The Elan touchpads over I2C/SMBus also can handle a
trackstick. Unfortunately, nothing tells us if the
device supports trackstick (the information lies in
the PS/2 node), so rely on a platform data to enable
or not the trackstick node.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=1313939

Signed-off-by: Benjamin Tissoires 

---

changes in v2:
- renamed ETP_PT_REPORT_ID into ETP_TP_REPORT_ID (pass-through to track-point)
  to stay more in line with the rest
- removed Host Notify support so amended to match parent
---
 drivers/input/mouse/elan_i2c.h  | 10 
 drivers/input/mouse/elan_i2c_core.c | 91 +++--
 2 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index 599544c1a91c..8f9c97267bc9 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -87,4 +87,14 @@ struct elan_transport_ops {
 
 extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops;
 
+/**
+ * struct elan_platform_data - system specific configuration info.
+ *
+ * @trackpoint - specify whether or not you want the trackstick input node to
+ * be created and handled by the driver.
+ */
+struct elan_platform_data {
+   bool trackpoint;
+};
+
 #endif /* _ELAN_I2C_H */
diff --git a/drivers/input/mouse/elan_i2c_core.c 
b/drivers/input/mouse/elan_i2c_core.c
index 75e757520ef0..8ed1e2a8a4dd 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -51,6 +51,7 @@
 #define ETP_MAX_FINGERS5
 #define ETP_FINGER_DATA_LEN5
 #define ETP_REPORT_ID  0x5D
+#define ETP_TP_REPORT_ID   0x5E
 #define ETP_REPORT_ID_OFFSET   2
 #define ETP_TOUCH_INFO_OFFSET  3
 #define ETP_FINGER_DATA_OFFSET 4
@@ -61,6 +62,7 @@
 struct elan_tp_data {
struct i2c_client   *client;
struct input_dev*input;
+   struct input_dev*tp_input; /* trackpoint input node */
struct regulator*vcc;
 
const struct elan_transport_ops *ops;
@@ -930,6 +932,34 @@ static void elan_report_absolute(struct elan_tp_data 
*data, u8 *packet)
input_sync(input);
 }
 
+static void elan_report_trackpoint(struct elan_tp_data *data, u8 *report)
+{
+   struct input_dev *input = data->tp_input;
+   u8 *packet = [ETP_REPORT_ID_OFFSET + 1];
+   int x, y;
+
+   if (!data->tp_input) {
+   dev_warn_once(>client->dev,
+ "received a trackpoint report while no trackpoint 
device has been created.\n"
+ "Please report upstream.\n");
+   return;
+   }
+
+   input_report_key(input, BTN_LEFT, packet[0] & 0x01);
+   input_report_key(input, BTN_RIGHT, packet[0] & 0x02);
+   input_report_key(input, BTN_MIDDLE, packet[0] & 0x04);
+
+   if ((packet[3] & 0x0F) == 0x06) {
+   x = packet[4] - (int)((packet[1]^0x80) << 1);
+   y = (int)((packet[2]^0x80) << 1) - packet[5];
+
+   input_report_rel(input, REL_X, x);
+   input_report_rel(input, REL_Y, y);
+   }
+
+   input_sync(input);
+}
+
 static irqreturn_t elan_isr(int irq, void *dev_id)
 {
struct elan_tp_data *data = dev_id;
@@ -951,11 +981,17 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
if (error)
goto out;
 
-   if (report[ETP_REPORT_ID_OFFSET] != ETP_REPORT_ID)
+   switch (report[ETP_REPORT_ID_OFFSET]) {
+   case ETP_REPORT_ID:
+   elan_report_absolute(data, report);
+   break;
+   case ETP_TP_REPORT_ID:
+   elan_report_trackpoint(data, report);
+   break;
+   default:
dev_err(dev, "invalid report id data (%x)\n",
report[ETP_REPORT_ID_OFFSET]);
-   else
-   elan_report_absolute(data, report);
+   }
 
 out:
return IRQ_HANDLED;
@@ -966,6 +1002,37 @@ static irqreturn_t elan_isr(int irq, void *dev_id)
  * Elan initialization functions
  **
  */
+
+static int elan_setup_trackpoint_input_device(struct elan_tp_data *data)
+{
+   struct device *dev = >client->dev;
+   struct input_dev *input;
+
+   input = devm_input_allocate_device(dev);
+   if (!input)
+   return -ENOMEM;
+
+   input->name = "Elan TrackPoint";
+   input->id.bustype = BUS_I2C;
+   input->id.vendor = ELAN_VENDOR_ID;
+   input->id.product = data->product_id;
+   input_set_drvdata(input, data);
+
+   input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+   input->relbit[BIT_WORD(REL_X)] =
+   BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+   input->keybit[BIT_WORD(BTN_LEFT)] =
+   BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
+

[PATCH 6/8] Input: elantech - add support for SMBus devices

2018-04-05 Thread Benjamin Tissoires
Many of the Elantech devices are connected through PS/2 and a different
bus (SMBus or plain I2C).

To not break any existing device, we only enable SMBus based
on a module parameter. If some laptops require the quirk to
be set, we will have to rely on a list of PNPIds or MDI matching
to individually expose those hardware over SMBus.
the parameter mentioned above is elantech_smbus from the psmouse
module.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/input/mouse/Kconfig|  12 +++
 drivers/input/mouse/elantech.c | 184 -
 drivers/input/mouse/elantech.h |  24 +
 drivers/input/mouse/psmouse-base.c |  21 -
 drivers/input/mouse/psmouse.h  |   1 +
 5 files changed, 235 insertions(+), 7 deletions(-)

diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 89ebb8f39fee..f27f23f2d99a 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -133,6 +133,18 @@ config MOUSE_PS2_ELANTECH
 
  If unsure, say N.
 
+config MOUSE_PS2_ELANTECH_SMBUS
+   bool "Elantech PS/2 SMbus companion" if EXPERT
+   default y
+   depends on MOUSE_PS2 && MOUSE_PS2_ELANTECH
+   depends on I2C=y || I2C=MOUSE_PS2
+   select MOUSE_PS2_SMBUS
+   help
+ Say Y here if you have a Elantech touchpad connected to
+ to an SMBus, but enumerated through PS/2.
+
+ If unsure, say Y.
+
 config MOUSE_PS2_SENTELIC
bool "Sentelic Finger Sensing Pad PS/2 protocol extension"
depends on MOUSE_PS2
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 41af0c9098af..a61fbddd6b92 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -14,13 +14,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include "psmouse.h"
 #include "elantech.h"
+#include "elan_i2c.h"
 
 #define elantech_debug(fmt, ...)   \
do {\
@@ -1084,7 +1087,8 @@ static unsigned int elantech_convert_res(unsigned int val)
 
 static int elantech_get_resolution_v4(struct psmouse *psmouse,
  unsigned int *x_res,
- unsigned int *y_res)
+ unsigned int *y_res,
+ unsigned int *bus)
 {
unsigned char param[3];
 
@@ -1093,6 +1097,7 @@ static int elantech_get_resolution_v4(struct psmouse 
*psmouse,
 
*x_res = elantech_convert_res(param[1] & 0x0f);
*y_res = elantech_convert_res((param[1] & 0xf0) >> 4);
+   *bus = param[2];
 
return 0;
 }
@@ -1474,6 +1479,12 @@ static void elantech_disconnect(struct psmouse *psmouse)
 {
struct elantech_data *etd = psmouse->private;
 
+   /*
+* We might have left a breadcrumb when trying to
+* set up SMbus companion.
+*/
+   psmouse_smbus_cleanup(psmouse);
+
if (etd->tp_dev)
input_unregister_device(etd->tp_dev);
sysfs_remove_group(>ps2dev.serio->dev.kobj,
@@ -1659,6 +1670,8 @@ int elantech_query_info(struct psmouse *psmouse,
 {
unsigned char param[3];
 
+   memset(info, 0, sizeof(*info));
+
/*
 * Do the version query again so we can store the result
 */
@@ -1717,7 +1730,8 @@ int elantech_query_info(struct psmouse *psmouse,
if (info->hw_version == 4) {
if (elantech_get_resolution_v4(psmouse,
   >x_res,
-  >y_res)) {
+  >y_res,
+  >bus)) {
psmouse_warn(psmouse,
 "failed to query resolution data.\n");
}
@@ -1726,6 +1740,125 @@ int elantech_query_info(struct psmouse *psmouse,
return 0;
 }
 
+#if defined(CONFIG_MOUSE_PS2_ELANTECH_SMBUS)
+
+/*
+ * The newest Elantech device can use a secondary bus (over SMBus) which
+ * provides a better bandwidth and allow a better control of the touchpads.
+ * This is used to decide if we need to use this bus or not.
+ */
+enum {
+   ELANTECH_SMBUS_NOT_SET = -1,
+   ELANTECH_SMBUS_OFF,
+   ELANTECH_SMBUS_ON,
+};
+
+static int elantech_smbus = IS_ENABLED(CONFIG_MOUSE_ELAN_I2C_SMBUS) ?
+   ELANTECH_SMBUS_NOT_SET : ELANTECH_SMBUS_OFF;
+module_param_named(elantech_smbus, elantech_smbus, int, 0644);
+MODULE_PARM_DESC(elantech_smbus, "Use a secondary bus for the Elantech 
device.");
+
+static int elantech_create_smbus(struct psmouse *psmouse,
+struct elantech_device_info *info,
+ 

[PATCH 7/8] Input: elantech - detect new ICs and setup Host Notify for them

2018-04-05 Thread Benjamin Tissoires
New ICs are using a different scheme for the alternate bus parameter.
Given that they are new and are only using either PS2 only or PS2 + SMBus
Host Notify, we force those new ICs to use the SMBus solution for enhanced
reporting.

This allows the touchpad found on the Lenovo T480s to report 5 fingers
every 8 ms, instead of having a limit of 2 every 8 ms.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/input/mouse/elantech.c | 11 +++
 drivers/input/mouse/elantech.h | 15 +++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index a61fbddd6b92..29f55e8e07e9 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1789,11 +1789,11 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 
if (elantech_smbus == ELANTECH_SMBUS_NOT_SET) {
/*
-* FIXME:
-* constraint the I2C capable devices by using FW version,
-* board version, or by using DMI matching
+* New ICs are enabled by default.
+* Old ICs are up to the user to decide.
 */
-   return -ENXIO;
+   if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return -ENXIO;
}
 
psmouse_info(psmouse, "Trying to set up SMBus access\n");
@@ -1814,6 +1814,9 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 static bool elantech_use_host_notify(struct psmouse *psmouse,
 struct elantech_device_info *info)
 {
+   if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return true;
+
switch (info->bus) {
case ETP_BUS_PS2_ONLY:
/* expected case */
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index f9b1c485e8d9..119727085a60 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -115,6 +115,21 @@
 #define ETP_BUS_PS2_SMB_ALERT  3
 #define ETP_BUS_PS2_SMB_HST_NTFY   4
 
+/*
+ * New ICs are either using SMBus Host Notify or just plain PS2.
+ *
+ * ETP_FW_VERSION_QUERY is:
+ * Byte 1:
+ *  - bit 0..3: IC BODY
+ * Byte 2:
+ *  - bit 4: HiddenButton
+ *  - bit 5: PS2_SMBUS_NOTIFY
+ *  - bit 6: PS2CRCCheck
+ */
+#define ETP_NEW_IC_SMBUS_HOST_NOTIFY(fw_version)   \
+   fw_version) & 0x0f2000) == 0x0f2000) && \
+((fw_version) & 0xff) > 0)
+
 /*
  * The base position for one finger, v4 hardware
  */
-- 
2.14.3



[PATCH 7/8] Input: elantech - detect new ICs and setup Host Notify for them

2018-04-05 Thread Benjamin Tissoires
New ICs are using a different scheme for the alternate bus parameter.
Given that they are new and are only using either PS2 only or PS2 + SMBus
Host Notify, we force those new ICs to use the SMBus solution for enhanced
reporting.

This allows the touchpad found on the Lenovo T480s to report 5 fingers
every 8 ms, instead of having a limit of 2 every 8 ms.

Signed-off-by: Benjamin Tissoires 
---
 drivers/input/mouse/elantech.c | 11 +++
 drivers/input/mouse/elantech.h | 15 +++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index a61fbddd6b92..29f55e8e07e9 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1789,11 +1789,11 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 
if (elantech_smbus == ELANTECH_SMBUS_NOT_SET) {
/*
-* FIXME:
-* constraint the I2C capable devices by using FW version,
-* board version, or by using DMI matching
+* New ICs are enabled by default.
+* Old ICs are up to the user to decide.
 */
-   return -ENXIO;
+   if (!ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return -ENXIO;
}
 
psmouse_info(psmouse, "Trying to set up SMBus access\n");
@@ -1814,6 +1814,9 @@ static int elantech_setup_smbus(struct psmouse *psmouse,
 static bool elantech_use_host_notify(struct psmouse *psmouse,
 struct elantech_device_info *info)
 {
+   if (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version))
+   return true;
+
switch (info->bus) {
case ETP_BUS_PS2_ONLY:
/* expected case */
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index f9b1c485e8d9..119727085a60 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -115,6 +115,21 @@
 #define ETP_BUS_PS2_SMB_ALERT  3
 #define ETP_BUS_PS2_SMB_HST_NTFY   4
 
+/*
+ * New ICs are either using SMBus Host Notify or just plain PS2.
+ *
+ * ETP_FW_VERSION_QUERY is:
+ * Byte 1:
+ *  - bit 0..3: IC BODY
+ * Byte 2:
+ *  - bit 4: HiddenButton
+ *  - bit 5: PS2_SMBUS_NOTIFY
+ *  - bit 6: PS2CRCCheck
+ */
+#define ETP_NEW_IC_SMBUS_HOST_NOTIFY(fw_version)   \
+   fw_version) & 0x0f2000) == 0x0f2000) && \
+((fw_version) & 0xff) > 0)
+
 /*
  * The base position for one finger, v4 hardware
  */
-- 
2.14.3



[PATCH 6/8] Input: elantech - add support for SMBus devices

2018-04-05 Thread Benjamin Tissoires
Many of the Elantech devices are connected through PS/2 and a different
bus (SMBus or plain I2C).

To not break any existing device, we only enable SMBus based
on a module parameter. If some laptops require the quirk to
be set, we will have to rely on a list of PNPIds or MDI matching
to individually expose those hardware over SMBus.
the parameter mentioned above is elantech_smbus from the psmouse
module.

Signed-off-by: Benjamin Tissoires 
---
 drivers/input/mouse/Kconfig|  12 +++
 drivers/input/mouse/elantech.c | 184 -
 drivers/input/mouse/elantech.h |  24 +
 drivers/input/mouse/psmouse-base.c |  21 -
 drivers/input/mouse/psmouse.h  |   1 +
 5 files changed, 235 insertions(+), 7 deletions(-)

diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 89ebb8f39fee..f27f23f2d99a 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -133,6 +133,18 @@ config MOUSE_PS2_ELANTECH
 
  If unsure, say N.
 
+config MOUSE_PS2_ELANTECH_SMBUS
+   bool "Elantech PS/2 SMbus companion" if EXPERT
+   default y
+   depends on MOUSE_PS2 && MOUSE_PS2_ELANTECH
+   depends on I2C=y || I2C=MOUSE_PS2
+   select MOUSE_PS2_SMBUS
+   help
+ Say Y here if you have a Elantech touchpad connected to
+ to an SMBus, but enumerated through PS/2.
+
+ If unsure, say Y.
+
 config MOUSE_PS2_SENTELIC
bool "Sentelic Finger Sensing Pad PS/2 protocol extension"
depends on MOUSE_PS2
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 41af0c9098af..a61fbddd6b92 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -14,13 +14,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include "psmouse.h"
 #include "elantech.h"
+#include "elan_i2c.h"
 
 #define elantech_debug(fmt, ...)   \
do {\
@@ -1084,7 +1087,8 @@ static unsigned int elantech_convert_res(unsigned int val)
 
 static int elantech_get_resolution_v4(struct psmouse *psmouse,
  unsigned int *x_res,
- unsigned int *y_res)
+ unsigned int *y_res,
+ unsigned int *bus)
 {
unsigned char param[3];
 
@@ -1093,6 +1097,7 @@ static int elantech_get_resolution_v4(struct psmouse 
*psmouse,
 
*x_res = elantech_convert_res(param[1] & 0x0f);
*y_res = elantech_convert_res((param[1] & 0xf0) >> 4);
+   *bus = param[2];
 
return 0;
 }
@@ -1474,6 +1479,12 @@ static void elantech_disconnect(struct psmouse *psmouse)
 {
struct elantech_data *etd = psmouse->private;
 
+   /*
+* We might have left a breadcrumb when trying to
+* set up SMbus companion.
+*/
+   psmouse_smbus_cleanup(psmouse);
+
if (etd->tp_dev)
input_unregister_device(etd->tp_dev);
sysfs_remove_group(>ps2dev.serio->dev.kobj,
@@ -1659,6 +1670,8 @@ int elantech_query_info(struct psmouse *psmouse,
 {
unsigned char param[3];
 
+   memset(info, 0, sizeof(*info));
+
/*
 * Do the version query again so we can store the result
 */
@@ -1717,7 +1730,8 @@ int elantech_query_info(struct psmouse *psmouse,
if (info->hw_version == 4) {
if (elantech_get_resolution_v4(psmouse,
   >x_res,
-  >y_res)) {
+  >y_res,
+  >bus)) {
psmouse_warn(psmouse,
 "failed to query resolution data.\n");
}
@@ -1726,6 +1740,125 @@ int elantech_query_info(struct psmouse *psmouse,
return 0;
 }
 
+#if defined(CONFIG_MOUSE_PS2_ELANTECH_SMBUS)
+
+/*
+ * The newest Elantech device can use a secondary bus (over SMBus) which
+ * provides a better bandwidth and allow a better control of the touchpads.
+ * This is used to decide if we need to use this bus or not.
+ */
+enum {
+   ELANTECH_SMBUS_NOT_SET = -1,
+   ELANTECH_SMBUS_OFF,
+   ELANTECH_SMBUS_ON,
+};
+
+static int elantech_smbus = IS_ENABLED(CONFIG_MOUSE_ELAN_I2C_SMBUS) ?
+   ELANTECH_SMBUS_NOT_SET : ELANTECH_SMBUS_OFF;
+module_param_named(elantech_smbus, elantech_smbus, int, 0644);
+MODULE_PARM_DESC(elantech_smbus, "Use a secondary bus for the Elantech 
device.");
+
+static int elantech_create_smbus(struct psmouse *psmouse,
+struct elantech_device_info *info,
+   

[PATCH 5/8] Input: elantech - query the resolution in query_info

2018-04-05 Thread Benjamin Tissoires
The command ETP_RESOLUTION_QUERY also contains the bus information.
It is better to fetch it once, while we are querying for device
information.

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/input/mouse/elantech.c | 27 +++
 drivers/input/mouse/elantech.h |  2 ++
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index d485664f1563..41af0c9098af 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1179,7 +1179,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
struct elantech_data *etd = psmouse->private;
struct elantech_device_info *info = >info;
unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
-   unsigned int x_res = 31, y_res = 31;
 
if (elantech_set_range(psmouse, _min, _min, _max, _max, ))
return -1;
@@ -1232,13 +1231,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
 
case 4:
-   if (elantech_get_resolution_v4(psmouse, _res, _res)) {
-   /*
-* if query failed, print a warning and leave the values
-* zero to resemble synaptics.c behavior.
-*/
-   psmouse_warn(psmouse, "couldn't query resolution 
data.\n");
-   }
elantech_set_buttonpad_prop(psmouse);
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
/* For X to recognize me as touchpad. */
@@ -1267,11 +1259,11 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
}
 
-   input_abs_set_res(dev, ABS_X, x_res);
-   input_abs_set_res(dev, ABS_Y, y_res);
+   input_abs_set_res(dev, ABS_X, info->x_res);
+   input_abs_set_res(dev, ABS_Y, info->y_res);
if (info->hw_version > 1) {
-   input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
-   input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_X, info->x_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_Y, info->y_res);
}
 
etd->y_max = y_max;
@@ -1720,6 +1712,17 @@ int elantech_query_info(struct psmouse *psmouse,
/* The MSB indicates the presence of the trackpoint */
info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
 
+   info->x_res = 31;
+   info->y_res = 31;
+   if (info->hw_version == 4) {
+   if (elantech_get_resolution_v4(psmouse,
+  >x_res,
+  >y_res)) {
+   psmouse_warn(psmouse,
+"failed to query resolution data.\n");
+   }
+   }
+
return 0;
 }
 
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index d8ac27fe4597..851df4ce6232 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -120,6 +120,8 @@ struct elantech_device_info {
unsigned char debug;
unsigned char hw_version;
unsigned int fw_version;
+   unsigned int x_res;
+   unsigned int y_res;
bool paritycheck;
bool jumpy_cursor;
bool reports_pressure;
-- 
2.14.3



[PATCH 5/8] Input: elantech - query the resolution in query_info

2018-04-05 Thread Benjamin Tissoires
The command ETP_RESOLUTION_QUERY also contains the bus information.
It is better to fetch it once, while we are querying for device
information.

Signed-off-by: Benjamin Tissoires 
---
 drivers/input/mouse/elantech.c | 27 +++
 drivers/input/mouse/elantech.h |  2 ++
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index d485664f1563..41af0c9098af 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1179,7 +1179,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
struct elantech_data *etd = psmouse->private;
struct elantech_device_info *info = >info;
unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
-   unsigned int x_res = 31, y_res = 31;
 
if (elantech_set_range(psmouse, _min, _min, _max, _max, ))
return -1;
@@ -1232,13 +1231,6 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
 
case 4:
-   if (elantech_get_resolution_v4(psmouse, _res, _res)) {
-   /*
-* if query failed, print a warning and leave the values
-* zero to resemble synaptics.c behavior.
-*/
-   psmouse_warn(psmouse, "couldn't query resolution 
data.\n");
-   }
elantech_set_buttonpad_prop(psmouse);
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
/* For X to recognize me as touchpad. */
@@ -1267,11 +1259,11 @@ static int elantech_set_input_params(struct psmouse 
*psmouse)
break;
}
 
-   input_abs_set_res(dev, ABS_X, x_res);
-   input_abs_set_res(dev, ABS_Y, y_res);
+   input_abs_set_res(dev, ABS_X, info->x_res);
+   input_abs_set_res(dev, ABS_Y, info->y_res);
if (info->hw_version > 1) {
-   input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
-   input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_X, info->x_res);
+   input_abs_set_res(dev, ABS_MT_POSITION_Y, info->y_res);
}
 
etd->y_max = y_max;
@@ -1720,6 +1712,17 @@ int elantech_query_info(struct psmouse *psmouse,
/* The MSB indicates the presence of the trackpoint */
info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
 
+   info->x_res = 31;
+   info->y_res = 31;
+   if (info->hw_version == 4) {
+   if (elantech_get_resolution_v4(psmouse,
+  >x_res,
+  >y_res)) {
+   psmouse_warn(psmouse,
+"failed to query resolution data.\n");
+   }
+   }
+
return 0;
 }
 
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index d8ac27fe4597..851df4ce6232 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -120,6 +120,8 @@ struct elantech_device_info {
unsigned char debug;
unsigned char hw_version;
unsigned int fw_version;
+   unsigned int x_res;
+   unsigned int y_res;
bool paritycheck;
bool jumpy_cursor;
bool reports_pressure;
-- 
2.14.3



[PATCH 8/8] input: psmouse-smbus: allow to control psmouse_deactivate

2018-04-05 Thread Benjamin Tissoires
This seems to be Synaptics specific, as some Elan touchpads are not
correctly switching to SMBus if we call deactivate before switching to
SMBus on cold boot and on resume.

Tested with the T480s

Signed-off-by: Benjamin Tissoires <benjamin.tissoi...@redhat.com>
---
 drivers/input/mouse/elantech.c  |  2 +-
 drivers/input/mouse/psmouse-smbus.c | 13 ++---
 drivers/input/mouse/psmouse.h   |  1 +
 drivers/input/mouse/synaptics.c |  2 +-
 4 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 29f55e8e07e9..6009fb7d0d31 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1771,7 +1771,7 @@ static int elantech_create_smbus(struct psmouse *psmouse,
};
 
return psmouse_smbus_init(psmouse, _board, ,
- sizeof(pdata), leave_breadcrumbs);
+ sizeof(pdata), false, leave_breadcrumbs);
 }
 
 /**
diff --git a/drivers/input/mouse/psmouse-smbus.c 
b/drivers/input/mouse/psmouse-smbus.c
index c7ac24d119c1..facfe902b073 100644
--- a/drivers/input/mouse/psmouse-smbus.c
+++ b/drivers/input/mouse/psmouse-smbus.c
@@ -23,6 +23,7 @@ struct psmouse_smbus_dev {
struct i2c_client *client;
struct list_head node;
bool dead;
+   bool need_deactivate;
 };
 
 static LIST_HEAD(psmouse_smbus_list);
@@ -118,7 +119,10 @@ static psmouse_ret_t psmouse_smbus_process_byte(struct 
psmouse *psmouse)
 
 static int psmouse_smbus_reconnect(struct psmouse *psmouse)
 {
-   psmouse_deactivate(psmouse);
+   struct psmouse_smbus_dev *smbdev = psmouse->private;
+
+   if (smbdev->need_deactivate)
+   psmouse_deactivate(psmouse);
 
return 0;
 }
@@ -225,6 +229,7 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse)
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs)
 {
struct psmouse_smbus_dev *smbdev;
@@ -236,6 +241,7 @@ int psmouse_smbus_init(struct psmouse *psmouse,
 
smbdev->psmouse = psmouse;
smbdev->board = *board;
+   smbdev->need_deactivate = need_deactivate;
 
smbdev->board.platform_data = kmemdup(pdata, pdata_size, GFP_KERNEL);
if (!smbdev->board.platform_data) {
@@ -243,6 +249,9 @@ int psmouse_smbus_init(struct psmouse *psmouse,
return -ENOMEM;
}
 
+   if (need_deactivate)
+   psmouse_deactivate(psmouse);
+
psmouse->private = smbdev;
psmouse->protocol_handler = psmouse_smbus_process_byte;
psmouse->reconnect = psmouse_smbus_reconnect;
@@ -250,8 +259,6 @@ int psmouse_smbus_init(struct psmouse *psmouse,
psmouse->disconnect = psmouse_smbus_disconnect;
psmouse->resync_time = 0;
 
-   psmouse_deactivate(psmouse);
-
mutex_lock(_smbus_mutex);
list_add_tail(>node, _smbus_list);
mutex_unlock(_smbus_mutex);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index dd4ec1f602d7..64c3a5d3fb3e 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -225,6 +225,7 @@ struct i2c_board_info;
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs);
 void psmouse_smbus_cleanup(struct psmouse *psmouse);
 
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 14a1188561aa..6b1ed53a8b03 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1751,7 +1751,7 @@ static int synaptics_create_intertouch(struct psmouse 
*psmouse,
};
 
return psmouse_smbus_init(psmouse, _board,
- , sizeof(pdata),
+ , sizeof(pdata), true,
  leave_breadcrumbs);
 }
 
-- 
2.14.3



[PATCH 8/8] input: psmouse-smbus: allow to control psmouse_deactivate

2018-04-05 Thread Benjamin Tissoires
This seems to be Synaptics specific, as some Elan touchpads are not
correctly switching to SMBus if we call deactivate before switching to
SMBus on cold boot and on resume.

Tested with the T480s

Signed-off-by: Benjamin Tissoires 
---
 drivers/input/mouse/elantech.c  |  2 +-
 drivers/input/mouse/psmouse-smbus.c | 13 ++---
 drivers/input/mouse/psmouse.h   |  1 +
 drivers/input/mouse/synaptics.c |  2 +-
 4 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 29f55e8e07e9..6009fb7d0d31 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1771,7 +1771,7 @@ static int elantech_create_smbus(struct psmouse *psmouse,
};
 
return psmouse_smbus_init(psmouse, _board, ,
- sizeof(pdata), leave_breadcrumbs);
+ sizeof(pdata), false, leave_breadcrumbs);
 }
 
 /**
diff --git a/drivers/input/mouse/psmouse-smbus.c 
b/drivers/input/mouse/psmouse-smbus.c
index c7ac24d119c1..facfe902b073 100644
--- a/drivers/input/mouse/psmouse-smbus.c
+++ b/drivers/input/mouse/psmouse-smbus.c
@@ -23,6 +23,7 @@ struct psmouse_smbus_dev {
struct i2c_client *client;
struct list_head node;
bool dead;
+   bool need_deactivate;
 };
 
 static LIST_HEAD(psmouse_smbus_list);
@@ -118,7 +119,10 @@ static psmouse_ret_t psmouse_smbus_process_byte(struct 
psmouse *psmouse)
 
 static int psmouse_smbus_reconnect(struct psmouse *psmouse)
 {
-   psmouse_deactivate(psmouse);
+   struct psmouse_smbus_dev *smbdev = psmouse->private;
+
+   if (smbdev->need_deactivate)
+   psmouse_deactivate(psmouse);
 
return 0;
 }
@@ -225,6 +229,7 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse)
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs)
 {
struct psmouse_smbus_dev *smbdev;
@@ -236,6 +241,7 @@ int psmouse_smbus_init(struct psmouse *psmouse,
 
smbdev->psmouse = psmouse;
smbdev->board = *board;
+   smbdev->need_deactivate = need_deactivate;
 
smbdev->board.platform_data = kmemdup(pdata, pdata_size, GFP_KERNEL);
if (!smbdev->board.platform_data) {
@@ -243,6 +249,9 @@ int psmouse_smbus_init(struct psmouse *psmouse,
return -ENOMEM;
}
 
+   if (need_deactivate)
+   psmouse_deactivate(psmouse);
+
psmouse->private = smbdev;
psmouse->protocol_handler = psmouse_smbus_process_byte;
psmouse->reconnect = psmouse_smbus_reconnect;
@@ -250,8 +259,6 @@ int psmouse_smbus_init(struct psmouse *psmouse,
psmouse->disconnect = psmouse_smbus_disconnect;
psmouse->resync_time = 0;
 
-   psmouse_deactivate(psmouse);
-
mutex_lock(_smbus_mutex);
list_add_tail(>node, _smbus_list);
mutex_unlock(_smbus_mutex);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index dd4ec1f602d7..64c3a5d3fb3e 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -225,6 +225,7 @@ struct i2c_board_info;
 int psmouse_smbus_init(struct psmouse *psmouse,
   const struct i2c_board_info *board,
   const void *pdata, size_t pdata_size,
+  bool need_deactivate,
   bool leave_breadcrumbs);
 void psmouse_smbus_cleanup(struct psmouse *psmouse);
 
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 14a1188561aa..6b1ed53a8b03 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1751,7 +1751,7 @@ static int synaptics_create_intertouch(struct psmouse 
*psmouse,
};
 
return psmouse_smbus_init(psmouse, _board,
- , sizeof(pdata),
+ , sizeof(pdata), true,
  leave_breadcrumbs);
 }
 
-- 
2.14.3



Re: [PATCH v7 1/2] HID: add driver for Valve Steam Controller

2018-03-26 Thread Benjamin Tissoires
Hi Rodrigo,

few comments inlined.

On Sun, Mar 25, 2018 at 6:07 PM, Rodrigo Rivas Costa
 wrote:
> There are two ways to connect the Steam Controller: directly to the USB
> or with the USB wireless adapter.  Both methods are similar, but the
> wireless adapter can connect up to 4 devices at the same time.
>
> The wired device will appear as 3 interfaces: a virtual mouse, a virtual
> keyboard and a custom HID device.
>
> The wireless device will appear as 5 interfaces: a virtual keyboard and
> 4 custom HID devices, that will remain silent until a device is actually
> connected.
>
> The custom HID device has a report descriptor with all vendor specific
> usages, so the hid-generic is not very useful. In a PC/SteamBox Valve
> Steam Client provices a software translation by using hidraw and a
> creates a uinput virtual gamepad and XTest keyboard/mouse.
>
> This driver intercepts the hidraw usage, so it can get out of the way
> when the Steam Client is in use.
>
> Signed-off-by: Rodrigo Rivas Costa 
> ---
>  drivers/hid/Kconfig |   8 +
>  drivers/hid/Makefile|   1 +
>  drivers/hid/hid-ids.h   |   4 +
>  drivers/hid/hid-steam.c | 840 
> 
>  include/linux/hid.h |   1 +
>  5 files changed, 854 insertions(+)
>  create mode 100644 drivers/hid/hid-steam.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 779c5ae47f36..de5f4849bfe4 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -811,6 +811,14 @@ config HID_SPEEDLINK
> ---help---
> Support for Speedlink Vicious and Divine Cezanne mouse.
>
> +config HID_STEAM
> +   tristate "Steam Controller support"
> +   depends on HID
> +   ---help---
> +   Say Y here if you have a Steam Controller if you want to use it
> +   without running the Steam Client. It supports both the wired and
> +   the wireless adaptor.
> +
>  config HID_STEELSERIES
> tristate "Steelseries SRW-S1 steering wheel support"
> depends on HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index 235bd2a7b333..e146c257285a 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -94,6 +94,7 @@ obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
>  obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
>  obj-$(CONFIG_HID_SONY) += hid-sony.o
>  obj-$(CONFIG_HID_SPEEDLINK)+= hid-speedlink.o
> +obj-$(CONFIG_HID_STEAM)+= hid-steam.o
>  obj-$(CONFIG_HID_STEELSERIES)  += hid-steelseries.o
>  obj-$(CONFIG_HID_SUNPLUS)  += hid-sunplus.o
>  obj-$(CONFIG_HID_GREENASIA)+= hid-gaff.o
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index a0baa5ba5b84..3014991e5d4b 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -987,6 +987,10 @@
>  #define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403
>  #define USB_DEVICE_ID_MTP_SITRONIX 0x5001
>
> +#define USB_VENDOR_ID_VALVE0x28de
> +#define USB_DEVICE_ID_STEAM_CONTROLLER 0x1102
> +#define USB_DEVICE_ID_STEAM_CONTROLLER_WIRELESS0x1142
> +
>  #define USB_VENDOR_ID_STEELSERIES  0x1038
>  #define USB_DEVICE_ID_STEELSERIES_SRWS10x1410
>
> diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
> new file mode 100644
> index ..3504d2e2d0e5
> --- /dev/null
> +++ b/drivers/hid/hid-steam.c
> @@ -0,0 +1,840 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * HID driver for Valve Steam Controller
> + *
> + * Copyright (c) 2018 Rodrigo Rivas Costa 
> + *
> + * Supports both the wired and wireless interfaces.
> + *
> + * This controller has a builtin emulation of mouse and keyboard: the right 
> pad
> + * can be used as a mouse, the shoulder buttons are mouse buttons, A and B
> + * buttons are ENTER and ESCAPE, and so on. This is implemented as additional
> + * HID interfaces.
> + *
> + * This is known as the "lizard mode", because apparently lizards like to use
> + * the computer from the coach, without a proper mouse and keyboard.
> + *
> + * This driver will disable the lizard mode when the input device is opened
> + * and re-enable it when the input device is closed, so as not to break user
> + * mode behaviour. The lizard_mode parameter can be used to change that.
> + *
> + * There are a few user space applications (notably Steam Client) that use
> + * the hidraw interface directly to create input devices (XTest, uinput...).
> + * In order to avoid breaking them this driver creates a layered hidraw 
> device,
> + * so it can detect when the client is running and then:
> + *  - it will not send any command to the controller.
> + *  - this input device will be disabled, to avoid double input of the same
> + *user action.
> + *
> + * For additional functions, such as changing the right-pad margin or 
> switching
> + * the led, you can use the user-space tool at:
> + *
> + *   

Re: [PATCH v7 1/2] HID: add driver for Valve Steam Controller

2018-03-26 Thread Benjamin Tissoires
Hi Rodrigo,

few comments inlined.

On Sun, Mar 25, 2018 at 6:07 PM, Rodrigo Rivas Costa
 wrote:
> There are two ways to connect the Steam Controller: directly to the USB
> or with the USB wireless adapter.  Both methods are similar, but the
> wireless adapter can connect up to 4 devices at the same time.
>
> The wired device will appear as 3 interfaces: a virtual mouse, a virtual
> keyboard and a custom HID device.
>
> The wireless device will appear as 5 interfaces: a virtual keyboard and
> 4 custom HID devices, that will remain silent until a device is actually
> connected.
>
> The custom HID device has a report descriptor with all vendor specific
> usages, so the hid-generic is not very useful. In a PC/SteamBox Valve
> Steam Client provices a software translation by using hidraw and a
> creates a uinput virtual gamepad and XTest keyboard/mouse.
>
> This driver intercepts the hidraw usage, so it can get out of the way
> when the Steam Client is in use.
>
> Signed-off-by: Rodrigo Rivas Costa 
> ---
>  drivers/hid/Kconfig |   8 +
>  drivers/hid/Makefile|   1 +
>  drivers/hid/hid-ids.h   |   4 +
>  drivers/hid/hid-steam.c | 840 
> 
>  include/linux/hid.h |   1 +
>  5 files changed, 854 insertions(+)
>  create mode 100644 drivers/hid/hid-steam.c
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 779c5ae47f36..de5f4849bfe4 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -811,6 +811,14 @@ config HID_SPEEDLINK
> ---help---
> Support for Speedlink Vicious and Divine Cezanne mouse.
>
> +config HID_STEAM
> +   tristate "Steam Controller support"
> +   depends on HID
> +   ---help---
> +   Say Y here if you have a Steam Controller if you want to use it
> +   without running the Steam Client. It supports both the wired and
> +   the wireless adaptor.
> +
>  config HID_STEELSERIES
> tristate "Steelseries SRW-S1 steering wheel support"
> depends on HID
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index 235bd2a7b333..e146c257285a 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -94,6 +94,7 @@ obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
>  obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
>  obj-$(CONFIG_HID_SONY) += hid-sony.o
>  obj-$(CONFIG_HID_SPEEDLINK)+= hid-speedlink.o
> +obj-$(CONFIG_HID_STEAM)+= hid-steam.o
>  obj-$(CONFIG_HID_STEELSERIES)  += hid-steelseries.o
>  obj-$(CONFIG_HID_SUNPLUS)  += hid-sunplus.o
>  obj-$(CONFIG_HID_GREENASIA)+= hid-gaff.o
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index a0baa5ba5b84..3014991e5d4b 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -987,6 +987,10 @@
>  #define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403
>  #define USB_DEVICE_ID_MTP_SITRONIX 0x5001
>
> +#define USB_VENDOR_ID_VALVE0x28de
> +#define USB_DEVICE_ID_STEAM_CONTROLLER 0x1102
> +#define USB_DEVICE_ID_STEAM_CONTROLLER_WIRELESS0x1142
> +
>  #define USB_VENDOR_ID_STEELSERIES  0x1038
>  #define USB_DEVICE_ID_STEELSERIES_SRWS10x1410
>
> diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
> new file mode 100644
> index ..3504d2e2d0e5
> --- /dev/null
> +++ b/drivers/hid/hid-steam.c
> @@ -0,0 +1,840 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * HID driver for Valve Steam Controller
> + *
> + * Copyright (c) 2018 Rodrigo Rivas Costa 
> + *
> + * Supports both the wired and wireless interfaces.
> + *
> + * This controller has a builtin emulation of mouse and keyboard: the right 
> pad
> + * can be used as a mouse, the shoulder buttons are mouse buttons, A and B
> + * buttons are ENTER and ESCAPE, and so on. This is implemented as additional
> + * HID interfaces.
> + *
> + * This is known as the "lizard mode", because apparently lizards like to use
> + * the computer from the coach, without a proper mouse and keyboard.
> + *
> + * This driver will disable the lizard mode when the input device is opened
> + * and re-enable it when the input device is closed, so as not to break user
> + * mode behaviour. The lizard_mode parameter can be used to change that.
> + *
> + * There are a few user space applications (notably Steam Client) that use
> + * the hidraw interface directly to create input devices (XTest, uinput...).
> + * In order to avoid breaking them this driver creates a layered hidraw 
> device,
> + * so it can detect when the client is running and then:
> + *  - it will not send any command to the controller.
> + *  - this input device will be disabled, to avoid double input of the same
> + *user action.
> + *
> + * For additional functions, such as changing the right-pad margin or 
> switching
> + * the led, you can use the user-space tool at:
> + *
> + *   https://github.com/rodrigorc/steamctrl
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 

Re: [PATCH v7 0/2] hid-steam driver with user mode client dection

2018-03-26 Thread Benjamin Tissoires
Hi Rodrigo,

On Sun, Mar 25, 2018 at 6:07 PM, Rodrigo Rivas Costa
 wrote:
> This is a reroll of the Steam Controller driver.
>
> This time the client usage is detected by using exposing a custom hidraw
> device (hid_ll_driver) to userland and forwarding that to the real one.

That is actually more clever than what I had in mind.
This way you reliably know if the hidraw node has been opened without
touching hid-core.c or hidraw.c, well played :)

>
> About how the lizard-mode/hidraw-client issue is handled, I have added a
> module parameter (I don't know if that is the best option, but it helps me
> illustrate different approaches to the problem):
>
> Independently of the lizard_mode parameter value:

I find the values of the lizard_mode parameter hard to understand. And
honestly, I do not think there is much a difference between 0 and 1.
AFAICT, the difference between these two values is that in the first
case you are disabling the lizard mode whether or not the joystick is
in used, and in the latter, you disable it only when the joystick is
in use. Does that gives any benefits to users?

I would think having a boolean "let the kernel handle the lizard mode
with some magic inside" would be simpler to understand. You do not
really want to support too many configurations and I think it would be
wiser to say either disable the new mode or just enable it.

Also, I think there will be races if a user changes the value of the
parameter while running the system. You might want to add an
additional patch that would trigger the mode change on module
parameter change.

As far as I can tell, I am happy with such hack. There are a few
points I'd like to raise in the patch 1, but I'll inline my comments
there.

Cheers,
Benjamin

>
>  1. When a hidraw client is running:
>a. I will not send any lizard-mode command to the device, so the client is
>   in full control.
>b. The input device will not send any input message. However it will not
>   dissappear nor return any error message. Maybe it could return ENODEV if
>   they try to open the input device when hidraw client is running?
>
> If lizard_mode == 0 ('disabled'):
>  2.0. When a hidraw client is not running, lizard_mode is disabled.
>
> If lizard_mode == 1, ('auto', the default):
>  2.1. When a hidraw client is not running:
>a. When the input device is not in use, lizard mode is enabled.
>b. When the input device is in use, lizard mode is disabled.
>
> If lizard_mode == 2 ('usermode'):
>  2.2. This driver does not send any lizard_mode-related command. So it is up
>   to user mode to configure it, with steamctrl or whatever.
>
> Note that when Steam Client opens it always disables lizard-mode (it creates
> keyboard/mouse XTest inputs with the same function, though). And when it 
> closed
> (but not when it crashes, I think) it always re-enables the lizard mode.
>
> About the input buttons/axes mapping, as per Clément suggestion, I tried to
> conform to Documentation/gamepad.rst, but with a few caveats and doubts:
>  * BTN_NORTH/BTN_WEST are alias of BTN_X/BTN_Y, but those buttons in this
>controller have the labels changed (BTN_NORTH is actually Y). I don't know
>the best option, so for now I'm mapping 'Y' to BTN_Y and 'X' to BTN_X.
>  * I'm mapping the lpad clicks to BTN_DPAD_{UP,RIGHT,DOWN,LEFT} but I'm not
>sure if that is such a good idea: it cannot do diagonals, for example.
>Maybe we could fake the whole dpad from the touch position?
>  * I'm mapping pressing the joystick to BTN_THUMBL and clicking the rpad to
>BTN_THUMBR. Clicking the lpad is unmapped because that is used for the
>dpad, depending on where it is clicked.
>  * Currently I'm mapping the lpad-touch to BTN_THUMB and rpad-touch to
>BTN_THUMB2, but I don't know if that is so useful. lpad-touch will overlap
>with any use of the dpad. And rpad-touch will overlap with rpad-click...
>
> Changes in v7:
>  * All the automatic lizard_mode stuff.
>  * Added the lizard_mode parameter.
>  * The patchset is reduced to 2 commits. The separation of the
>steam_get_serial command no longer makes sense, since I need the
>steam_send_cmd in the first commit to implement the lizard mode.
>  * Change the input mapping to conform to Documentation/gamepad.rst.
>
> (v6 was a RFC, it does not count).
>
> Changes in v5:
>  * Fix license SPDX to GPL-2.0+.
>  * Minor stylistic changes (BIT(3) instead 0x08 and so on).
>
> Changes in v4:
>  * Add command to check the wireless connection status on probe, without
>waiting for a message (thanks to Clément Vuchener for the tip).
>  * Removed the error code on redundant connection/disconnection messages. That
>was harmless but polluted dmesg.
>  * Added buttons for touching the left-pad and right-pad.
>  * Fixed a misplaced #include from 2/4 to 1/4.
>
> Changes in v3:
>  * Use RCU to do the dynamic connec/disconnect of wireless devices.
>  * Remove entries in hid-quirks.c as 

Re: [PATCH v7 0/2] hid-steam driver with user mode client dection

2018-03-26 Thread Benjamin Tissoires
Hi Rodrigo,

On Sun, Mar 25, 2018 at 6:07 PM, Rodrigo Rivas Costa
 wrote:
> This is a reroll of the Steam Controller driver.
>
> This time the client usage is detected by using exposing a custom hidraw
> device (hid_ll_driver) to userland and forwarding that to the real one.

That is actually more clever than what I had in mind.
This way you reliably know if the hidraw node has been opened without
touching hid-core.c or hidraw.c, well played :)

>
> About how the lizard-mode/hidraw-client issue is handled, I have added a
> module parameter (I don't know if that is the best option, but it helps me
> illustrate different approaches to the problem):
>
> Independently of the lizard_mode parameter value:

I find the values of the lizard_mode parameter hard to understand. And
honestly, I do not think there is much a difference between 0 and 1.
AFAICT, the difference between these two values is that in the first
case you are disabling the lizard mode whether or not the joystick is
in used, and in the latter, you disable it only when the joystick is
in use. Does that gives any benefits to users?

I would think having a boolean "let the kernel handle the lizard mode
with some magic inside" would be simpler to understand. You do not
really want to support too many configurations and I think it would be
wiser to say either disable the new mode or just enable it.

Also, I think there will be races if a user changes the value of the
parameter while running the system. You might want to add an
additional patch that would trigger the mode change on module
parameter change.

As far as I can tell, I am happy with such hack. There are a few
points I'd like to raise in the patch 1, but I'll inline my comments
there.

Cheers,
Benjamin

>
>  1. When a hidraw client is running:
>a. I will not send any lizard-mode command to the device, so the client is
>   in full control.
>b. The input device will not send any input message. However it will not
>   dissappear nor return any error message. Maybe it could return ENODEV if
>   they try to open the input device when hidraw client is running?
>
> If lizard_mode == 0 ('disabled'):
>  2.0. When a hidraw client is not running, lizard_mode is disabled.
>
> If lizard_mode == 1, ('auto', the default):
>  2.1. When a hidraw client is not running:
>a. When the input device is not in use, lizard mode is enabled.
>b. When the input device is in use, lizard mode is disabled.
>
> If lizard_mode == 2 ('usermode'):
>  2.2. This driver does not send any lizard_mode-related command. So it is up
>   to user mode to configure it, with steamctrl or whatever.
>
> Note that when Steam Client opens it always disables lizard-mode (it creates
> keyboard/mouse XTest inputs with the same function, though). And when it 
> closed
> (but not when it crashes, I think) it always re-enables the lizard mode.
>
> About the input buttons/axes mapping, as per Clément suggestion, I tried to
> conform to Documentation/gamepad.rst, but with a few caveats and doubts:
>  * BTN_NORTH/BTN_WEST are alias of BTN_X/BTN_Y, but those buttons in this
>controller have the labels changed (BTN_NORTH is actually Y). I don't know
>the best option, so for now I'm mapping 'Y' to BTN_Y and 'X' to BTN_X.
>  * I'm mapping the lpad clicks to BTN_DPAD_{UP,RIGHT,DOWN,LEFT} but I'm not
>sure if that is such a good idea: it cannot do diagonals, for example.
>Maybe we could fake the whole dpad from the touch position?
>  * I'm mapping pressing the joystick to BTN_THUMBL and clicking the rpad to
>BTN_THUMBR. Clicking the lpad is unmapped because that is used for the
>dpad, depending on where it is clicked.
>  * Currently I'm mapping the lpad-touch to BTN_THUMB and rpad-touch to
>BTN_THUMB2, but I don't know if that is so useful. lpad-touch will overlap
>with any use of the dpad. And rpad-touch will overlap with rpad-click...
>
> Changes in v7:
>  * All the automatic lizard_mode stuff.
>  * Added the lizard_mode parameter.
>  * The patchset is reduced to 2 commits. The separation of the
>steam_get_serial command no longer makes sense, since I need the
>steam_send_cmd in the first commit to implement the lizard mode.
>  * Change the input mapping to conform to Documentation/gamepad.rst.
>
> (v6 was a RFC, it does not count).
>
> Changes in v5:
>  * Fix license SPDX to GPL-2.0+.
>  * Minor stylistic changes (BIT(3) instead 0x08 and so on).
>
> Changes in v4:
>  * Add command to check the wireless connection status on probe, without
>waiting for a message (thanks to Clément Vuchener for the tip).
>  * Removed the error code on redundant connection/disconnection messages. That
>was harmless but polluted dmesg.
>  * Added buttons for touching the left-pad and right-pad.
>  * Fixed a misplaced #include from 2/4 to 1/4.
>
> Changes in v3:
>  * Use RCU to do the dynamic connec/disconnect of wireless devices.
>  * Remove entries in hid-quirks.c as they are no longer needed. 

Re: [PATCH v3] Fix modifier keys for Redragon Asura Keyboard

2018-03-22 Thread Benjamin Tissoires
On Wed, Mar 21, 2018 at 5:33 PM, Robert Munteanu <romb...@apache.org> wrote:
> Hi Benjamin,
>
> On Wed, 2018-03-21 at 17:12 +0100, Benjamin Tissoires wrote:
>> Hi Robert,
>>
>> First, apologies for not answering to the RFC. I missed it and it
>> fell
>> down in my INBOX.
>>
>> On Wed, Mar 21, 2018 at 11:43 AM, Robert Munteanu <romb...@apache.org
>> > wrote:
>> > The microdia family of keyboards uses a non-standard way of sending
>> > modifier keys.
>> >
>> > The down event always sets the first bit to 0x04 and the second
>> > keycode
>>
>> Pretty sure you are talking about bytes here, not bits.
>> And in the HID world, the first byte is usually a report ID.
>
> Right, thanks for spotting that.
>
>>
>> > to a custom value For instance, left shift sends the following bits
>> >
>> >   04 02 00 00 00 00 00 00
>> >
>> > while left control sends
>> >
>> >   04 01 00 00 00 00 00 00
>>
>> This sounds like bit(0) is mapped to LEFT_SHIFT and bit(1) mapped to
>> LEFT_CONTROL in the second byte.
>> Fortunately, LeftControl is designed in HID as 0xe0 in the keyboard
>> HID usage table, and LeftShift is 0xe1. So that would match the
>> behavior you are seeing.
>> If you have 04 04 00 00 00 00 00 00 when pressing LeftAlt, then
>> definitively you are just facing a bitmask, which is fairly common.
>>
>> >
>> > As a result all modifier keys are mapped to left shift and the
>> > keyboard is
>> > non-functional in that respect. To solve the problem, we capture
>> > the
>> > raw data in raw_event and manually generate the correct input
>> > events.
>>
>> I'd like to see the hid-recorder events from these keypresses. The
>> device might be buggy, but I have a gut feeling your solution is not
>> the simplest one.
>> Please grab hid-recorder from http://bentiss.github.io/hid-replay-
>> docs/
>
> See below, I recorded the output for pressing left ctrl, left alt, left
> shift, right ctrl, right alt, right shift, meta.
>
> D: 0
> R: 169 05 0c 09 01 a1 01 85 01 19 00 2a 80 03 15 00 26 80 03 95 01 75
> 10 81 00 c0 05 01 09 80 a1 01 85 02 19 81 29 83 15 00 25 01 75 01 95 03
> 81 02 95 05 81 01 c0 06 00 ff 09 01 a1 01 85 03 1a f1 00 2a f8 00 15 00
> 25 01 75 01 95 08 81 02 c0 05 01 09 06 a1 01 85 04 05 07 19 e0 29 e7 15
> 00 25 01 75 01 95 08 81 00 95 30 75 01 15 00 25 01 05 07 19 00 29 2f 81
> 02 c0 05 01 09 06 a1 01 85 05 95 38 75 01 15 00 25 01 05 07 19 30 29 67
> 81 02 c0 05 01 09 06 a1 01 85 06 95 38 75 01 15 00 25 01 05 07 19 68 29
> 9f 81 02 c0
> N: USB Keyboard
> P: usb-:00:14.0-6/input1
> I: 3 0c45 760b
> D: 0
> E: 0.00 8 04 01 00 00 00 00 00 00
> E: 0.039920 8 04 00 00 00 00 00 00 00
> E: 0.751952 8 04 04 00 00 00 00 00 00
> E: 0.823977 8 04 00 00 00 00 00 00 00
> E: 2.639887 8 04 02 00 00 00 00 00 00
> E: 2.711896 8 04 00 00 00 00 00 00 00
> E: 3.583932 8 04 10 00 00 00 00 00 00
> E: 3.663919 8 04 00 00 00 00 00 00 00
> E: 4.871886 8 04 40 00 00 00 00 00 00
> E: 4.935906 8 04 00 00 00 00 00 00 00
> E: 6.503872 8 04 20 00 00 00 00 00 00
> E: 6.575850 8 04 00 00 00 00 00 00 00
> E: 7.383844 8 04 08 00 00 00 00 00 00
> E: 7.455861 8 04 00 00 00 00 00 00 00

Thanks. So it's indeed an issue with the report descriptor. Not sure
how this can also work under Windows.
FYI, the Report ID 4 translates to:

0x05, 0x01,// Usage Page (Generic Desktop)78
0x09, 0x06,// Usage (Keyboard)80
0xa1, 0x01,// Collection (Application)82
0x85, 0x04,//  Report ID (4)  84
0x05, 0x07,//  Usage Page (Keyboard)  86
0x19, 0xe0,//  Usage Minimum (224)88
0x29, 0xe7,//  Usage Maximum (231)90
0x15, 0x00,//  Logical Minimum (0)92
0x25, 0x01,//  Logical Maximum (1)94
0x75, 0x01,//  Report Size (1)96
0x95, 0x08,//  Report Count (8)   98
0x81, 0x00,//  Input (Data,Arr,Abs)   100
0x95, 0x30,//  Report Count (48)  102
0x75, 0x01,//  Report Size (1)104
0x15, 0x00,//  Logical Minimum (0)106
0x25, 0x01,//  Logical Maximum (1)108
0x05, 0x07,//  Usage Page (Keyboard)  110
0x19, 0x00,//  Usage M

Re: [PATCH v3] Fix modifier keys for Redragon Asura Keyboard

2018-03-22 Thread Benjamin Tissoires
On Wed, Mar 21, 2018 at 5:33 PM, Robert Munteanu  wrote:
> Hi Benjamin,
>
> On Wed, 2018-03-21 at 17:12 +0100, Benjamin Tissoires wrote:
>> Hi Robert,
>>
>> First, apologies for not answering to the RFC. I missed it and it
>> fell
>> down in my INBOX.
>>
>> On Wed, Mar 21, 2018 at 11:43 AM, Robert Munteanu > > wrote:
>> > The microdia family of keyboards uses a non-standard way of sending
>> > modifier keys.
>> >
>> > The down event always sets the first bit to 0x04 and the second
>> > keycode
>>
>> Pretty sure you are talking about bytes here, not bits.
>> And in the HID world, the first byte is usually a report ID.
>
> Right, thanks for spotting that.
>
>>
>> > to a custom value For instance, left shift sends the following bits
>> >
>> >   04 02 00 00 00 00 00 00
>> >
>> > while left control sends
>> >
>> >   04 01 00 00 00 00 00 00
>>
>> This sounds like bit(0) is mapped to LEFT_SHIFT and bit(1) mapped to
>> LEFT_CONTROL in the second byte.
>> Fortunately, LeftControl is designed in HID as 0xe0 in the keyboard
>> HID usage table, and LeftShift is 0xe1. So that would match the
>> behavior you are seeing.
>> If you have 04 04 00 00 00 00 00 00 when pressing LeftAlt, then
>> definitively you are just facing a bitmask, which is fairly common.
>>
>> >
>> > As a result all modifier keys are mapped to left shift and the
>> > keyboard is
>> > non-functional in that respect. To solve the problem, we capture
>> > the
>> > raw data in raw_event and manually generate the correct input
>> > events.
>>
>> I'd like to see the hid-recorder events from these keypresses. The
>> device might be buggy, but I have a gut feeling your solution is not
>> the simplest one.
>> Please grab hid-recorder from http://bentiss.github.io/hid-replay-
>> docs/
>
> See below, I recorded the output for pressing left ctrl, left alt, left
> shift, right ctrl, right alt, right shift, meta.
>
> D: 0
> R: 169 05 0c 09 01 a1 01 85 01 19 00 2a 80 03 15 00 26 80 03 95 01 75
> 10 81 00 c0 05 01 09 80 a1 01 85 02 19 81 29 83 15 00 25 01 75 01 95 03
> 81 02 95 05 81 01 c0 06 00 ff 09 01 a1 01 85 03 1a f1 00 2a f8 00 15 00
> 25 01 75 01 95 08 81 02 c0 05 01 09 06 a1 01 85 04 05 07 19 e0 29 e7 15
> 00 25 01 75 01 95 08 81 00 95 30 75 01 15 00 25 01 05 07 19 00 29 2f 81
> 02 c0 05 01 09 06 a1 01 85 05 95 38 75 01 15 00 25 01 05 07 19 30 29 67
> 81 02 c0 05 01 09 06 a1 01 85 06 95 38 75 01 15 00 25 01 05 07 19 68 29
> 9f 81 02 c0
> N: USB Keyboard
> P: usb-:00:14.0-6/input1
> I: 3 0c45 760b
> D: 0
> E: 0.00 8 04 01 00 00 00 00 00 00
> E: 0.039920 8 04 00 00 00 00 00 00 00
> E: 0.751952 8 04 04 00 00 00 00 00 00
> E: 0.823977 8 04 00 00 00 00 00 00 00
> E: 2.639887 8 04 02 00 00 00 00 00 00
> E: 2.711896 8 04 00 00 00 00 00 00 00
> E: 3.583932 8 04 10 00 00 00 00 00 00
> E: 3.663919 8 04 00 00 00 00 00 00 00
> E: 4.871886 8 04 40 00 00 00 00 00 00
> E: 4.935906 8 04 00 00 00 00 00 00 00
> E: 6.503872 8 04 20 00 00 00 00 00 00
> E: 6.575850 8 04 00 00 00 00 00 00 00
> E: 7.383844 8 04 08 00 00 00 00 00 00
> E: 7.455861 8 04 00 00 00 00 00 00 00

Thanks. So it's indeed an issue with the report descriptor. Not sure
how this can also work under Windows.
FYI, the Report ID 4 translates to:

0x05, 0x01,// Usage Page (Generic Desktop)78
0x09, 0x06,// Usage (Keyboard)80
0xa1, 0x01,// Collection (Application)82
0x85, 0x04,//  Report ID (4)  84
0x05, 0x07,//  Usage Page (Keyboard)  86
0x19, 0xe0,//  Usage Minimum (224)88
0x29, 0xe7,//  Usage Maximum (231)90
0x15, 0x00,//  Logical Minimum (0)92
0x25, 0x01,//  Logical Maximum (1)94
0x75, 0x01,//  Report Size (1)96
0x95, 0x08,//  Report Count (8)   98
0x81, 0x00,//  Input (Data,Arr,Abs)   100
0x95, 0x30,//  Report Count (48)  102
0x75, 0x01,//  Report Size (1)104
0x15, 0x00,//  Logical Minimum (0)106
0x25, 0x01,//  Logical Maximum (1)108
0x05, 0x07,//  Usage Page (Keyboard)  110
0x19, 0x00,//  Usage Minimum (0)  112
0x29, 0x2f, 

<    2   3   4   5   6   7   8   9   10   11   >