* Re: [PATCH bpf-next v3 0/3] Annotate kfuncs in .BTF_ids section
From: Jiri Olsa @ 2024-01-13 13:57 UTC (permalink / raw)
To: Daniel Xu
Cc: Jiri Olsa, linux-input, coreteam, linux-arm-kernel, linux-kernel,
netfilter-devel, linux-kselftest, linux-trace-kernel, fsverity,
bpf, netdev, linux-stm32, cgroups, alexei.starovoitov, quentin,
alan.maguire, memxor
In-Reply-To: <2dhmwvfnnqnlrui2qcr5fob54gdsuse5caievct42trvvia6qe@p24nymz3uttv>
On Fri, Jan 12, 2024 at 01:03:59PM -0700, Daniel Xu wrote:
> On Fri, Jan 12, 2024 at 05:20:39PM +0100, Jiri Olsa wrote:
> > On Sat, Jan 06, 2024 at 11:24:07AM -0700, Daniel Xu wrote:
> > > === Description ===
> > >
> > > This is a bpf-treewide change that annotates all kfuncs as such inside
> > > .BTF_ids. This annotation eventually allows us to automatically generate
> > > kfunc prototypes from bpftool.
> > >
> > > We store this metadata inside a yet-unused flags field inside struct
> > > btf_id_set8 (thanks Kumar!). pahole will be taught where to look.
> > >
> > > More details about the full chain of events are available in commit 3's
> > > description.
> > >
> > > The accompanying pahole changes (still needs some cleanup) can be viewed
> > > here on this "frozen" branch [0].
> >
> > so the plan is to have bpftool support to generate header file
> > with detected kfuncs?
>
> Yep, that's the major use case. But I see other use cases as well like
ok, any chance you could already include it in the patchset?
would be a great way to test this.. maybe we could change
selftests to use that
thanks,
jirka
> precision probing of kfuncs. Rather than guess and check which progs can
> load (in the event of backwards incompatible kfunc changes), programs
> can look at kfunc type signature thru BTF.
^ permalink raw reply
* Re: [PATCH V2] Input: adc-joystick: Handle inverted axes
From: Artur Rojek @ 2024-01-13 11:28 UTC (permalink / raw)
To: Chris Morgan
Cc: linux-input, dmitry.torokhov, hdegoede, paul, peter.hutterer, svv,
biswarupp, Chris Morgan
In-Reply-To: <20240111220333.66060-1-macroalpha82@gmail.com>
Hi Chris,
some comments inline.
On 2024-01-11 23:03, Chris Morgan wrote:
> From: Chris Morgan <macromorgan@hotmail.com>
>
> When one or more axes are inverted, (where min > max), normalize the
> data so that min < max and invert the values reported to the input
> stack.
>
> This ensures we can continue defining the device correctly in the
> device tree while not breaking downstream assumptions that min is
> always less than max.
>
> Changes since V1:
> - Moved proposed helper for inversion from input stack to adc-joystick
> driver.
The changes summary should go after the "---" separator, otherwise it
ends up in the commit description.
>
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> ---
> drivers/input/joystick/adc-joystick.c | 21 ++++++++++++++++++++-
> 1 file changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/input/joystick/adc-joystick.c
> b/drivers/input/joystick/adc-joystick.c
> index c0deff5d4282..46197ebd3564 100644
> --- a/drivers/input/joystick/adc-joystick.c
> +++ b/drivers/input/joystick/adc-joystick.c
> @@ -18,6 +18,7 @@ struct adc_joystick_axis {
> s32 range[2];
> s32 fuzz;
> s32 flat;
> + bool inverted;
> };
>
> struct adc_joystick {
> @@ -29,6 +30,14 @@ struct adc_joystick {
> bool polled;
> };
>
> +static int adc_joystick_invert(struct input_dev *dev, unsigned int
> axis, int val)
As the parameter list exceeds 80 characters, can you move "int val" into
a second line?
> +{
> + int min = dev->absinfo[axis].minimum;
> + int max = dev->absinfo[axis].maximum;
> +
> + return (max + min) - val;
> +}
> +
> static void adc_joystick_poll(struct input_dev *input)
> {
> struct adc_joystick *joy = input_get_drvdata(input);
> @@ -38,6 +47,8 @@ static void adc_joystick_poll(struct input_dev
> *input)
> ret = iio_read_channel_raw(&joy->chans[i], &val);
> if (ret < 0)
> return;
> + if (joy->axes[i].inverted)
> + val = adc_joystick_invert(input, i, val);
> input_report_abs(input, joy->axes[i].code, val);
> }
> input_sync(input);
> @@ -86,6 +97,8 @@ static int adc_joystick_handle(const void *data,
> void *private)
> val = sign_extend32(val, msb);
> else
> val &= GENMASK(msb, 0);
> + if (joy->axes[i].inverted)
> + val = adc_joystick_invert(joy->input, i, val);
> input_report_abs(joy->input, joy->axes[i].code, val);
> }
>
> @@ -168,11 +181,17 @@ static int adc_joystick_set_axes(struct device
> *dev, struct adc_joystick *joy)
> goto err_fwnode_put;
> }
>
> + if (axes[i].range[0] > axes[i].range[1]) {
> + dev_dbg(dev, "abs-axis %d inverted\n", i);
There is no "abs-axis" property. Make it "Axis %d inverted\n" instead.
> + axes[i].inverted = 1;
Turn this into an explicit "true", as its a bool.
With all above nits fixed:
Acked-by: Artur Rojek <contact@artur-rojek.eu>
Cheers,
Artur
> + }
> +
> fwnode_property_read_u32(child, "abs-fuzz", &axes[i].fuzz);
> fwnode_property_read_u32(child, "abs-flat", &axes[i].flat);
>
> input_set_abs_params(joy->input, axes[i].code,
> - axes[i].range[0], axes[i].range[1],
> + min_array(axes[i].range, 2),
> + max_array(axes[i].range, 2),
> axes[i].fuzz, axes[i].flat);
> input_set_capability(joy->input, EV_ABS, axes[i].code);
> }
^ permalink raw reply
* [PATCH v2 2/2] HID: input: add support for micmute LED
From: Bernhard Seibold @ 2024-01-13 10:37 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, Benjamin Tissoires, Dmitry Torokhov, Hans de Goede,
Jamie Lentin, Bernhard Seibold
In-Reply-To: <20240113103743.97205-1-mail@bernhard-seibold.de>
Since LED support via input-leds is grandfathered, the new LED is added
directly in hid-input.
Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de>
---
drivers/hid/Kconfig | 11 +++++
drivers/hid/hid-input.c | 92 +++++++++++++++++++++++++++++++++++++++++
include/linux/hid.h | 1 +
3 files changed, 104 insertions(+)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 4ce74af79657..71de0af8f460 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -42,6 +42,17 @@ config HID_BATTERY_STRENGTH
that support this feature) through power_supply class so that userspace
tools, such as upower, can display it.
+config HID_LEDS
+ bool "LED support for HID devices"
+ select LEDS_CLASS
+ default y
+ help
+ This option adds support for LEDs on HID devices. Currently, the
+ only supported LED is microphone mute. For all other LEDs,
+ enable CONFIG_INPUT_LEDS.
+
+ If unsure, say Y.
+
config HIDRAW
bool "/dev/hidraw raw HID device support"
help
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index c8b20d44b147..32d3e6a2ac44 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <linux/leds.h>
#include <linux/hid.h>
#include <linux/hid-debug.h>
@@ -104,6 +105,9 @@ static const struct usage_priority hidinput_usages_priorities[] = {
#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \
&max, EV_KEY, (c))
+#define setup_led(name, trigger) \
+ hidinput_setup_led(device, field, usage_index, name, trigger)
+
static bool match_scancode(struct hid_usage *usage,
unsigned int cur_idx, unsigned int scancode)
{
@@ -674,6 +678,88 @@ static bool hidinput_set_battery_charge_status(struct hid_device *dev,
}
#endif /* CONFIG_HID_BATTERY_STRENGTH */
+#ifdef CONFIG_HID_LEDS
+
+struct hid_led {
+ struct list_head list;
+ struct led_classdev cdev;
+ struct hid_field *field;
+ unsigned int offset;
+ char *name;
+};
+
+static int hidinput_led_brightness_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct device *dev = cdev->dev->parent;
+ struct hid_device *device = to_hid_device(dev);
+ struct hid_led *led = container_of(cdev, struct hid_led, cdev);
+
+ hid_set_field(led->field, led->offset, !!value);
+ schedule_work(&device->led_work);
+
+ return 0;
+}
+
+static void hidinput_setup_led(struct hid_device *device,
+ struct hid_field *field, unsigned int offset,
+ const char *name, const char *trigger)
+{
+ struct hid_led *led;
+ struct device *dev = &device->dev;
+ struct device *idev = &field->hidinput->input->dev;
+
+ led = kzalloc(sizeof(*led), GFP_KERNEL);
+ if (!led)
+ return;
+
+ led->name = kasprintf(GFP_KERNEL, "%s::%s", dev_name(idev), name);
+ if (!led->name) {
+ kfree(led);
+ return;
+ }
+
+ led->cdev.name = led->name;
+ led->cdev.default_trigger = trigger;
+ led->cdev.max_brightness = 1;
+ led->cdev.brightness_set_blocking = hidinput_led_brightness_set;
+ led->field = field;
+ led->offset = offset;
+
+ if (led_classdev_register(dev, &led->cdev)) {
+ kfree(name);
+ kfree(led);
+ return;
+ }
+
+ list_add_tail(&led->list, &device->leds);
+}
+
+static void hidinput_cleanup_leds(struct hid_device *device)
+{
+ struct hid_led *led, *tmp;
+
+ list_for_each_entry_safe(led, tmp, &device->leds, list) {
+ led_classdev_unregister(&led->cdev);
+ kfree(led->name);
+ kfree(led);
+ }
+}
+
+#else /* !CONFIG_HID_LEDS */
+
+static void hidinput_setup_led(struct hid_device *device,
+ struct hid_field *field, unsigned int offset,
+ const char *name, const char *trigger)
+{
+}
+
+static void hidinput_cleanup_leds(struct hid_device *device)
+{
+}
+
+#endif /* CONFIG_HID_LEDS */
+
static bool hidinput_field_in_collection(struct hid_device *device, struct hid_field *field,
unsigned int type, unsigned int usage)
{
@@ -935,6 +1021,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x19: map_led (LED_MAIL); break; /* "Message Waiting" */
case 0x4d: map_led (LED_CHARGING); break; /* "External Power Connected" */
+ case 0x21: /* "Microphone" */
+ setup_led("micmute", "audio-micmute");
+ break;
+
default: goto ignore;
}
break;
@@ -2282,6 +2372,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
int i, k;
INIT_LIST_HEAD(&hid->inputs);
+ INIT_LIST_HEAD(&hid->leds);
INIT_WORK(&hid->led_work, hidinput_led_worker);
hid->status &= ~HID_STAT_DUP_DETECTED;
@@ -2380,6 +2471,7 @@ void hidinput_disconnect(struct hid_device *hid)
{
struct hid_input *hidinput, *next;
+ hidinput_cleanup_leds(hid);
hidinput_cleanup_battery(hid);
list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index bf43f3ff6664..d7cea5476979 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -617,6 +617,7 @@ struct hid_device { /* device report descriptor */
unsigned country; /* HID country */
struct hid_report_enum report_enum[HID_REPORT_TYPES];
struct work_struct led_work; /* delayed LED worker */
+ struct list_head leds; /* List of associated LEDs */
struct semaphore driver_input_lock; /* protects the current driver */
struct device dev; /* device */
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/2] Input: leds - set default-trigger for mute
From: Bernhard Seibold @ 2024-01-13 10:37 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, Benjamin Tissoires, Dmitry Torokhov, Hans de Goede,
Jamie Lentin, Bernhard Seibold
In-Reply-To: <ZZbxHpibdyNY_zUt@google.com>
Set the default-trigger for the mute led to audio-mute.
Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de>
---
drivers/input/input-leds.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c
index 0e935914bc3a..b16fc81940f5 100644
--- a/drivers/input/input-leds.c
+++ b/drivers/input/input-leds.c
@@ -18,6 +18,12 @@
#define VT_TRIGGER(_name) .trigger = NULL
#endif
+#if IS_ENABLED(CONFIG_LEDS_TRIGGER_AUDIO)
+#define AUDIO_TRIGGER(_name) .trigger = _name
+#else
+#define AUDIO_TRIGGER(_name) .trigger = NULL
+#endif
+
static const struct {
const char *name;
const char *trigger;
@@ -29,7 +35,7 @@ static const struct {
[LED_KANA] = { "kana", VT_TRIGGER("kbd-kanalock") },
[LED_SLEEP] = { "sleep" } ,
[LED_SUSPEND] = { "suspend" },
- [LED_MUTE] = { "mute" },
+ [LED_MUTE] = { "mute", AUDIO_TRIGGER("audio-mute") },
[LED_MISC] = { "misc" },
[LED_MAIL] = { "mail" },
[LED_CHARGING] = { "charging" },
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 2/2] HID: hid-steam: Fix cleanup in probe()
From: Vicki Pfau @ 2024-01-13 2:11 UTC (permalink / raw)
To: Dan Carpenter
Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel,
kernel-janitors
In-Reply-To: <1fd87904-dabf-4879-bb89-72d13ebfc91e@moroto.mountain>
I have applied this to our downstream and made sure it compiles and runs
without obvious issues.
Reviewed-by: Vicki Pfau <vi@endrift.com>
Thanks,
Vicki
On 1/12/24 06:35, Dan Carpenter wrote:
> There are a number of issues in this code. First of all if
> steam_create_client_hid() fails then it leads to an error pointer
> dereference when we call hid_destroy_device(steam->client_hdev).
>
> Also there are a number of leaks. hid_hw_stop() is not called if
> hid_hw_open() fails for example. And it doesn't call steam_unregister()
> or hid_hw_close().
>
> Fixes: 691ead124a0c ("HID: hid-steam: Clean up locking")
> Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
> ---
> This is just from static analysis and code review. I haven't tested
> it. I only included the fixes tag for the error pointer dereference.
>
> drivers/hid/hid-steam.c | 26 +++++++++++++++-----------
> 1 file changed, 15 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
> index 59df6ead7b54..b08a5ab58528 100644
> --- a/drivers/hid/hid-steam.c
> +++ b/drivers/hid/hid-steam.c
> @@ -1128,14 +1128,14 @@ static int steam_probe(struct hid_device *hdev,
> */
> ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDRAW);
> if (ret)
> - goto hid_hw_start_fail;
> + goto err_cancel_work;
>
> ret = hid_hw_open(hdev);
> if (ret) {
> hid_err(hdev,
> "%s:hid_hw_open\n",
> __func__);
> - goto hid_hw_open_fail;
> + goto err_hw_stop;
> }
>
> if (steam->quirks & STEAM_QUIRK_WIRELESS) {
> @@ -1151,33 +1151,37 @@ static int steam_probe(struct hid_device *hdev,
> hid_err(hdev,
> "%s:steam_register failed with error %d\n",
> __func__, ret);
> - goto input_register_fail;
> + goto err_hw_close;
> }
> }
>
> steam->client_hdev = steam_create_client_hid(hdev);
> if (IS_ERR(steam->client_hdev)) {
> ret = PTR_ERR(steam->client_hdev);
> - goto client_hdev_fail;
> + goto err_stream_unregister;
> }
> steam->client_hdev->driver_data = steam;
>
> ret = hid_add_device(steam->client_hdev);
> if (ret)
> - goto client_hdev_add_fail;
> + goto err_destroy;
>
> return 0;
>
> -client_hdev_add_fail:
> - hid_hw_stop(hdev);
> -client_hdev_fail:
> +err_destroy:
> hid_destroy_device(steam->client_hdev);
> -input_register_fail:
> -hid_hw_open_fail:
> -hid_hw_start_fail:
> +err_stream_unregister:
> + if (steam->connected)
> + steam_unregister(steam);
> +err_hw_close:
> + hid_hw_close(hdev);
> +err_hw_stop:
> + hid_hw_stop(hdev);
> +err_cancel_work:
> cancel_work_sync(&steam->work_connect);
> cancel_delayed_work_sync(&steam->mode_switch);
> cancel_work_sync(&steam->rumble_work);
> +
> return ret;
> }
>
^ permalink raw reply
* Re: [PATCH bpf-next v3 0/3] Annotate kfuncs in .BTF_ids section
From: Daniel Xu @ 2024-01-12 20:03 UTC (permalink / raw)
To: Jiri Olsa
Cc: linux-input, coreteam, linux-arm-kernel, linux-kernel,
netfilter-devel, linux-kselftest, linux-trace-kernel, fsverity,
bpf, netdev, linux-stm32, cgroups, alexei.starovoitov, quentin,
alan.maguire, memxor
In-Reply-To: <ZaFm13GyXUukcnkm@krava>
On Fri, Jan 12, 2024 at 05:20:39PM +0100, Jiri Olsa wrote:
> On Sat, Jan 06, 2024 at 11:24:07AM -0700, Daniel Xu wrote:
> > === Description ===
> >
> > This is a bpf-treewide change that annotates all kfuncs as such inside
> > .BTF_ids. This annotation eventually allows us to automatically generate
> > kfunc prototypes from bpftool.
> >
> > We store this metadata inside a yet-unused flags field inside struct
> > btf_id_set8 (thanks Kumar!). pahole will be taught where to look.
> >
> > More details about the full chain of events are available in commit 3's
> > description.
> >
> > The accompanying pahole changes (still needs some cleanup) can be viewed
> > here on this "frozen" branch [0].
>
> so the plan is to have bpftool support to generate header file
> with detected kfuncs?
Yep, that's the major use case. But I see other use cases as well like
precision probing of kfuncs. Rather than guess and check which progs can
load (in the event of backwards incompatible kfunc changes), programs
can look at kfunc type signature thru BTF.
^ permalink raw reply
* Re: [PATCH bpf-next v3 0/3] Annotate kfuncs in .BTF_ids section
From: Jiri Olsa @ 2024-01-12 16:20 UTC (permalink / raw)
To: Daniel Xu
Cc: linux-input, coreteam, linux-arm-kernel, linux-kernel,
netfilter-devel, linux-kselftest, linux-trace-kernel, fsverity,
bpf, netdev, linux-stm32, cgroups, alexei.starovoitov, olsajiri,
quentin, alan.maguire, memxor
In-Reply-To: <cover.1704565248.git.dxu@dxuuu.xyz>
On Sat, Jan 06, 2024 at 11:24:07AM -0700, Daniel Xu wrote:
> === Description ===
>
> This is a bpf-treewide change that annotates all kfuncs as such inside
> .BTF_ids. This annotation eventually allows us to automatically generate
> kfunc prototypes from bpftool.
>
> We store this metadata inside a yet-unused flags field inside struct
> btf_id_set8 (thanks Kumar!). pahole will be taught where to look.
>
> More details about the full chain of events are available in commit 3's
> description.
>
> The accompanying pahole changes (still needs some cleanup) can be viewed
> here on this "frozen" branch [0].
so the plan is to have bpftool support to generate header file
with detected kfuncs?
jirka
>
> [0]: https://github.com/danobi/pahole/tree/kfunc_btf-mailed
>
> === Changelog ===
>
> Changes from v2:
> * Only WARN() for vmlinux kfuncs
>
> Changes from v1:
> * Move WARN_ON() up a call level
> * Also return error when kfunc set is not properly tagged
> * Use BTF_KFUNCS_START/END instead of flags
> * Rename BTF_SET8_KFUNC to BTF_SET8_KFUNCS
>
> Daniel Xu (3):
> bpf: btf: Support flags for BTF_SET8 sets
> bpf: btf: Add BTF_KFUNCS_START/END macro pair
> bpf: treewide: Annotate BPF kfuncs in BTF
>
> drivers/hid/bpf/hid_bpf_dispatch.c | 8 +++----
> fs/verity/measure.c | 4 ++--
> include/linux/btf_ids.h | 21 +++++++++++++++----
> kernel/bpf/btf.c | 8 +++++++
> kernel/bpf/cpumask.c | 4 ++--
> kernel/bpf/helpers.c | 8 +++----
> kernel/bpf/map_iter.c | 4 ++--
> kernel/cgroup/rstat.c | 4 ++--
> kernel/trace/bpf_trace.c | 8 +++----
> net/bpf/test_run.c | 8 +++----
> net/core/filter.c | 16 +++++++-------
> net/core/xdp.c | 4 ++--
> net/ipv4/bpf_tcp_ca.c | 4 ++--
> net/ipv4/fou_bpf.c | 4 ++--
> net/ipv4/tcp_bbr.c | 4 ++--
> net/ipv4/tcp_cubic.c | 4 ++--
> net/ipv4/tcp_dctcp.c | 4 ++--
> net/netfilter/nf_conntrack_bpf.c | 4 ++--
> net/netfilter/nf_nat_bpf.c | 4 ++--
> net/xfrm/xfrm_interface_bpf.c | 4 ++--
> net/xfrm/xfrm_state_bpf.c | 4 ++--
> .../selftests/bpf/bpf_testmod/bpf_testmod.c | 8 +++----
> 22 files changed, 81 insertions(+), 60 deletions(-)
>
> --
> 2.42.1
>
^ permalink raw reply
* Re: [PATCH v5 4/5] Input: cs40l50 - Add support for the CS40L50 haptic driver
From: James Ogletree @ 2024-01-12 15:41 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: James Ogletree, Fred Treven, Ben Bright, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Simon Trimmer, Charles Keepax,
Richard Fitzgerald, Lee Jones, Liam Girdwood, Mark Brown,
Jaroslav Kysela, Takashi Iwai, James Schulman, David Rhodes,
Alexandre Belloni, Peng Fan, Jeff LaBundy, Sebastian Reichel,
Jacky Bai, Weidong Wang, Arnd Bergmann, Herve Codina, Shuming Fan,
Shenghao Ding, Ryan Lee, Linus Walleij,
open list:CIRRUS LOGIC HAPTIC DRIVERS,
open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list,
open list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
moderated list:CIRRUS LOGIC AUDIO CODEC DRIVERS
In-Reply-To: <ZZ-YhtIulqrSFc3R@google.com>
> On Jan 11, 2024, at 1:28 AM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>
> On Wed, Jan 10, 2024 at 02:36:55PM +0000, James Ogletree wrote:
>>
>>> On Jan 9, 2024, at 4:31 PM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>>>
>>> On Tue, Jan 09, 2024 at 10:03:02PM +0000, James Ogletree wrote:
>>>>
>>>>
>>>>> On Jan 6, 2024, at 7:58 PM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>>>>>
>>>>> On Thu, Jan 04, 2024 at 10:36:37PM +0000, James Ogletree wrote:
>>>>>> + } else {
>>>>>> + queue_work(info->vibe_wq, &info->vibe_stop_work);
>>>>>
>>>>> Which effect are you stopping? All of them? You need to stop a
>>>>> particular one.
>>>>
>>>> Our implementation of “stop” stops all effects in flight which is intended.
>>>> That is probably unusual so I will add a comment here in the next
>>>> version.
>>>
>>> Again, please implement the driver properly, not define your own
>>> carveouts for the expected behavior.
>>
>> Ack, and a clarification question: the device is not actually able to
>> play multiple effects at once. In that case, does stopping a specific
>> effect entail just cancelling an effect in the queue?
>
> In this case I believe the device should declare maximum number of
> effects as 1. Userspace is supposed to determine maximum number of
> simultaneously playable effects by issuing EVIOCGEFFECTS ioctl on the
> corresponding event device.
Is it possible to specify the device’s maximum simultaneous effects
without also restricting the number of effects the user can upload? It
looks like both are tied to ff->max_effects.
Best,
James
^ permalink raw reply
* Re: [PATCH] Input: i8042 - add quirk for Lenovo ThinkPad T14 Gen 1
From: Jonathan Denose @ 2024-01-12 15:10 UTC (permalink / raw)
To: Hans de Goede
Cc: Dmitry Torokhov, linux-input, Jonathan Denose, Huacai Chen,
Mattijs Korpershoek, Takashi Iwai, Werner Sembach, linux-kernel
In-Reply-To: <005a6d3c-ffba-45df-bdc0-cb2d32e6b676@redhat.com>
Hans,
On Thu, Jan 11, 2024 at 4:48 AM Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi Jonathan,
>
> On 1/11/24 00:42, Jonathan Denose wrote:
> > Dmitry,
> >
> > Sorry I forgot to reply all, so I'm resending my other email.
> >
> > On Tue, Jan 9, 2024 at 1:28 PM Dmitry Torokhov
> > <dmitry.torokhov@gmail.com> wrote:
> >>
> >> Hi Jonathan,
> >>
> >> On Mon, Nov 27, 2023 at 10:38:57AM -0600, Jonathan Denose wrote:
> >>> Hi Dmitry
> >>>
> >>> On Fri, Nov 24, 2023 at 10:45 PM Dmitry Torokhov
> >>> <dmitry.torokhov@gmail.com> wrote:
> >>>>
> >>>> Hi Jonathan,
> >>>>
> >>>> On Mon, Sep 25, 2023 at 04:33:20PM -0500, Jonathan Denose wrote:
> >>>>> The ThinkPad T14 Gen 1 touchpad works fine except that clicking
> >>>>> and dragging by tapping the touchpad or depressing the touchpad
> >>>>> do not work. Disabling PNP for controller setting discovery enables
> >>>>> click and drag without negatively impacting other touchpad features.
> >>>>
> >>>> I would like to understand more on how enabling PnP discovery for i8042
> >>>> affects the touchpad. Do you see it using different interrupt or IO
> >>>> ports? What protocol does the touchpad use with/without PnP? If the
> >>>> protocol is the same, do you see difference in the ranges (pressure,
> >>>> etc) reported by the device?
> >>>>
> >>>> Thanks.
> >>>>
> >>>> --
> >>>> Dmitry
> >>>
> >>> Without PnP discovery the touchpad is using the SynPS/2 protocol, with
> >>> PnP discovery, the touchpad is using the rmi4 protocol. Since the
> >>> protocols are different, so are the ranges but let me know if you
> >>> still want to see them.
> >>
> >> Thank you for this information. So it is not PnP discovery that appears
> >> harmful in your case, but rather that legacy PS/2 mode appears to be
> >> working better than RMI4 for the device in question.
> >>
> >> I will note that the original enablement of RMI4 for T14 was done by
> >> Hans in [1]. Later T14 with AMD were added to the list of devices that
> >> should use RMI4 [2], however this was reverted in [3].
> >>
> >> Could you please tell me what exact device you are dealing with? What's
> >> it ACPI ID?
> >>
> >> [1] https://lore.kernel.org/all/20201005114919.371592-1-hdegoede@redhat.com/
> >> [2] https://lore.kernel.org/r/20220318113949.32722-1-snafu109@gmail.com
> >> [3] https://lore.kernel.org/r/20220920193936.8709-1-markpearson@lenovo.com
> >>
> >> Thanks.
> >>
> >> --
> >> Dmitry
> >
> > Thanks for your reply!
> >
> > I'm not 100% sure which of these is the ACPI ID, but from `udevadm
> > info -e` there's:
> > N: Name="Synaptics TM3471-020"
> > P: Phys=rmi4-00/input0
>
> To get the ACPI ID you need to run e.g. :``
>
> cat /sys/bus/serio/devices/serio1/firmware_id
>
> After reading the original bug report again I take back my
> Reviewed-by and I'm tending towards a nack for this.
>
> Jonathan upon re-reading things I think that your problem
> is more a case of user space mis-configuration then
> a kernel problem.
>
> You mention both tap-n-drag not working as well as click+drag
> not working.
>
> tap-n-drag is purely done in userspace and typically only
> works if tap-to-click is enabled in the touchpad configuration
> of your desktop environment.
>
> Click + drag requires you to use the bottom of the touchpad
> (the only part which actually clicks) as if there still were
> 2 physical buttons there and then click the touchpad down
> with 1 finger till it clicks and then drags with another
> finger (you can click+drag with one finger but the force
> required to keep the touchpad clicked down while dragging
> makes this uncomfortable to do).
>
> This will likely also only work if the mouse click emulation
> mode is set to "area" and not "fingers" with "fingers" being
> the default now. In GNOME you can configure
> the "click emulation mode" in the "tweaks" tools under
> "mouse & touchpad" (and tap to click is in the normal
> settings menu / control panel).
>
> If you have the click emulations set to fingers and
> then do the click with 1 finger + drag with another
> finger thing, I think the drag will turn into a
> right button drag instead of a left button drag which
> is likely why this is not working.
>
> You can check which mode you are in by seeing how
> you right click. If you right-click by pressing down
> in the right bottom corner of the touchpad then
> your userspace (libinput) config is set to areas,
> if you can right click anywhere by pressing down
> with 2 fingers at once then your click emulation
> is in fingers mode and this is likely why click-n-drag
> is not working.
>
> I have just dug up my T14 gen1 (Intel) and updated it
> to kernel 6.6.11 to rule out kernel regressions.
>
> And both click-n-drag and tap-n-drag (double-tap then
> drag) both work fine there with a touchpad with
> an ACPI id of LEN2068 as shown by
> cat /sys/bus/serio/devices/serio1/firmware_id
>
> (with the Desktop Environment configured for bottom
> area click emulation and tap-to-click enabled)
>
> As for why changing things back to synps2 works,
> I don't know. One guess is that you already configured
> the touchpad behavior of your desktop environment to
> your liking in the past and your desktop environment
> has remembered this only for the input device-name
> which is used in SynPS/2 mode and the different
> input device-name in RMI4 mode in new (new-ish)
> kernels causes the desktop environment to use
> default settings which are typically "fingers"
> click emulation and tap-to-click disabled.
>
> This can e.g. also happen if you have moved your
> disk (contents) over from an older machine. IIRC
> the SynPS/2 driver always used the same input
> device-name where as with RMI4 the name is tied
> to the actual laptop model.
>
> Regards,
>
> Hans
>
>
Thank you for your thorough reply. Based on what you've written, I
agree this sounds more like a user-space issue than a kernel issue. At
least that narrows it down for me, so I'll take a look at what could
be misconfigured in user-space.
Thanks so much for your help!
Jonathan
^ permalink raw reply
* Re: [PATCH v14 2/4] Input: add core support for Goodix Berlin Touchscreen IC
From: Neil Armstrong @ 2024-01-12 15:08 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg, Jeff LaBundy,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <ZZ-W0UPHOdpU-8el@google.com>
Hi Dmitry,
On 11/01/2024 08:20, Dmitry Torokhov wrote:
> Hi Neil,
>
> On Thu, Dec 21, 2023 at 04:21:20PM +0100, Neil Armstrong wrote:
>> Add initial support for the new Goodix "Berlin" touchscreen ICs.
>
> Thank you very much for explaining how reading of additional contacts
> and checksum works, it makes sense now.
>
> I was a bit unhappy about number of times we copy/move the data over;
> could you please try the patch below to see if the device still works
> with it?
Sure, I'll test it and report you.
>
> I also shortened some #defines and defines some additional structures.
> Also as far as I can see not everything needs to be packed as the data
> is naturally aligned on the word boundaries.
Great, thank!
Neil
>
> Thanks!
>
^ permalink raw reply
* [PATCH 2/2] HID: hid-steam: Fix cleanup in probe()
From: Dan Carpenter @ 2024-01-12 14:35 UTC (permalink / raw)
To: Vicki Pfau
Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel,
kernel-janitors
In-Reply-To: <305898fb-6bd4-4749-806c-05ec51bbeb80@moroto.mountain>
There are a number of issues in this code. First of all if
steam_create_client_hid() fails then it leads to an error pointer
dereference when we call hid_destroy_device(steam->client_hdev).
Also there are a number of leaks. hid_hw_stop() is not called if
hid_hw_open() fails for example. And it doesn't call steam_unregister()
or hid_hw_close().
Fixes: 691ead124a0c ("HID: hid-steam: Clean up locking")
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
---
This is just from static analysis and code review. I haven't tested
it. I only included the fixes tag for the error pointer dereference.
drivers/hid/hid-steam.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index 59df6ead7b54..b08a5ab58528 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -1128,14 +1128,14 @@ static int steam_probe(struct hid_device *hdev,
*/
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDRAW);
if (ret)
- goto hid_hw_start_fail;
+ goto err_cancel_work;
ret = hid_hw_open(hdev);
if (ret) {
hid_err(hdev,
"%s:hid_hw_open\n",
__func__);
- goto hid_hw_open_fail;
+ goto err_hw_stop;
}
if (steam->quirks & STEAM_QUIRK_WIRELESS) {
@@ -1151,33 +1151,37 @@ static int steam_probe(struct hid_device *hdev,
hid_err(hdev,
"%s:steam_register failed with error %d\n",
__func__, ret);
- goto input_register_fail;
+ goto err_hw_close;
}
}
steam->client_hdev = steam_create_client_hid(hdev);
if (IS_ERR(steam->client_hdev)) {
ret = PTR_ERR(steam->client_hdev);
- goto client_hdev_fail;
+ goto err_stream_unregister;
}
steam->client_hdev->driver_data = steam;
ret = hid_add_device(steam->client_hdev);
if (ret)
- goto client_hdev_add_fail;
+ goto err_destroy;
return 0;
-client_hdev_add_fail:
- hid_hw_stop(hdev);
-client_hdev_fail:
+err_destroy:
hid_destroy_device(steam->client_hdev);
-input_register_fail:
-hid_hw_open_fail:
-hid_hw_start_fail:
+err_stream_unregister:
+ if (steam->connected)
+ steam_unregister(steam);
+err_hw_close:
+ hid_hw_close(hdev);
+err_hw_stop:
+ hid_hw_stop(hdev);
+err_cancel_work:
cancel_work_sync(&steam->work_connect);
cancel_delayed_work_sync(&steam->mode_switch);
cancel_work_sync(&steam->rumble_work);
+
return ret;
}
--
2.43.0
^ permalink raw reply related
* [PATCH 1/2] HID: hid-steam: remove pointless error message
From: Dan Carpenter @ 2024-01-12 14:34 UTC (permalink / raw)
To: Jiri Kosina
Cc: Benjamin Tissoires, linux-input, linux-kernel, kernel-janitors
This error message doesn't really add any information. If modprobe
fails then the user will already know what the error code is. In the
case of kmalloc() it's a style violation to print an error message for
that because kmalloc has it's own better error messages built in.
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
---
drivers/hid/hid-steam.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index b3c4e50e248a..59df6ead7b54 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -1109,10 +1109,9 @@ static int steam_probe(struct hid_device *hdev,
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
steam = devm_kzalloc(&hdev->dev, sizeof(*steam), GFP_KERNEL);
- if (!steam) {
- ret = -ENOMEM;
- goto steam_alloc_fail;
- }
+ if (!steam)
+ return -ENOMEM;
+
steam->hdev = hdev;
hid_set_drvdata(hdev, steam);
spin_lock_init(&steam->lock);
@@ -1179,9 +1178,6 @@ static int steam_probe(struct hid_device *hdev,
cancel_work_sync(&steam->work_connect);
cancel_delayed_work_sync(&steam->mode_switch);
cancel_work_sync(&steam->rumble_work);
-steam_alloc_fail:
- hid_err(hdev, "%s: failed with error %d\n",
- __func__, ret);
return ret;
}
--
2.43.0
^ permalink raw reply related
* [PATCH] Input: fix atomicity violation in gameport_run_poll_handler
From: Gui-Dong Han @ 2024-01-12 7:38 UTC (permalink / raw)
To: dmitry.torokhov, arnd, schnelle
Cc: linux-input, linux-kernel, baijiaju1990, Gui-Dong Han, stable
In gameport_run_poll_handler():
...
if (gameport->poll_cnt)
mod_timer(&gameport->poll_timer, jiffies + ...));
In gameport_stop_polling():
spin_lock(&gameport->timer_lock);
if (!--gameport->poll_cnt)
del_timer(&gameport->poll_timer);
spin_unlock(&gameport->timer_lock);
An atomicity violation occurs due to the concurrent execution of
gameport_run_poll_handler() and gameport_stop_polling(). The current check
for gameport->poll_cnt in gameport_run_poll_handler() is not effective
because poll_cnt can be decremented to 0 and del_timer can be called in
gameport_stop_polling() before mod_timer is called in
gameport_run_poll_handler(). This situation leads to the risk of calling
mod_timer for a timer that has already been deleted in
gameport_stop_polling(). Since calling mod_timer on a deleted timer
reactivates it, this atomicity violation could result in the timer being
activated while the poll_cnt value is 0.
This possible bug is found by an experimental static analysis tool
developed by our team, BassCheck[1]. This tool analyzes the locking APIs
to extract function pairs that can be concurrently executed, and then
analyzes the instructions in the paired functions to identify possible
concurrency bugs including data races and atomicity violations. The above
possible bug is reported when our tool analyzes the source code of
Linux 5.17.
To resolve this issue, it is suggested to add a spinlock pair in
gameport_run_poll_handler() to ensure atomicity. With this patch applied,
our tool no longer reports the bug, with the kernel configuration
allyesconfig for x86_64. Due to the absence of the requisite hardware, we
are unable to conduct runtime testing of the patch. Therefore, our
verification is solely based on code logic analysis.
[1] https://sites.google.com/view/basscheck/
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Gui-Dong Han <2045gemini@gmail.com>
---
drivers/input/gameport/gameport.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 34f416a3ebcb..12af46d3c059 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -202,8 +202,13 @@ static void gameport_run_poll_handler(struct timer_list *t)
struct gameport *gameport = from_timer(gameport, t, poll_timer);
gameport->poll_handler(gameport);
+
+ spin_lock(&gameport->timer_lock);
+
if (gameport->poll_cnt)
mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
+
+ spin_unlock(&gameport->timer_lock);
}
/*
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 1/2] Input: uinput - Allow uinput_request_submit wait interrupting
From: Vi Pfau @ 2024-01-12 1:37 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
In-Reply-To: <853baa9e-1c76-4e61-b1f6-a1155ccb5dd7@endrift.com>
Hello Dmitry,
It's been almost a month since I replied addressing your concerns on
this patch. Can you please comment?
On 12/14/23 19:04, Vicki Pfau wrote:
> Hi Dmitry
>
> On 12/8/23 19:24, Vicki Pfau wrote:
>> Hi Dmitry,
>>
>> On 12/8/23 11:32, Dmitry Torokhov wrote:
>>> Hi Vicki,
>>>
>>> On Wed, Dec 06, 2023 at 10:34:05PM -0800, Vicki Pfau wrote:
>>>> Currently, uinput_request_submit will only fail if the request wait times out.
>>>> However, in other places this wait is interruptable, and in this specific
>>>> location it can lead to issues, such as causing system suspend to hang until
>>>> the request times out.
>>>
>>> Could you please explain how a sleeping process can cause suspend to
>>> hang?
>>
>> While I'm not 100% sure how it happens, given I found this by reproducing it before I came up with a theory for why it happened, my guess is that as it's trying to suspend all of userspace programs, it suspends the process that owns the uinput handle, so it can't continue to service requests, while the other process hangs in the uninterruptable call, blocking suspend for 30 seconds until the call times out.
>>
>>>
>>>> Since the timeout is so long, this can cause the
>>>> appearance of a total system freeze. Making the wait interruptable resolves
>>>> this and possibly further issues.
>>>
>>> I think you are trying to find a justification too hard and it does not
>>> make sense, however I agree that allowing to kill the process issuing
>>> the request without waiting for the timeout to expire if the other side
>>> is stuck might be desirable.
>>
>> This isn't reaching. As I said above, I discovered the patched line of code *after* observing suspend hanging for 30 seconds while trying to reproduce another bug. I wrote this patch, retested, and found that it now suspended immediately, leading to a visible -ERESTARTSYS in strace on coming back from suspend.
>>
>> I can post the reproduction case somewhere, but the test program is only the evdev client end, with the uinput side being Steam, which I don't have source code for.
>>
>>>
>>> I think the best way to use wait_for_completion_killable_timeout()
>>> so that stray signals do not disturb userspace, but the processes can
>>> still be terminated.
>>
>> There's already a mutex_lock_interruptable in uinput_request_send that could cause this to fall back to userspace under similar circumstances. The only difference I can find, which is admittedly a bug in this patch now that I look at it again, is that uinput_dev_event would get called twice, leading to the request getting duplicated.
>
> After further investigation, it seems this would still be the case even if the request times out--an invalid request would get left in the buffer, which means that while this is a new way to trigger the issue, it's not actually a new issue.
>
> It seems to me that this driver could use a lot of love to get it into better shape, which I could work on, but I'm not actually sure where to begin. Especially if we don't want to break ABI.
>
>>
>> If there's a better way to handle the suspend case let me know, but this is not a hypothetical issue.
>>
>>>
>>> Thanks.
>>>
>>
>> Vicki
>
> Vici
Vicki
^ permalink raw reply
* [PATCH V2] Input: adc-joystick: Handle inverted axes
From: Chris Morgan @ 2024-01-11 22:03 UTC (permalink / raw)
To: linux-input
Cc: dmitry.torokhov, hdegoede, paul, peter.hutterer, svv, biswarupp,
contact, Chris Morgan
From: Chris Morgan <macromorgan@hotmail.com>
When one or more axes are inverted, (where min > max), normalize the
data so that min < max and invert the values reported to the input
stack.
This ensures we can continue defining the device correctly in the
device tree while not breaking downstream assumptions that min is
always less than max.
Changes since V1:
- Moved proposed helper for inversion from input stack to adc-joystick
driver.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/input/joystick/adc-joystick.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c
index c0deff5d4282..46197ebd3564 100644
--- a/drivers/input/joystick/adc-joystick.c
+++ b/drivers/input/joystick/adc-joystick.c
@@ -18,6 +18,7 @@ struct adc_joystick_axis {
s32 range[2];
s32 fuzz;
s32 flat;
+ bool inverted;
};
struct adc_joystick {
@@ -29,6 +30,14 @@ struct adc_joystick {
bool polled;
};
+static int adc_joystick_invert(struct input_dev *dev, unsigned int axis, int val)
+{
+ int min = dev->absinfo[axis].minimum;
+ int max = dev->absinfo[axis].maximum;
+
+ return (max + min) - val;
+}
+
static void adc_joystick_poll(struct input_dev *input)
{
struct adc_joystick *joy = input_get_drvdata(input);
@@ -38,6 +47,8 @@ static void adc_joystick_poll(struct input_dev *input)
ret = iio_read_channel_raw(&joy->chans[i], &val);
if (ret < 0)
return;
+ if (joy->axes[i].inverted)
+ val = adc_joystick_invert(input, i, val);
input_report_abs(input, joy->axes[i].code, val);
}
input_sync(input);
@@ -86,6 +97,8 @@ static int adc_joystick_handle(const void *data, void *private)
val = sign_extend32(val, msb);
else
val &= GENMASK(msb, 0);
+ if (joy->axes[i].inverted)
+ val = adc_joystick_invert(joy->input, i, val);
input_report_abs(joy->input, joy->axes[i].code, val);
}
@@ -168,11 +181,17 @@ static int adc_joystick_set_axes(struct device *dev, struct adc_joystick *joy)
goto err_fwnode_put;
}
+ if (axes[i].range[0] > axes[i].range[1]) {
+ dev_dbg(dev, "abs-axis %d inverted\n", i);
+ axes[i].inverted = 1;
+ }
+
fwnode_property_read_u32(child, "abs-fuzz", &axes[i].fuzz);
fwnode_property_read_u32(child, "abs-flat", &axes[i].flat);
input_set_abs_params(joy->input, axes[i].code,
- axes[i].range[0], axes[i].range[1],
+ min_array(axes[i].range, 2),
+ max_array(axes[i].range, 2),
axes[i].fuzz, axes[i].flat);
input_set_capability(joy->input, EV_ABS, axes[i].code);
}
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v6 2/4] Input: touch-overlay - Add touchscreen overlay handling
From: Jeff LaBundy @ 2024-01-11 13:55 UTC (permalink / raw)
To: Javier Carrasco
Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg, Bastian Hecht, Michael Riesch, linux-kernel,
linux-input, devicetree
In-Reply-To: <12ac3718-2c69-4d11-8ea4-b555f2321232@wolfvision.net>
Hi Javier,
On Fri, Jan 05, 2024 at 08:21:25PM +0100, Javier Carrasco wrote:
> Hi Jeff,
>
> On 30.12.23 21:29, Jeff LaBundy wrote:
> > Having reviewed this version in detail, it's clear how the implementation
> > imposes this restriction. However, it's not clear why we have to have this
> > restriction straight out of the gate; it also breaks the "square doughnut"
> > example we discussed in v5, where a button resides inside a touch surface
> > which is split into four discrete rectangles that report X/Y coordinates
> > relative to the same origin.
> >
> > From my naive point of view, a driver should merely pass a contact's ID
> > (for HW that can track contacts), coordinates, and pressure. Your helper(s)
> > are then responisble for iterating over the list, determining the segment
> > in which the coordinates fall, and then reporting the event by way of
> > input_report_abs() or input_report_key() based on whether or not a keycode
> > is defined.
> >
> > I think the problem with that approach is that touchscreen drivers only
> > report coordinates when the pressure is nonzero. The process of dropping
> > a contact, i.e. button release for some segments, happens inside input-mt
> > by virtue of the driver calling input_mt_sync_frame().
> >
> > It makes sense now why you are duplicating the contact tracking to a degree
> > here. Therefore, it's starting to look more and more like the overlay segment
> > handling needs to move into the input-mt core, where much of the information
> > you need already exists.
> >
> > If we look at input_mt_report_pointer_emulation(), the concept of button
> > release is already happening; all we really want to do here is gently
> > expand the core to understand that some ranges of coordinates are simply
> > quantized to a keycode with binary pressure (i.e. press/release).
> >
> > In addition to removing duplicate code as well as the restriction of supporting
> > only one X/Y surface, moving overlay support into the input-mt core would
> > remove the need to modify each touchscreen driver one at a time with what
> > are largely the same nontrivial changes. If we think about it more, the
> > touchscreen controller itself is not changing, so the driver really shouldn't
> > have to change much either.
> >
> > Stated another way, I think it's a better design pattern if we let drivers
> > continue to do their job of merely lobbing hardware state to the input
> > subsytem via input_mt_slot(), touchscreen_report_pos() and input_mt_sync_frame(),
> > then leave it to the input subsystem alone to iterate over the list and
> > determine whether some coordinates must be handled differently.
> >
> > The main drawback to this approach is that the overlay buttons would need
> > to go back to being part of the touchscreen input device as in v1, as opposed
> > to giving the driver the flexibility of splitting the buttons and X/Y surfaces
> > into two separate input devices.
> >
> > When we first discussed this with Peter, we agreed that splitting them into two
> > input devices grants the most flexibility, in case user space opts to inhibit
> > one but not the other, etc. However since the buttons and X/Y surfaces are all
> > part of the same physical substrate, it seems the chances of user space being
> > interested in one but not the other are low.
> >
> > Furthermore, folding the buttons and X/Y surfaces back into the same input
> > device would remove the need for each touchscreen driver to preemptively
> > allocate a second input device, but then remove it later as in patch [4/4]
> > in case the helpers did not find any buttons.
> >
> > What are your thoughts on evolving the approach in this way? It's obviously
> > another big change and carries some risk to the core, so I'm curious to hear
> > Dmitry's and others' thoughts as well. I appreciate that you've been iterating
> > on this for some time, and good is not the enemy of great; therefore, maybe
> > a compromise is to move forward with the current approach in support of the
> > hardware you have today, then work it into the input-mt core over time. But
> > it would be nice to avoid ripping up participating touchscreen drivers twice.
> >
> > Thank you for your patience and continued effort. In the meantime, please note
> > some minor comments that are independent of this architectural decision.
> >
>
> Thanks again for your thorough reviews and proposals to improve the code.
>
> I am basically open to any solution that improves the quality of the
> feature. If I get you right, moving everything to the input-mt core
> would hide the overlay stuff from the device drivers (which sounds good)
> and a bit of code could be simplified by using the existing infrastructure.
Yes, that is the idea.
>
> On the other hand, adding this feature to the input-mt core right away
> increases the risk of breaking things that many users need. We are
> already using this feature in some prototypes since v1 without any issue
> so far, but it would be great if it could be tested under different
> circumstances (hardware, configurations, etc.) before it goes into the
> core, wouldn't it?
I agree with you. Thinking about this more, immediately introducing this
feature to the core is a relatively high risk that would be shared by all
users. I like your idea of introducing a preliminary version first before
making heavy-handed changes. That's the beauty of helper functions; they
only impact users who explicitly opt in.
>
> I would also like to know what more experienced people think about it,
> if we should go all out and add it to the input-mt core now or as you
> also suggested, move forward with the current approach and let it
> "mature" first. The cost of that would be modifying device driver code
> twice, but I suppose that not so many drivers will add this feature in
> the next kernel iterations... maybe you? it sounds like that you might
> have a use case for it :)
I don't have an immediate use case, but I've been looking at this from
the perspective of a future customer of it. Maybe the right path forward
is as follows:
1. Stick with the same general architecture of v6 and its "limitations",
which in practice are unlikely to be encountered. I imagine the overlay
layout you have been using would be the most common use case.
2. Make the handful of small changes that have been suggested thus far.
3. Consider updating patch [4/4] to combine the touchscreen and buttons
into the same input device as you had in v1. This sets a little simpler
precedent for the first user of these helpers. If later these helpers
do get absorbed into the core, thereby forcing a single input device,
the st1232 would continue to appear the same to user space.
Does this seem reasonable?
>
> >> +struct button {
> >> + u32 key;
> >> + bool pressed;
> >> + int slot;
> >> +};
> >> +
> >> +struct touch_overlay_segment {
> >> + struct list_head list;
> >> + u32 x_origin;
> >> + u32 y_origin;
> >> + u32 x_size;
> >> + u32 y_size;
> >> + struct button *btn;
> >
> > I think you can simply declare the struct itself here as opposed to a pointer to
> > one; this would avoid a second call to devm_kzalloc().
> >
>
> That was the other option I mentioned in my reply and I am fine with the
> modification you propose.
>
> >> + if (fwnode_property_present(segment_node, "linux,code")) {
> >
> > Instead of walking the device tree twice by calling fwnode_property_present()
> > followed by fwnode_property_read_u32(), you can simply check whether the
> > latter returns -EINVAL, which indicates the optional property was absent.
> >
>
> Ack.
>
> >> + segment->btn = devm_kzalloc(dev, sizeof(*segment->btn),
> >> + GFP_KERNEL);
> >> + if (!segment->btn)
> >> + return -ENOMEM;
> >> +
>
>
> >> + fwnode_for_each_child_node(overlay, fw_segment) {
> >> + segment = devm_kzalloc(dev, sizeof(*segment), GFP_KERNEL);
> >> + if (!segment) {
> >> + error = -ENOMEM;
> >> + goto put_overlay;
> >
> > For this and the below case where you exit the loop early in case of an
> > error, you must call fwnode_handle_put(fw_segment) manually. The reference
> > count is handled automatically only when the loop iterates and terminates
> > naturally.
> >
> > Since nothing else happens between the loop and the 'put_overlay' label,
> > you can also replace the goto with a break and remove the label altogether.
> >
>
> Ack.
>
> >
> > Kind regards,
> > Jeff LaBundy
>
>
> Thanks and best regards,
> Javier Carrasco
Kind regards,
Jeff LaBundy
^ permalink raw reply
* Re: [PATCH] Input: i8042 - add quirk for Lenovo ThinkPad T14 Gen 1
From: Hans de Goede @ 2024-01-11 10:48 UTC (permalink / raw)
To: Jonathan Denose, Dmitry Torokhov
Cc: linux-input, Jonathan Denose, Huacai Chen, Mattijs Korpershoek,
Takashi Iwai, Werner Sembach, linux-kernel
In-Reply-To: <CALNJtpWr0h+r3=R2scxyCGzgbZ1C6FiYrCGWW1_aSVPBdmNc3Q@mail.gmail.com>
Hi Jonathan,
On 1/11/24 00:42, Jonathan Denose wrote:
> Dmitry,
>
> Sorry I forgot to reply all, so I'm resending my other email.
>
> On Tue, Jan 9, 2024 at 1:28 PM Dmitry Torokhov
> <dmitry.torokhov@gmail.com> wrote:
>>
>> Hi Jonathan,
>>
>> On Mon, Nov 27, 2023 at 10:38:57AM -0600, Jonathan Denose wrote:
>>> Hi Dmitry
>>>
>>> On Fri, Nov 24, 2023 at 10:45 PM Dmitry Torokhov
>>> <dmitry.torokhov@gmail.com> wrote:
>>>>
>>>> Hi Jonathan,
>>>>
>>>> On Mon, Sep 25, 2023 at 04:33:20PM -0500, Jonathan Denose wrote:
>>>>> The ThinkPad T14 Gen 1 touchpad works fine except that clicking
>>>>> and dragging by tapping the touchpad or depressing the touchpad
>>>>> do not work. Disabling PNP for controller setting discovery enables
>>>>> click and drag without negatively impacting other touchpad features.
>>>>
>>>> I would like to understand more on how enabling PnP discovery for i8042
>>>> affects the touchpad. Do you see it using different interrupt or IO
>>>> ports? What protocol does the touchpad use with/without PnP? If the
>>>> protocol is the same, do you see difference in the ranges (pressure,
>>>> etc) reported by the device?
>>>>
>>>> Thanks.
>>>>
>>>> --
>>>> Dmitry
>>>
>>> Without PnP discovery the touchpad is using the SynPS/2 protocol, with
>>> PnP discovery, the touchpad is using the rmi4 protocol. Since the
>>> protocols are different, so are the ranges but let me know if you
>>> still want to see them.
>>
>> Thank you for this information. So it is not PnP discovery that appears
>> harmful in your case, but rather that legacy PS/2 mode appears to be
>> working better than RMI4 for the device in question.
>>
>> I will note that the original enablement of RMI4 for T14 was done by
>> Hans in [1]. Later T14 with AMD were added to the list of devices that
>> should use RMI4 [2], however this was reverted in [3].
>>
>> Could you please tell me what exact device you are dealing with? What's
>> it ACPI ID?
>>
>> [1] https://lore.kernel.org/all/20201005114919.371592-1-hdegoede@redhat.com/
>> [2] https://lore.kernel.org/r/20220318113949.32722-1-snafu109@gmail.com
>> [3] https://lore.kernel.org/r/20220920193936.8709-1-markpearson@lenovo.com
>>
>> Thanks.
>>
>> --
>> Dmitry
>
> Thanks for your reply!
>
> I'm not 100% sure which of these is the ACPI ID, but from `udevadm
> info -e` there's:
> N: Name="Synaptics TM3471-020"
> P: Phys=rmi4-00/input0
To get the ACPI ID you need to run e.g. :``
cat /sys/bus/serio/devices/serio1/firmware_id
After reading the original bug report again I take back my
Reviewed-by and I'm tending towards a nack for this.
Jonathan upon re-reading things I think that your problem
is more a case of user space mis-configuration then
a kernel problem.
You mention both tap-n-drag not working as well as click+drag
not working.
tap-n-drag is purely done in userspace and typically only
works if tap-to-click is enabled in the touchpad configuration
of your desktop environment.
Click + drag requires you to use the bottom of the touchpad
(the only part which actually clicks) as if there still were
2 physical buttons there and then click the touchpad down
with 1 finger till it clicks and then drags with another
finger (you can click+drag with one finger but the force
required to keep the touchpad clicked down while dragging
makes this uncomfortable to do).
This will likely also only work if the mouse click emulation
mode is set to "area" and not "fingers" with "fingers" being
the default now. In GNOME you can configure
the "click emulation mode" in the "tweaks" tools under
"mouse & touchpad" (and tap to click is in the normal
settings menu / control panel).
If you have the click emulations set to fingers and
then do the click with 1 finger + drag with another
finger thing, I think the drag will turn into a
right button drag instead of a left button drag which
is likely why this is not working.
You can check which mode you are in by seeing how
you right click. If you right-click by pressing down
in the right bottom corner of the touchpad then
your userspace (libinput) config is set to areas,
if you can right click anywhere by pressing down
with 2 fingers at once then your click emulation
is in fingers mode and this is likely why click-n-drag
is not working.
I have just dug up my T14 gen1 (Intel) and updated it
to kernel 6.6.11 to rule out kernel regressions.
And both click-n-drag and tap-n-drag (double-tap then
drag) both work fine there with a touchpad with
an ACPI id of LEN2068 as shown by
cat /sys/bus/serio/devices/serio1/firmware_id
(with the Desktop Environment configured for bottom
area click emulation and tap-to-click enabled)
As for why changing things back to synps2 works,
I don't know. One guess is that you already configured
the touchpad behavior of your desktop environment to
your liking in the past and your desktop environment
has remembered this only for the input device-name
which is used in SynPS/2 mode and the different
input device-name in RMI4 mode in new (new-ish)
kernels causes the desktop environment to use
default settings which are typically "fingers"
click emulation and tap-to-click disabled.
This can e.g. also happen if you have moved your
disk (contents) over from an older machine. IIRC
the SynPS/2 driver always used the same input
device-name where as with RMI4 the name is tied
to the actual laptop model.
Regards,
Hans
^ permalink raw reply
* [dtor-input:next] BUILD SUCCESS 52c4e5985a730796a3fa555b83b404708b960f9d
From: kernel test robot @ 2024-01-11 9:20 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
branch HEAD: 52c4e5985a730796a3fa555b83b404708b960f9d Input: driver for Adafruit Seesaw Gamepad
elapsed time: 1446m
configs tested: 193
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc
alpha allyesconfig gcc
alpha defconfig gcc
arc allmodconfig gcc
arc allnoconfig gcc
arc allyesconfig gcc
arc defconfig gcc
arc haps_hs_smp_defconfig gcc
arc randconfig-001-20240111 gcc
arc randconfig-002-20240111 gcc
arm allmodconfig gcc
arm allnoconfig gcc
arm allyesconfig gcc
arm aspeed_g4_defconfig clang
arm collie_defconfig clang
arm defconfig clang
arm multi_v4t_defconfig gcc
arm omap1_defconfig clang
arm randconfig-001-20240111 gcc
arm randconfig-002-20240111 gcc
arm randconfig-003-20240111 gcc
arm randconfig-004-20240111 gcc
arm s5pv210_defconfig clang
arm socfpga_defconfig clang
arm spitz_defconfig clang
arm64 allmodconfig clang
arm64 allnoconfig gcc
arm64 defconfig gcc
arm64 randconfig-001-20240111 gcc
arm64 randconfig-002-20240111 gcc
arm64 randconfig-003-20240111 gcc
arm64 randconfig-004-20240111 gcc
csky allmodconfig gcc
csky allnoconfig gcc
csky allyesconfig gcc
csky defconfig gcc
csky randconfig-001-20240111 gcc
csky randconfig-002-20240111 gcc
hexagon allmodconfig clang
hexagon allnoconfig clang
hexagon allyesconfig clang
hexagon defconfig clang
hexagon randconfig-001-20240111 clang
hexagon randconfig-002-20240111 clang
i386 allmodconfig clang
i386 allnoconfig clang
i386 allyesconfig clang
i386 buildonly-randconfig-001-20240111 gcc
i386 buildonly-randconfig-002-20240111 gcc
i386 buildonly-randconfig-003-20240111 gcc
i386 buildonly-randconfig-004-20240111 gcc
i386 buildonly-randconfig-005-20240111 gcc
i386 buildonly-randconfig-006-20240111 gcc
i386 defconfig gcc
i386 randconfig-001-20240111 gcc
i386 randconfig-002-20240111 gcc
i386 randconfig-003-20240111 gcc
i386 randconfig-004-20240111 gcc
i386 randconfig-005-20240111 gcc
i386 randconfig-006-20240111 gcc
i386 randconfig-011-20240111 clang
i386 randconfig-012-20240111 clang
i386 randconfig-013-20240111 clang
i386 randconfig-014-20240111 clang
i386 randconfig-015-20240111 clang
i386 randconfig-016-20240111 clang
loongarch allmodconfig gcc
loongarch allnoconfig gcc
loongarch defconfig gcc
loongarch randconfig-001-20240111 gcc
loongarch randconfig-002-20240111 gcc
m68k allmodconfig gcc
m68k allnoconfig gcc
m68k allyesconfig gcc
m68k atari_defconfig gcc
m68k defconfig gcc
m68k m5249evb_defconfig gcc
m68k mac_defconfig gcc
microblaze allmodconfig gcc
microblaze allnoconfig gcc
microblaze allyesconfig gcc
microblaze defconfig gcc
mips allnoconfig clang
mips allyesconfig gcc
mips bcm47xx_defconfig gcc
mips cu1000-neo_defconfig clang
mips ip27_defconfig gcc
mips malta_defconfig clang
nios2 allmodconfig gcc
nios2 allnoconfig gcc
nios2 allyesconfig gcc
nios2 defconfig gcc
nios2 randconfig-001-20240111 gcc
nios2 randconfig-002-20240111 gcc
openrisc allnoconfig gcc
openrisc allyesconfig gcc
openrisc defconfig gcc
openrisc or1klitex_defconfig gcc
openrisc simple_smp_defconfig gcc
parisc allmodconfig gcc
parisc allnoconfig gcc
parisc allyesconfig gcc
parisc defconfig gcc
parisc randconfig-001-20240111 gcc
parisc randconfig-002-20240111 gcc
parisc64 defconfig gcc
powerpc acadia_defconfig clang
powerpc allmodconfig clang
powerpc allnoconfig gcc
powerpc allyesconfig clang
powerpc icon_defconfig clang
powerpc mpc832x_rdb_defconfig clang
powerpc mpc836x_rdk_defconfig clang
powerpc ps3_defconfig gcc
powerpc randconfig-001-20240111 gcc
powerpc randconfig-002-20240111 gcc
powerpc randconfig-003-20240111 gcc
powerpc redwood_defconfig gcc
powerpc64 randconfig-001-20240111 gcc
powerpc64 randconfig-002-20240111 gcc
powerpc64 randconfig-003-20240111 gcc
riscv allmodconfig gcc
riscv allnoconfig clang
riscv allyesconfig gcc
riscv defconfig gcc
riscv nommu_k210_defconfig gcc
riscv randconfig-001-20240111 gcc
riscv randconfig-002-20240111 gcc
riscv rv32_defconfig clang
s390 alldefconfig clang
s390 allmodconfig gcc
s390 allnoconfig gcc
s390 allyesconfig gcc
s390 defconfig gcc
s390 randconfig-001-20240111 clang
s390 randconfig-002-20240111 clang
sh allmodconfig gcc
sh allnoconfig gcc
sh allyesconfig gcc
sh defconfig gcc
sh edosk7760_defconfig gcc
sh magicpanelr2_defconfig gcc
sh randconfig-001-20240111 gcc
sh randconfig-002-20240111 gcc
sh rts7751r2d1_defconfig gcc
sh se7722_defconfig gcc
sh sh2007_defconfig gcc
sh sh7763rdp_defconfig gcc
sparc allmodconfig gcc
sparc64 allmodconfig gcc
sparc64 allyesconfig gcc
sparc64 defconfig gcc
sparc64 randconfig-001-20240111 gcc
sparc64 randconfig-002-20240111 gcc
um allmodconfig clang
um allnoconfig clang
um allyesconfig clang
um defconfig gcc
um i386_defconfig gcc
um randconfig-001-20240111 gcc
um randconfig-002-20240111 gcc
um x86_64_defconfig gcc
x86_64 allnoconfig gcc
x86_64 allyesconfig clang
x86_64 buildonly-randconfig-001-20240111 gcc
x86_64 buildonly-randconfig-002-20240111 gcc
x86_64 buildonly-randconfig-003-20240111 gcc
x86_64 buildonly-randconfig-004-20240111 gcc
x86_64 buildonly-randconfig-005-20240111 gcc
x86_64 buildonly-randconfig-006-20240111 gcc
x86_64 defconfig gcc
x86_64 randconfig-001-20240111 clang
x86_64 randconfig-002-20240111 clang
x86_64 randconfig-003-20240111 clang
x86_64 randconfig-004-20240111 clang
x86_64 randconfig-005-20240111 clang
x86_64 randconfig-006-20240111 clang
x86_64 randconfig-011-20240111 gcc
x86_64 randconfig-012-20240111 gcc
x86_64 randconfig-013-20240111 gcc
x86_64 randconfig-014-20240111 gcc
x86_64 randconfig-015-20240111 gcc
x86_64 randconfig-016-20240111 gcc
x86_64 randconfig-071-20240111 gcc
x86_64 randconfig-072-20240111 gcc
x86_64 randconfig-073-20240111 gcc
x86_64 randconfig-074-20240111 gcc
x86_64 randconfig-075-20240111 gcc
x86_64 randconfig-076-20240111 gcc
x86_64 rhel-8.3-rust clang
xtensa allnoconfig gcc
xtensa randconfig-001-20240111 gcc
xtensa randconfig-002-20240111 gcc
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v5 4/5] Input: cs40l50 - Add support for the CS40L50 haptic driver
From: Dmitry Torokhov @ 2024-01-11 7:28 UTC (permalink / raw)
To: James Ogletree
Cc: James Ogletree, Fred Treven, Ben Bright, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Simon Trimmer, Charles Keepax,
Richard Fitzgerald, Lee Jones, Liam Girdwood, Mark Brown,
Jaroslav Kysela, Takashi Iwai, James Schulman, David Rhodes,
Alexandre Belloni, Peng Fan, Jeff LaBundy, Sebastian Reichel,
Jacky Bai, Weidong Wang, Arnd Bergmann, Herve Codina, Shuming Fan,
Shenghao Ding, Ryan Lee, Linus Walleij,
open list:CIRRUS LOGIC HAPTIC DRIVERS,
open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list,
open list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM...,
moderated list:CIRRUS LOGIC AUDIO CODEC DRIVERS
In-Reply-To: <42A07166-6569-4872-B5E0-6D71C6F3656D@cirrus.com>
On Wed, Jan 10, 2024 at 02:36:55PM +0000, James Ogletree wrote:
>
> > On Jan 9, 2024, at 4:31 PM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> >
> > On Tue, Jan 09, 2024 at 10:03:02PM +0000, James Ogletree wrote:
> >> Hi Dmitry,
> >>
> >> Thank you for your excellent review. Just a few questions.
> >>
> >>> On Jan 6, 2024, at 7:58 PM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> >>>
> >>> On Thu, Jan 04, 2024 at 10:36:37PM +0000, James Ogletree wrote:
> >>>> +
> >>>> + info->add_effect.u.periodic.custom_data = kcalloc(len, sizeof(s16), GFP_KERNEL);
> >>>> + if (!info->add_effect.u.periodic.custom_data)
> >>>> + return -ENOMEM;
> >>>> +
> >>>> + if (copy_from_user(info->add_effect.u.periodic.custom_data,
> >>>> + effect->u.periodic.custom_data, sizeof(s16) * len)) {
> >>>> + info->add_error = -EFAULT;
> >>>> + goto out_free;
> >>>> + }
> >>>> +
> >>>> + queue_work(info->vibe_wq, &info->add_work);
> >>>> + flush_work(&info->add_work);
> >>>
> >>> I do not understand the need of scheduling a work here. You are
> >>> obviously in a sleeping context (otherwise you would not be able to
> >>> execute flush_work()) so you should be able to upload the effect right
> >>> here.
> >>
> >> Scheduling work here is to ensure its ordering with “playback" worker
> >> items, which themselves are called in atomic context and so need
> >> deferred work. I think this explains why we need a workqueue as well,
> >> but please correct me.
> >>
> >>>
> >>>> +
> >>>> +static int vibra_playback(struct input_dev *dev, int effect_id, int val)
> >>>> +{
> >>>> + struct vibra_info *info = input_get_drvdata(dev);
> >>>> +
> >>>> + if (val > 0) {
> >>>
> >>> value is supposed to signal how many times an effect should be repeated.
> >>> It looks like you are not handling this at all.
> >>
> >> For playbacks, we mandate that the input_event value field is set to either 1
> >
> > I am sorry, who is "we"?
>
> Just a royal “I”. Apologies, no claim to authority intended here. :)
>
> >
> >> or 0 to command either a start playback or stop playback respectively.
> >> Values other than that should be rejected, so in the next version I will fix this
> >> to explicitly check for 1 or 0.
> >
> > No, please implement the API properly.
>
> Ack.
>
> >
> >>
> >>>
> >>>> + info->start_effect = &dev->ff->effects[effect_id];
> >>>> + queue_work(info->vibe_wq, &info->vibe_start_work);
> >>>
> >>> The API allows playback of several effects at once, the way you have it
> >>> done here if multiple requests come at same time only one will be
> >>> handled.
> >>
> >> I think I may need some clarification on this point. Why would concurrent
> >> start/stop playback commands get dropped? It seems they would all be
> >> added to the workqueue and executed eventually.
> >
> > You only have one instance of vibe_start_work, as well as only one
> > "slot" to hold the effect you want to start. So if you issue 2 request
> > back to back to play effect 1 and 2 you are likely to end with
> > info->start_effect == 2 and that is what vibe_start_work handler will
> > observe, effectively dropping request to play effect 1 on the floor.
>
> Understood, ack.
>
> >
> >>
> >>>
> >>>> + } else {
> >>>> + queue_work(info->vibe_wq, &info->vibe_stop_work);
> >>>
> >>> Which effect are you stopping? All of them? You need to stop a
> >>> particular one.
> >>
> >> Our implementation of “stop” stops all effects in flight which is intended.
> >> That is probably unusual so I will add a comment here in the next
> >> version.
> >
> > Again, please implement the driver properly, not define your own
> > carveouts for the expected behavior.
>
> Ack, and a clarification question: the device is not actually able to
> play multiple effects at once. In that case, does stopping a specific
> effect entail just cancelling an effect in the queue?
In this case I believe the device should declare maximum number of
effects as 1. Userspace is supposed to determine maximum number of
simultaneously playable effects by issuing EVIOCGEFFECTS ioctl on the
corresponding event device.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] vt: remove superfluous CONFIG_HW_CONSOLE
From: Dmitry Torokhov @ 2024-01-11 7:21 UTC (permalink / raw)
To: Lukas Bulwahn
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, Geert Uytterhoeven,
Helge Deller, Andrew Morton, linux-input, linux-m68k, linux-fbdev,
dri-devel, kernel-janitors, linux-kernel
In-Reply-To: <20240108134102.601-1-lukas.bulwahn@gmail.com>
On Mon, Jan 08, 2024 at 02:41:02PM +0100, Lukas Bulwahn wrote:
> The config HW_CONSOLE is always identical to the config VT and is not
> visible in the kernel's build menuconfig. So, CONFIG_HW_CONSOLE is
> redundant.
>
> Replace all references to CONFIG_HW_CONSOLE with CONFIG_VT and remove
> CONFIG_HW_CONSOLE.
>
> Signed-off-by: Lukas Bulwahn <lukas.bulwahn@gmail.com>
> ---
> I think this patch is best picked up by Greg rather than splitting it
> in smaller pieces for m68k, amiga keyboard, fbdev etc.
>
> Greg, if that is fine, could you pick this for the next merge window?
>
> I was also considering to rename config VT_HW_CONSOLE_BINDING to
> VT_CONSOLE_BINDING, as the dependency is on VT, not HW_CONSOLE, but
> at the moment, that seemed more churn than value of clarification.
>
> arch/m68k/amiga/config.c | 2 +-
> drivers/input/keyboard/amikbd.c | 6 +++---
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v14 2/4] Input: add core support for Goodix Berlin Touchscreen IC
From: Dmitry Torokhov @ 2024-01-11 7:20 UTC (permalink / raw)
To: Neil Armstrong
Cc: linux-input, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bastien Nocera, Hans de Goede, Henrik Rydberg, Jeff LaBundy,
linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20231221-topic-goodix-berlin-upstream-initial-v14-2-04459853b640@linaro.org>
Hi Neil,
On Thu, Dec 21, 2023 at 04:21:20PM +0100, Neil Armstrong wrote:
> Add initial support for the new Goodix "Berlin" touchscreen ICs.
Thank you very much for explaining how reading of additional contacts
and checksum works, it makes sense now.
I was a bit unhappy about number of times we copy/move the data over;
could you please try the patch below to see if the device still works
with it?
I also shortened some #defines and defines some additional structures.
Also as far as I can see not everything needs to be packed as the data
is naturally aligned on the word boundaries.
Thanks!
--
Dmitry
diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c
index 6aca57e6b5d6..d1f1c0474116 100644
--- a/drivers/input/touchscreen/goodix_berlin_core.c
+++ b/drivers/input/touchscreen/goodix_berlin_core.c
@@ -39,19 +39,6 @@
#define GOODIX_BERLIN_NORMAL_RESET_DELAY_MS 100
-#define GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN 8
-#define GOODIX_BERLIN_STATUS_OFFSET 0
-#define GOODIX_BERLIN_REQUEST_TYPE_OFFSET 2
-
-#define GOODIX_BERLIN_BYTES_PER_POINT 8
-#define GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE 2
-#define GOODIX_BERLIN_COOR_DATA_CHECKSUM_MASK GENMASK(15, 0)
-
-/* Read n finger events */
-#define GOODIX_BERLIN_IRQ_READ_LEN(n) (GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN + \
- (GOODIX_BERLIN_BYTES_PER_POINT * (n)) + \
- GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE)
-
#define GOODIX_BERLIN_TOUCH_EVENT BIT(7)
#define GOODIX_BERLIN_REQUEST_EVENT BIT(6)
#define GOODIX_BERLIN_TOUCH_COUNT_MASK GENMASK(3, 0)
@@ -71,6 +58,8 @@
#define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K
#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070
+#define GOODIX_BERLIN_CHECKSUM_SIZE sizeof(u16)
+
struct goodix_berlin_fw_version {
u8 rom_pid[6];
u8 rom_vid[3];
@@ -81,7 +70,7 @@ struct goodix_berlin_fw_version {
u8 sensor_id;
u8 reserved[2];
__le16 checksum;
-} __packed;
+};
struct goodix_berlin_ic_info_version {
u8 info_customer_id;
@@ -147,13 +136,30 @@ struct goodix_berlin_ic_info_misc {
__le32 esd_addr;
} __packed;
-struct goodix_berlin_touch_data {
- u8 id;
- u8 unused;
+struct goodix_berlin_touch {
+ u8 status;
+ u8 reserved;
__le16 x;
__le16 y;
__le16 w;
-} __packed;
+};
+#define GOODIX_BERLIN_TOUCH_SIZE sizeof(struct goodix_berlin_touch)
+
+struct goodix_berlin_header {
+ u8 status;
+ u8 reserved1;
+ u8 request_type;
+ u8 reserved2[3];
+ __le16 checksum;
+};
+#define GOODIX_BERLIN_HEADER_SIZE sizeof(struct goodix_berlin_header)
+
+struct goodix_berlin_event {
+ struct goodix_berlin_header hdr;
+ /* The data below is u16/__le16 aligned */
+ u8 data[GOODIX_BERLIN_TOUCH_SIZE * GOODIX_BERLIN_MAX_TOUCH +
+ GOODIX_BERLIN_CHECKSUM_SIZE];
+};
struct goodix_berlin_core {
struct device *dev;
@@ -168,25 +174,25 @@ struct goodix_berlin_core {
/* Runtime parameters extracted from IC_INFO buffer */
u32 touch_data_addr;
+
+ struct goodix_berlin_event event;
};
static bool goodix_berlin_checksum_valid(const u8 *data, int size)
{
u32 cal_checksum = 0;
u16 r_checksum;
- u32 i;
+ int i;
- if (size < GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE)
+ if (size < GOODIX_BERLIN_CHECKSUM_SIZE)
return false;
- for (i = 0; i < size - GOODIX_BERLIN_COOR_DATA_CHECKSUM_SIZE; i++)
+ for (i = 0; i < size - GOODIX_BERLIN_CHECKSUM_SIZE; i++)
cal_checksum += data[i];
- cal_checksum = FIELD_GET(GOODIX_BERLIN_COOR_DATA_CHECKSUM_MASK,
- cal_checksum);
r_checksum = get_unaligned_le16(&data[i]);
- return cal_checksum == r_checksum;
+ return (u16)cal_checksum == r_checksum;
}
static bool goodix_berlin_is_dummy_data(struct goodix_berlin_core *cd,
@@ -291,33 +297,30 @@ static void goodix_berlin_power_off(struct goodix_berlin_core *cd)
static int goodix_berlin_read_version(struct goodix_berlin_core *cd)
{
- u8 buf[sizeof(struct goodix_berlin_fw_version)];
int error;
error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR,
- buf, sizeof(buf));
+ &cd->fw_version, sizeof(cd->fw_version));
if (error) {
dev_err(cd->dev, "error reading fw version, %d\n", error);
return error;
}
- if (!goodix_berlin_checksum_valid(buf, sizeof(buf))) {
+ if (!goodix_berlin_checksum_valid((u8 *)&cd->fw_version,
+ sizeof(cd->fw_version))) {
dev_err(cd->dev, "invalid fw version: checksum error\n");
return -EINVAL;
}
- memcpy(&cd->fw_version, buf, sizeof(cd->fw_version));
-
return 0;
}
/* Only extract necessary data for runtime */
-static int goodix_berlin_convert_ic_info(struct goodix_berlin_core *cd,
- const u8 *data, u16 length)
+static int goodix_berlin_parse_ic_info(struct goodix_berlin_core *cd,
+ const u8 *data, u16 length)
{
- struct goodix_berlin_ic_info_misc misc;
+ struct goodix_berlin_ic_info_misc *misc;
unsigned int offset = 0;
- u8 param_num;
offset += sizeof(__le16); /* length */
offset += sizeof(struct goodix_berlin_ic_info_version);
@@ -325,49 +328,25 @@ static int goodix_berlin_convert_ic_info(struct goodix_berlin_core *cd,
/* IC_INFO Parameters, variable width structure */
offset += 4 * sizeof(u8); /* drv_num, sen_num, button_num, force_num */
-
- if (offset >= length)
- goto invalid_offset;
-
- param_num = data[offset++]; /* active_scan_rate_num */
-
- offset += param_num * sizeof(__le16);
-
- if (offset >= length)
- goto invalid_offset;
-
- param_num = data[offset++]; /* mutual_freq_num*/
-
- offset += param_num * sizeof(__le16);
-
- if (offset >= length)
- goto invalid_offset;
-
- param_num = data[offset++]; /* self_tx_freq_num */
-
- offset += param_num * sizeof(__le16);
-
- if (offset >= length)
- goto invalid_offset;
-
- param_num = data[offset++]; /* self_rx_freq_num */
-
- offset += param_num * sizeof(__le16);
-
if (offset >= length)
goto invalid_offset;
- param_num = data[offset++]; /* stylus_freq_num */
-
- offset += param_num * sizeof(__le16);
-
- if (offset + sizeof(misc) > length)
- goto invalid_offset;
-
- /* goodix_berlin_ic_info_misc */
- memcpy(&misc, &data[offset], sizeof(misc));
-
- cd->touch_data_addr = le32_to_cpu(misc.touch_data_addr);
+#define ADVANCE_LE16_PARAMS() \
+ do { \
+ u8 param_num = data[offset++]; \
+ offset += param_num * sizeof(__le16); \
+ if (offset >= length) \
+ goto invalid_offset; \
+ } while (0)
+ ADVANCE_LE16_PARAMS(); /* active_scan_rate_num */
+ ADVANCE_LE16_PARAMS(); /* mutual_freq_num*/
+ ADVANCE_LE16_PARAMS(); /* self_tx_freq_num */
+ ADVANCE_LE16_PARAMS(); /* self_rx_freq_num */
+ ADVANCE_LE16_PARAMS(); /* stylus_freq_num */
+#undef ADVANCE_LE16_PARAMS
+
+ misc = (struct goodix_berlin_ic_info_misc *)&data[offset];
+ cd->touch_data_addr = le32_to_cpu(misc->touch_data_addr);
return 0;
@@ -419,7 +398,7 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
return -EINVAL;
}
- error = goodix_berlin_convert_ic_info(cd, afe_data, length);
+ error = goodix_berlin_parse_ic_info(cd, afe_data, length);
if (error)
return error;
@@ -432,20 +411,47 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd)
return 0;
}
-static void goodix_berlin_parse_finger(struct goodix_berlin_core *cd,
- const void *buf, int touch_num)
+static int goodix_berlin_get_remaining_contacts(struct goodix_berlin_core *cd,
+ int n)
+{
+ size_t offset = 2 * GOODIX_BERLIN_TOUCH_SIZE +
+ GOODIX_BERLIN_CHECKSUM_SIZE;
+ u32 addr = cd->touch_data_addr + GOODIX_BERLIN_HEADER_SIZE + offset;
+ int error;
+
+ error = regmap_raw_read(cd->regmap, addr,
+ &cd->event.data[offset],
+ (n - 2) * GOODIX_BERLIN_TOUCH_SIZE);
+ if (error) {
+ dev_err_ratelimited(cd->dev, "failed to get touch data, %d\n",
+ error);
+ return error;
+ }
+
+ return 0;
+}
+
+static void goodix_berlin_report_state(struct goodix_berlin_core *cd, int n)
{
- const struct goodix_berlin_touch_data *touch_data = buf;
+ struct goodix_berlin_touch *touch_data =
+ (struct goodix_berlin_touch *)cd->event.data;
+ struct goodix_berlin_touch *t;
int i;
+ u8 type, id;
+
+ for (i = 0; i < n; i++) {
+ t = &touch_data[i];
- /* Report finger touches */
- for (i = 0; i < touch_num; i++) {
- unsigned int id = FIELD_GET(GOODIX_BERLIN_TOUCH_ID_MASK,
- touch_data[i].id);
+ type = FIELD_GET(GOODIX_BERLIN_POINT_TYPE_MASK, t->status);
+ if (type == GOODIX_BERLIN_POINT_TYPE_STYLUS ||
+ type == GOODIX_BERLIN_POINT_TYPE_STYLUS_HOVER) {
+ dev_warn_once(cd->dev, "Stylus event type not handled\n");
+ continue;
+ }
+ id = FIELD_GET(GOODIX_BERLIN_TOUCH_ID_MASK, t->status);
if (id >= GOODIX_BERLIN_MAX_TOUCH) {
- dev_warn_ratelimited(cd->dev,
- "invalid finger id %d\n", id);
+ dev_warn_ratelimited(cd->dev, "invalid finger id %d\n", id);
continue;
}
@@ -453,69 +459,46 @@ static void goodix_berlin_parse_finger(struct goodix_berlin_core *cd,
input_mt_report_slot_state(cd->input_dev, MT_TOOL_FINGER, true);
touchscreen_report_pos(cd->input_dev, &cd->props,
- __le16_to_cpu(touch_data[i].x),
- __le16_to_cpu(touch_data[i].y),
+ __le16_to_cpu(t->x), __le16_to_cpu(t->y),
true);
input_report_abs(cd->input_dev, ABS_MT_TOUCH_MAJOR,
- __le16_to_cpu(touch_data[i].w));
+ __le16_to_cpu(t->w));
}
input_mt_sync_frame(cd->input_dev);
input_sync(cd->input_dev);
}
-static void goodix_berlin_touch_handler(struct goodix_berlin_core *cd,
- const void *pre_buf, u32 pre_buf_len)
+static void goodix_berlin_touch_handler(struct goodix_berlin_core *cd)
{
- u8 buffer[GOODIX_BERLIN_IRQ_READ_LEN(GOODIX_BERLIN_MAX_TOUCH)];
- u8 point_type, touch_num;
+ u8 touch_num;
int error;
- /* copy pre-data to buffer */
- memcpy(buffer, pre_buf, pre_buf_len);
-
touch_num = FIELD_GET(GOODIX_BERLIN_TOUCH_COUNT_MASK,
- buffer[GOODIX_BERLIN_REQUEST_TYPE_OFFSET]);
-
+ cd->event.hdr.request_type);
if (touch_num > GOODIX_BERLIN_MAX_TOUCH) {
dev_warn(cd->dev, "invalid touch num %d\n", touch_num);
return;
}
- if (touch_num) {
- /* read more data if more than 2 touch events */
- if (unlikely(touch_num > 2)) {
- error = regmap_raw_read(cd->regmap,
- cd->touch_data_addr + pre_buf_len,
- &buffer[pre_buf_len],
- (touch_num - 2) * GOODIX_BERLIN_BYTES_PER_POINT);
- if (error) {
- dev_err_ratelimited(cd->dev, "failed to get touch data, %d\n",
- error);
- return;
- }
- }
-
- point_type = FIELD_GET(GOODIX_BERLIN_POINT_TYPE_MASK,
- buffer[GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN]);
-
- if (point_type == GOODIX_BERLIN_POINT_TYPE_STYLUS ||
- point_type == GOODIX_BERLIN_POINT_TYPE_STYLUS_HOVER) {
- dev_warn_once(cd->dev, "Stylus event type not handled\n");
+ if (touch_num > 2) {
+ /* read additional contact data if more than 2 touch events */
+ error = goodix_berlin_get_remaining_contacts(cd, touch_num);
+ if (error)
return;
- }
+ }
- if (!goodix_berlin_checksum_valid(&buffer[GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN],
- touch_num * GOODIX_BERLIN_BYTES_PER_POINT + 2)) {
+ if (touch_num) {
+ int len = touch_num * GOODIX_BERLIN_TOUCH_SIZE +
+ GOODIX_BERLIN_CHECKSUM_SIZE;
+ if (!goodix_berlin_checksum_valid(cd->event.data, len)) {
dev_err(cd->dev, "touch data checksum error: %*ph\n",
- touch_num * GOODIX_BERLIN_BYTES_PER_POINT + 2,
- &buffer[GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN]);
+ len, cd->event.data);
return;
}
}
- goodix_berlin_parse_finger(cd, &buffer[GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN],
- touch_num);
+ goodix_berlin_report_state(cd, touch_num);
}
static int goodix_berlin_request_handle_reset(struct goodix_berlin_core *cd)
@@ -532,68 +515,72 @@ static int goodix_berlin_request_handle_reset(struct goodix_berlin_core *cd)
static irqreturn_t goodix_berlin_irq(int irq, void *data)
{
struct goodix_berlin_core *cd = data;
- u8 buf[GOODIX_BERLIN_IRQ_READ_LEN(2)];
- u8 event_status;
int error;
/*
* First, read buffer with space for 2 touch events:
- * - GOODIX_BERLIN_IRQ_EVENT_HEAD = 8 bytes
- * - GOODIX_BERLIN_BYTES_PER_POINT * 2 +
- * GOODIX_BERLIN_COOR_DATA_CHECKSUM = 18 bytes
+ * - GOODIX_BERLIN_HEADER_SIZE = 8 bytes
+ * - GOODIX_BERLIN_TOUCH_SIZE * 2 = 16 bytes
+ * - GOODIX_BERLIN_CHECKLSUM_SIZE = 2 bytes
* For a total of 26 bytes.
*
- * If only a single finger is reported, we will read 8 bytes more than needed:
- * - bytes 0-7: GOODIX_BERLIN_IRQ_EVENT_HEAD
+ * If only a single finger is reported, we will read 8 bytes more than
+ * needed:
+ * - bytes 0-7: Header (GOODIX_BERLIN_HEADER_SIZE)
* - bytes 8-15: Finger 0 Data
- * - bytes 16-17: GOODIX_BERLIN_COOR_DATA_CHECKSUM
+ * - bytes 24-25: Checksum
* - bytes 18-25: Unused 8 bytes
*
- * If 2 fingers are reported, we would have read the exact needed amount of
- * data and checkout would be at the end of the buffer:
- * - bytes 0-7: GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN
+ * If 2 fingers are reported, we would have read the exact needed
+ * amount of data and checksum would be at the end of the buffer:
+ * - bytes 0-7: Header (GOODIX_BERLIN_HEADER_SIZE)
* - bytes 8-15: Finger 0 Bytes 0-7
* - bytes 16-23: Finger 1 Bytes 0-7
- * - bytes 24-25: GOODIX_BERLIN_COOR_DATA_CHECKSUM
+ * - bytes 24-25: Checksum
*
- * If more than 2 fingers were reported, the "Checksum" bytes would in fact
- * contain part of the next finger data, and then we would complete the buffer
- * with the missing bytes, but by keeping the GOODIX_BERLIN_IRQ_READ_LEN(2)
- * size as base, it will still contain space for the final 2 bytes checksum:
- * - bytes 0-7: GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN]
+ * If more than 2 fingers were reported, the "Checksum" bytes would
+ * in fact contain part of the next finger data, and then
+ * goodix_berlin_get_remaining_contacts() would complete the buffer
+ * with the missing bytes, including the trailing checksum.
+ * For example, if 3 fingers are reported, then we would do:
+ * Read 1:
+ * - bytes 0-7: Header (GOODIX_BERLIN_HEADER_SIZE)
* - bytes 8-15: Finger 0 Bytes 0-7
* - bytes 16-23: Finger 1 Bytes 0-7
* - bytes 24-25: Finger 2 Bytes 0-1
- * for example if 3 fingers are reported, (3 - 2) * 8 = 8 bytes would be read:
+ * Read 2 (with length of (3 - 2) * 8 = 8 bytes):
* - bytes 26-31: Finger 2 Bytes 2-7
- * - bytes 32-33: GOODIX_BERLIN_COOR_DATA_CHECKSUM
+ * - bytes 32-33: Checksum
*/
- error = regmap_raw_read(cd->regmap, cd->touch_data_addr, buf,
- GOODIX_BERLIN_IRQ_READ_LEN(2));
+ error = regmap_raw_read(cd->regmap, cd->touch_data_addr,
+ &cd->event,
+ GOODIX_BERLIN_HEADER_SIZE +
+ 2 * GOODIX_BERLIN_TOUCH_SIZE +
+ GOODIX_BERLIN_CHECKSUM_SIZE);
if (error) {
dev_warn_ratelimited(cd->dev,
"failed get event head data: %d\n", error);
- return IRQ_HANDLED;
+ goto out;
}
- if (buf[GOODIX_BERLIN_STATUS_OFFSET] == 0)
- return IRQ_HANDLED;
+ if (cd->event.hdr.status == 0)
+ goto out;
- if (!goodix_berlin_checksum_valid(buf, GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN)) {
+ if (!goodix_berlin_checksum_valid((u8 *)&cd->event.hdr,
+ GOODIX_BERLIN_HEADER_SIZE)) {
dev_warn_ratelimited(cd->dev,
"touch head checksum error: %*ph\n",
- GOODIX_BERLIN_IRQ_EVENT_HEAD_LEN, buf);
- return IRQ_HANDLED;
+ (int)GOODIX_BERLIN_HEADER_SIZE,
+ &cd->event.hdr);
+ // FIXME: should we clear the status?
+ goto out;
}
- event_status = buf[GOODIX_BERLIN_STATUS_OFFSET];
-
- if (event_status & GOODIX_BERLIN_TOUCH_EVENT)
- goodix_berlin_touch_handler(cd, buf,
- GOODIX_BERLIN_IRQ_READ_LEN(2));
+ if (cd->event.hdr.status & GOODIX_BERLIN_TOUCH_EVENT)
+ goodix_berlin_touch_handler(cd);
- if (event_status & GOODIX_BERLIN_REQUEST_EVENT) {
- switch (buf[GOODIX_BERLIN_REQUEST_TYPE_OFFSET]) {
+ if (cd->event.hdr.status & GOODIX_BERLIN_REQUEST_EVENT) {
+ switch (cd->event.hdr.request_type) {
case GOODIX_BERLIN_REQUEST_CODE_RESET:
if (cd->reset_gpio)
goodix_berlin_request_handle_reset(cd);
@@ -601,13 +588,14 @@ static irqreturn_t goodix_berlin_irq(int irq, void *data)
default:
dev_warn(cd->dev, "unsupported request code 0x%x\n",
- buf[GOODIX_BERLIN_REQUEST_TYPE_OFFSET]);
+ cd->event.hdr.request_type);
}
}
/* Clear up status field */
regmap_write(cd->regmap, cd->touch_data_addr, 0);
+out:
return IRQ_HANDLED;
}
^ permalink raw reply related
* [PATCH] Input: adafruit-seesaw - only report buttons that changed state
From: Dmitry Torokhov @ 2024-01-11 7:13 UTC (permalink / raw)
To: Anshul Dalal; +Cc: Thomas Weißschuh, linux-input, linux-kernel
If a button has not changed its state when we poll the device the
driver does not need to report it. While duplicate events will be
filtered out by the input core anyway we can do it very cheaply
directly in the driver.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/joystick/adafruit-seesaw.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/input/joystick/adafruit-seesaw.c b/drivers/input/joystick/adafruit-seesaw.c
index 1b9279f024cc..5c775ca886a5 100644
--- a/drivers/input/joystick/adafruit-seesaw.c
+++ b/drivers/input/joystick/adafruit-seesaw.c
@@ -56,7 +56,7 @@
#define SEESAW_GAMEPAD_POLL_MIN 8
#define SEESAW_GAMEPAD_POLL_MAX 32
-static const unsigned long SEESAW_BUTTON_MASK =
+static const u32 SEESAW_BUTTON_MASK =
BIT(SEESAW_BUTTON_A) | BIT(SEESAW_BUTTON_B) | BIT(SEESAW_BUTTON_X) |
BIT(SEESAW_BUTTON_Y) | BIT(SEESAW_BUTTON_START) |
BIT(SEESAW_BUTTON_SELECT);
@@ -64,6 +64,7 @@ static const unsigned long SEESAW_BUTTON_MASK =
struct seesaw_gamepad {
struct input_dev *input_dev;
struct i2c_client *i2c_client;
+ u32 button_state;
};
struct seesaw_data {
@@ -178,10 +179,20 @@ static int seesaw_read_data(struct i2c_client *client, struct seesaw_data *data)
return 0;
}
+static int seesaw_open(struct input_dev *input)
+{
+ struct seesaw_gamepad *private = input_get_drvdata(input);
+
+ private->button_state = 0;
+
+ return 0;
+}
+
static void seesaw_poll(struct input_dev *input)
{
struct seesaw_gamepad *private = input_get_drvdata(input);
struct seesaw_data data;
+ unsigned long changed;
int err, i;
err = seesaw_read_data(private->i2c_client, &data);
@@ -194,8 +205,11 @@ static void seesaw_poll(struct input_dev *input)
input_report_abs(input, ABS_X, data.x);
input_report_abs(input, ABS_Y, data.y);
- for_each_set_bit(i, &SEESAW_BUTTON_MASK,
- BITS_PER_TYPE(SEESAW_BUTTON_MASK)) {
+ data.button_state &= SEESAW_BUTTON_MASK;
+ changed = private->button_state ^ data.button_state;
+ private->button_state = data.button_state;
+
+ for_each_set_bit(i, &changed, fls(SEESAW_BUTTON_MASK)) {
if (!sparse_keymap_report_event(input, i,
data.button_state & BIT(i),
false))
@@ -253,6 +267,7 @@ static int seesaw_probe(struct i2c_client *client)
seesaw->input_dev->id.bustype = BUS_I2C;
seesaw->input_dev->name = "Adafruit Seesaw Gamepad";
seesaw->input_dev->phys = "i2c/" SEESAW_DEVICE_NAME;
+ seesaw->input_dev->open = seesaw_open;
input_set_drvdata(seesaw->input_dev, seesaw);
input_set_abs_params(seesaw->input_dev, ABS_X,
0, SEESAW_JOYSTICK_MAX_AXIS,
--
2.43.0.275.g3460e3d667-goog
--
Dmitry
^ permalink raw reply related
* Re: [PATCH v12 1/2] dt-bindings: input: bindings for Adafruit Seesaw Gamepad
From: Dmitry Torokhov @ 2024-01-11 1:20 UTC (permalink / raw)
To: Anshul Dalal
Cc: linux-input, devicetree, Conor Dooley, Thomas Weißschuh,
linux-kernel, Krzysztof Kozlowski, Conor Dooley, Rob Herring,
Krzysztof Kozlowski, Jeff LaBundy, linux-kernel-mentees
In-Reply-To: <20240106015111.882325-1-anshulusr@gmail.com>
On Sat, Jan 06, 2024 at 07:20:59AM +0530, Anshul Dalal wrote:
> Adds bindings for the Adafruit Seesaw Gamepad.
>
> The gamepad functions as an i2c device with the default address of 0x50
> and has an IRQ pin that can be enabled in the driver to allow for a rising
> edge trigger on each button press or joystick movement.
>
> Product page:
> https://www.adafruit.com/product/5743
> Arduino driver:
> https://github.com/adafruit/Adafruit_Seesaw
>
> Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Signed-off-by: Anshul Dalal <anshulusr@gmail.com>
>
Applied, thank you.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v12 2/2] input: joystick: driver for Adafruit Seesaw Gamepad
From: Dmitry Torokhov @ 2024-01-11 1:20 UTC (permalink / raw)
To: Anshul Dalal
Cc: linux-input, devicetree, Conor Dooley, Thomas Weißschuh,
linux-kernel, Krzysztof Kozlowski, Conor Dooley, Rob Herring,
Krzysztof Kozlowski, Jeff LaBundy, linux-kernel-mentees
In-Reply-To: <20240106015111.882325-2-anshulusr@gmail.com>
Hi Anshul,
On Sat, Jan 06, 2024 at 07:21:00AM +0530, Anshul Dalal wrote:
> +
> + for_each_set_bit(i, (long *)&SEESAW_BUTTON_MASK,
> + BITS_PER_TYPE(SEESAW_BUTTON_MASK)) {
This is not really safe as it might not be aligned properly, and we can
potentially try to peek beyond the data element (even though we limit
how many bits we consider valid). I changed SEESAW_BUTTON_MASK to be
unsigned long.
I also dropped bunch of unneeded casts and applied, thank you.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input: i8042 - add quirk for Lenovo ThinkPad T14 Gen 1
From: Jonathan Denose @ 2024-01-10 23:42 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Jonathan Denose, Hans de Goede, Huacai Chen,
Mattijs Korpershoek, Takashi Iwai, Werner Sembach, linux-kernel
In-Reply-To: <ZZ2eduF_h7lcBrSL@google.com>
Dmitry,
Sorry I forgot to reply all, so I'm resending my other email.
On Tue, Jan 9, 2024 at 1:28 PM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
>
> Hi Jonathan,
>
> On Mon, Nov 27, 2023 at 10:38:57AM -0600, Jonathan Denose wrote:
> > Hi Dmitry
> >
> > On Fri, Nov 24, 2023 at 10:45 PM Dmitry Torokhov
> > <dmitry.torokhov@gmail.com> wrote:
> > >
> > > Hi Jonathan,
> > >
> > > On Mon, Sep 25, 2023 at 04:33:20PM -0500, Jonathan Denose wrote:
> > > > The ThinkPad T14 Gen 1 touchpad works fine except that clicking
> > > > and dragging by tapping the touchpad or depressing the touchpad
> > > > do not work. Disabling PNP for controller setting discovery enables
> > > > click and drag without negatively impacting other touchpad features.
> > >
> > > I would like to understand more on how enabling PnP discovery for i8042
> > > affects the touchpad. Do you see it using different interrupt or IO
> > > ports? What protocol does the touchpad use with/without PnP? If the
> > > protocol is the same, do you see difference in the ranges (pressure,
> > > etc) reported by the device?
> > >
> > > Thanks.
> > >
> > > --
> > > Dmitry
> >
> > Without PnP discovery the touchpad is using the SynPS/2 protocol, with
> > PnP discovery, the touchpad is using the rmi4 protocol. Since the
> > protocols are different, so are the ranges but let me know if you
> > still want to see them.
>
> Thank you for this information. So it is not PnP discovery that appears
> harmful in your case, but rather that legacy PS/2 mode appears to be
> working better than RMI4 for the device in question.
>
> I will note that the original enablement of RMI4 for T14 was done by
> Hans in [1]. Later T14 with AMD were added to the list of devices that
> should use RMI4 [2], however this was reverted in [3].
>
> Could you please tell me what exact device you are dealing with? What's
> it ACPI ID?
>
> [1] https://lore.kernel.org/all/20201005114919.371592-1-hdegoede@redhat.com/
> [2] https://lore.kernel.org/r/20220318113949.32722-1-snafu109@gmail.com
> [3] https://lore.kernel.org/r/20220920193936.8709-1-markpearson@lenovo.com
>
> Thanks.
>
> --
> Dmitry
Thanks for your reply!
I'm not 100% sure which of these is the ACPI ID, but from `udevadm
info -e` there's:
N: Name="Synaptics TM3471-020"
P: Phys=rmi4-00/input0
^ permalink raw reply
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