* Re: [PATCH] typo fixes (coordiante -> coordinate) in am335x
From: Jan Lübbe @ 2013-11-05 16:01 UTC (permalink / raw)
To: Lee Jones
Cc: Dmitry Torokhov, Tony Lindgren, Samuel Ortiz, Zubair Lutfullah,
linux-doc, linux-kernel, linux-omap, linux-arm-kernel,
linux-input
In-Reply-To: <20131022090552.GE19112@lee--X1>
On Tue, 2013-10-22 at 10:05 +0100, Lee Jones wrote:
> This is the first time this patch has been sent to me.
>
> I need Dmitry's input (no pun intended) on how he's like to deal with
> this. At a bare minimum I'd like his Ack.
Is there anything I can do to push this forward? The earlier we get the
typo fixed in the documentation, the less chance that someone will use
it that way.
Regards,
Jan
^ permalink raw reply
* Re: [PATCH] typo fixes (coordiante -> coordinate) in am335x
From: Lee Jones @ 2013-11-05 17:15 UTC (permalink / raw)
To: Jan Lübbe
Cc: Dmitry Torokhov, Tony Lindgren, Samuel Ortiz, Zubair Lutfullah,
linux-doc, linux-kernel, linux-omap, linux-arm-kernel,
linux-input
In-Reply-To: <1383667293.6753.35.camel@polaris.local>
On Tue, 05 Nov 2013, Jan Lübbe wrote:
> On Tue, 2013-10-22 at 10:05 +0100, Lee Jones wrote:
> > This is the first time this patch has been sent to me.
> >
> > I need Dmitry's input (no pun intended) on how he's like to deal with
> > this. At a bare minimum I'd like his Ack.
>
> Is there anything I can do to push this forward? The earlier we get the
> typo fixed in the documentation, the less chance that someone will use
> it that way.
I think you should sent it again, but this time Cc the Device Tree
list, Dmitry and myself when you submit.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] typo fixes (coordiante -> coordinate) in am335x
From: Jan Lübbe @ 2013-11-05 17:51 UTC (permalink / raw)
To: Lee Jones
Cc: Dmitry Torokhov, Tony Lindgren, Samuel Ortiz, Zubair Lutfullah,
linux-doc, linux-kernel, linux-omap, linux-arm-kernel,
linux-input
In-Reply-To: <20131105171553.GB30901@lee--X1>
On Tue, 2013-11-05 at 17:15 +0000, Lee Jones wrote:
> On Tue, 05 Nov 2013, Jan Lübbe wrote:
>
> > On Tue, 2013-10-22 at 10:05 +0100, Lee Jones wrote:
> > > This is the first time this patch has been sent to me.
> > >
> > > I need Dmitry's input (no pun intended) on how he's like to deal with
> > > this. At a bare minimum I'd like his Ack.
> >
> > Is there anything I can do to push this forward? The earlier we get the
> > typo fixed in the documentation, the less chance that someone will use
> > it that way.
>
> I think you should sent it again, but this time Cc the Device Tree
> list, Dmitry and myself when you submit.
The original patch was not from me. But sure, I can resend it.
Jan
^ permalink raw reply
* Re: [PATCH] typo fixes (coordiante -> coordinate) in am335x
From: Lee Jones @ 2013-11-05 18:03 UTC (permalink / raw)
To: Jan Lübbe
Cc: Dmitry Torokhov, Tony Lindgren, Samuel Ortiz, Zubair Lutfullah,
linux-doc, linux-kernel, linux-omap, linux-arm-kernel,
linux-input
In-Reply-To: <1383673871.6753.36.camel@polaris.local>
On Tue, 05 Nov 2013, Jan Lübbe wrote:
> On Tue, 2013-11-05 at 17:15 +0000, Lee Jones wrote:
> > On Tue, 05 Nov 2013, Jan Lübbe wrote:
> >
> > > On Tue, 2013-10-22 at 10:05 +0100, Lee Jones wrote:
> > > > This is the first time this patch has been sent to me.
> > > >
> > > > I need Dmitry's input (no pun intended) on how he's like to deal with
> > > > this. At a bare minimum I'd like his Ack.
> > >
> > > Is there anything I can do to push this forward? The earlier we get the
> > > typo fixed in the documentation, the less chance that someone will use
> > > it that way.
> >
> > I think you should sent it again, but this time Cc the Device Tree
> > list, Dmitry and myself when you submit.
>
> The original patch was not from me. But sure, I can resend it.
I'm not worried about who re-sends the patch. Just make sure whoever
does sends in correctly with regards to the $SUBJECT line etc. The one
on this patch looks odd.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 02/13] Input: introduce ABS_MAX2/CNT2 and friends
From: David Herrmann @ 2013-11-05 22:29 UTC (permalink / raw)
To: open list:HID CORE LAYER
Cc: Dmitry Torokhov, Jiri Kosina, Peter Hutterer, Benjamin Tissoires,
David Herrmann
In-Reply-To: <1383336984-26601-3-git-send-email-dh.herrmann@gmail.com>
Hi
On Fri, Nov 1, 2013 at 9:16 PM, David Herrmann <dh.herrmann@gmail.com> wrote:
> As we painfully noticed during the 3.12 merge-window our
> EVIOCGABS/EVIOCSABS API is limited to ABS_MAX<=0x3f. We tried several
> hacks to work around it but if we ever decide to increase ABS_MAX, the
> EVIOCSABS ioctl ABI might overflow into the next byte causing horrible
> misinterpretations in the kernel that we cannot catch.
>
> Therefore, we decided to go with ABS_MAX2/CNT2 and introduce two new
> ioctls to get/set abs-params. They no longer encode the ABS code in the
> ioctl number and thus allow up to 4 billion ABS codes.
>
> The new API also allows to query multiple ABS values with one call. To
> allow EVIOCSABS2(code = 0, cnt = ABS_CNT2) we need to silently ignore
> writes to ABS_MT_SLOT. Other than that, semantics are the same as for the
> legacy API.
I'm currently having a hard time making this properly work with
backwards-compatibility in mind. It can get really hairy to properly
detect whether a kernel supports ABS2 or not (during runtime). Any
objections to increasing the EVDEV version field? User-space could
then easily know whether EVIOCGABS2 is supported.
Just as a note: the libevdev test-suite runs just fine with this
patch, so at least it shouldn't break backwards-compat this time.
Anyway, I would feel a lot better if we can let this stay in
linux-next for one cycle.
Thanks
David
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> ---
> drivers/hid/hid-debug.c | 2 +-
> drivers/hid/hid-input.c | 2 +-
> drivers/input/evdev.c | 88 +++++++++++++++++++++++++++++++-
> drivers/input/input.c | 14 ++---
> drivers/input/keyboard/goldfish_events.c | 6 +--
> drivers/input/keyboard/hil_kbd.c | 2 +-
> drivers/input/misc/uinput.c | 6 +--
> include/linux/hid.h | 2 +-
> include/linux/input.h | 6 +--
> include/uapi/linux/input.h | 37 +++++++++++++-
> include/uapi/linux/uinput.h | 2 +-
> 11 files changed, 144 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
> index 8453214..d32fa30 100644
> --- a/drivers/hid/hid-debug.c
> +++ b/drivers/hid/hid-debug.c
> @@ -862,7 +862,7 @@ static const char *relatives[REL_MAX + 1] = {
> [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc",
> };
>
> -static const char *absolutes[ABS_CNT] = {
> +static const char *absolutes[ABS_CNT2] = {
> [ABS_X] = "X", [ABS_Y] = "Y",
> [ABS_Z] = "Z", [ABS_RX] = "Rx",
> [ABS_RY] = "Ry", [ABS_RZ] = "Rz",
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index d97f232..a02721c 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -1300,7 +1300,7 @@ static bool hidinput_has_been_populated(struct hid_input *hidinput)
> for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++)
> r |= hidinput->input->relbit[i];
>
> - for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++)
> + for (i = 0; i < BITS_TO_LONGS(ABS_CNT2); i++)
> r |= hidinput->input->absbit[i];
>
> for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++)
> diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
> index b6ded17..ffe65fd 100644
> --- a/drivers/input/evdev.c
> +++ b/drivers/input/evdev.c
> @@ -635,7 +635,7 @@ static int handle_eviocgbit(struct input_dev *dev,
> case 0: bits = dev->evbit; len = EV_MAX; break;
> case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
> case EV_REL: bits = dev->relbit; len = REL_MAX; break;
> - case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
> + case EV_ABS: bits = dev->absbit; len = ABS_MAX2; break;
> case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
> case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
> case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
> @@ -663,6 +663,86 @@ static int handle_eviocgbit(struct input_dev *dev,
> }
> #undef OLD_KEY_MAX
>
> +static int evdev_handle_get_abs2(struct input_dev *dev, void __user *p)
> +{
> + u32 code, cnt, i;
> + struct input_absinfo2 __user *pinfo = p;
> + struct input_absinfo abs;
> +
> + if (!dev->absinfo)
> + return -EINVAL;
> +
> + if (copy_from_user(&code, &pinfo->code, sizeof(code)))
> + return -EFAULT;
> + if (copy_from_user(&cnt, &pinfo->cnt, sizeof(cnt)))
> + return -EFAULT;
> +
> + if (!cnt || code > ABS_MAX2 || cnt > ABS_CNT2)
> + return -EINVAL;
> + if (code + cnt > ABS_MAX2)
> + return -EINVAL;
> +
> + for (i = 0; i < cnt; ++i) {
> + /*
> + * Take event lock to ensure that we are not
> + * copying data while EVIOCSABS2 changes it.
> + * Might be inconsistent, otherwise.
> + */
> + spin_lock_irq(&dev->event_lock);
> + abs = dev->absinfo[code + i];
> + spin_unlock_irq(&dev->event_lock);
> +
> + if (copy_to_user(&pinfo->info[i], &abs, sizeof(abs)))
> + return -EFAULT;
> + }
> +
> + return 0;
> +}
> +
> +static int evdev_handle_set_abs2(struct input_dev *dev, void __user *p)
> +{
> + struct input_absinfo2 __user *pinfo = p;
> + struct input_absinfo *abs;
> + u32 code, cnt, i;
> + size_t size;
> +
> + if (!dev->absinfo)
> + return -EINVAL;
> +
> + if (copy_from_user(&code, &pinfo->code, sizeof(code)))
> + return -EFAULT;
> + if (copy_from_user(&cnt, &pinfo->cnt, sizeof(cnt)))
> + return -EFAULT;
> +
> + if (!cnt || code > ABS_MAX2 || cnt > ABS_CNT2)
> + return -EINVAL;
> + if (code + cnt > ABS_MAX2)
> + return -EINVAL;
> +
> + size = cnt * sizeof(*abs);
> + abs = memdup_user(&pinfo->info[0], size);
> + if (IS_ERR(abs))
> + return PTR_ERR(abs);
> +
> + /*
> + * Take event lock to ensure that we are not
> + * changing device parameters in the middle
> + * of event.
> + */
> + spin_lock_irq(&dev->event_lock);
> + for (i = 0; i < cnt; ++i) {
> + /* silently drop ABS_MT_SLOT */
> + if (code + i == ABS_MT_SLOT)
> + continue;
> +
> + dev->absinfo[code + i] = abs[i];
> + }
> + spin_unlock_irq(&dev->event_lock);
> +
> + kfree(abs);
> + return 0;
> +}
> +
> static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)
> {
> struct input_keymap_entry ke = {
> @@ -890,6 +970,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
> client->clkid = i;
> return 0;
>
> + case EVIOCGABS2:
> + return evdev_handle_get_abs2(dev, p);
> +
> + case EVIOCSABS2:
> + return evdev_handle_set_abs2(dev, p);
> +
> case EVIOCGKEYCODE:
> return evdev_handle_get_keycode(dev, p);
>
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index c044699..bc88f17 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -305,7 +305,7 @@ static int input_get_disposition(struct input_dev *dev,
> break;
>
> case EV_ABS:
> - if (is_event_supported(code, dev->absbit, ABS_MAX))
> + if (is_event_supported(code, dev->absbit, ABS_MAX2))
> disposition = input_handle_abs_event(dev, code, &value);
>
> break;
> @@ -474,7 +474,7 @@ EXPORT_SYMBOL(input_inject_event);
> void input_alloc_absinfo(struct input_dev *dev)
> {
> if (!dev->absinfo)
> - dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
> + dev->absinfo = kcalloc(ABS_CNT2, sizeof(struct input_absinfo),
> GFP_KERNEL);
>
> WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
> @@ -954,7 +954,7 @@ static const struct input_device_id *input_match_device(struct input_handler *ha
> if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
> continue;
>
> - if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
> + if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX2))
> continue;
>
> if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
> @@ -1147,7 +1147,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
> if (test_bit(EV_REL, dev->evbit))
> input_seq_print_bitmap(seq, "REL", dev->relbit, REL_MAX);
> if (test_bit(EV_ABS, dev->evbit))
> - input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX);
> + input_seq_print_bitmap(seq, "ABS", dev->absbit, ABS_MAX2);
> if (test_bit(EV_MSC, dev->evbit))
> input_seq_print_bitmap(seq, "MSC", dev->mscbit, MSC_MAX);
> if (test_bit(EV_LED, dev->evbit))
> @@ -1333,7 +1333,7 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
> len += input_print_modalias_bits(buf + len, size - len,
> 'r', id->relbit, 0, REL_MAX);
> len += input_print_modalias_bits(buf + len, size - len,
> - 'a', id->absbit, 0, ABS_MAX);
> + 'a', id->absbit, 0, ABS_MAX2);
> len += input_print_modalias_bits(buf + len, size - len,
> 'm', id->mscbit, 0, MSC_MAX);
> len += input_print_modalias_bits(buf + len, size - len,
> @@ -1592,7 +1592,7 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
> if (test_bit(EV_REL, dev->evbit))
> INPUT_ADD_HOTPLUG_BM_VAR("REL=", dev->relbit, REL_MAX);
> if (test_bit(EV_ABS, dev->evbit))
> - INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX);
> + INPUT_ADD_HOTPLUG_BM_VAR("ABS=", dev->absbit, ABS_MAX2);
> if (test_bit(EV_MSC, dev->evbit))
> INPUT_ADD_HOTPLUG_BM_VAR("MSC=", dev->mscbit, MSC_MAX);
> if (test_bit(EV_LED, dev->evbit))
> @@ -1924,7 +1924,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
>
> events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */
>
> - for (i = 0; i < ABS_CNT; i++) {
> + for (i = 0; i < ABS_CNT2; i++) {
> if (test_bit(i, dev->absbit)) {
> if (input_is_mt_axis(i))
> events += mt_slots;
> diff --git a/drivers/input/keyboard/goldfish_events.c b/drivers/input/keyboard/goldfish_events.c
> index 9f60a2e..9999cea 100644
> --- a/drivers/input/keyboard/goldfish_events.c
> +++ b/drivers/input/keyboard/goldfish_events.c
> @@ -90,8 +90,8 @@ static void events_import_abs_params(struct event_dev *edev)
> __raw_writel(PAGE_ABSDATA, addr + REG_SET_PAGE);
>
> count = __raw_readl(addr + REG_LEN) / sizeof(val);
> - if (count > ABS_MAX)
> - count = ABS_MAX;
> + if (count > ABS_MAX2)
> + count = ABS_MAX2;
>
> for (i = 0; i < count; i++) {
> if (!test_bit(i, input_dev->absbit))
> @@ -158,7 +158,7 @@ static int events_probe(struct platform_device *pdev)
> events_import_bits(edev, input_dev->evbit, EV_SYN, EV_MAX);
> events_import_bits(edev, input_dev->keybit, EV_KEY, KEY_MAX);
> events_import_bits(edev, input_dev->relbit, EV_REL, REL_MAX);
> - events_import_bits(edev, input_dev->absbit, EV_ABS, ABS_MAX);
> + events_import_bits(edev, input_dev->absbit, EV_ABS, ABS_MAX2);
> events_import_bits(edev, input_dev->mscbit, EV_MSC, MSC_MAX);
> events_import_bits(edev, input_dev->ledbit, EV_LED, LED_MAX);
> events_import_bits(edev, input_dev->sndbit, EV_SND, SND_MAX);
> diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
> index 589e3c2..4e4e010 100644
> --- a/drivers/input/keyboard/hil_kbd.c
> +++ b/drivers/input/keyboard/hil_kbd.c
> @@ -387,7 +387,7 @@ static void hil_dev_pointer_setup(struct hil_dev *ptr)
> 0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0);
>
> #ifdef TABLET_AUTOADJUST
> - for (i = 0; i < ABS_MAX; i++) {
> + for (i = 0; i < ABS_MAX2; i++) {
> int diff = input_abs_get_max(input_dev, ABS_X + i) / 10;
> input_abs_set_min(input_dev, ABS_X + i,
> input_abs_get_min(input_dev, ABS_X + i) + diff);
> diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
> index 3cd84d2..2f7355e 100644
> --- a/drivers/input/misc/uinput.c
> +++ b/drivers/input/misc/uinput.c
> @@ -311,7 +311,7 @@ static int uinput_validate_absbits(struct input_dev *dev)
> unsigned int cnt;
> int retval = 0;
>
> - for (cnt = 0; cnt < ABS_CNT; cnt++) {
> + for (cnt = 0; cnt < ABS_CNT2; cnt++) {
> int min, max;
> if (!test_bit(cnt, dev->absbit))
> continue;
> @@ -474,7 +474,7 @@ static int uinput_setup_device2(struct uinput_device *udev,
> return -EINVAL;
>
> /* rough check to avoid huge kernel space allocations */
> - max = ABS_CNT * sizeof(*user_dev2->abs) + sizeof(*user_dev2);
> + max = ABS_CNT2 * sizeof(*user_dev2->abs) + sizeof(*user_dev2);
> if (count > max)
> return -EINVAL;
>
> @@ -770,7 +770,7 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
> break;
>
> case UI_SET_ABSBIT:
> - retval = uinput_set_bit(arg, absbit, ABS_MAX);
> + retval = uinput_set_bit(arg, absbit, ABS_MAX2);
> break;
>
> case UI_SET_MSCBIT:
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index 31b9d29..c21d8bb 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -828,7 +828,7 @@ static inline void hid_map_usage(struct hid_input *hidinput,
> switch (type) {
> case EV_ABS:
> *bit = input->absbit;
> - *max = ABS_MAX;
> + *max = ABS_MAX2;
> break;
> case EV_REL:
> *bit = input->relbit;
> diff --git a/include/linux/input.h b/include/linux/input.h
> index 82ce323..c6add6f 100644
> --- a/include/linux/input.h
> +++ b/include/linux/input.h
> @@ -129,7 +129,7 @@ struct input_dev {
> unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
> unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
> unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
> - unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
> + unsigned long absbit[BITS_TO_LONGS(ABS_CNT2)];
> unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
> unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
> unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
> @@ -210,8 +210,8 @@ struct input_dev {
> #error "REL_MAX and INPUT_DEVICE_ID_REL_MAX do not match"
> #endif
>
> -#if ABS_MAX != INPUT_DEVICE_ID_ABS_MAX
> -#error "ABS_MAX and INPUT_DEVICE_ID_ABS_MAX do not match"
> +#if ABS_MAX2 != INPUT_DEVICE_ID_ABS_MAX
> +#error "ABS_MAX2 and INPUT_DEVICE_ID_ABS_MAX do not match"
> #endif
>
> #if MSC_MAX != INPUT_DEVICE_ID_MSC_MAX
> diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
> index a372627..9e525f9 100644
> --- a/include/uapi/linux/input.h
> +++ b/include/uapi/linux/input.h
> @@ -74,6 +74,27 @@ struct input_absinfo {
> };
>
> /**
> + * struct input_absinfo2 - used by EVIOC[G/S]ABS2 ioctls
> + * @code: First ABS code to query
> + * @cnt: Number of ABS codes to query starting at @code
> + * @info: #@cnt absinfo structures to get/set abs parameters for all codes
> + *
> + * This structure is used by the new EVIOC[G/S]ABS2 ioctls which
> + * do the same as the old EVIOC[G/S]ABS ioctls but avoid encoding
> + * the ABS code in the ioctl number. This allows a much wider
> + * range of ABS codes. Furthermore, it allows to query multiple codes with a
> + * single call.
> + *
> + * Note that this silently drops any requests to set ABS_MT_SLOT. Hence, it is
> + * allowed to call this with code=0 cnt=ABS_CNT2.
> + */
> +struct input_absinfo2 {
> + __u32 code;
> + __u32 cnt;
> + struct input_absinfo info[1];
> +};
> +
> +/**
> * struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
> * @scancode: scancode represented in machine-endian form.
> * @len: length of the scancode that resides in @scancode buffer.
> @@ -153,6 +174,8 @@ struct input_keymap_entry {
>
> #define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
> #define EVIOCREVOKE _IOW('E', 0x91, int) /* Revoke device access */
> +#define EVIOCGABS2 _IOR('E', 0x92, struct input_absinfo2) /* get abs value/limits */
> +#define EVIOCSABS2 _IOW('E', 0x93, struct input_absinfo2) /* set abs value/limits */
>
> #define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
>
> @@ -832,11 +855,23 @@ struct input_keymap_entry {
> #define ABS_MT_TOOL_X 0x3c /* Center X tool position */
> #define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
>
> -
> +/*
> + * ABS_MAX/CNT is limited to a maximum of 0x3f due to the design of EVIOCGABS
> + * and EVIOCSABS ioctls. Other kernel APIs like uinput also hardcoded it. Do
> + * not modify this value and instead use the extended ABS_MAX2/CNT2 API.
> + */
> #define ABS_MAX 0x3f
> #define ABS_CNT (ABS_MAX+1)
>
> /*
> + * Due to API restrictions the legacy evdev API only supports ABS values up to
> + * ABS_MAX/CNT. Use the extended *ABS2 ioctls to operate on any ABS values in
> + * between ABS_MAX and ABS_MAX2.
> + */
> +#define ABS_MAX2 0x3f
> +#define ABS_CNT2 (ABS_MAX2+1)
> +
> +/*
> * Switch events
> */
>
> diff --git a/include/uapi/linux/uinput.h b/include/uapi/linux/uinput.h
> index c2e8710..27ee521 100644
> --- a/include/uapi/linux/uinput.h
> +++ b/include/uapi/linux/uinput.h
> @@ -140,7 +140,7 @@ struct uinput_user_dev2 {
> char name[UINPUT_MAX_NAME_SIZE];
> struct input_id id;
> __u32 ff_effects_max;
> - struct input_absinfo abs[ABS_CNT];
> + struct input_absinfo abs[ABS_CNT2];
> };
>
> #endif /* _UAPI__UINPUT_H_ */
> --
> 1.8.4.1
>
^ permalink raw reply
* [PATCH] Input: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:54 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
drivers/input/touchscreen/cyttsp4_spi.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c
index a71e114..b19434c 100644
--- a/drivers/input/touchscreen/cyttsp4_spi.c
+++ b/drivers/input/touchscreen/cyttsp4_spi.c
@@ -171,10 +171,7 @@ static int cyttsp4_spi_probe(struct spi_device *spi)
ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq,
CY_SPI_DATA_BUF_SIZE);
- if (IS_ERR(ts))
- return PTR_ERR(ts);
-
- return 0;
+ return PTR_ERR_OR_ZERO(ts);
}
static int cyttsp4_spi_remove(struct spi_device *spi)
--
1.8.3.1
^ permalink raw reply related
* [PATCH] leds: leds-mc13783: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:54 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
arch/arm/mach-imx/mach-mx31moboard.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index 6f424ec..118ea68 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -446,10 +446,7 @@ static int __init moboard_usbh2_init(void)
return -ENODEV;
pdev = imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- return 0;
+ return PTR_ERR_OR_ZERO(pdev);
}
static const struct gpio_led mx31moboard_leds[] __initconst = {
--
1.8.3.1
^ permalink raw reply related
* [PATCH] libcrc32c: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:55 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
lib/libcrc32c.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lib/libcrc32c.c b/lib/libcrc32c.c
index 244f548..b3131f5 100644
--- a/lib/libcrc32c.c
+++ b/lib/libcrc32c.c
@@ -62,10 +62,7 @@ EXPORT_SYMBOL(crc32c);
static int __init libcrc32c_mod_init(void)
{
tfm = crypto_alloc_shash("crc32c", 0, 0);
- if (IS_ERR(tfm))
- return PTR_ERR(tfm);
-
- return 0;
+ return PTR_ERR_OR_ZERO(tfm);
}
static void __exit libcrc32c_mod_fini(void)
--
1.8.3.1
^ permalink raw reply related
* [PATCH] block: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:55 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov, axboe
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
devel, Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
block/blk-timeout.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index 4e9cfd1..cdf5711 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -32,7 +32,7 @@ static int __init fail_io_timeout_debugfs(void)
struct dentry *dir = fault_create_debugfs_attr("fail_io_timeout",
NULL, &fail_io_timeout);
- return IS_ERR(dir) ? PTR_ERR(dir) : 0;
+ return PTR_ERR_OR_ZERO(dir);
}
late_initcall(fail_io_timeout_debugfs);
--
1.8.3.1
^ permalink raw reply related
* [PATCH] block: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:57 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov, axboe
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
devel, Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
block/ioctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/ioctl.c b/block/ioctl.c
index a31d91d..7d5c3b2 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -64,7 +64,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
part = add_partition(disk, partno, start, length,
ADDPART_FLAG_NONE, NULL);
mutex_unlock(&bdev->bd_mutex);
- return IS_ERR(part) ? PTR_ERR(part) : 0;
+ return PTR_ERR_OR_ZERO(part);
case BLKPG_DEL_PARTITION:
part = disk_get_part(disk, partno);
if (!part)
--
1.8.3.1
^ permalink raw reply related
* [PATCH] smsc: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:57 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov, axboe
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
devel, netdev, Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
drivers/net/ethernet/smsc/smc9194.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c
index 6f3491f..67d9fde 100644
--- a/drivers/net/ethernet/smsc/smc9194.c
+++ b/drivers/net/ethernet/smsc/smc9194.c
@@ -1545,9 +1545,7 @@ int __init init_module(void)
/* copy the parameters from insmod into the device structure */
devSMC9194 = smc_init(-1);
- if (IS_ERR(devSMC9194))
- return PTR_ERR(devSMC9194);
- return 0;
+ return PTR_ERR_OR_ZERO(devSMC9194);
}
void __exit cleanup_module(void)
--
1.8.3.1
^ permalink raw reply related
* [PATCH] lustre/fld: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:55 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
devel, Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
drivers/staging/lustre/lustre/fld/fld_request.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c
index e47fd50..3191a39 100644
--- a/drivers/staging/lustre/lustre/fld/fld_request.c
+++ b/drivers/staging/lustre/lustre/fld/fld_request.c
@@ -504,10 +504,7 @@ static int __init fld_mod_init(void)
fld_type_proc_dir = lprocfs_register(LUSTRE_FLD_NAME,
proc_lustre_root,
NULL, NULL);
- if (IS_ERR(fld_type_proc_dir))
- return PTR_ERR(fld_type_proc_dir);
-
- return 0;
+ return PTR_ERR_OR_ZERO(fld_type_proc_dir);
}
static void __exit fld_mod_exit(void)
--
1.8.3.1
^ permalink raw reply related
* [PATCH] block: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:56 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov, axboe
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
devel, Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
block/blk-timeout.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index 4e9cfd1..cdf5711 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -32,7 +32,7 @@ static int __init fail_io_timeout_debugfs(void)
struct dentry *dir = fault_create_debugfs_attr("fail_io_timeout",
NULL, &fail_io_timeout);
- return IS_ERR(dir) ? PTR_ERR(dir) : 0;
+ return PTR_ERR_OR_ZERO(dir);
}
late_initcall(fail_io_timeout_debugfs);
--
1.8.3.1
^ permalink raw reply related
* [PATCH] block: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:56 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov, axboe
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
devel, Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
block/ioctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/ioctl.c b/block/ioctl.c
index a31d91d..7d5c3b2 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -64,7 +64,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
part = add_partition(disk, partno, start, length,
ADDPART_FLAG_NONE, NULL);
mutex_unlock(&bdev->bd_mutex);
- return IS_ERR(part) ? PTR_ERR(part) : 0;
+ return PTR_ERR_OR_ZERO(part);
case BLKPG_DEL_PARTITION:
part = disk_get_part(disk, partno);
if (!part)
--
1.8.3.1
^ permalink raw reply related
* [PATCH] net:drivers/net: replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
From: Duan Jiong @ 2013-11-06 7:58 UTC (permalink / raw)
To: kernel, linux, a.zummo, airlied, dmitry.torokhov, axboe
Cc: linux-kernel, rtc-linux, dri-devel, linux-tegra, linux-input,
devel, netdev, Duan Jiong
This patch fixes coccinelle error regarding usage of IS_ERR and
PTR_ERR instead of PTR_ERR_OR_ZERO.
Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
drivers/net/ethernet/i825xx/82596.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/i825xx/82596.c b/drivers/net/ethernet/i825xx/82596.c
index a15877a..7ce6379 100644
--- a/drivers/net/ethernet/i825xx/82596.c
+++ b/drivers/net/ethernet/i825xx/82596.c
@@ -1527,9 +1527,7 @@ int __init init_module(void)
if (debug >= 0)
i596_debug = debug;
dev_82596 = i82596_probe(-1);
- if (IS_ERR(dev_82596))
- return PTR_ERR(dev_82596);
- return 0;
+ return PTR_ERR_OR_ZERO(dev_82596);
}
void __exit cleanup_module(void)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3] add sur40 driver for Samsung SUR40 (aka MS Surface 2.0/Pixelsense)
From: Florian Echtler @ 2013-11-06 14:26 UTC (permalink / raw)
To: linux-input, benjamin.tissoires, rydberg, dmitry.torokhov,
dh.herrmann
Cc: Florian Echtler
From: "Florian Echtler" <floe@butterbrot.org>
This patch adds support for the built-in multitouch sensor in the Samsung
SUR40 touchscreen device, also known as Microsoft Surface 2.0 or Microsoft
Pixelsense. Support for raw video output from the sensor as well as the
accelerometer will be added in a later patch.
Signed-off-by: Florian Echtler <floe@butterbrot.org>
---
drivers/input/touchscreen/Kconfig | 10 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/sur40.c | 467 ++++++++++++++++++++++++++++++++++++
3 files changed, 478 insertions(+)
create mode 100644 drivers/input/touchscreen/sur40.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 515cfe7..99aaf10 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -876,6 +876,16 @@ config TOUCHSCREEN_STMPE
To compile this driver as a module, choose M here: the
module will be called stmpe-ts.
+config TOUCHSCREEN_SUR40
+ tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
+ depends on USB
+ help
+ Say Y here if you want support for the Samsung SUR40 touchscreen
+ (also known as Microsoft Surface 2.0 or Microsoft PixelSense).
+
+ To compile this driver as a module, choose M here: the
+ module will be called sur40.
+
config TOUCHSCREEN_TPS6507X
tristate "TPS6507x based touchscreens"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 6bfbeab..b63a25d 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
+obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
new file mode 100644
index 0000000..48787fd
--- /dev/null
+++ b/drivers/input/touchscreen/sur40.c
@@ -0,0 +1,467 @@
+/*
+ Surface2.0/SUR40/PixelSense input driver
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ Copyright (c) 2013 by Florian 'floe' Echtler <floe@butterbrot.org>
+
+ Derived from the USB Skeleton driver 1.1,
+ Copyright (c) 2003 Greg Kroah-Hartman (greg@kroah.com)
+
+ and from the Apple USB BCM5974 multitouch driver,
+ Copyright (c) 2008 Henrik Rydberg (rydberg@euromail.se)
+
+ and from the generic hid-multitouch driver,
+ Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
+*/
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/printk.h>
+#include <linux/input-polldev.h>
+#include <linux/input/mt.h>
+#include <linux/usb/input.h>
+
+/* read 512 bytes from endpoint 0x86 -> get header + blobs */
+struct sur40_header {
+
+ __le16 type; /* always 0x0001 */
+ __le16 count; /* count of blobs (if 0: continue prev. packet) */
+
+ __le32 packet_id; /* unique ID for all packets in one frame */
+
+ __le32 timestamp; /* milliseconds (inc. by 16 or 17 each frame) */
+ __le32 unknown; /* "epoch?" always 02/03 00 00 00 */
+
+} __packed;
+
+struct sur40_blob {
+
+ __le16 blob_id;
+
+ __u8 action; /* 0x02 = enter/exit, 0x03 = update (?) */
+ __u8 unknown; /* always 0x01 or 0x02 (no idea what this is?) */
+
+ __le16 bb_pos_x; /* upper left corner of bounding box */
+ __le16 bb_pos_y;
+
+ __le16 bb_size_x; /* size of bounding box */
+ __le16 bb_size_y;
+
+ __le16 pos_x; /* finger tip position */
+ __le16 pos_y;
+
+ __le16 ctr_x; /* centroid position */
+ __le16 ctr_y;
+
+ __le16 axis_x; /* somehow related to major/minor axis, mostly: */
+ __le16 axis_y; /* axis_x == bb_size_y && axis_y == bb_size_x */
+
+ __le32 angle; /* orientation in radians relative to x axis -
+ actually an IEEE754 float, don't use in kernel */
+
+ __le32 area; /* size in pixels/pressure (?) */
+
+ __u8 padding[32];
+
+} __packed;
+
+/* combined header/blob data */
+struct sur40_data {
+ struct sur40_header header;
+ struct sur40_blob blobs[];
+} __packed;
+
+
+/* version information */
+#define DRIVER_SHORT "sur40"
+#define DRIVER_AUTHOR "Florian 'floe' Echtler <floe@butterbrot.org>"
+#define DRIVER_DESC "Surface2.0/SUR40/PixelSense input driver"
+
+/* vendor and device IDs */
+#define ID_MICROSOFT 0x045e
+#define ID_SUR40 0x0775
+
+/* sensor resolution */
+#define SENSOR_RES_X 1920
+#define SENSOR_RES_Y 1080
+
+/* touch data endpoint */
+#define TOUCH_ENDPOINT 0x86
+
+/* polling interval (ms) */
+#define POLL_INTERVAL 10
+
+/* maximum number of contacts FIXME: this is a guess? */
+#define MAX_CONTACTS 64
+
+/* device ID table */
+static const struct usb_device_id sur40_table[] = {
+ {USB_DEVICE(ID_MICROSOFT, ID_SUR40)}, /* Samsung SUR40 */
+ {} /* terminating null entry */
+};
+
+/* control commands */
+#define SUR40_GET_VERSION 0xb0 /* 12 bytes string */
+#define SUR40_UNKNOWN1 0xb3 /* 5 bytes */
+#define SUR40_UNKNOWN2 0xc1 /* 24 bytes */
+
+#define SUR40_GET_STATE 0xc5 /* 4 bytes state (?) */
+#define SUR40_GET_SENSORS 0xb1 /* 8 bytes sensors */
+
+/*
+ * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
+ * here by mistake which is very likely to have corrupted the firmware EEPROM
+ * on two separate SUR40 devices. Thanks to Alan Stern who spotted this bug.
+ * Should you ever run into a similar problem, the background story to this
+ * incident and instructions on how to fix the corrupted EEPROM are available
+ * at https://floe.butterbrot.org/matrix/hacking/surface/brick.html
+*/
+#define sur40_command(dev, command, index, buffer, size) \
+ usb_control_msg(dev->usbdev, usb_rcvctrlpipe(dev->usbdev, 0), \
+ command, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x00, \
+ index, buffer, size, 1000)
+
+MODULE_DEVICE_TABLE(usb, sur40_table);
+
+/* structure to hold all of our device specific stuff */
+struct sur40_state {
+
+ struct usb_device *usbdev; /* save the usb device pointer */
+ struct device *dev; /* save the generic device pointer */
+ struct input_polled_dev *input; /* struct for polled input device */
+
+ struct sur40_data *bulk_in_buffer; /* the buffer to receive data */
+ size_t bulk_in_size; /* the maximum bulk packet size */
+ __u8 bulk_in_epaddr; /* address of the bulk in endpoint */
+
+ char phys[64]; /* buffer for phys name */
+};
+
+/* initialization routine, called from sur40_open */
+static int sur40_init(struct sur40_state *dev)
+{
+ int result;
+ __u8 buffer[24];
+
+ /* stupidly replay the original MS driver init sequence */
+ result = sur40_command(dev, SUR40_GET_VERSION, 0x00, buffer, 12);
+ if (result < 0)
+ return result;
+
+ result = sur40_command(dev, SUR40_GET_VERSION, 0x01, buffer, 12);
+ if (result < 0)
+ return result;
+
+ result = sur40_command(dev, SUR40_GET_VERSION, 0x02, buffer, 12);
+ if (result < 0)
+ return result;
+
+ result = sur40_command(dev, SUR40_UNKNOWN2, 0x00, buffer, 24);
+ if (result < 0)
+ return result;
+
+ result = sur40_command(dev, SUR40_UNKNOWN1, 0x00, buffer, 5);
+ if (result < 0)
+ return result;
+
+ result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12);
+
+ /* discard the result buffer - no known data inside except
+ some version strings, maybe extract these sometime.. */
+
+ return result;
+}
+
+/*
+ * callback routines from input_polled_dev
+*/
+
+/* enable the device, polling will now start */
+void sur40_open(struct input_polled_dev *polldev)
+{
+ struct sur40_state *sur40 = polldev->private;
+ dev_dbg(sur40->dev, "open\n");
+ sur40_init(sur40);
+}
+
+/* disable device, polling has stopped */
+void sur40_close(struct input_polled_dev *polldev)
+{
+ /* no known way to stop the device, except to stop polling */
+ struct sur40_state *sur40 = polldev->private;
+ dev_dbg(sur40->dev, "close\n");
+}
+
+/*
+ * this function is called when a whole contact has been processed,
+ * so that it can assign it to a slot and store the data there
+ */
+static void report_blob(struct sur40_blob *blob, struct input_dev *input)
+{
+ int wide, major, minor;
+
+ int bb_size_x = le16_to_cpu(blob->bb_size_x);
+ int bb_size_y = le16_to_cpu(blob->bb_size_y);
+
+ int pos_x = le16_to_cpu(blob->pos_x);
+ int pos_y = le16_to_cpu(blob->pos_y);
+
+ int ctr_x = le16_to_cpu(blob->ctr_x);
+ int ctr_y = le16_to_cpu(blob->ctr_y);
+
+ int slotnum = input_mt_get_slot_by_key(input, blob->blob_id);
+ if (slotnum < 0 || slotnum >= MAX_CONTACTS)
+ return;
+
+ input_mt_slot(input, slotnum);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
+ wide = (bb_size_x > bb_size_y);
+ major = max(bb_size_x, bb_size_y);
+ minor = min(bb_size_x, bb_size_y);
+
+ input_event(input, EV_ABS, ABS_MT_POSITION_X, pos_x);
+ input_event(input, EV_ABS, ABS_MT_POSITION_Y, pos_y);
+ input_event(input, EV_ABS, ABS_MT_TOOL_X, ctr_x);
+ input_event(input, EV_ABS, ABS_MT_TOOL_Y, ctr_y);
+
+ /* TODO: use a better orientation measure */
+ input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
+ input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+ input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
+}
+
+/* core function: poll for new input data */
+void sur40_poll(struct input_polled_dev *polldev)
+{
+
+ struct sur40_state *sur40 = polldev->private;
+ struct input_dev *input = polldev->input;
+ int result, bulk_read, need_blobs, packet_blobs, i;
+ uint32_t packet_id;
+
+ struct sur40_header *header = &sur40->bulk_in_buffer->header;
+ struct sur40_blob *inblob = &sur40->bulk_in_buffer->blobs[0];
+
+ need_blobs = -1;
+
+ dev_dbg(sur40->dev, "poll\n");
+
+ do {
+
+ /* perform a blocking bulk read to get data from the device */
+ result = usb_bulk_msg(sur40->usbdev,
+ usb_rcvbulkpipe(sur40->usbdev, sur40->bulk_in_epaddr),
+ sur40->bulk_in_buffer, sur40->bulk_in_size,
+ &bulk_read, 1000);
+
+ dev_dbg(sur40->dev, "received %d bytes\n", bulk_read);
+
+ if (result < 0) {
+ dev_err(sur40->dev, "error in usb_bulk_read\n");
+ return;
+ }
+
+ result = bulk_read - sizeof(struct sur40_header);
+
+ if (result % sizeof(struct sur40_blob) != 0) {
+ dev_err(sur40->dev, "transfer size mismatch\n");
+ return;
+ }
+
+ /* first packet? */
+ if (need_blobs == -1) {
+ need_blobs = le16_to_cpu(header->count);
+ dev_dbg(sur40->dev, "need %d blobs\n", need_blobs);
+ packet_id = header->packet_id;
+ }
+
+ /* sanity check. when video data is also being retrieved, the
+ * packet ID will usually increase in the middle of a series
+ * instead of at the end. */
+ if (packet_id != header->packet_id)
+ dev_warn(sur40->dev, "packet ID mismatch\n");
+
+ packet_blobs = result / sizeof(struct sur40_blob);
+ dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs);
+
+ /* packets always contain at least 4 blobs, even if empty */
+ if (packet_blobs > need_blobs)
+ packet_blobs = need_blobs;
+
+ for (i = 0; i < packet_blobs; i++) {
+ need_blobs--;
+ dev_dbg(sur40->dev, "processing blob\n");
+ report_blob(&(inblob[i]), input);
+ }
+
+ } while (need_blobs > 0);
+
+ input_mt_sync_frame(input);
+ input_sync(input);
+}
+
+/*
+ * housekeeping routines
+*/
+
+/* initialize input device parameters */
+static void sur40_input_setup(struct input_dev *input_dev)
+{
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_ABS, input_dev->evbit);
+
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, SENSOR_RES_X, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, SENSOR_RES_Y, 0, 0);
+
+ input_set_abs_params(input_dev, ABS_MT_TOOL_X,
+ 0, SENSOR_RES_X, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOOL_Y,
+ 0, SENSOR_RES_Y, 0, 0);
+
+ /* max value unknown, but major/minor axis
+ * can never be larger than screen */
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, SENSOR_RES_X, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
+ 0, SENSOR_RES_Y, 0, 0);
+
+ input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+
+ input_mt_init_slots(input_dev, MAX_CONTACTS,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+}
+
+/* clean up all allocated buffers/structs */
+static inline void sur40_delete(struct sur40_state *sur40)
+{
+ input_free_polled_device(sur40->input);
+ kfree(sur40->bulk_in_buffer);
+ kfree(sur40);
+}
+
+/* check candidate USB interface */
+static int sur40_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *usbdev = interface_to_usbdev(interface);
+ struct sur40_state *sur40;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ struct input_polled_dev *poll_dev;
+ int result;
+
+ /* check if we really have the right interface */
+ iface_desc = &interface->altsetting[0];
+ if (iface_desc->desc.bInterfaceClass != 0xFF)
+ return -ENODEV;
+
+ /* use endpoint #4 (0x86) */
+ endpoint = &iface_desc->endpoint[4].desc;
+ if (endpoint->bEndpointAddress != TOUCH_ENDPOINT)
+ return -ENODEV;
+
+ /* allocate memory for our device state and initialize it */
+ sur40 = kzalloc(sizeof(struct sur40_state), GFP_KERNEL);
+ if (!sur40)
+ return -ENOMEM;
+
+ poll_dev = input_allocate_polled_device();
+ if (!poll_dev) {
+ result = -ENOMEM;
+ goto err_free_dev;
+ }
+
+ /* setup polled input device control struct */
+ poll_dev->private = sur40;
+ poll_dev->poll_interval = POLL_INTERVAL;
+ poll_dev->open = sur40_open;
+ poll_dev->poll = sur40_poll;
+ poll_dev->close = sur40_close;
+
+ /* setup regular input device struct */
+ sur40_input_setup(poll_dev->input);
+
+ poll_dev->input->name = "Samsung SUR40";
+ usb_to_input_id(usbdev, &(poll_dev->input->id));
+ usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
+ strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
+ poll_dev->input->phys = sur40->phys;
+
+ sur40->usbdev = usbdev;
+ sur40->dev = &usbdev->dev;
+ sur40->input = poll_dev;
+
+ /* use the bulk-in endpoint tested above */
+ sur40->bulk_in_size = usb_endpoint_maxp(endpoint);
+ sur40->bulk_in_epaddr = endpoint->bEndpointAddress;
+ sur40->bulk_in_buffer = kmalloc(sur40->bulk_in_size, GFP_KERNEL);
+ if (!sur40->bulk_in_buffer) {
+ dev_err(&interface->dev, "Unable to allocate input buffer.");
+ result = -ENOMEM;
+ goto err_free_polldev;
+ }
+
+ result = input_register_polled_device(poll_dev);
+ if (result) {
+ dev_err(&interface->dev,
+ "Unable to register polled input device.");
+ goto err_free_buffer;
+ }
+
+ /* we can register the device now, as it is ready */
+ usb_set_intfdata(interface, sur40);
+ dev_dbg(&interface->dev, "%s now attached\n", DRIVER_DESC);
+
+ return 0;
+
+err_free_buffer:
+ kfree(sur40->bulk_in_buffer);
+err_free_polldev:
+ input_free_polled_device(sur40->input);
+err_free_dev:
+ kfree(sur40);
+
+ return result;
+}
+
+/* unregister device & clean up */
+static void sur40_disconnect(struct usb_interface *interface)
+{
+ struct sur40_state *sur40 = usb_get_intfdata(interface);
+
+ input_unregister_polled_device(sur40->input);
+
+ usb_set_intfdata(interface, NULL);
+
+ sur40_delete(sur40);
+
+ dev_dbg(&interface->dev, "%s now disconnected\n", DRIVER_DESC);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver sur40_driver = {
+ .name = DRIVER_SHORT,
+ .probe = sur40_probe,
+ .disconnect = sur40_disconnect,
+ .id_table = sur40_table,
+};
+
+module_usb_driver(sur40_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] Input: Adding support for touchpad on Dell XT2 model
From: Gaspard Jankowiak @ 2013-11-06 15:24 UTC (permalink / raw)
To: Dmitry Torokhov, Yunkang Tang
Cc: cernekee, dturvene, linux-input, ndevos, jclift, yunkang.tang
In-Reply-To: <20131031075613.GA2590@core.coreip.homeip.net>
On 31/10/13 08:56, Dmitry Torokhov wrote:
>
> Applied, thank you.
>
Hi,
I don't know how to go about this, but it seems the patch is affecting
other input devices. The trackpoint goes haywire when used, making the
cursor jump all over the place and triggering random "right clicks" on
the Latitude XT2. I don't know if it affects other models too.
Sorry for not spotting this earlier.
Name : kernel
Version : 3.11.6
Release : 201.fc19
Architecture: x86_64
Install Date: Tue 05 Nov 2013 09:22:37 CET
Group : System Environment/Kernel
Size : 134433560
License : GPLv2 and Redistributable, no modification permitted
Signature : RSA/SHA256, Sat 02 Nov 2013 22:00:51 CET, Key ID
07477e65fb4b18e6
Source RPM : kernel-3.11.6-201.fc19.src.rpm
Build Date : Sat 02 Nov 2013 15:35:07 CET
Best,
Gaspard
^ permalink raw reply
* Re: [appleir] BUG: unable to handle kernel NULL pointer dereference
From: Jiri Kosina @ 2013-11-06 15:38 UTC (permalink / raw)
To: Luis Henriques
Cc: Benjamin Tissoires, linux-kernel, linux-input, James Henstridge,
Fabien André, Bastien Nocera
In-Reply-To: <20131029145139.GA2788@hercules>
On Tue, 29 Oct 2013, Luis Henriques wrote:
> James has reported a NULL pointer dereference[1] on the appleir
> driver. From the bug report[2] it looks like it is 100%
> reproducible using a 3.12-rc6 kernel simply by pressing any button on
> the IR remote.
>
> >From the stack trace, it looks like input_event is invoked with the
> input_dev parameter set to NULL, which seems to indicate that
> appleir_input_configured is never invoked.
>
> Any ideas?
>
> [1] https://launchpadlibrarian.net/154942024/macmini-oops.jpg
> [2] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1244505
[ adding some more CCs ]
Okay, so apparently we didn't register with input, but only hiddev /
hidraw.
appleir 0003:05AC:8240.0005: hiddev0,hidraw4: USB HID v1.11 Device [Apple Computer, Inc. IR Receiver] on usb-0000:00:1d.3-2/input0
Therefore ->input_configured() callback has never been called, and thus we
oops due to appleir->input_dev being NULL when the first raw event is
reported.
Could you please provide report descriptor of the device?
The driver apparently relies on it being registered with hid-input, but
for some reason that doesn't happen.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [appleir] BUG: unable to handle kernel NULL pointer dereference
From: Bastien Nocera @ 2013-11-06 17:13 UTC (permalink / raw)
To: Jiri Kosina
Cc: Luis Henriques, Benjamin Tissoires, linux-kernel, linux-input,
James Henstridge, Fabien André
In-Reply-To: <alpine.LNX.2.00.1311061635160.835@pobox.suse.cz>
On Wed, 2013-11-06 at 16:38 +0100, Jiri Kosina wrote:
> On Tue, 29 Oct 2013, Luis Henriques wrote:
>
> > James has reported a NULL pointer dereference[1] on the appleir
> > driver. From the bug report[2] it looks like it is 100%
> > reproducible using a 3.12-rc6 kernel simply by pressing any button on
> > the IR remote.
> >
> > >From the stack trace, it looks like input_event is invoked with the
> > input_dev parameter set to NULL, which seems to indicate that
> > appleir_input_configured is never invoked.
> >
> > Any ideas?
> >
> > [1] https://launchpadlibrarian.net/154942024/macmini-oops.jpg
> > [2] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1244505
>
> [ adding some more CCs ]
>
> Okay, so apparently we didn't register with input, but only hiddev /
> hidraw.
>
> appleir 0003:05AC:8240.0005: hiddev0,hidraw4: USB HID v1.11 Device [Apple Computer, Inc. IR Receiver] on usb-0000:00:1d.3-2/input0
>
> Therefore ->input_configured() callback has never been called, and thus we
> oops due to appleir->input_dev being NULL when the first raw event is
> reported.
>
> Could you please provide report descriptor of the device?
>
> The driver apparently relies on it being registered with hid-input, but
> for some reason that doesn't happen.
FWIW, my original patch (and driver) was an input driver, not a hid one.
I'm not sure either how the new driver got tested.
^ permalink raw reply
* [PATCH 1/5] HID:hid-lg4ff: Scale autocentering force properly on Logitech wheel
From: Simon Wood @ 2013-11-06 19:30 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, linux-kernel, simon, Elias Vanderstuyft,
Michal Malý
Adjust the scaling and lineartity to match that of the Windows
driver (from MOMO testing).
Reported-by: Elias Vanderstuyft <elias.vds@gmail.com>
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 8782fe1..530fcd19 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -218,12 +218,21 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
__s32 *value = report->field[0]->value;
+ __u32 expand_a, expand_b;
+
+ if (magnitude <= 0xaaaa) {
+ expand_a = 0x0c * magnitude;
+ expand_b = 0x80 * magnitude;
+ } else {
+ expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa);
+ expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa);
+ }
value[0] = 0xfe;
value[1] = 0x0d;
- value[2] = magnitude >> 13;
- value[3] = magnitude >> 13;
- value[4] = magnitude >> 8;
+ value[2] = expand_a / 0xaaaa;
+ value[3] = expand_a / 0xaaaa;
+ value[4] = expand_b / 0xaaaa;
value[5] = 0x00;
value[6] = 0x00;
--
1.8.1.2
^ permalink raw reply related
* [PATCH 2/5] HID:hid-lg4ff: Switch autocentering off when strength is set to zero.
From: Simon Wood @ 2013-11-06 19:30 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, linux-kernel, simon, Elias Vanderstuyft,
Michal Malý
In-Reply-To: <1383766244-2336-1-git-send-email-simon@mungewell.org>
When the autocenter is set to zero, this patch issues a command to
totally disable the autocenter - this results in less resistance
in the wheel.
Reported-by: Elias Vanderstuyft <elias.vds@gmail.com>
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 530fcd19..49f6cc0 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -220,6 +220,20 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
__s32 *value = report->field[0]->value;
__u32 expand_a, expand_b;
+ /* De-activate Auto-Center */
+ if (magnitude == 0) {
+ value[0] = 0xf5;
+ value[1] = 0x00;
+ value[2] = 0x00;
+ value[3] = 0x00;
+ value[4] = 0x00;
+ value[5] = 0x00;
+ value[6] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+ return;
+ }
+
if (magnitude <= 0xaaaa) {
expand_a = 0x0c * magnitude;
expand_b = 0x80 * magnitude;
@@ -237,6 +251,17 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
value[6] = 0x00;
hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+
+ /* Activate Auto-Center */
+ value[0] = 0x14;
+ value[1] = 0x00;
+ value[2] = 0x00;
+ value[3] = 0x00;
+ value[4] = 0x00;
+ value[5] = 0x00;
+ value[6] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
}
/* Sends autocentering command compatible with Formula Force EX */
--
1.8.1.2
^ permalink raw reply related
* [PATCH 3/5] HID:hid-lg4ff: ensure ConstantForce is disabled when set to 0
From: Simon Wood @ 2013-11-06 19:30 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, linux-kernel, simon, Elias Vanderstuyft,
Michal Malý
In-Reply-To: <1383766244-2336-1-git-send-email-simon@mungewell.org>
When 'Constant Force' is set to 0 it is not turned off completely,
the wheel feels 'heavy'. This patch issues the '13 00..' command
to ensure that the force in slot 1 (the Constant Force) is
deactivated.
Reported-by: Elias Vanderstuyft <elias.vds@gmail.com>
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 49f6cc0..5d140b7 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -196,6 +196,21 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e
case FF_CONSTANT:
x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */
CLAMP(x);
+
+ if (x == 0x80) {
+ /* De-activate force in slot-1*/
+ value[0] = 0x13;
+ value[1] = 0x00;
+ value[2] = 0x00;
+ value[3] = 0x00;
+ value[4] = 0x00;
+ value[5] = 0x00;
+ value[6] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+ return 0;
+ }
+
value[0] = 0x11; /* Slot 1 */
value[1] = 0x08;
value[2] = x;
--
1.8.1.2
^ permalink raw reply related
* [PATCH 5/5] HID:hid-lg4ff: Correct Auto-center strength for wheels other than MOMO and MOMO2
From: Simon Wood @ 2013-11-06 19:30 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, linux-kernel, simon, Elias Vanderstuyft,
Michal Malý
In-Reply-To: <1383766244-2336-1-git-send-email-simon@mungewell.org>
The MOMO and MOMO2 wheels have a slightly different autocenter command,
and accept values in the range 0..F (rather than 0..7 for the other wheels).
This patch uses the product ID to determine how to compute the strength.
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 5492809..befe0e3 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -234,6 +234,20 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
__s32 *value = report->field[0]->value;
__u32 expand_a, expand_b;
+ struct lg4ff_device_entry *entry;
+ struct lg_drv_data *drv_data;
+
+ drv_data = hid_get_drvdata(hid);
+ if (!drv_data) {
+ hid_err(hid, "Private driver data not found!\n");
+ return;
+ }
+
+ entry = drv_data->device_props;
+ if (!entry) {
+ hid_err(hid, "Device properties not found!\n");
+ return;
+ }
/* De-activate Auto-Center */
if (magnitude == 0) {
@@ -257,6 +271,16 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa);
}
+ /* Adjust for non-MOMO wheels */
+ switch (entry->product_id) {
+ case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
+ case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+ break;
+ default:
+ expand_a = expand_a >> 1;
+ break;
+ }
+
value[0] = 0xfe;
value[1] = 0x0d;
value[2] = expand_a / 0xaaaa;
--
1.8.1.2
^ permalink raw reply related
* [PATCH 4/5] HID:hid-lg4ff: Initialize device properties before we touch autocentering.
From: Simon Wood @ 2013-11-06 19:30 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, linux-kernel, simon, Elias Vanderstuyft,
Michal Malý
In-Reply-To: <1383766244-2336-1-git-send-email-simon@mungewell.org>
Re-arrange code slightly to ensure that device properties are configured
before calling auto-center command.
Reported-by: Michal Malý <madcatxster@prifuk.cz>
Signed-off-by: Simon Wood <simon@mungewell.org>
---
drivers/hid/hid-lg4ff.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 5d140b7..5492809 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -589,17 +589,6 @@ int lg4ff_init(struct hid_device *hid)
if (error)
return error;
- /* Check if autocentering is available and
- * set the centering force to zero by default */
- if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
- if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */
- dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
- else
- dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
-
- dev->ff->set_autocenter(dev, 0);
- }
-
/* Get private driver data */
drv_data = hid_get_drvdata(hid);
if (!drv_data) {
@@ -620,6 +609,17 @@ int lg4ff_init(struct hid_device *hid)
entry->max_range = lg4ff_devices[i].max_range;
entry->set_range = lg4ff_devices[i].set_range;
+ /* Check if autocentering is available and
+ * set the centering force to zero by default */
+ if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+ if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */
+ dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
+ else
+ dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
+
+ dev->ff->set_autocenter(dev, 0);
+ }
+
/* Create sysfs interface */
error = device_create_file(&hid->dev, &dev_attr_range);
if (error)
--
1.8.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [appleir] BUG: unable to handle kernel NULL pointer dereference
From: James Henstridge @ 2013-11-07 7:52 UTC (permalink / raw)
To: Jiri Kosina
Cc: Luis Henriques, Benjamin Tissoires, linux-kernel, linux-input,
Fabien André, Bastien Nocera
In-Reply-To: <alpine.LNX.2.00.1311061635160.835@pobox.suse.cz>
On Wed, Nov 6, 2013 at 11:38 PM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Tue, 29 Oct 2013, Luis Henriques wrote:
>
>> James has reported a NULL pointer dereference[1] on the appleir
>> driver. From the bug report[2] it looks like it is 100%
>> reproducible using a 3.12-rc6 kernel simply by pressing any button on
>> the IR remote.
>>
>> >From the stack trace, it looks like input_event is invoked with the
>> input_dev parameter set to NULL, which seems to indicate that
>> appleir_input_configured is never invoked.
>>
>> Any ideas?
>>
>> [1] https://launchpadlibrarian.net/154942024/macmini-oops.jpg
>> [2] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1244505
>
> [ adding some more CCs ]
>
> Okay, so apparently we didn't register with input, but only hiddev /
> hidraw.
>
> appleir 0003:05AC:8240.0005: hiddev0,hidraw4: USB HID v1.11 Device [Apple Computer, Inc. IR Receiver] on usb-0000:00:1d.3-2/input0
>
> Therefore ->input_configured() callback has never been called, and thus we
> oops due to appleir->input_dev being NULL when the first raw event is
> reported.
>
> Could you please provide report descriptor of the device?
>
> The driver apparently relies on it being registered with hid-input, but
> for some reason that doesn't happen.
Here is the relevant lsusb output that I think contains what you're
asking for (I had to unbind usbhid for it to include the descriptor):
Bus 005 Device 003: ID 05ac:8240 Apple, Inc. Built-in IR Receiver
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x05ac Apple, Inc.
idProduct 0x8240 Built-in IR Receiver
bcdDevice 1.10
iManufacturer 1 Apple Computer, Inc.
iProduct 2 IR Receiver
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 41
Report Descriptor: (length is 41)
Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x04 ] 4
Item(Global): Report ID, data= [ 0x24 ] 36
Item(Local ): Usage, data= [ 0x00 ] 0
(null)
Item(Main ): Input, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position
Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x04 ] 4
Item(Global): Report ID, data= [ 0x25 ] 37
Item(Local ): Usage, data= [ 0x00 ] 0
(null)
Item(Main ): Input, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position
Non_Volatile Bitfield
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x04 ] 4
Item(Global): Report ID, data= [ 0x26 ] 38
Item(Local ): Usage, data= [ 0x00 ] 0
(null)
Item(Main ): Input, data= [ 0x22 ] 34
Data Variable Absolute No_Wrap Linear
No_Preferred_State No_Null_Position
Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 10
Device Status: 0x0000
(Bus Powered)
James.
^ 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