* Re: [PATCH v3 0/2] input/serio: Add a firmware_id sysfs attribute
From: Dmitry Torokhov @ 2014-04-20 5:31 UTC (permalink / raw)
To: Hans de Goede; +Cc: Benjamin Tissoires, Peter Hutterer, linux-input
In-Reply-To: <1397471419-31224-1-git-send-email-hdegoede@redhat.com>
On Mon, Apr 14, 2014 at 12:30:17PM +0200, Hans de Goede wrote:
> Hi All,
>
> Here is v3 of my serio firmware_id sysfs attribute patch-set
>
> Changes in v2:
> -Add a helper function to avoid copy/pasting the code for building
> the firmware_id string from pnp_ids
>
> Changes in v3:
> -Prefix the firmware_id string for 8042-pnp devices which "PNP: " so that
> it will be easy to differentiate pnp-ids from ie devicetree ids in the future
Applied, thank you.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v3] synaptics: Add min/max quirk for ThinkPad T431s, L440, L540, S1 Yoga and X1
From: Dmitry Torokhov @ 2014-04-20 5:32 UTC (permalink / raw)
To: Hans de Goede
Cc: Benjamin Tissoires, Peter Hutterer, linux-input, stable,
Benjamin Tissoires
In-Reply-To: <534FF8E6.7060305@redhat.com>
On Thu, Apr 17, 2014 at 05:53:10PM +0200, Hans de Goede wrote:
> Hi,
>
> On 04/17/2014 05:35 PM, Dmitry Torokhov wrote:
> > Hi Hans,
> >
> > On Thu, Apr 17, 2014 at 01:41:43PM +0200, Hans de Goede wrote:
> >> We expect that all the Haswell series will need such quirks, sigh.
> >
> > Given this statement do we really want this to be handled in kernel?
>
> I know this answer won't make you happy, but short term: Yes, we are
> getting many many bugreports about this, ie:
>
> https://bugzilla.redhat.com/show_bug.cgi?id=1060885
> https://bugzilla.redhat.com/show_bug.cgi?id=1068716
> https://bugzilla.redhat.com/show_bug.cgi?id=1085582
> https://bugzilla.redhat.com/show_bug.cgi?id=1085697
> https://bugzilla.redhat.com/show_bug.cgi?id=1086227
>
> And by extending the *already present* quirk table we can get this
> issue resolved quickly, and also resolve it for people running
> older kernels through the various stable series.
>
> > Maybe we simply want udev to fix up the limits with EVIOSABS(),
>
> Ah, I did not know that it is possible to fixup the min/max values
> from user space, that is good to know.
>
> > similarly to how we adjust keymaps for laptops?
>
> We're currently looking into various ways to make this less painful,
> specifically for most laptops the problem seems to be the min value
> and not the max value. And the troublesome min value is the synaptics
> driver default, not the one we get from the firmware. The problem is
> we never ask the firmware because even though it has the "I can report
> min values" capability bit, its "maximum understood request" number
> is too low, so one of our 2 checks for getting the min value is
> failing. If we remove that check some models do give us a proper
> range (but not all, ie the T440s is still wrong).
>
> We're currently trying to figure out if it will be safe for all models
> to remove the "maximum understood request" number check. That should ie
> remove the quirk for the x240 and possible others.
>
> An other option to make this better is to switch the quirks to using
> pnp-ids, ie the L440 and L540 share the same pnp-id. Once you've
> merged the firmware_id patches I can take a shot at simplifying the
> quirk table that way. Downside is that we then probably need to
> put the firmware_id patches in the various stable kernels.
>
> Note that even if we end up moving this to userspace, then we still
> need the firmware_id, because I believe any userspace solution should
> be using pnp-ids too.
>
> TL;DR: It is complicated and for now we would like to continue with
> the quirks as we've done sofar. We are aware that this is undesirable
> from a maintenance pov and are looking into making this better.
OK, fair enough. I applied the patch.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 1/2] input: wacom - missed the last bit of expresskey for DTU-1031
From: Dmitry Torokhov @ 2014-04-20 5:34 UTC (permalink / raw)
To: Ping Cheng; +Cc: linux-input, Ping Cheng
In-Reply-To: <1397244742-20012-1-git-send-email-pingc@wacom.com>
On Fri, Apr 11, 2014 at 12:32:22PM -0700, Ping Cheng wrote:
> Signed-off-by: Ping Cheng <pingc@wacom.com>
Applied, thank you.
> ---
> drivers/input/tablet/wacom_wac.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
> index 05f371d..3d094c9 100644
> --- a/drivers/input/tablet/wacom_wac.c
> +++ b/drivers/input/tablet/wacom_wac.c
> @@ -1838,7 +1838,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
> case DTU:
> if (features->type == DTUS) {
> input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
> - for (i = 0; i < 3; i++)
> + for (i = 0; i < 4; i++)
> __set_bit(BTN_0 + i, input_dev->keybit);
> }
> __set_bit(BTN_TOOL_PEN, input_dev->keybit);
> --
> 1.8.3.2
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH 2/2] input: wacom - unify outbound support for Cintiq and Intuos series
From: Dmitry Torokhov @ 2014-04-20 5:34 UTC (permalink / raw)
To: Ping Cheng; +Cc: linux-input, Ping Cheng
In-Reply-To: <1397244785-20052-1-git-send-email-pingc@wacom.com>
On Fri, Apr 11, 2014 at 12:33:05PM -0700, Ping Cheng wrote:
> Signed-off-by: Ping Cheng <pingc@wacom.com>
Applied, thank you.
> ---
> drivers/input/tablet/wacom_wac.c | 88 ++++++++++++++++++++++++++++++++--------
> drivers/input/tablet/wacom_wac.h | 4 +-
> 2 files changed, 75 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
> index 3d094c9..0e37cde 100644
> --- a/drivers/input/tablet/wacom_wac.c
> +++ b/drivers/input/tablet/wacom_wac.c
> @@ -488,6 +488,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
> input_report_key(input, BTN_TOUCH, 0);
> input_report_abs(input, ABS_PRESSURE, 0);
> input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
> + if (features->quirks & WACOM_QUIRK_MULTI_INPUT)
> + wacom->shared->stylus_in_proximity = true;
> }
>
> /* Exit report */
> @@ -562,6 +564,55 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
> }
> }
>
> +static bool wacom_intuos_outbound(struct wacom_wac *wacom)
> +{
> + struct wacom_features *features = &wacom->features;
> + unsigned char *data = wacom->data;
> + struct input_dev *input = wacom->input;
> + unsigned int bound = 200;
> + bool outbound = false;
> +
> + /* Intuos and old Cintiqs use ready bit for outbound tracking */
> + if (!(data[1] & 0x40))
> + outbound = true;
> +
> + /* New Cintiqs have 200 counts of outbound */
> + if (features->type >= WACOM_21UX2 && features->type <= WACOM_13HD) {
> + if (wacom->x_mapped < bound) {
> + wacom->x_mapped = 0;
> + outbound = true;
> + } else {
> + wacom->x_mapped -= bound;
> + if (wacom->x_mapped > features->x_max) {
> + wacom->x_mapped = features->x_max;
> + outbound = true;
> + }
> + }
> +
> + if (wacom->y_mapped < bound) {
> + wacom->y_mapped = 0;
> + outbound = true;
> + } else {
> + wacom->y_mapped -= bound;
> + if (wacom->y_mapped > features->y_max) {
> + wacom->y_mapped = features->y_max;
> + outbound = true;
> + }
> + }
> + }
> +
> + /* Intuos supports outbound tracking */
> + if (outbound && (features->type >= INTUOS3S && features->type <= INTUOSPL)) {
> + input_report_abs(input, ABS_X, wacom->x_mapped);
> + input_report_abs(input, ABS_Y, wacom->y_mapped);
> + input_report_abs(input, ABS_MISC, wacom->id[0]);
> + input_report_key(input, wacom->tool[0], 1);
> + input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[0]);
> + }
> +
> + return outbound;
> +}
> +
> static int wacom_intuos_irq(struct wacom_wac *wacom)
> {
> struct wacom_features *features = &wacom->features;
> @@ -802,17 +853,22 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
> return 0;
> }
>
> - /* Cintiq doesn't send data when RDY bit isn't set */
> - if (features->type == CINTIQ && !(data[1] & 0x40))
> - return 0;
> + if (features->type >= INTUOS3S) {
> + wacom->x_mapped = (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1);
> + wacom->y_mapped = (data[4] << 9) | (data[5] << 1) | (data[9] & 1);
> + } else {
> + wacom->x_mapped = be16_to_cpup((__be16 *)&data[2]);
> + wacom->y_mapped = be16_to_cpup((__be16 *)&data[4]);
> + }
> +
> + if (wacom_intuos_outbound(wacom))
> + return 0;
>
> + input_report_abs(input, ABS_X, wacom->x_mapped);
> + input_report_abs(input, ABS_Y, wacom->y_mapped);
> if (features->type >= INTUOS3S) {
> - input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
> - input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
> input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
> } else {
> - input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2]));
> - input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4]));
> input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
> }
>
> @@ -2132,10 +2188,10 @@ static const struct wacom_features wacom_features_0x317 =
> 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
> .touch_max = 16 };
> static const struct wacom_features wacom_features_0xF4 =
> - { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
> + { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104080, 65200, 2047,
> 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
> static const struct wacom_features wacom_features_0xF8 =
> - { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, /* Pen */
> + { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104080, 65200, 2047, /* Pen */
> 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
> .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
> static const struct wacom_features wacom_features_0xF6 =
> @@ -2151,7 +2207,7 @@ static const struct wacom_features wacom_features_0xC6 =
> { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023,
> 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
> static const struct wacom_features wacom_features_0x304 =
> - { "Wacom Cintiq 13HD", WACOM_PKGLEN_INTUOS, 59552, 33848, 1023,
> + { "Wacom Cintiq 13HD", WACOM_PKGLEN_INTUOS, 59152, 33448, 1023,
> 63, WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
> static const struct wacom_features wacom_features_0xC7 =
> { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511,
> @@ -2166,23 +2222,23 @@ static const struct wacom_features wacom_features_0xFB =
> { "Wacom DTU1031", WACOM_PKGLEN_DTUS, 22096, 13960, 511,
> 0, DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
> static const struct wacom_features wacom_features_0x57 =
> - { "Wacom DTK2241", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047,
> + { "Wacom DTK2241", WACOM_PKGLEN_INTUOS, 95440, 53860, 2047,
> 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES};
> static const struct wacom_features wacom_features_0x59 = /* Pen */
> - { "Wacom DTH2242", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047,
> + { "Wacom DTH2242", WACOM_PKGLEN_INTUOS, 95440, 53860, 2047,
> 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
> .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
> static const struct wacom_features wacom_features_0x5D = /* Touch */
> { "Wacom DTH2242", .type = WACOM_24HDT,
> .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10 };
> static const struct wacom_features wacom_features_0xCC =
> - { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047,
> + { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 86400, 64800, 2047,
> 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
> static const struct wacom_features wacom_features_0xFA =
> - { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047,
> + { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95440, 53860, 2047,
> 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
> static const struct wacom_features wacom_features_0x5B =
> - { "Wacom Cintiq 22HDT", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047,
> + { "Wacom Cintiq 22HDT", WACOM_PKGLEN_INTUOS, 95440, 53860, 2047,
> 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
> .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
> static const struct wacom_features wacom_features_0x5E =
> @@ -2325,7 +2381,7 @@ static const struct wacom_features wacom_features_0x6004 =
> { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
> 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
> static const struct wacom_features wacom_features_0x0307 =
> - { "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS, 59552, 33848, 2047,
> + { "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS, 59152, 33448, 2047,
> 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
> .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
> static const struct wacom_features wacom_features_0x0309 =
> diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
> index f69c0eb..9f947c3 100644
> --- a/drivers/input/tablet/wacom_wac.h
> +++ b/drivers/input/tablet/wacom_wac.h
> @@ -93,9 +93,9 @@ enum {
> DTK,
> WACOM_24HD,
> CINTIQ_HYBRID,
> + WACOM_13HD,
> CINTIQ,
> WACOM_BEE,
> - WACOM_13HD,
> WACOM_MO,
> WIRELESS,
> BAMBOO_PT,
> @@ -148,6 +148,8 @@ struct wacom_wac {
> int tool[2];
> int id[2];
> __u32 serial[2];
> + unsigned int x_mapped;
> + unsigned int y_mapped;
> struct wacom_features features;
> struct wacom_shared *shared;
> struct input_dev *input;
> --
> 1.8.3.2
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input: w90p910_ts - depend on ARCH_W90X900
From: Dmitry Torokhov @ 2014-04-20 5:38 UTC (permalink / raw)
To: Wan ZongShun; +Cc: Jean Delvare, linux-input, linux-arm-kernel
In-Reply-To: <CAKT61h__8fuJDs94akU73grWns82+mk1vmSdQw5fwd1Cx-455g@mail.gmail.com>
On Tue, Apr 01, 2014 at 09:17:03PM +0800, Wan ZongShun wrote:
> ---------- Forwarded message ----------
> From: Jean Delvare <jdelvare@suse.de>
> Date: 2014-04-01 20:20 GMT+08:00
> Subject: [PATCH] Input: w90p910_ts - depend on ARCH_W90X900
> To: linux-input@vger.kernel.org, linux-arm-kernel@lists.infradead.org
> 抄送: Wan ZongShun <mcuos.com@gmail.com>, Dmitry Torokhov
> <dmitry.torokhov@gmail.com>
>
>
> The w90p910_ts touchscreen driver is heavily architecture dependent,
> so there is no point in letting it be built on other architectures
> than it was written for.
>
> All other W90P910/W90X900 drivers already have that dependency, so it
> makes things more consistent and configuration easier.
>
> Signed-off-by: Jean Delvare <jdelvare@suse.de>
> Cc: Wan ZongShun <mcuos.com@gmail.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/touchscreen/Kconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> --- linux-3.14-rc8.orig/drivers/input/touchscreen/Kconfig
> 2014-02-09 16:53:02.945634113 +0100
> +++ linux-3.14-rc8/drivers/input/touchscreen/Kconfig 2014-04-01
> 14:10:08.936933702 +0200
> @@ -867,7 +867,7 @@ config TOUCHSCREEN_TSC2007
>
> config TOUCHSCREEN_W90X900
> tristate "W90P910 touchscreen driver"
> - depends on HAVE_CLK
> + depends on ARCH_W90X900
> help
> Say Y here if you have a W90P910 based touchscreen.
>
> Sure, your idea is reasonable.
>
> Acked-by Wan Zongshun <mcuos.com@gmail.com>
Applied, thank you.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 0/24] Introduce ff-memless-next as an improved replacement for ff-memless
From: simon @ 2014-04-20 17:27 UTC (permalink / raw)
To: "Michal Malý"
Cc: dmitry.torokhov, jkosina, linux-input, linux-kernel,
Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
[-- Attachment #1: Type: text/plain, Size: 671 bytes --]
> ff-memless-next (MLNX) is a largely improved version of the current
> ff-memless
> (FFML) driver. MLNX supports all force feedback effects currently
> available in
> the Linux force feedback userspace API. All effects are handled in
> accordance
> with Microsoft's DirectInput/XInput.
Hi all,
I got a chance to build this series of patches and test with the
controllers I have (*). Without specific instructions I wasn't sure
exactly what to test, but it seems to be OK and the devices
rumbled/wobbled appropriately,
Simon
tested-by: Simon Wood <simon@mungewell.org>
* controllers:
hid-sony: DS4, DS3SA, Intec
hid-lg: WiiWheel, MomoRed, MomoBlack, DFP, WingMan Force
[-- Attachment #2: ff-memles.txt --]
[-- Type: text/plain, Size: 7105 bytes --]
just testing that fftest does something:
DS4 = ok
DS3-SA = ok
Intec (3rd party PS3 cotroller) = ok
Logitech Wingman Force 3D
Bus 005 Device 009: ID 046d:c283 Logitech, Inc. WingMan Force 3D
--
simon@slipstream:~$ fftest /dev/input/event8
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event8 opened
Features:
* Absolute axes: X, Y, RZ, Throttle, Hat 0 X, Hat 0 Y,
[63 00 03 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Constant, Periodic, Ramp, Rumble, Gain,
Force feedback periodic effects: Square, Triangle, Sine, Saw up, Saw down,
[00 00 00 00 00 00 00 00 00 00 87 1F 01 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... OK (id 0)
Uploading effect #1 (Constant) ... OK (id 1)
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... OK (id 2)
Uploading effect #5 (Weak rumble, with light motor) ... OK (id 3)
Enter effect number, -1 to exit
--
0 - something, but not sine. hard to back/right after effect ends
1 - hard forward/center, then back/right after effect
4 - slow back <-> forward, then back/right after effect
5 - fast back <-> forward, ""
--
simon@slipstream:~$ ffset -a 100 /dev/input/event8 [no force]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -a 0 /dev/input/event8 [no force]
Device /dev/input/event8 opened
--
Logitech Wii Wheel
Bus 005 Device 006: ID 046d:c29c Logitech, Inc. Speed Force Wireless Wheel for Wii
--
simon@slipstream:~$ fftest /dev/input/event8
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event8 opened
Features:
* Absolute axes: X, Y, Z,
[07 00 00 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Constant, Periodic, Ramp, Rumble, Gain, Autocenter,
Force feedback periodic effects: Square, Triangle, Sine, Saw up, Saw down,
[00 00 00 00 00 00 00 00 00 00 87 1F 03 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... OK (id 0)
Uploading effect #1 (Constant) ... OK (id 1)
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... OK (id 2)
Uploading effect #5 (Weak rumble, with light motor) ... OK (id 3)
Enter effect number, -1 to exit
--
0 - wobble
1 - nothing?
4 - slow wobble
5 - fast wobble
--
simon@slipstream:~$ ffset -a 100 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -g 10 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffcfstress -d /dev/input/event8 [ok]
--
Logitech Momo-Red
Bus 005 Device 010: ID 046d:c295 Logitech, Inc. Momo Force Steering Wheel
--
simon@slipstream:~$ fftest /dev/input/event8
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event8 opened
Features:
* Absolute axes: X, Y, Z,
[07 00 00 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Constant, Periodic, Ramp, Rumble, Gain, Autocenter,
Force feedback periodic effects: Square, Triangle, Sine, Saw up, Saw down,
[00 00 00 00 00 00 00 00 00 00 87 1F 03 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... OK (id 0)
Uploading effect #1 (Constant) ... OK (id 1)
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... OK (id 2)
Uploading effect #5 (Weak rumble, with light motor) ... OK (id 3)
Enter effect number, -1 to exit
--
0 - slow wobble
1 - very weak CF to left
2 - nothing
3 - nothing
4 - slow wobble
5 - fast wobble
--
simon@slipstream:~$ ffset -a 100 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -a 0 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -g 100 /dev/input/event8 [ok]
Device /dev/input/event8 opened
--
Logitech Momo-Black
Bus 005 Device 004: ID 046d:ca03 Logitech, Inc. MOMO Racing
--
mon@slipstream:~$ fftest /dev/input/event8
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event8 opened
Features:
* Absolute axes: X, Y, Z,
[07 00 00 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Constant, Periodic, Ramp, Rumble, Gain, Autocenter,
Force feedback periodic effects: Square, Triangle, Sine, Saw up, Saw down,
[00 00 00 00 00 00 00 00 00 00 87 1F 03 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... OK (id 0)
Uploading effect #1 (Constant) ... OK (id 1)
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... OK (id 2)
Uploading effect #5 (Weak rumble, with light motor) ... OK (id 3)
Enter effect number, -1 to exit
--
0 - slow wobble
1 - very weak CF to left
2 - nothing
3 - nothing
4 - slow wobble
5 - fast wobble
--
simon@slipstream:~$ ffset -a 100 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -a 0 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -g 100 /dev/input/event8 [ok]
Device /dev/input/event8 opened
--
Logitech DFP
Bus 005 Device 006: ID 046d:c298 Logitech, Inc. Driving Force Pro
--
simon@slipstream:~$ fftest /dev/input/event8
Force feedback test program.
HOLD FIRMLY YOUR WHEEL OR JOYSTICK TO PREVENT DAMAGES
Device /dev/input/event8 opened
Features:
* Absolute axes: X, Y, RZ, Hat 0 X, Hat 0 Y,
[23 00 03 00 00 00 00 00 ]
* Relative axes:
[00 00 ]
* Force feedback effects types: Constant, Periodic, Ramp, Rumble, Gain, Autocenter,
Force feedback periodic effects: Square, Triangle, Sine, Saw up, Saw down,
[00 00 00 00 00 00 00 00 00 00 87 1F 03 00 00 00 ]
* Number of simultaneous effects: 16
Setting master gain to 75% ... OK
Uploading effect #0 (Periodic sinusoidal) ... OK (id 0)
Uploading effect #1 (Constant) ... OK (id 1)
Uploading effect #2 (Spring) ... Error: Invalid argument
Uploading effect #3 (Damper) ... Error: Invalid argument
Uploading effect #4 (Strong rumble, with heavy motor) ... OK (id 2)
Uploading effect #5 (Weak rumble, with light motor) ... OK (id 3)
Enter effect number, -1 to exit
--
0 - slow wobble
1 - very weak CF to left
2 - nothing
3 - nothing
4 - slow wobble
5 - fast wobble
--
simon@slipstream:~$ ffset -a 100 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -a 0 /dev/input/event8 [ok]
Device /dev/input/event8 opened
simon@slipstream:~$ ffset -g 100 /dev/input/event8 [ok]
Device /dev/input/event8 opened
--
^ permalink raw reply
* Re: [PATCH 23/24] Port hid-lg4ff to ff-memless-next
From: simon @ 2014-04-20 17:27 UTC (permalink / raw)
To: "Michal Malý"
Cc: dmitry.torokhov, jkosina, linux-input, linux-kernel,
Elias Vanderstuyft
In-Reply-To: <1545736.mMj2y7JqSb@sigyn>
> Port hid-lg4ff to ff-memless-next
Signed-off-by: Simon Wood <simon@mungewell.org>
^ permalink raw reply
* Re: [RESEND: PATCH 2/2] input: tc3589x-keypad: support probing from device tree
From: Dmitry Torokhov @ 2014-04-20 19:36 UTC (permalink / raw)
To: Linus Walleij
Cc: devicetree, linux-input, Samuel Ortiz, Lee Jones, linux-kernel,
linux-arm-kernel, Mark Rutland
In-Reply-To: <1397028491-15462-1-git-send-email-linus.walleij@linaro.org>
On Wed, Apr 09, 2014 at 09:28:11AM +0200, Linus Walleij wrote:
> Implement device tree probing for the tc3589x keypad driver.
> This is modeled on the STMPE keypad driver and tested on the
> Ux500 TVK1281618 UIB.
>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v2->v3:
> - Use two local u32 variables to avoid weirdness in u8 casting
> of the resulting values to the pointers.
> ChangeLog v1->v2:
> - Fix rows/columns binding to read two u32's insead of two
> u8 /bits/ as noted by Mark Rutland.
Applied, thank you.
--
Dmitry
^ permalink raw reply
* Re: [patch]GPIO button is supposed to wake the system up if the wakeup attribute is set
From: Dmitry Torokhov @ 2014-04-20 19:39 UTC (permalink / raw)
To: Li, Aubrey
Cc: Laxman Dewangan, One Thousand Gnomes, sachin.kamat@linaro.org,
linux-input@vger.kernel.org
In-Reply-To: <5350B6BF.2090206@linux.intel.com>
On Fri, Apr 18, 2014 at 01:23:11PM +0800, Li, Aubrey wrote:
> On 2014/4/18 7:54, Dmitry Torokhov wrote:
> > Hi Aubrey,
> >
> > On Fri, Apr 18, 2014 at 12:42:24AM +0800, Li, Aubrey wrote:
> >> On 2014/4/16 20:35, Laxman Dewangan wrote:
> >>> On Tuesday 15 April 2014 09:48 PM, Li, Aubrey wrote:
> >>>> On 2014/4/15 20:38, Laxman Dewangan wrote:
> >>>>> On Monday 14 April 2014 09:12 PM, Li, Aubrey wrote:
> >>>>>> ping...
> >>>>>>
> >>>>>> On 2014/4/10 18:48, One Thousand Gnomes wrote:
> >>>>>>>
> >>>>> I think when we say irq_wake_enable() then based on underlying HW, it
> >>>>> should not turn off the irq if it is require for the wakeup. I mean it
> >>>>> need to be handle in the hw specific callbacks to keep enabling the
> >>>>> wakeup irq on suspend also.
> >>>> I failed to see why this can't be generic to all of the GPIO buttons for
> >>>> suspend wakeup. Do you see any cases broken by this proposal?
> >>>
> >>> My point here is that if underlying HW needs to have irq enabled for
> >>> wakup then it need to handle in centralized location i.e. the driver
> >>> which is implementing it for the irq callbacks.
> >>> Otherwise, we need to change this on multiple places who needs wakeups
> >>> which is vast in nature like sd driver for sdcard insert/remove etc.
> >>> almost all drivers which need wakeups through GPIOs.
> >>
> >> I think we have to handle this driver by driver. I didn't see how can we
> >> make it in a centralized location. Looking forward to see your proposal.
> >>
> >>>
> >>>>> For me, I have key which is interrupt based from PMIC, not based on GPIO
> >>>>> and on that if I set it to IRQF_EARLY_RESUME then it works fine.
> >>>>>
> >>>> IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
> >>>> IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
> >>>> resume time.
> >>>>
> >>>> IRQF_NO_SUSPEND is exactly what I want, instead of IRQF_EARLY_RESUME.
> >>>> Can you please send your proposal/code to help me understand why this
> >>>> has to hw specific and why IRQF_EARLY_RESUME is better than
> >>>> IRQF_NO_SUSPEND?
> >>>
> >>> IRQF_EARLY_RESUME helps to re-enable mask or irq before parent interrupt
> >>> resume and so parent isr handler sees the irq flag enabled when it try
> >>> to scan source of interrupt. Otherwise parent isr handler treat this as
> >>> spurious interrupt and does not call handler as irq flag disabled for that.
> >>>
> >>> This only happen when on resume, parent inettrupt enabled before the
> >>> child interrupt on irq resume. Because as soon as parent isr re-enabled
> >>> on resume, its hadnler get called before actually child interrupt
> >>> enabled. This is what I observed mainly on PMIC and its sub irq. Not
> >>> observed on SoC level of interrupts.
> >>>
> >>
> >> This is expected behavior. I think I still need IRQF_NO_SUSPEND here.
> >> What I want is, this IRQ is able to generate pm wakeup event to wake the
> >> system up. It's enough for my case.
> >
> > The driver does call enable_irq_wake() in its suspend routine to prepare
> > the interrupt in question to be used as a wakeup source. Why isn't it
> > enough? It seems to me that your platform code should properly handle
> > this case instead of relying on the driver to modify IRQ flags.
>
> Yes, gpio_keys_suspend() does call enable_irq_wake() to enable the irq
> of the button. So when the button is pressed, hardware interrupt from
> this irq does occur.
>
> However, after gpio_keys_suspend(), irq_desc of this irq will be
> disabled if there is no IRQF_NO_SUSPEND flag. So when the hardware
> interrupt occurs, the irq handler won't call the action of the irq desc.
> That is, for this case, even if the driver call enable_irq_wake() during
> suspend, the irq handler in this driver won't be called because it's an
> action handler, not a irq handler.
Right, so what I am saying is that enable_irq_wake() should really be
taking care of that and ensuring that if device is marked as wakeup
source it should prepare irq handler code to run all necessary parts
instead of sprinkling random flags all over individual drivers.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: Fwd: Re: [PATCH v2] input: misc: Add driver for Intel Bay Trail GPIO buttons
From: Dmitry Torokhov @ 2014-04-20 19:58 UTC (permalink / raw)
To: Pavel Machek
Cc: Zhu, Lejun, One Thousand Gnomes, linux-kernel, linux-input,
yu-sheng Chen
In-Reply-To: <20140415222001.GA2431@amd.pavel.ucw.cz>
On Wed, Apr 16, 2014 at 12:20:01AM +0200, Pavel Machek wrote:
> Hi!
> >
> > Input: misc - Add driver for Intel Bay Trail GPIO buttons
> >
> > From: Lejun Zhu <lejun.zhu@linux.intel.com>
> >
> > This patch adds support for the GPIO buttons on some Intel Bay Trail
> > tablets originally running Windows 8. The ACPI description of these
> > buttons follows "Windows ACPI Design Guide for SoC Platforms".
>
> Hmm. Is it time for x86 to adopt device tree? Because this is 200
> lines of C code which should really have been 10 lines of .dts...
>
> > +
> > +/*
> > + * Some of the buttons like volume up/down are auto repeat, while others
> > + * are not. To support both, we register two platform devices, and put
> > + * buttons into them based on whether the key should be auto repeat.
> > + */
> > +#define BUTTON_TYPES 2
> > +
> > +struct soc_button_data {
> > + struct platform_device *children[BUTTON_TYPES];
> > +};
>
> Would it be possible to extend device description so that this hack is
> not needed?
It would be not that easy as that would mean we need to control
autorepeat (and thus control repeat delay/repeat rate and also report
them) on a per-key basis.
Having 2 separate devices, one offering autorepeat and another not using
it, is much simpler.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 12/24] Port hid-lgff to ff-memless-next
From: Elias Vanderstuyft @ 2014-04-20 22:00 UTC (permalink / raw)
To: Michal Malý; +Cc: Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <1533887.5nzvy1GCXV@sigyn>
On Wed, Apr 9, 2014 at 1:24 PM, Michal Malý
<madcatxster@devoid-pointer.net> wrote:
> Port hid-lgff to ff-memless-next
>
> Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
> ---
> drivers/hid/Kconfig | 2 +-
> drivers/hid/hid-lgff.c | 63 ++++++++++++++++++++++++++++++++++----------------
> 2 files changed, 44 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index d1d4e77..c7794ae 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -356,7 +356,7 @@ config HID_LOGITECH_DJ
> config LOGITECH_FF
> bool "Logitech force feedback support"
> depends on HID_LOGITECH
> - select INPUT_FF_MEMLESS
> + select INPUT_FF_MEMLESS_NEXT
> help
> Say Y here if you have one of these devices:
> - Logitech WingMan Cordless RumblePad
> diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
> index e1394af..b929a3a 100644
> --- a/drivers/hid/hid-lgff.c
> +++ b/drivers/hid/hid-lgff.c
> @@ -31,9 +31,12 @@
>
> #include <linux/input.h>
> #include <linux/hid.h>
> +#include <linux/input/ff-memless-next.h>
>
> #include "hid-lg.h"
>
> +#define FF_UPDATE_RATE 50
> +
> struct dev_type {
> u16 idVendor;
> u16 idProduct;
> @@ -47,6 +50,13 @@ static const signed short ff_rumble[] = {
>
> static const signed short ff_joystick[] = {
> FF_CONSTANT,
> + FF_RAMP,
> + FF_PERIODIC,
> + FF_SQUARE,
> + FF_TRIANGLE,
> + FF_SINE,
> + FF_SAW_UP,
> + FF_SAW_DOWN,
> -1
> };
Also do the same for the ff_joystick_ac[] array, as it also contains
the FF_CONSTANT capability.
>
> @@ -66,45 +76,58 @@ static const struct dev_type devices[] = {
> { 0x046d, 0xc295, ff_joystick },
> };
>
> -static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
> +static int hid_lgff_play(struct input_dev *dev, void *data,
> + const struct mlnx_effect_command *command)
> {
> struct hid_device *hid = input_get_drvdata(dev);
> struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
> struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
> - int x, y;
> - unsigned int left, right;
>
> -#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
> + switch (command->cmd) {
> + case MLNX_START_COMBINED: {
> + const struct mlnx_simple_force *simple_force = &command->u.simple_force;
> + /* Scale down from MLNX range */
> + const int x = 0x80 - (simple_force->x * 0xff / 0xffff);
> + const int y = simple_force->y * 0xff / 0xffff;
This should be concentrated about the center, which is 0x7f (see * in
next comment.)
Something like this:
const int x = 0x7f - (simple_force->x * 0xff / 0xffff);
const int y = 0x7f - (simple_force->y * 0xff / 0xffff);
>
> - switch (effect->type) {
> - case FF_CONSTANT:
> - x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */
* Here.
> - y = effect->u.ramp.end_level + 0x7f;
> - CLAMP(x);
> - CLAMP(y);
> report->field[0]->value[0] = 0x51;
> report->field[0]->value[1] = 0x08;
> report->field[0]->value[2] = x;
> report->field[0]->value[3] = y;
> dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
> - hid_hw_request(hid, report, HID_REQ_SET_REPORT);
> break;
> + }
> + case MLNX_STOP_COMBINED:
> + report->field[0]->value[0] = 0x51;
> + report->field[0]->value[1] = 0x08;
> + report->field[0]->value[2] = 0;
> + report->field[0]->value[3] = 0;
Then this should become the center-position:
report->field[0]->value[2] = 0x7f;
report->field[0]->value[3] = 0x7f;
> + break;
> + case MLNX_START_RUMBLE: {
> + const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
> + /* Scale down from MLNX range */
> + const unsigned int right = rumble_force->weak * 0xff / 0xffff;
> + const unsigned int left = rumble_force->strong * 0xff / 0xffff;
>
> - case FF_RUMBLE:
> - right = effect->u.rumble.strong_magnitude;
> - left = effect->u.rumble.weak_magnitude;
> - right = right * 0xff / 0xffff;
> - left = left * 0xff / 0xffff;
> - CLAMP(left);
> - CLAMP(right);
> report->field[0]->value[0] = 0x42;
> report->field[0]->value[1] = 0x00;
> report->field[0]->value[2] = left;
> report->field[0]->value[3] = right;
> dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
> - hid_hw_request(hid, report, HID_REQ_SET_REPORT);
> break;
> }
> + case MLNX_STOP_RUMBLE:
> + report->field[0]->value[0] = 0x42;
> + report->field[0]->value[1] = 0x00;
> + report->field[0]->value[2] = 0;
> + report->field[0]->value[3] = 0;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
> +
> return 0;
> }
>
> @@ -148,7 +171,7 @@ int lgff_init(struct hid_device* hid)
> for (i = 0; ff_bits[i] >= 0; i++)
> set_bit(ff_bits[i], dev->ffbit);
>
> - error = input_ff_create_memless(dev, NULL, hid_lgff_play);
> + error = input_ff_create_mlnx(dev, NULL, hid_lgff_play, FF_UPDATE_RATE);
> if (error)
> return error;
>
> --
> 1.9.1
>
>
These comments might fix the weird behaviour (when effects stopped
playing) Simon saw when testing the patchset with his Logitech Wingman
Force 3D.
Elias
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 0/24] Introduce ff-memless-next as an improved replacement for ff-memless
From: Elias Vanderstuyft @ 2014-04-20 22:05 UTC (permalink / raw)
To: Simon Wood
Cc: Michal Malý, Dmitry Torokhov, Jiri Kosina, linux-input,
linux-kernel
In-Reply-To: <c49c4ad2bfabfe75ac065f8ad878d697.squirrel@mungewell.org>
On Sun, Apr 20, 2014 at 7:27 PM, <simon@mungewell.org> wrote:
> Hi all,
> I got a chance to build this series of patches and test with the
> controllers I have (*). Without specific instructions I wasn't sure
> exactly what to test, but it seems to be OK and the devices
> rumbled/wobbled appropriately,
> Simon
>
> tested-by: Simon Wood <simon@mungewell.org>
>
> * controllers:
> hid-sony: DS4, DS3SA, Intec
> hid-lg: WiiWheel, MomoRed, MomoBlack, DFP, WingMan Force
Did the WiiWheel have working FF_CONSTANT before this patchset?
It would be weird if yes, because lg4ff is also used for MOMO-Black
which works fine.
Elias
^ permalink raw reply
* Re: [PATCH 13/24] Port hid-lg3ff to ff-memless-next
From: Elias Vanderstuyft @ 2014-04-20 22:13 UTC (permalink / raw)
To: Michal Malý; +Cc: Dmitry Torokhov, Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <1950497.jofl5Si0qz@sigyn>
On Wed, Apr 9, 2014 at 1:24 PM, Michal Malý
<madcatxster@devoid-pointer.net> wrote:
> Port hid-lg3ff to ff-memless-next
>
> Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
> ---
> drivers/hid/Kconfig | 2 +-
> drivers/hid/hid-lg3ff.c | 56 +++++++++++++++++++++++++++++++------------------
> 2 files changed, 37 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index c7794ae..6f2941a 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -382,7 +382,7 @@ config LOGIRUMBLEPAD2_FF
> config LOGIG940_FF
> bool "Logitech Flight System G940 force feedback support"
> depends on HID_LOGITECH
> - select INPUT_FF_MEMLESS
> + select INPUT_FF_MEMLESS_NEXT
> help
> Say Y here if you want to enable force feedback support for Logitech
> Flight System G940 devices.
> diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c
> index 8c2da18..a85f8e5 100644
> --- a/drivers/hid/hid-lg3ff.c
> +++ b/drivers/hid/hid-lg3ff.c
> @@ -23,9 +23,12 @@
>
> #include <linux/input.h>
> #include <linux/hid.h>
> +#include <linux/input/ff-memless-next.h>
>
> #include "hid-lg.h"
>
> +#define FF_UPDATE_RATE 50
> +
> /*
> * G940 Theory of Operation (from experimentation)
> *
> @@ -58,12 +61,11 @@ struct lg3ff_device {
> };
>
> static int hid_lg3ff_play(struct input_dev *dev, void *data,
> - struct ff_effect *effect)
> + const struct mlnx_effect_command *command)
> {
> struct hid_device *hid = input_get_drvdata(dev);
> struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
> struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
> - int x, y;
>
> /*
> * Available values in the field should always be 63, but we only use up to
> @@ -72,30 +74,37 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data,
> memset(report->field[0]->value, 0,
> sizeof(__s32) * report->field[0]->report_count);
>
> - switch (effect->type) {
> - case FF_CONSTANT:
> -/*
> - * Already clamped in ff_memless
> - * 0 is center (different then other logitech)
> - */
> - x = effect->u.ramp.start_level;
> - y = effect->u.ramp.end_level;
> -
> - /* send command byte */
> - report->field[0]->value[0] = 0x51;
> + /* send command byte */
> + report->field[0]->value[0] = 0x51;
>
> -/*
> - * Sign backwards from other Force3d pro
> - * which get recast here in two's complement 8 bits
> - */
> + switch (command->cmd) {
> + case MLNX_START_COMBINED: {
> + const struct mlnx_simple_force *simple_force = &command->u.simple_force;
> + /* Scale down from MLNX range */
> + const int x = 0x80 - (simple_force->x * 0xff / 0xffff);
> + const int y = simple_force->y * 0xff / 0xffff;
Similarly as in the lgff port, change previous two lines by:
const int x = -(simple_force->x * 0xff / 0xffff);
const int y = -(simple_force->y * 0xff / 0xffff);
> +
> + /*
> + * Sign backwards from other Force3d pro
> + * which get recast here in two's complement 8 bits
> + */
> report->field[0]->value[1] = (unsigned char)(-x);
> report->field[0]->value[31] = (unsigned char)(-y);
> -
> - hid_hw_request(hid, report, HID_REQ_SET_REPORT);
> break;
> + }
> + case MLNX_STOP_COMBINED:
> + report->field[0]->value[1] = 0;
> + report->field[0]->value[31] = 0;
> + break;
> + default:
> + return -EINVAL;
> }
> +
> + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
> +
> return 0;
> }
> +
> static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
> {
> struct hid_device *hid = input_get_drvdata(dev);
> @@ -123,6 +132,13 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
>
> static const signed short ff3_joystick_ac[] = {
> FF_CONSTANT,
> + FF_RAMP,
> + FF_PERIODIC,
> + FF_SQUARE,
> + FF_TRIANGLE,
> + FF_SINE,
> + FF_SAW_UP,
> + FF_SAW_DOWN,
> FF_AUTOCENTER,
> -1
> };
> @@ -143,7 +159,7 @@ int lg3ff_init(struct hid_device *hid)
> for (i = 0; ff_bits[i] >= 0; i++)
> set_bit(ff_bits[i], dev->ffbit);
>
> - error = input_ff_create_memless(dev, NULL, hid_lg3ff_play);
> + error = input_ff_create_mlnx(dev, NULL, hid_lg3ff_play, FF_UPDATE_RATE);
> if (error)
> return error;
>
> --
> 1.9.1
>
>
Elias
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 0/24] Introduce ff-memless-next as an improved replacement for ff-memless
From: simon @ 2014-04-20 22:29 UTC (permalink / raw)
To: Elias Vanderstuyft
Cc: Simon Wood, "Michal Malý", Dmitry Torokhov,
Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <CADbOyBSxHj80zA7UNq+yAtmSPgTqCXgOUUsQ30DQQ66cGw9egw@mail.gmail.com>
> Did the WiiWheel have working FF_CONSTANT before this patchset?
> It would be weird if yes, because lg4ff is also used for MOMO-Black
> which works fine.
Yes, I think that the force requested by fftest was just too weak to
actually move the wheel. ffcfstress (or whatever it is called) works OK.
Simon
^ permalink raw reply
* Re: [patch]GPIO button is supposed to wake the system up if the wakeup attribute is set
From: Li, Aubrey @ 2014-04-21 1:34 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Laxman Dewangan, One Thousand Gnomes, sachin.kamat@linaro.org,
linux-input@vger.kernel.org
In-Reply-To: <20140420193936.GH12454@core.coreip.homeip.net>
On 2014/4/21 3:39, Dmitry Torokhov wrote:
> On Fri, Apr 18, 2014 at 01:23:11PM +0800, Li, Aubrey wrote:
>> On 2014/4/18 7:54, Dmitry Torokhov wrote:
>>> Hi Aubrey,
>>>
>>> On Fri, Apr 18, 2014 at 12:42:24AM +0800, Li, Aubrey wrote:
>>>> On 2014/4/16 20:35, Laxman Dewangan wrote:
>>>>> On Tuesday 15 April 2014 09:48 PM, Li, Aubrey wrote:
>>>>>> On 2014/4/15 20:38, Laxman Dewangan wrote:
>>>>>>> On Monday 14 April 2014 09:12 PM, Li, Aubrey wrote:
>>>>>>>> ping...
>>>>>>>>
>>>>>>>> On 2014/4/10 18:48, One Thousand Gnomes wrote:
>>>>>>>>>
>>>>>>> I think when we say irq_wake_enable() then based on underlying HW, it
>>>>>>> should not turn off the irq if it is require for the wakeup. I mean it
>>>>>>> need to be handle in the hw specific callbacks to keep enabling the
>>>>>>> wakeup irq on suspend also.
>>>>>> I failed to see why this can't be generic to all of the GPIO buttons for
>>>>>> suspend wakeup. Do you see any cases broken by this proposal?
>>>>>
>>>>> My point here is that if underlying HW needs to have irq enabled for
>>>>> wakup then it need to handle in centralized location i.e. the driver
>>>>> which is implementing it for the irq callbacks.
>>>>> Otherwise, we need to change this on multiple places who needs wakeups
>>>>> which is vast in nature like sd driver for sdcard insert/remove etc.
>>>>> almost all drivers which need wakeups through GPIOs.
>>>>
>>>> I think we have to handle this driver by driver. I didn't see how can we
>>>> make it in a centralized location. Looking forward to see your proposal.
>>>>
>>>>>
>>>>>>> For me, I have key which is interrupt based from PMIC, not based on GPIO
>>>>>>> and on that if I set it to IRQF_EARLY_RESUME then it works fine.
>>>>>>>
>>>>>> IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
>>>>>> IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
>>>>>> resume time.
>>>>>>
>>>>>> IRQF_NO_SUSPEND is exactly what I want, instead of IRQF_EARLY_RESUME.
>>>>>> Can you please send your proposal/code to help me understand why this
>>>>>> has to hw specific and why IRQF_EARLY_RESUME is better than
>>>>>> IRQF_NO_SUSPEND?
>>>>>
>>>>> IRQF_EARLY_RESUME helps to re-enable mask or irq before parent interrupt
>>>>> resume and so parent isr handler sees the irq flag enabled when it try
>>>>> to scan source of interrupt. Otherwise parent isr handler treat this as
>>>>> spurious interrupt and does not call handler as irq flag disabled for that.
>>>>>
>>>>> This only happen when on resume, parent inettrupt enabled before the
>>>>> child interrupt on irq resume. Because as soon as parent isr re-enabled
>>>>> on resume, its hadnler get called before actually child interrupt
>>>>> enabled. This is what I observed mainly on PMIC and its sub irq. Not
>>>>> observed on SoC level of interrupts.
>>>>>
>>>>
>>>> This is expected behavior. I think I still need IRQF_NO_SUSPEND here.
>>>> What I want is, this IRQ is able to generate pm wakeup event to wake the
>>>> system up. It's enough for my case.
>>>
>>> The driver does call enable_irq_wake() in its suspend routine to prepare
>>> the interrupt in question to be used as a wakeup source. Why isn't it
>>> enough? It seems to me that your platform code should properly handle
>>> this case instead of relying on the driver to modify IRQ flags.
>>
>> Yes, gpio_keys_suspend() does call enable_irq_wake() to enable the irq
>> of the button. So when the button is pressed, hardware interrupt from
>> this irq does occur.
>>
>> However, after gpio_keys_suspend(), irq_desc of this irq will be
>> disabled if there is no IRQF_NO_SUSPEND flag. So when the hardware
>> interrupt occurs, the irq handler won't call the action of the irq desc.
>> That is, for this case, even if the driver call enable_irq_wake() during
>> suspend, the irq handler in this driver won't be called because it's an
>> action handler, not a irq handler.
>
> Right, so what I am saying is that enable_irq_wake() should really be
> taking care of that and ensuring that if device is marked as wakeup
> source it should prepare irq handler code to run all necessary parts
> instead of sprinkling random flags all over individual drivers.
>
If the IRQ is shared, how to handle the case of the one is marked as
wakeup source and the other is not?
Thanks,
-Aubrey
^ permalink raw reply
* Re: [PATCH] input: add support for ALPS v7 protocol device
From: Elaine Chen @ 2014-04-21 2:12 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: david turvene, Kevin Cernekee, linux-input, Justin Clift,
Tommy Will, Qiting Chen
In-Reply-To: <CAKvfdt+TY8MMmbEybOjj=uta_4ZmwddUEGk2m3rutAJKq+k6+w@mail.gmail.com>
Hi, Dmitry,
Waiting for the reviewing of the patch. Is there some steps I missed
before our patch being reviewed? Please tell me. Thank you!
2014-04-14 11:05 GMT+08:00 Elaine Chen <elaineee66@gmail.com>:
> Hi, Dmitry,
>
> Would you please send your suggestions for this patch? Thank you!
>
> 2014-03-19 16:55 GMT+08:00 Qiting Chen <elaineee66@gmail.com>:
>> Here is a patch of supporting ALPS v7 protocol device.
>> ALPS v7 protocol device is a clickpad that is currently used on
>> Lenovo S430/S435/S530, Lenovo Z410/Z510, HP Odie, HP Revolve 810 G1,
>> as well as other machines with ALPS Touchpad of following infomation:
>> Device ID = 0x73, 0x03, 0x0a
>> Firmware ID = 0x88, 0xb*, 0x**
>>suggestion
>
>> A v7 protocol support patch is first relesed 2 months ago:
>> http://www.spinics.net/lists/linux-input/msg29084.html
>> After that some feedbacks were received from end user. Now this patch fixed the bugs
>> reported by them:
>> 1) Fix cursor jump when doing a right click drag
>> 2) Fix cursor jitter when button clicking
>>
>> Signed-off-by: Qiting Chen <qiting.chen@cn.alps.com>
>> ---
>> drivers/input/mouse/alps.c | 560 ++++++++++++++++++++++++++++++++++++++++++---
>> drivers/input/mouse/alps.h | 132 +++++++++--
>> 2 files changed, 641 insertions(+), 51 deletions(-)
>>
>> diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
>> index fb15c64..383281f 100644
>> --- a/drivers/input/mouse/alps.c
>> +++ b/drivers/input/mouse/alps.c
>> @@ -32,6 +32,13 @@
>> #define ALPS_REG_BASE_RUSHMORE 0xc2c0
>> #define ALPS_REG_BASE_PINNACLE 0x0000
>>
>> +#define LEFT_BUTTON_BIT 0x01
>> +#define RIGHT_BUTTON_BIT 0x02
>> +
>> +#define V7_LARGE_MOVEMENT 130
>> +#define V7_DEAD_ZONE_OFFSET_X 72
>> +#define V7_DEAD_ZONE_OFFSET_Y 72
>> +
>> static const struct alps_nibble_commands alps_v3_nibble_commands[] = {
>> { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */
>> { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
>> @@ -99,6 +106,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
>> #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
>> #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
>> 6-byte ALPS packet */
>> +#define ALPS_BTNLESS 0x100 /* ALPS ClickPad flag */
>>
>> static const struct alps_model_info alps_model_data[] = {
>> { { 0x32, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
>> @@ -140,6 +148,20 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
>> * isn't valid per PS/2 spec.
>> */
>>
>> +static unsigned int alps_pt_distance(struct alps_abs_data *pt0,
>> + struct alps_abs_data *pt1)
>> +{
>> + int vect_x, vect_y;
>> +
>> + if (!pt0 || !pt1)
>> + return 0;
>> +
>> + vect_x = pt0->x - pt1->x;
>> + vect_y = pt0->y - pt1->y;
>> +
>> + return int_sqrt(vect_x * vect_x + vect_y * vect_y);
>> +}
>> +
>> /* Packet formats are described in Documentation/input/alps.txt */
>>
>> static bool alps_is_valid_first_byte(struct alps_data *priv,
>> @@ -320,8 +342,8 @@ static void alps_process_bitmap_dolphin(struct alps_data *priv,
>> end_bit = y_msb - 1;
>> box_middle_y = (priv->y_max * (start_bit + end_bit)) /
>> (2 * (priv->y_bits - 1));
>> - *x1 = fields->x;
>> - *y1 = fields->y;
>> + *x1 = fields->pt.x;
>> + *y1 = fields->pt.y;
>> *x2 = 2 * box_middle_x - *x1;
>> *y2 = 2 * box_middle_y - *y1;
>> }
>> @@ -461,6 +483,38 @@ static void alps_report_semi_mt_data(struct input_dev *dev, int num_fingers,
>> alps_set_slot(dev, 1, num_fingers == 2, x2, y2);
>> }
>>
>> +static void alps_report_coord_and_btn(struct psmouse *psmouse,
>> + struct alps_fields *f)
>> +{
>> + struct input_dev *dev;
>> +
>> + if (!psmouse || !f)
>> + return;
>> +
>> + dev = psmouse->dev;
>> +
>> + if (f->fingers) {
>> + input_report_key(dev, BTN_TOUCH, 1);
>> + alps_report_semi_mt_data(dev, f->fingers,
>> + f->pt_img[0].x, f->pt_img[0].y,
>> + f->pt_img[1].x, f->pt_img[1].y);
>> + input_mt_report_finger_count(dev, f->fingers);
>> +
>> + input_report_abs(dev, ABS_X, f->pt_img[0].x);
>> + input_report_abs(dev, ABS_Y, f->pt_img[0].y);
>> + input_report_abs(dev, ABS_PRESSURE, f->pt_img[0].z);
>> + } else {
>> + input_report_key(dev, BTN_TOUCH, 0);
>> + input_mt_report_finger_count(dev, 0);
>> + input_report_abs(dev, ABS_PRESSURE, 0);
>> + }
>> +
>> + input_report_key(dev, BTN_LEFT, f->btn.left);
>> + input_report_key(dev, BTN_RIGHT, f->btn.right);
>> +
>> + input_sync(dev);
>> +}
>> +
>> static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
>> {
>> struct alps_data *priv = psmouse->private;
>> @@ -523,13 +577,13 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
>>
>> static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
>> {
>> - f->left = !!(p[3] & 0x01);
>> - f->right = !!(p[3] & 0x02);
>> - f->middle = !!(p[3] & 0x04);
>> + f->btn.left = !!(p[3] & 0x01);
>> + f->btn.right = !!(p[3] & 0x02);
>> + f->btn.middle = !!(p[3] & 0x04);
>>
>> - f->ts_left = !!(p[3] & 0x10);
>> - f->ts_right = !!(p[3] & 0x20);
>> - f->ts_middle = !!(p[3] & 0x40);
>> + f->btn.ts_left = !!(p[3] & 0x10);
>> + f->btn.ts_right = !!(p[3] & 0x20);
>> + f->btn.ts_middle = !!(p[3] & 0x40);
>> }
>>
>> static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
>> @@ -546,10 +600,10 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
>> ((p[2] & 0x7f) << 1) |
>> (p[4] & 0x01);
>>
>> - f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
>> + f->pt.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
>> ((p[0] & 0x30) >> 4);
>> - f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
>> - f->z = p[5] & 0x7f;
>> + f->pt.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
>> + f->pt.z = p[5] & 0x7f;
>>
>> alps_decode_buttons_v3(f, p);
>> }
>> @@ -573,9 +627,9 @@ static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
>> f->is_mp = !!(p[0] & 0x20);
>>
>> if (!f->is_mp) {
>> - f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
>> - f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
>> - f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
>> + f->pt.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
>> + f->pt.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
>> + f->pt.z = (p[0] & 4) ? 0 : p[5] & 0x7f;
>> alps_decode_buttons_v3(f, p);
>> } else {
>> f->fingers = ((p[0] & 0x6) >> 1 |
>> @@ -687,7 +741,7 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
>> * with x, y, and z all zero, so these seem to be flukes.
>> * Ignore them.
>> */
>> - if (f.x && f.y && !f.z)
>> + if (f.pt.x && f.pt.y && !f.pt.z)
>> return;
>>
>> /*
>> @@ -695,12 +749,12 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
>> * to rely on ST data.
>> */
>> if (!fingers) {
>> - x1 = f.x;
>> - y1 = f.y;
>> - fingers = f.z > 0 ? 1 : 0;
>> + x1 = f.pt.x;
>> + y1 = f.pt.y;
>> + fingers = f.pt.z > 0 ? 1 : 0;
>> }
>>
>> - if (f.z >= 64)
>> + if (f.pt.z >= 64)
>> input_report_key(dev, BTN_TOUCH, 1);
>> else
>> input_report_key(dev, BTN_TOUCH, 0);
>> @@ -709,22 +763,22 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
>>
>> input_mt_report_finger_count(dev, fingers);
>>
>> - input_report_key(dev, BTN_LEFT, f.left);
>> - input_report_key(dev, BTN_RIGHT, f.right);
>> - input_report_key(dev, BTN_MIDDLE, f.middle);
>> + input_report_key(dev, BTN_LEFT, f.btn.left);
>> + input_report_key(dev, BTN_RIGHT, f.btn.right);
>> + input_report_key(dev, BTN_MIDDLE, f.btn.middle);
>>
>> - if (f.z > 0) {
>> - input_report_abs(dev, ABS_X, f.x);
>> - input_report_abs(dev, ABS_Y, f.y);
>> + if (f.pt.z > 0) {
>> + input_report_abs(dev, ABS_X, f.pt.x);
>> + input_report_abs(dev, ABS_Y, f.pt.y);
>> }
>> - input_report_abs(dev, ABS_PRESSURE, f.z);
>> + input_report_abs(dev, ABS_PRESSURE, f.pt.z);
>>
>> input_sync(dev);
>>
>> if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
>> - input_report_key(dev2, BTN_LEFT, f.ts_left);
>> - input_report_key(dev2, BTN_RIGHT, f.ts_right);
>> - input_report_key(dev2, BTN_MIDDLE, f.ts_middle);
>> + input_report_key(dev2, BTN_LEFT, f.btn.ts_left);
>> + input_report_key(dev2, BTN_RIGHT, f.btn.ts_right);
>> + input_report_key(dev2, BTN_MIDDLE, f.btn.ts_middle);
>> input_sync(dev2);
>> }
>> }
>> @@ -916,6 +970,364 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
>> input_sync(dev);
>> }
>>
>> +static bool alps_is_valid_package_v7(struct psmouse *psmouse)
>> +{
>> + if ((psmouse->pktcnt == 3) && ((psmouse->packet[2] & 0x40) != 0x40))
>> + return false;
>> + if ((psmouse->pktcnt == 4) && ((psmouse->packet[3] & 0x48) != 0x48))
>> + return false;
>> + if ((psmouse->pktcnt == 6) && ((psmouse->packet[5] & 0x40) != 0x0))
>> + return false;
>> + return true;
>> +}
>> +
>> +static int alps_drop_unsupported_packet_v7(struct psmouse *psmouse)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> + int drop = 1;
>> +
>> + if (priv->r.v7.pkt_id == V7_PACKET_ID_NEW ||
>> + priv->r.v7.pkt_id == V7_PACKET_ID_TWO ||
>> + priv->r.v7.pkt_id == V7_PACKET_ID_MULTI ||
>> + priv->r.v7.pkt_id == V7_PACKET_ID_IDLE)
>> + drop = 0;
>> +
>> + return drop;
>> +}
>> +
>> +static unsigned char alps_get_packet_id_v7(char *byte)
>> +{
>> + unsigned char packet_id;
>> +
>> + if (byte[4] & 0x40)
>> + packet_id = V7_PACKET_ID_TWO;
>> + else if (byte[4] & 0x01)
>> + packet_id = V7_PACKET_ID_MULTI;
>> + else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
>> + packet_id = V7_PACKET_ID_NEW;
>> + else
>> + packet_id = V7_PACKET_ID_IDLE;
>> +
>> + return packet_id;
>> +}
>> +
>> +static void alps_get_finger_coordinate_v7(struct alps_abs_data *pt,
>> + unsigned char *pkt,
>> + unsigned char pkt_id)
>> +{
>> + if ((pkt_id == V7_PACKET_ID_TWO) ||
>> + (pkt_id == V7_PACKET_ID_MULTI) ||
>> + (pkt_id == V7_PACKET_ID_NEW)) {
>> + pt[0].x = ((pkt[2] & 0x80) << 4);
>> + pt[0].x |= ((pkt[2] & 0x3F) << 5);
>> + pt[0].x |= ((pkt[3] & 0x30) >> 1);
>> + pt[0].x |= (pkt[3] & 0x07);
>> + pt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
>> +
>> + pt[1].x = ((pkt[3] & 0x80) << 4);
>> + pt[1].x |= ((pkt[4] & 0x80) << 3);
>> + pt[1].x |= ((pkt[4] & 0x3F) << 4);
>> + pt[1].y = ((pkt[5] & 0x80) << 3);
>> + pt[1].y |= ((pkt[5] & 0x3F) << 4);
>> +
>> + if (pkt_id == V7_PACKET_ID_TWO) {
>> + pt[1].x &= ~0x000F;
>> + pt[1].y |= 0x000F;
>> + } else if (pkt_id == V7_PACKET_ID_MULTI) {
>> + pt[1].x &= ~0x003F;
>> + pt[1].y &= ~0x0020;
>> + pt[1].y |= ((pkt[4] & 0x02) << 4);
>> + pt[1].y |= 0x001F;
>> + } else if (pkt_id == V7_PACKET_ID_NEW) {
>> + pt[1].x &= ~0x003F;
>> + pt[1].x |= (pkt[0] & 0x20);
>> + pt[1].y |= 0x000F;
>> + }
>> +
>> + pt[0].y = 0x7FF - pt[0].y;
>> + pt[1].y = 0x7FF - pt[1].y;
>> +
>> + pt[0].z = (pt[0].x && pt[0].y) ? 62 : 0;
>> + pt[1].z = (pt[1].x && pt[1].y) ? 62 : 0;
>> + }
>> +}
>> +
>> +static void alps_decode_packet_v7(struct alps_fields *f,
>> + unsigned char *p,
>> + struct psmouse *psmouse)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> + static struct v7_raw prev_r;
>> +
>> + priv->r.v7.pkt_id = alps_get_packet_id_v7(p);
>> +
>> + alps_get_finger_coordinate_v7(f->pt_img, p, priv->r.v7.pkt_id);
>> +
>> + priv->r.v7.rest_left = 0;
>> + priv->r.v7.rest_right = 0;
>> + priv->r.v7.additional_fingers = 0;
>> + priv->phy_btn = 0;
>> +
>> + if (priv->r.v7.pkt_id == V7_PACKET_ID_TWO ||
>> + priv->r.v7.pkt_id == V7_PACKET_ID_MULTI) {
>> + priv->r.v7.rest_left = (p[0] & 0x10) >> 4;
>> + priv->r.v7.rest_right = (p[0] & 0x20) >> 5;
>> + }
>> +
>> + if (priv->r.v7.pkt_id == V7_PACKET_ID_MULTI)
>> + priv->r.v7.additional_fingers = p[5] & 0x03;
>> +
>> + priv->phy_btn = (p[0] & 0x80) >> 7;
>> +
>> + if (priv->r.v7.pkt_id == V7_PACKET_ID_TWO) {
>> + if (f->pt_img[0].z != 0 && f->pt_img[1].z != 0)
>> + priv->r.v7.raw_fn = 2;
>> + else
>> + priv->r.v7.raw_fn = 1;
>> + } else if (priv->r.v7.pkt_id == V7_PACKET_ID_MULTI)
>> + priv->r.v7.raw_fn = 3 + priv->r.v7.additional_fingers;
>> + else if (priv->r.v7.pkt_id == V7_PACKET_ID_IDLE)
>> + priv->r.v7.raw_fn = 0;
>> + else if (priv->r.v7.pkt_id == V7_PACKET_ID_NEW)
>> + priv->r.v7.raw_fn = prev_r.raw_fn;
>> +
>> + /* It is a trick to bypass firmware bug of older version
>> + that 'New' Packet is missed when finger number changed.
>> + We fake a 'New' Packet in such cases.*/
>> + if (priv->r.v7.pkt_id == V7_PACKET_ID_TWO ||
>> + priv->r.v7.pkt_id == V7_PACKET_ID_MULTI ||
>> + priv->r.v7.pkt_id == V7_PACKET_ID_IDLE) {
>> + if (priv->r.v7.raw_fn != prev_r.raw_fn)
>> + priv->r.v7.pkt_id = V7_PACKET_ID_NEW;
>> + }
>> +
>> + memcpy(&prev_r, &priv->r.v7, sizeof(struct v7_raw));
>> +}
>> +
>> +static void alps_set_each_pt_attr_v7(struct psmouse *psmouse,
>> + struct alps_abs_data *pt,
>> + struct alps_bl_pt_attr *pt_attr)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> + unsigned int dist;
>> +
>> + if (!pt_attr->is_init_pt_got && pt->z != 0) {
>> + pt_attr->is_init_pt_got = 1;
>> + pt_attr->is_counted = 0;
>> + memcpy(&pt_attr->init_pt, pt, sizeof(pt_attr->init_pt));
>> + }
>> +
>> + if (pt->z != 0) {
>> + if (pt->y < priv->resting_zone_y_min) {
>> + /* A finger is recognized as a non-resting finger
>> + if it's position is outside the resting finger zone.*/
>> + pt_attr->zone = ZONE_NORMAL;
>> + pt_attr->is_counted = 1;
>> + } else {
>> + /* A finger is recognized as a resting finger if it's
>> + position is inside the resting finger zone and there's
>> + no large movement from it's touch down position.*/
>> + pt_attr->zone = ZONE_RESTING;
>> +
>> + if (pt->x > priv->x_max / 2)
>> + pt_attr->zone |= ZONE_RIGHT_BTN;
>> + else
>> + pt_attr->zone |= ZONE_LEFT_BTN;
>> +
>> + /* A resting finger will turn to be a non-resting
>> + finger if it has made large movement from it's touch
>> + down position. A non-resting finger will never turn
>> + to a resting finger before it leaves the touchpad
>> + surface.*/
>> + if (pt_attr->is_init_pt_got) {
>> + dist = alps_pt_distance(pt, &pt_attr->init_pt);
>> +
>> + if (dist > V7_LARGE_MOVEMENT)
>> + pt_attr->is_counted = 1;
>> + }
>> + }
>> + }
>> +}
>> +
>> +static void alps_set_pt_attr_v7(struct psmouse *psmouse,
>> + struct alps_fields *f)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> + int i;
>> +
>> + switch (priv->r.v7.pkt_id) {
>> + case V7_PACKET_ID_TWO:
>> + case V7_PACKET_ID_MULTI:
>> + for (i = 0; i < V7_IMG_PT_NUM; i++) {
>> + alps_set_each_pt_attr_v7(psmouse,
>> + &f->pt_img[i],
>> + &priv->pt_attr[i]);
>> + }
>> + break;
>> + default:
>> + /*All finger attributes are cleared when packet ID is
>> + 'IDLE', 'New'or other unknown IDs. An 'IDLE' packet
>> + indicates that there's no finger and no button activity.
>> + A 'NEW' packet indicates the finger position in packet
>> + is not continues from previous packet. Such as the
>> + condition there's finger placed or lifted. In these cases,
>> + finger attributes will be reset.*/
>> + memset(priv->pt_attr, 0, sizeof(priv->pt_attr[0]) * 2);
>> + break;
>> + }
>> +}
>> +
>> +static void alps_cal_output_finger_num_v7(struct psmouse *psmouse,
>> + struct alps_fields *f)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> + unsigned int fn = 0;
>> + int i;
>> +
>> + switch (priv->r.v7.pkt_id) {
>> + case V7_PACKET_ID_IDLE:
>> + case V7_PACKET_ID_NEW:
>> + /*No finger is reported when packet ID is 'IDLE' or 'New'.
>> + An 'IDLE' packet indicates that there's no finger on touchpad.
>> + A 'NEW' packet indicates there's finger placed or lifted.
>> + Finger position of 'New' packet is not continues from the
>> + previous packet.*/
>> + fn = 0;
>> + break;
>> + case V7_PACKET_ID_TWO:
>> + if (f->pt_img[0].z == 0) {
>> + /*The first finger slot is zero when a non-resting
>> + finger lifted and remaining only one resting finger
>> + on touchpad. Hardware report the remaining resting
>> + finger in second slot. This resting is ignored*/
>> + fn = 0;
>> + } else if (f->pt_img[1].z == 0) {
>> + /* The second finger slot is zero if there's
>> + only one finger*/
>> + fn = 1;
>> + } else {
>> + /*All non-resting fingers will be counted to report*/
>> + fn = 0;
>> + for (i = 0; i < V7_IMG_PT_NUM; i++) {
>> + if (priv->pt_attr[i].is_counted)
>> + fn++;
>> + }
>> +
>> + /*In the case that both fingers are
>> + resting fingers, report the first one*/
>> + if (!priv->pt_attr[0].is_counted &&
>> + !priv->pt_attr[1].is_counted) {
>> + fn = 1;
>> + }
>> + }
>> + break;
>> + case V7_PACKET_ID_MULTI:
>> + /*A packet ID 'MULTI' indicats that at least 3 non-resting
>> + finger exist.*/
>> + fn = 3 + priv->r.v7.additional_fingers;
>> + break;
>> + }
>> +
>> + f->fingers = fn;
>> +}
>> +
>> +static void alps_button_dead_zone_filter(struct psmouse *psmouse,
>> + struct alps_fields *f,
>> + struct alps_fields *prev_f)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> + int dx, dy;
>> +
>> + if (priv->prev_phy_btn == 0 && priv->phy_btn != 0) {
>> + memcpy(&priv->pt_attr[0].init_dead_pt,
>> + &f->pt_img[0],
>> + sizeof(struct alps_abs_data));
>> + }
>> +
>> + if (priv->pt_attr[0].init_dead_pt.x != 0 &&
>> + priv->pt_attr[0].init_dead_pt.x != 0) {
>> + dx = f->pt_img[0].x - priv->pt_attr[0].init_dead_pt.x;
>> + dy = f->pt_img[0].y - priv->pt_attr[0].init_dead_pt.y;
>> + if ((abs(dx) > V7_DEAD_ZONE_OFFSET_X) ||
>> + (abs(dy) > V7_DEAD_ZONE_OFFSET_Y)) {
>> + memset(&priv->pt_attr[0].init_dead_pt, 0,
>> + sizeof(struct alps_abs_data));
>> + priv->btn_delay_cnt = 0;
>> + } else {
>> + memcpy(&f->pt_img[0],
>> + &prev_f->pt_img[0],
>> + sizeof(struct alps_abs_data));
>> + if (priv->prev_phy_btn == 0 && priv->phy_btn != 0)
>> + priv->btn_delay_cnt = 2;
>> + }
>> + }
>> +
>> + if (priv->btn_delay_cnt > 0) {
>> + f->btn.left = 0;
>> + f->btn.right = 0;
>> + priv->btn_delay_cnt--;
>> + }
>> +}
>> +
>> +static void alps_assign_buttons_v7(struct psmouse *psmouse,
>> + struct alps_fields *f,
>> + struct alps_fields *prev_f)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> +
>> + if (priv->phy_btn) {
>> + if (!priv->prev_phy_btn) {
>> + /* Report a right click as long as there's finger on
>> + right button zone. Othrewise, report a left click.*/
>> + if (priv->r.v7.rest_right ||
>> + priv->pt_attr[0].zone & ZONE_RIGHT_BTN ||
>> + priv->pt_attr[1].zone & ZONE_RIGHT_BTN) {
>> + f->btn.right = 1;
>> + priv->pressed_btn_bits |= RIGHT_BUTTON_BIT;
>> + } else {
>> + f->btn.left = 1;
>> + priv->pressed_btn_bits |= LEFT_BUTTON_BIT;
>> + }
>> + } else {
>> + if (priv->pressed_btn_bits & RIGHT_BUTTON_BIT)
>> + f->btn.right = 1;
>> + if (priv->pressed_btn_bits & LEFT_BUTTON_BIT)
>> + f->btn.left = 1;
>> + }
>> + } else {
>> + priv->pressed_btn_bits = 0;
>> + f->btn.right = 0;
>> + f->btn.left = 0;
>> + }
>> +
>> + alps_button_dead_zone_filter(psmouse, f, prev_f);
>> +
>> + priv->prev_phy_btn = priv->phy_btn;
>> +}
>> +
>> +static void alps_process_packet_v7(struct psmouse *psmouse)
>> +{
>> + struct alps_data *priv = psmouse->private;
>> + struct alps_fields f = {0};
>> + static struct alps_fields prev_f;
>> + unsigned char *packet = psmouse->packet;
>> +
>> + priv->decode_fields(&f, packet, psmouse);
>> +
>> + if (alps_drop_unsupported_packet_v7(psmouse))
>> + return;
>> +
>> + alps_set_pt_attr_v7(psmouse, &f);
>> +
>> + alps_cal_output_finger_num_v7(psmouse, &f);
>> +
>> + alps_assign_buttons_v7(psmouse, &f, &prev_f);
>> +
>> + alps_report_coord_and_btn(psmouse, &f);
>> +
>> + memcpy(&prev_f, &f, sizeof(struct alps_fields));
>> +}
>> +
>> static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
>> unsigned char packet[],
>> bool report_buttons)
>> @@ -1080,6 +1492,14 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
>> return PSMOUSE_BAD_DATA;
>> }
>>
>> + if ((priv->proto_version == ALPS_PROTO_V7 &&
>> + !alps_is_valid_package_v7(psmouse))) {
>> + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
>> + psmouse->pktcnt - 1,
>> + psmouse->packet[psmouse->pktcnt - 1]);
>> + return PSMOUSE_BAD_DATA;
>> + }
>> +
>> if (psmouse->pktcnt == psmouse->pktsize) {
>> priv->process_packet(psmouse);
>> return PSMOUSE_FULL_PACKET;
>> @@ -1192,6 +1612,22 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
>> return 0;
>> }
>>
>> +static int alps_check_valid_firmware_id(unsigned char id[])
>> +{
>> + int valid = 1;
>> +
>> + if (id[0] == 0x73)
>> + valid = 1;
>> + else if (id[0] == 0x88) {
>> + if ((id[1] == 0x07) ||
>> + (id[1] == 0x08) ||
>> + ((id[1] & 0xf0) == 0xB0))
>> + valid = 1;
>> + }
>> +
>> + return valid;
>> +}
>> +
>> static int alps_enter_command_mode(struct psmouse *psmouse)
>> {
>> unsigned char param[4];
>> @@ -1201,8 +1637,7 @@ static int alps_enter_command_mode(struct psmouse *psmouse)
>> return -1;
>> }
>>
>> - if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
>> - param[0] != 0x73) {
>> + if (!alps_check_valid_firmware_id(param)) {
>> psmouse_dbg(psmouse,
>> "unknown response while entering command mode\n");
>> return -1;
>> @@ -1704,6 +2139,36 @@ error:
>> return ret;
>> }
>>
>> +static int alps_hw_init_v7(struct psmouse *psmouse)
>> +{
>> + struct ps2dev *ps2dev = &psmouse->ps2dev;
>> + int reg_val, ret = -1;
>> +
>> + if (alps_enter_command_mode(psmouse))
>> + goto error;
>> +
>> + reg_val = alps_command_mode_read_reg(psmouse, 0xc2d9);
>> + if (reg_val == -1)
>> + goto error;
>> +
>> + if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
>> + goto error;
>> +
>> + reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
>> + if (reg_val == -1)
>> + goto error;
>> +
>> + if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
>> + goto error;
>> +
>> + alps_exit_command_mode(psmouse);
>> + return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
>> +
>> +error:
>> + alps_exit_command_mode(psmouse);
>> + return ret;
>> +}
>> +
>> /* Must be in command mode when calling this function */
>> static int alps_absolute_mode_v4(struct psmouse *psmouse)
>> {
>> @@ -1875,6 +2340,7 @@ static void alps_set_defaults(struct alps_data *priv)
>> priv->set_abs_params = alps_set_abs_params_st;
>> priv->x_max = 1023;
>> priv->y_max = 767;
>> + priv->slot_number = 1;
>> break;
>> case ALPS_PROTO_V3:
>> priv->hw_init = alps_hw_init_v3;
>> @@ -1883,6 +2349,7 @@ static void alps_set_defaults(struct alps_data *priv)
>> priv->decode_fields = alps_decode_pinnacle;
>> priv->nibble_commands = alps_v3_nibble_commands;
>> priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
>> + priv->slot_number = 2;
>> break;
>> case ALPS_PROTO_V4:
>> priv->hw_init = alps_hw_init_v4;
>> @@ -1890,6 +2357,7 @@ static void alps_set_defaults(struct alps_data *priv)
>> priv->set_abs_params = alps_set_abs_params_mt;
>> priv->nibble_commands = alps_v4_nibble_commands;
>> priv->addr_command = PSMOUSE_CMD_DISABLE;
>> + priv->slot_number = 2;
>> break;
>> case ALPS_PROTO_V5:
>> priv->hw_init = alps_hw_init_dolphin_v1;
>> @@ -1905,6 +2373,7 @@ static void alps_set_defaults(struct alps_data *priv)
>> priv->y_max = 660;
>> priv->x_bits = 23;
>> priv->y_bits = 12;
>> + priv->slot_number = 2;
>> break;
>> case ALPS_PROTO_V6:
>> priv->hw_init = alps_hw_init_v6;
>> @@ -1913,6 +2382,28 @@ static void alps_set_defaults(struct alps_data *priv)
>> priv->nibble_commands = alps_v6_nibble_commands;
>> priv->x_max = 2047;
>> priv->y_max = 1535;
>> + priv->slot_number = 2;
>> + break;
>> + case ALPS_PROTO_V7:
>> + priv->hw_init = alps_hw_init_v7;
>> + priv->process_packet = alps_process_packet_v7;
>> + priv->decode_fields = alps_decode_packet_v7;
>> + priv->set_abs_params = alps_set_abs_params_mt;
>> + priv->nibble_commands = alps_v3_nibble_commands;
>> + priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
>> + priv->x_max = 0xfff;
>> + priv->y_max = 0x7ff;
>> + priv->resting_zone_y_min = 0x654;
>> + priv->byte0 = 0x48;
>> + priv->mask0 = 0x48;
>> + priv->flags = 0;
>> + priv->slot_number = 2;
>> +
>> + priv->phy_btn = 0;
>> + priv->prev_phy_btn = 0;
>> + priv->btn_delay_cnt = 0;
>> + priv->pressed_btn_bits = 0;
>> + memset(priv->pt_attr, 0, sizeof(priv->pt_attr[0]) * 2);
>> break;
>> }
>> }
>> @@ -1982,6 +2473,11 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
>> return -EIO;
>> else
>> return 0;
>> + } else if (ec[0] == 0x88 && (ec[1] & 0xf0) == 0xB0) {
>> + priv->proto_version = ALPS_PROTO_V7;
>> + alps_set_defaults(priv);
>> +
>> + return 0;
>> } else if (ec[0] == 0x88 && ec[1] == 0x08) {
>> priv->proto_version = ALPS_PROTO_V3;
>> alps_set_defaults(priv);
>> @@ -2045,7 +2541,7 @@ static void alps_set_abs_params_mt(struct alps_data *priv,
>> struct input_dev *dev1)
>> {
>> set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
>> - input_mt_init_slots(dev1, 2, 0);
>> + input_mt_init_slots(dev1, priv->slot_number, 0);
>> input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
>> input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
>>
>> diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
>> index 03f88b6..dedbd27 100644
>> --- a/drivers/input/mouse/alps.h
>> +++ b/drivers/input/mouse/alps.h
>> @@ -18,11 +18,36 @@
>> #define ALPS_PROTO_V4 4
>> #define ALPS_PROTO_V5 5
>> #define ALPS_PROTO_V6 6
>> +#define ALPS_PROTO_V7 7
>> +
>> +#define MAX_IMG_PT_NUM 5
>> +#define V7_IMG_PT_NUM 2
>> +
>> +#define ZONE_NORMAL 0x01
>> +#define ZONE_RESTING 0x02
>> +#define ZONE_LEFT_BTN 0x04
>> +#define ZONE_RIGHT_BTN 0x08
>>
>> #define DOLPHIN_COUNT_PER_ELECTRODE 64
>> #define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */
>> #define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */
>>
>> +/*
>> + * enum V7_PACKET_ID - defines the packet type for V7
>> + * V7_PACKET_ID_IDLE: There's no finger and no button activity.
>> + * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad
>> + * or there's button activities.
>> + * V7_PACKET_ID_MULTI: There are at least three non-resting fingers.
>> + * V7_PACKET_ID_NEW: The finger position in slot is not continues from
>> + * previous packet.
>> +*/
>> +enum V7_PACKET_ID {
>> + V7_PACKET_ID_IDLE,
>> + V7_PACKET_ID_TWO,
>> + V7_PACKET_ID_MULTI,
>> + V7_PACKET_ID_NEW,
>> +};
>> +
>> /**
>> * struct alps_model_info - touchpad ID table
>> * @signature: E7 response string to match.
>> @@ -66,15 +91,7 @@ struct alps_nibble_commands {
>> };
>>
>> /**
>> - * struct alps_fields - decoded version of the report packet
>> - * @x_map: Bitmap of active X positions for MT.
>> - * @y_map: Bitmap of active Y positions for MT.
>> - * @fingers: Number of fingers for MT.
>> - * @x: X position for ST.
>> - * @y: Y position for ST.
>> - * @z: Z position for ST.
>> - * @first_mp: Packet is the first of a multi-packet report.
>> - * @is_mp: Packet is part of a multi-packet report.
>> + * struct alps_btn - decoded version of the button status
>> * @left: Left touchpad button is active.
>> * @right: Right touchpad button is active.
>> * @middle: Middle touchpad button is active.
>> @@ -82,16 +99,7 @@ struct alps_nibble_commands {
>> * @ts_right: Right trackstick button is active.
>> * @ts_middle: Middle trackstick button is active.
>> */
>> -struct alps_fields {
>> - unsigned int x_map;
>> - unsigned int y_map;
>> - unsigned int fingers;
>> - unsigned int x;
>> - unsigned int y;
>> - unsigned int z;
>> - unsigned int first_mp:1;
>> - unsigned int is_mp:1;
>> -
>> +struct alps_btn {
>> unsigned int left:1;
>> unsigned int right:1;
>> unsigned int middle:1;
>> @@ -102,6 +110,73 @@ struct alps_fields {
>> };
>>
>> /**
>> + * struct alps_btn - decoded version of the X Y Z postion for ST.
>> + * @x: X position for ST.
>> + * @y: Y position for ST.
>> + * @z: Z position for ST.
>> + */
>> +struct alps_abs_data {
>> + unsigned int x;
>> + unsigned int y;
>> + unsigned int z;
>> +};
>> +
>> +/**
>> + * struct alps_fields - decoded version of the report packet
>> + * @fingers: Number of fingers for MT.
>> + * @pt: X Y Z postion for ST.
>> + * @pt: X Y Z postion for image MT.
>> + * @x_map: Bitmap of active X positions for MT.
>> + * @y_map: Bitmap of active Y positions for MT.
>> + * @first_mp: Packet is the first of a multi-packet report.
>> + * @is_mp: Packet is part of a multi-packet report.
>> + * @btn: Button activity status
>> + */
>> +struct alps_fields {
>> + unsigned int fingers;
>> + struct alps_abs_data pt;
>> + struct alps_abs_data pt_img[MAX_IMG_PT_NUM];
>> + unsigned int x_map;
>> + unsigned int y_map;
>> + unsigned int first_mp:1;
>> + unsigned int is_mp:1;
>> + struct alps_btn btn;
>> +};
>> +
>> +/**
>> + * struct v7_raw - data decoded from raw packet for V7.
>> + * @pkt_id: An id that specifies the type of packet.
>> + * @additional_fingers: Number of additional finger that is neighter included
>> + * in pt slot nor reflected in rest_left and rest_right flag of data packet.
>> + * @rest_left: There are fingers on left resting zone.
>> + * @rest_right: There are fingers on right resting zone.
>> + * @raw_fn: The number of finger on touchpad.
>> + */
>> +struct v7_raw {
>> + unsigned char pkt_id;
>> + unsigned int additional_fingers;
>> + unsigned char rest_left;
>> + unsigned char rest_right;
>> + unsigned char raw_fn;
>> +};
>> +
>> +/**
>> + * struct alps_bl_pt_attr - generic attributes of touch points for buttonless device
>> + * @zone: The part of touchpad that the touch point locates
>> + * @is_counted: The touch point is not a resting finger.
>> + * @is_init_pt_got: The touch down point is got.
>> + * @init_pt: The X Y Z position of the touch down point.
>> + * @init_dead_pt: The touch down point of a finger used by dead zone process.
>> + */
>> +struct alps_bl_pt_attr {
>> + unsigned char zone;
>> + unsigned char is_counted;
>> + unsigned char is_init_pt_got;
>> + struct alps_abs_data init_pt;
>> + struct alps_abs_data init_dead_pt;
>> +};
>> +
>> +/**
>> * struct alps_data - private data structure for the ALPS driver
>> * @dev2: "Relative" device used to report trackstick or mouse activity.
>> * @phys: Physical path for the relative device.
>> @@ -116,8 +191,10 @@ struct alps_fields {
>> * @flags: Additional device capabilities (passthrough port, trackstick, etc.).
>> * @x_max: Largest possible X position value.
>> * @y_max: Largest possible Y position value.
>> + * @resting_zone_y_min: Smallest Y postion value of the bottom resting zone.
>> * @x_bits: Number of X bits in the MT bitmap.
>> * @y_bits: Number of Y bits in the MT bitmap.
>> + * @img_fingers: Number of image fingers.
>> * @hw_init: Protocol-specific hardware init function.
>> * @process_packet: Protocol-specific function to process a report packet.
>> * @decode_fields: Protocol-specific function to read packet bitfields.
>> @@ -132,6 +209,11 @@ struct alps_fields {
>> * @fingers: Number of fingers from last MT report.
>> * @quirks: Bitmap of ALPS_QUIRK_*.
>> * @timer: Timer for flushing out the final report packet in the stream.
>> + * @v7: Data decoded from raw packet for V7
>> + * @phy_btn: Physical button is active.
>> + * @prev_phy_btn: Physical button of previous packet is active.
>> + * @pressed_btn_bits: Pressed positon of button zone
>> + * @pt_attr: Generic attributes of touch points for buttonless device.
>> */
>> struct alps_data {
>> struct input_dev *dev2;
>> @@ -145,8 +227,10 @@ struct alps_data {
>> unsigned char flags;
>> int x_max;
>> int y_max;
>> + int resting_zone_y_min;
>> int x_bits;
>> int y_bits;
>> + unsigned char slot_number;
>>
>> int (*hw_init)(struct psmouse *psmouse);
>> void (*process_packet)(struct psmouse *psmouse);
>> @@ -161,6 +245,16 @@ struct alps_data {
>> int fingers;
>> u8 quirks;
>> struct timer_list timer;
>> +
>> + /* these are used for buttonless touchpad*/
>> + union {
>> + struct v7_raw v7;
>> + } r;
>> + unsigned char phy_btn;
>> + unsigned char prev_phy_btn;
>> + unsigned char btn_delay_cnt;
>> + unsigned char pressed_btn_bits;
>> + struct alps_bl_pt_attr pt_attr[MAX_IMG_PT_NUM];
>> };
>>
>> #define ALPS_QUIRK_TRACKSTICK_BUTTONS 1 /* trakcstick buttons in trackstick packet */
>> --
>> 1.8.3.2
>>
^ permalink raw reply
* Re: [PATCH 0/24] Introduce ff-memless-next as an improved replacement for ff-memless
From: Elias Vanderstuyft @ 2014-04-21 11:25 UTC (permalink / raw)
To: Simon Wood
Cc: Michal Malý, Dmitry Torokhov, Jiri Kosina, linux-input,
linux-kernel
In-Reply-To: <9307026b9160edfb785b894fe6d539b7.squirrel@mungewell.org>
On Mon, Apr 21, 2014 at 12:29 AM, <simon@mungewell.org> wrote:
>
>> Did the WiiWheel have working FF_CONSTANT before this patchset?
>> It would be weird if yes, because lg4ff is also used for MOMO-Black
>> which works fine.
>
> Yes, I think that the force requested by fftest was just too weak to
> actually move the wheel. ffcfstress (or whatever it is called) works OK.
Ah, nice to hear.
I had some additional questions that might benefit to the porting of
the lgff and sony driver, concerning the optimal value for
FF_UPDATE_RATE (at the moment it defaults to a safe 50ms):
- Could you try to sniff FF command USB traffic with the Windows
driver of the WingMan Force, just to learn what the update interval is
when playing a ConstantForce effect with an envelope (I'm only
interested in the envelope part)?
- If official/decent Windows drivers are present for one of the Sony
controllers you have, can you please do the same, but now when playing
a vibration effect (using XInput)?
Elias
^ permalink raw reply
* Re: Issues with hid-multitouch driver
From: Benjamin Tissoires @ 2014-04-21 13:47 UTC (permalink / raw)
To: Tomas Sokorai; +Cc: linux-input
In-Reply-To: <CAEQQWc5My-QBoiX7Yqx_-Rer-OdaD7OxJgci5DScJf012s15Aw@mail.gmail.com>
Hi Thomas,
Can you install hid-recorder from here:
http://bentiss.github.io/hid-replay-docs/
and give me the following hid-recorder logs:
- normal usage (when it is working fine)
- multi-touch taps which breaks the driver,
- normal usage (which should be broken now)
I should be able to understand where the problem lies.
Thanks,
Benjamin
On Sat, Apr 19, 2014 at 7:02 PM, Tomas Sokorai <tsokorai@gmail.com> wrote:
> Hi guys,
>
> I'm having issues with the hid-multitouch driver in kernel 3.14.
> I have the following touchscreen device:
>
> Bus 001 Device 003: ID 03fc:05d8 Elitegroup Computer Systems
>
> The thing is that the driver detects the device correctly and even
> works seemingly OK, until you start doing multi-touch taps on the
> screen.
>
> At some point, the input to the Xorg server stops.
>
> I investigated this further, and using evtest, I can see that the events
> ABS_X and ABS_Y stop being generated, and also that BTN_TOUCH event
> gets a "value 1" for the touch before the freeze, but it is never
> released: no "value 0" for the touch release event, ever.
>
> After the driver gets braindamaged, it only generates
> ABS_MT_POSITION_Y, ABS_MT_POSITION_X and ABS_MT_TRACKING_ID events,
> and therefore no further clicks or normal Xorg pointer movement
> on-screen.
>
> I even tried backporting the lastest version from the HID git, with
> the same results.
>
> Thanks in advance,
> --
> Tomas J. Sokorai Sch.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [patch]GPIO button is supposed to wake the system up if the wakeup attribute is set
From: Dmitry Torokhov @ 2014-04-21 15:55 UTC (permalink / raw)
To: Li, Aubrey
Cc: Laxman Dewangan, One Thousand Gnomes, sachin.kamat@linaro.org,
linux-input@vger.kernel.org
In-Reply-To: <5354759C.7090403@linux.intel.com>
On Mon, Apr 21, 2014 at 09:34:20AM +0800, Li, Aubrey wrote:
> On 2014/4/21 3:39, Dmitry Torokhov wrote:
> > On Fri, Apr 18, 2014 at 01:23:11PM +0800, Li, Aubrey wrote:
> >> On 2014/4/18 7:54, Dmitry Torokhov wrote:
> >>> Hi Aubrey,
> >>>
> >>> On Fri, Apr 18, 2014 at 12:42:24AM +0800, Li, Aubrey wrote:
> >>>> On 2014/4/16 20:35, Laxman Dewangan wrote:
> >>>>> On Tuesday 15 April 2014 09:48 PM, Li, Aubrey wrote:
> >>>>>> On 2014/4/15 20:38, Laxman Dewangan wrote:
> >>>>>>> On Monday 14 April 2014 09:12 PM, Li, Aubrey wrote:
> >>>>>>>> ping...
> >>>>>>>>
> >>>>>>>> On 2014/4/10 18:48, One Thousand Gnomes wrote:
> >>>>>>>>>
> >>>>>>> I think when we say irq_wake_enable() then based on underlying HW, it
> >>>>>>> should not turn off the irq if it is require for the wakeup. I mean it
> >>>>>>> need to be handle in the hw specific callbacks to keep enabling the
> >>>>>>> wakeup irq on suspend also.
> >>>>>> I failed to see why this can't be generic to all of the GPIO buttons for
> >>>>>> suspend wakeup. Do you see any cases broken by this proposal?
> >>>>>
> >>>>> My point here is that if underlying HW needs to have irq enabled for
> >>>>> wakup then it need to handle in centralized location i.e. the driver
> >>>>> which is implementing it for the irq callbacks.
> >>>>> Otherwise, we need to change this on multiple places who needs wakeups
> >>>>> which is vast in nature like sd driver for sdcard insert/remove etc.
> >>>>> almost all drivers which need wakeups through GPIOs.
> >>>>
> >>>> I think we have to handle this driver by driver. I didn't see how can we
> >>>> make it in a centralized location. Looking forward to see your proposal.
> >>>>
> >>>>>
> >>>>>>> For me, I have key which is interrupt based from PMIC, not based on GPIO
> >>>>>>> and on that if I set it to IRQF_EARLY_RESUME then it works fine.
> >>>>>>>
> >>>>>> IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
> >>>>>> IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
> >>>>>> resume time.
> >>>>>>
> >>>>>> IRQF_NO_SUSPEND is exactly what I want, instead of IRQF_EARLY_RESUME.
> >>>>>> Can you please send your proposal/code to help me understand why this
> >>>>>> has to hw specific and why IRQF_EARLY_RESUME is better than
> >>>>>> IRQF_NO_SUSPEND?
> >>>>>
> >>>>> IRQF_EARLY_RESUME helps to re-enable mask or irq before parent interrupt
> >>>>> resume and so parent isr handler sees the irq flag enabled when it try
> >>>>> to scan source of interrupt. Otherwise parent isr handler treat this as
> >>>>> spurious interrupt and does not call handler as irq flag disabled for that.
> >>>>>
> >>>>> This only happen when on resume, parent inettrupt enabled before the
> >>>>> child interrupt on irq resume. Because as soon as parent isr re-enabled
> >>>>> on resume, its hadnler get called before actually child interrupt
> >>>>> enabled. This is what I observed mainly on PMIC and its sub irq. Not
> >>>>> observed on SoC level of interrupts.
> >>>>>
> >>>>
> >>>> This is expected behavior. I think I still need IRQF_NO_SUSPEND here.
> >>>> What I want is, this IRQ is able to generate pm wakeup event to wake the
> >>>> system up. It's enough for my case.
> >>>
> >>> The driver does call enable_irq_wake() in its suspend routine to prepare
> >>> the interrupt in question to be used as a wakeup source. Why isn't it
> >>> enough? It seems to me that your platform code should properly handle
> >>> this case instead of relying on the driver to modify IRQ flags.
> >>
> >> Yes, gpio_keys_suspend() does call enable_irq_wake() to enable the irq
> >> of the button. So when the button is pressed, hardware interrupt from
> >> this irq does occur.
> >>
> >> However, after gpio_keys_suspend(), irq_desc of this irq will be
> >> disabled if there is no IRQF_NO_SUSPEND flag. So when the hardware
> >> interrupt occurs, the irq handler won't call the action of the irq desc.
> >> That is, for this case, even if the driver call enable_irq_wake() during
> >> suspend, the irq handler in this driver won't be called because it's an
> >> action handler, not a irq handler.
> >
> > Right, so what I am saying is that enable_irq_wake() should really be
> > taking care of that and ensuring that if device is marked as wakeup
> > source it should prepare irq handler code to run all necessary parts
> > instead of sprinkling random flags all over individual drivers.
> >
>
> If the IRQ is shared, how to handle the case of the one is marked as
> wakeup source and the other is not?
How do we handle this now? You can either make enable_irq_wake() fail
or, like with other shared interrupts, have it runi both handlers and
let drivers sort it out.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [patch]GPIO button is supposed to wake the system up if the wakeup attribute is set
From: Li, Aubrey @ 2014-04-21 16:16 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Laxman Dewangan, One Thousand Gnomes, sachin.kamat@linaro.org,
linux-input@vger.kernel.org
In-Reply-To: <20140421155513.GA16418@core.coreip.homeip.net>
On 2014/4/21 23:55, Dmitry Torokhov wrote:
> On Mon, Apr 21, 2014 at 09:34:20AM +0800, Li, Aubrey wrote:
>> On 2014/4/21 3:39, Dmitry Torokhov wrote:
>>> On Fri, Apr 18, 2014 at 01:23:11PM +0800, Li, Aubrey wrote:
>>>> On 2014/4/18 7:54, Dmitry Torokhov wrote:
>>>>> Hi Aubrey,
>>>>>
>>>>> On Fri, Apr 18, 2014 at 12:42:24AM +0800, Li, Aubrey wrote:
>>>>>> On 2014/4/16 20:35, Laxman Dewangan wrote:
>>>>>>> On Tuesday 15 April 2014 09:48 PM, Li, Aubrey wrote:
>>>>>>>> On 2014/4/15 20:38, Laxman Dewangan wrote:
>>>>>>>>> On Monday 14 April 2014 09:12 PM, Li, Aubrey wrote:
>>>>>>>>>> ping...
>>>>>>>>>>
>>>>>>>>>> On 2014/4/10 18:48, One Thousand Gnomes wrote:
>>>>>>>>>>>
>>>>>>>>> I think when we say irq_wake_enable() then based on underlying HW, it
>>>>>>>>> should not turn off the irq if it is require for the wakeup. I mean it
>>>>>>>>> need to be handle in the hw specific callbacks to keep enabling the
>>>>>>>>> wakeup irq on suspend also.
>>>>>>>> I failed to see why this can't be generic to all of the GPIO buttons for
>>>>>>>> suspend wakeup. Do you see any cases broken by this proposal?
>>>>>>>
>>>>>>> My point here is that if underlying HW needs to have irq enabled for
>>>>>>> wakup then it need to handle in centralized location i.e. the driver
>>>>>>> which is implementing it for the irq callbacks.
>>>>>>> Otherwise, we need to change this on multiple places who needs wakeups
>>>>>>> which is vast in nature like sd driver for sdcard insert/remove etc.
>>>>>>> almost all drivers which need wakeups through GPIOs.
>>>>>>
>>>>>> I think we have to handle this driver by driver. I didn't see how can we
>>>>>> make it in a centralized location. Looking forward to see your proposal.
>>>>>>
>>>>>>>
>>>>>>>>> For me, I have key which is interrupt based from PMIC, not based on GPIO
>>>>>>>>> and on that if I set it to IRQF_EARLY_RESUME then it works fine.
>>>>>>>>>
>>>>>>>> IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
>>>>>>>> IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
>>>>>>>> resume time.
>>>>>>>>
>>>>>>>> IRQF_NO_SUSPEND is exactly what I want, instead of IRQF_EARLY_RESUME.
>>>>>>>> Can you please send your proposal/code to help me understand why this
>>>>>>>> has to hw specific and why IRQF_EARLY_RESUME is better than
>>>>>>>> IRQF_NO_SUSPEND?
>>>>>>>
>>>>>>> IRQF_EARLY_RESUME helps to re-enable mask or irq before parent interrupt
>>>>>>> resume and so parent isr handler sees the irq flag enabled when it try
>>>>>>> to scan source of interrupt. Otherwise parent isr handler treat this as
>>>>>>> spurious interrupt and does not call handler as irq flag disabled for that.
>>>>>>>
>>>>>>> This only happen when on resume, parent inettrupt enabled before the
>>>>>>> child interrupt on irq resume. Because as soon as parent isr re-enabled
>>>>>>> on resume, its hadnler get called before actually child interrupt
>>>>>>> enabled. This is what I observed mainly on PMIC and its sub irq. Not
>>>>>>> observed on SoC level of interrupts.
>>>>>>>
>>>>>>
>>>>>> This is expected behavior. I think I still need IRQF_NO_SUSPEND here.
>>>>>> What I want is, this IRQ is able to generate pm wakeup event to wake the
>>>>>> system up. It's enough for my case.
>>>>>
>>>>> The driver does call enable_irq_wake() in its suspend routine to prepare
>>>>> the interrupt in question to be used as a wakeup source. Why isn't it
>>>>> enough? It seems to me that your platform code should properly handle
>>>>> this case instead of relying on the driver to modify IRQ flags.
>>>>
>>>> Yes, gpio_keys_suspend() does call enable_irq_wake() to enable the irq
>>>> of the button. So when the button is pressed, hardware interrupt from
>>>> this irq does occur.
>>>>
>>>> However, after gpio_keys_suspend(), irq_desc of this irq will be
>>>> disabled if there is no IRQF_NO_SUSPEND flag. So when the hardware
>>>> interrupt occurs, the irq handler won't call the action of the irq desc.
>>>> That is, for this case, even if the driver call enable_irq_wake() during
>>>> suspend, the irq handler in this driver won't be called because it's an
>>>> action handler, not a irq handler.
>>>
>>> Right, so what I am saying is that enable_irq_wake() should really be
>>> taking care of that and ensuring that if device is marked as wakeup
>>> source it should prepare irq handler code to run all necessary parts
>>> instead of sprinkling random flags all over individual drivers.
>>>
>>
>> If the IRQ is shared, how to handle the case of the one is marked as
>> wakeup source and the other is not?
>
> How do we handle this now? You can either make enable_irq_wake() fail
> or, like with other shared interrupts, have it runi both handlers and
> let drivers sort it out.
>
Hi Dmitry,
The current implementation is, setup the irq with the desired/correct
flags, so the irq and the corresponding irq_desc handler will be enabled
or disabled properly during suspend and resume.
My patch is exactly following this way and the impact is gpio key driver
only. What you suggest seems not to be a small change and need a widely
testing because the change is supposed to cover all of the drivers.
I'm looking forward to seeing your patch or if you want me to do this
change, please let me know.
Thanks,
-Aubrey
> Thanks.
>
^ permalink raw reply
* Re: [patch]GPIO button is supposed to wake the system up if the wakeup attribute is set
From: Dmitry Torokhov @ 2014-04-21 16:26 UTC (permalink / raw)
To: Li, Aubrey
Cc: Laxman Dewangan, One Thousand Gnomes, sachin.kamat@linaro.org,
linux-input@vger.kernel.org
In-Reply-To: <53554474.5000502@linux.intel.com>
On Tue, Apr 22, 2014 at 12:16:52AM +0800, Li, Aubrey wrote:
> On 2014/4/21 23:55, Dmitry Torokhov wrote:
> > On Mon, Apr 21, 2014 at 09:34:20AM +0800, Li, Aubrey wrote:
> >> On 2014/4/21 3:39, Dmitry Torokhov wrote:
> >>> On Fri, Apr 18, 2014 at 01:23:11PM +0800, Li, Aubrey wrote:
> >>>> On 2014/4/18 7:54, Dmitry Torokhov wrote:
> >>>>> Hi Aubrey,
> >>>>>
> >>>>> On Fri, Apr 18, 2014 at 12:42:24AM +0800, Li, Aubrey wrote:
> >>>>>> On 2014/4/16 20:35, Laxman Dewangan wrote:
> >>>>>>> On Tuesday 15 April 2014 09:48 PM, Li, Aubrey wrote:
> >>>>>>>> On 2014/4/15 20:38, Laxman Dewangan wrote:
> >>>>>>>>> On Monday 14 April 2014 09:12 PM, Li, Aubrey wrote:
> >>>>>>>>>> ping...
> >>>>>>>>>>
> >>>>>>>>>> On 2014/4/10 18:48, One Thousand Gnomes wrote:
> >>>>>>>>>>>
> >>>>>>>>> I think when we say irq_wake_enable() then based on underlying HW, it
> >>>>>>>>> should not turn off the irq if it is require for the wakeup. I mean it
> >>>>>>>>> need to be handle in the hw specific callbacks to keep enabling the
> >>>>>>>>> wakeup irq on suspend also.
> >>>>>>>> I failed to see why this can't be generic to all of the GPIO buttons for
> >>>>>>>> suspend wakeup. Do you see any cases broken by this proposal?
> >>>>>>>
> >>>>>>> My point here is that if underlying HW needs to have irq enabled for
> >>>>>>> wakup then it need to handle in centralized location i.e. the driver
> >>>>>>> which is implementing it for the irq callbacks.
> >>>>>>> Otherwise, we need to change this on multiple places who needs wakeups
> >>>>>>> which is vast in nature like sd driver for sdcard insert/remove etc.
> >>>>>>> almost all drivers which need wakeups through GPIOs.
> >>>>>>
> >>>>>> I think we have to handle this driver by driver. I didn't see how can we
> >>>>>> make it in a centralized location. Looking forward to see your proposal.
> >>>>>>
> >>>>>>>
> >>>>>>>>> For me, I have key which is interrupt based from PMIC, not based on GPIO
> >>>>>>>>> and on that if I set it to IRQF_EARLY_RESUME then it works fine.
> >>>>>>>>>
> >>>>>>>> IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
> >>>>>>>> IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
> >>>>>>>> resume time.
> >>>>>>>>
> >>>>>>>> IRQF_NO_SUSPEND is exactly what I want, instead of IRQF_EARLY_RESUME.
> >>>>>>>> Can you please send your proposal/code to help me understand why this
> >>>>>>>> has to hw specific and why IRQF_EARLY_RESUME is better than
> >>>>>>>> IRQF_NO_SUSPEND?
> >>>>>>>
> >>>>>>> IRQF_EARLY_RESUME helps to re-enable mask or irq before parent interrupt
> >>>>>>> resume and so parent isr handler sees the irq flag enabled when it try
> >>>>>>> to scan source of interrupt. Otherwise parent isr handler treat this as
> >>>>>>> spurious interrupt and does not call handler as irq flag disabled for that.
> >>>>>>>
> >>>>>>> This only happen when on resume, parent inettrupt enabled before the
> >>>>>>> child interrupt on irq resume. Because as soon as parent isr re-enabled
> >>>>>>> on resume, its hadnler get called before actually child interrupt
> >>>>>>> enabled. This is what I observed mainly on PMIC and its sub irq. Not
> >>>>>>> observed on SoC level of interrupts.
> >>>>>>>
> >>>>>>
> >>>>>> This is expected behavior. I think I still need IRQF_NO_SUSPEND here.
> >>>>>> What I want is, this IRQ is able to generate pm wakeup event to wake the
> >>>>>> system up. It's enough for my case.
> >>>>>
> >>>>> The driver does call enable_irq_wake() in its suspend routine to prepare
> >>>>> the interrupt in question to be used as a wakeup source. Why isn't it
> >>>>> enough? It seems to me that your platform code should properly handle
> >>>>> this case instead of relying on the driver to modify IRQ flags.
> >>>>
> >>>> Yes, gpio_keys_suspend() does call enable_irq_wake() to enable the irq
> >>>> of the button. So when the button is pressed, hardware interrupt from
> >>>> this irq does occur.
> >>>>
> >>>> However, after gpio_keys_suspend(), irq_desc of this irq will be
> >>>> disabled if there is no IRQF_NO_SUSPEND flag. So when the hardware
> >>>> interrupt occurs, the irq handler won't call the action of the irq desc.
> >>>> That is, for this case, even if the driver call enable_irq_wake() during
> >>>> suspend, the irq handler in this driver won't be called because it's an
> >>>> action handler, not a irq handler.
> >>>
> >>> Right, so what I am saying is that enable_irq_wake() should really be
> >>> taking care of that and ensuring that if device is marked as wakeup
> >>> source it should prepare irq handler code to run all necessary parts
> >>> instead of sprinkling random flags all over individual drivers.
> >>>
> >>
> >> If the IRQ is shared, how to handle the case of the one is marked as
> >> wakeup source and the other is not?
> >
> > How do we handle this now? You can either make enable_irq_wake() fail
> > or, like with other shared interrupts, have it runi both handlers and
> > let drivers sort it out.
> >
> Hi Dmitry,
>
> The current implementation is, setup the irq with the desired/correct
> flags, so the irq and the corresponding irq_desc handler will be enabled
> or disabled properly during suspend and resume.
>
> My patch is exactly following this way and the impact is gpio key driver
> only. What you suggest seems not to be a small change and need a widely
> testing because the change is supposed to cover all of the drivers.
Right, you are working around issue in IRQ core by adjusting the driver.
Once the core is fixed you (and others) won't be needing to change
drivers at all.
>
> I'm looking forward to seeing your patch or if you want me to do this
> change, please let me know.
Yes please ;)
Thanks.
--
Dmitry
^ permalink raw reply
* Bug: HID-Sony: DS4 touch-pad corrupts Axis0
From: simon @ 2014-04-21 16:49 UTC (permalink / raw)
To: Frank Praznik, Frank Praznik, HID CORE LAYER, Jiri Kosina
Hi,
I've noticed a glitch with the Dualshock4 on 3.15rc1 (plus LEDs patch, if
that makes a difference).
Sometimes everything works as expected, the thumbsticks work OK and the
touch-pad changes axis 15 & 16 (as reported by jstest). Other times axis
15 and 16 do not report changes, instead axis 0 is corrupted/changed when
the touch-pad is 'swiped'.
Evtest appears to report correctly all the time.
It seems that the controller works first time it is plugged in (after
boot), but then fails subsequent times. I think that the first time I
don't get the pop-up message about battery being charged, which occurs on
other times.
I have not found a trigger yet, but was wondering whether others are
seeing this. I am using a USB connected DS4 (no BT on this machine). OS is
Xubuntu 13.10 with patched kernel,
Simon.
--
simon@slipstream:~$ jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (Sony Computer Entertainment Wireless Controller) has 14 axes (X,
Y, Z,
and 14 buttons (BtnX, BtnY, BtnZ, BtnTL, BtnTR, BtnTL2, BtnTR2, BtnSelect,
BtnSt
Testing ... (interrupt to exit)
--
Apr 21 10:21:01 slipstream kernel: [ 818.052095] usb 5-1: USB disconnect,
devic
Apr 21 10:21:33 slipstream kernel: [ 849.684027] usb 5-1: new full-speed
USB de
Apr 21 10:21:33 slipstream kernel: [ 849.855036] usb 5-1: New USB device
found,
Apr 21 10:21:33 slipstream kernel: [ 849.855041] usb 5-1: New USB device
string
Apr 21 10:21:33 slipstream kernel: [ 849.855045] usb 5-1: Product:
Wireless Con
Apr 21 10:21:33 slipstream kernel: [ 849.855049] usb 5-1: Manufacturer:
Sony Co
Apr 21 10:21:33 slipstream kernel: [ 849.861096] sony
0003:054C:05C4.0005: Usin
Apr 21 10:21:33 slipstream kernel: [ 849.906141] input: Sony Computer
Entertain
Apr 21 10:21:33 slipstream kernel: [ 849.906344] sony
0003:054C:05C4.0005: inpu
--
^ permalink raw reply
* Re: Bug: HID-Sony: DS4 touch-pad corrupts Axis0
From: simon @ 2014-04-21 17:18 UTC (permalink / raw)
To: simon; +Cc: Frank Praznik, Frank Praznik, HID CORE LAYER, Jiri Kosina
In-Reply-To: <23e61b7ee30edafb338935ae40285dce.squirrel@mungewell.org>
> Hi,
> I've noticed a glitch with the Dualshock4 on 3.15rc1 (plus LEDs patch, if
> that makes a difference).
Seems only to work on the the first time the device is connected (with
USB), even in 'repair' mode (with no GUI). Subsequent plug-ins shows axis
0 being corrupted.
Checking through the kernels I have available on this machine, mostly
patched in one way or the other.
--
linux-image-3.11.0-12-generic - works (no gyros)
linux-image-3.13.0-ds4blink+ - fails
linux-image-3.14.0-ff-memless-next+ - fails
linux-image-3.15.0-rc1-ds4leds+ - fails
--
Booting into a LiveCD of Xubuntu 14.04 (kernel 3.13.0-24) does not show
problem, but it is not using hid-sony for this device. Just shows 8 axis
available.
Simon.
Simon.
^ permalink raw reply
* Re: Bug: HID-Sony: DS4 touch-pad corrupts Axis0
From: Frank Praznik @ 2014-04-21 17:30 UTC (permalink / raw)
To: simon, Frank Praznik, HID CORE LAYER, Jiri Kosina
In-Reply-To: <23e61b7ee30edafb338935ae40285dce.squirrel@mungewell.org>
On 4/21/2014 12:49, simon@mungewell.org wrote:
> Hi,
> I've noticed a glitch with the Dualshock4 on 3.15rc1 (plus LEDs patch, if
> that makes a difference).
>
> Sometimes everything works as expected, the thumbsticks work OK and the
> touch-pad changes axis 15 & 16 (as reported by jstest). Other times axis
> 15 and 16 do not report changes, instead axis 0 is corrupted/changed when
> the touch-pad is 'swiped'.
>
> Evtest appears to report correctly all the time.
>
> It seems that the controller works first time it is plugged in (after
> boot), but then fails subsequent times. I think that the first time I
> don't get the pop-up message about battery being charged, which occurs on
> other times.
>
> I have not found a trigger yet, but was wondering whether others are
> seeing this. I am using a USB connected DS4 (no BT on this machine). OS is
> Xubuntu 13.10 with patched kernel,
> Simon.
>
> --
> simon@slipstream:~$ jstest /dev/input/js0
> Driver version is 2.1.0.
> Joystick (Sony Computer Entertainment Wireless Controller) has 14 axes (X,
> Y, Z,
> and 14 buttons (BtnX, BtnY, BtnZ, BtnTL, BtnTR, BtnTL2, BtnTR2, BtnSelect,
> BtnSt
> Testing ... (interrupt to exit)
> --
> Apr 21 10:21:01 slipstream kernel: [ 818.052095] usb 5-1: USB disconnect,
> devic
> Apr 21 10:21:33 slipstream kernel: [ 849.684027] usb 5-1: new full-speed
> USB de
> Apr 21 10:21:33 slipstream kernel: [ 849.855036] usb 5-1: New USB device
> found,
> Apr 21 10:21:33 slipstream kernel: [ 849.855041] usb 5-1: New USB device
> string
> Apr 21 10:21:33 slipstream kernel: [ 849.855045] usb 5-1: Product:
> Wireless Con
> Apr 21 10:21:33 slipstream kernel: [ 849.855049] usb 5-1: Manufacturer:
> Sony Co
> Apr 21 10:21:33 slipstream kernel: [ 849.861096] sony
> 0003:054C:05C4.0005: Usin
> Apr 21 10:21:33 slipstream kernel: [ 849.906141] input: Sony Computer
> Entertain
> Apr 21 10:21:33 slipstream kernel: [ 849.906344] sony
> 0003:054C:05C4.0005: inpu
> --
>
>
I've seen this before and it's a bug in jstest and jstest-gtk, not the
driver or event system. These programs do their own internal axis
mapping and don't properly handle axes above ABS_MISC which is where the
touch axes are. jstest-gtk just default maps these to 0 and the old
jstest just doesn't look like it does any bounds checking at all.
^ permalink raw reply
* [PATCH] Input: Add REP_MAX_COUNT to autorepeat parameters
From: Petri Gynther @ 2014-04-21 20:00 UTC (permalink / raw)
To: linux-input; +Cc: dmitry.torokhov
Add REP_MAX_COUNT to autorepeat parameters. This enables an input device to be
configured for maximum autorepeat count, so that a keypress is not repeated
forever. This is important for Bluetooth keyboards and remote controls that may
lose the Bluetooth link at any time, e.g. right after sending a key-down event
but before sending the corresponding key-up event.
Signed-off-by: Petri Gynther <pgynther@google.com>
---
drivers/input/evdev.c | 11 ++++++++++-
drivers/input/input.c | 6 +++++-
include/linux/input.h | 1 +
include/uapi/linux/input.h | 5 ++++-
4 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a06e125..be1887e 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -847,25 +847,34 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return 0;
case EVIOCGREP:
+ case EVIOCGREP_V2:
if (!test_bit(EV_REP, dev->evbit))
return -ENOSYS;
if (put_user(dev->rep[REP_DELAY], ip))
return -EFAULT;
if (put_user(dev->rep[REP_PERIOD], ip + 1))
return -EFAULT;
+ if (cmd == EVIOCGREP_V2 &&
+ put_user(dev->rep[REP_MAX_COUNT], ip + 2))
+ return -EFAULT;
return 0;
case EVIOCSREP:
+ case EVIOCSREP_V2:
if (!test_bit(EV_REP, dev->evbit))
return -ENOSYS;
if (get_user(u, ip))
return -EFAULT;
if (get_user(v, ip + 1))
return -EFAULT;
+ if (cmd == EVIOCSREP_V2 && get_user(t, ip + 2))
+ return -EFAULT;
input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
-
+ if (cmd == EVIOCSREP_V2)
+ input_inject_event(&evdev->handle, EV_REP,
+ REP_MAX_COUNT, t);
return 0;
case EVIOCRMFF:
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 1c4c0db..a5314c5 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -78,6 +78,7 @@ static void input_start_autorepeat(struct input_dev *dev, int code)
dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
dev->timer.data) {
dev->repeat_key = code;
+ dev->repeat_count = 0;
mod_timer(&dev->timer,
jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
}
@@ -191,7 +192,8 @@ static void input_repeat_key(unsigned long data)
input_pass_values(dev, vals, ARRAY_SIZE(vals));
- if (dev->rep[REP_PERIOD])
+ if (dev->rep[REP_PERIOD] && (dev->rep[REP_MAX_COUNT] == 0 ||
+ ++dev->repeat_count <= dev->rep[REP_MAX_COUNT]))
mod_timer(&dev->timer, jiffies +
msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
@@ -1640,6 +1642,7 @@ static void input_dev_toggle(struct input_dev *dev, bool activate)
if (activate && test_bit(EV_REP, dev->evbit)) {
dev->event(dev, EV_REP, REP_PERIOD, dev->rep[REP_PERIOD]);
dev->event(dev, EV_REP, REP_DELAY, dev->rep[REP_DELAY]);
+ dev->event(dev, EV_REP, REP_MAX_COUNT, dev->rep[REP_MAX_COUNT]);
}
}
@@ -2110,6 +2113,7 @@ int input_register_device(struct input_dev *dev)
dev->timer.function = input_repeat_key;
dev->rep[REP_DELAY] = 250;
dev->rep[REP_PERIOD] = 33;
+ dev->rep[REP_MAX_COUNT] = 0;
}
if (!dev->getkeycode)
diff --git a/include/linux/input.h b/include/linux/input.h
index 82ce323..5f98714 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -151,6 +151,7 @@ struct input_dev {
struct ff_device *ff;
unsigned int repeat_key;
+ unsigned int repeat_count;
struct timer_list timer;
int rep[REP_CNT];
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index bd24470..d7e08ff 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -100,7 +100,9 @@ struct input_keymap_entry {
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
#define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */
+#define EVIOCGREP_V2 _IOR('E', 0x03, unsigned int[3])
#define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */
+#define EVIOCSREP_V2 _IOW('E', 0x03, unsigned int[3])
#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */
#define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry)
@@ -900,7 +902,8 @@ struct input_keymap_entry {
#define REP_DELAY 0x00
#define REP_PERIOD 0x01
-#define REP_MAX 0x01
+#define REP_MAX_COUNT 0x02
+#define REP_MAX 0x02
#define REP_CNT (REP_MAX+1)
/*
--
1.9.1.423.g4596e3a
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox