From 597b49ec6f19b6df975e2101c42b7b1cfe168280 Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Wed, 26 May 2010 20:50:50 +0200 Subject: [PATCH 01/16] HID: roccat: remove obsolete comment Removed comment that is obsolete since roccat char device is implemented Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat-kone.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 17f2dc04f883..3e5b5534f2ed 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -22,11 +22,6 @@ * Is it possible to remove and reinstall the urb in raw-event- or any * other handler, or to defer this action to be executed somewhere else? * - * TODO implement notification mechanism for overlong macro execution - * If user wants to execute an overlong macro only the names of macroset - * and macro are given. Should userland tap hidraw or is there an - * additional streaming mechanism? - * * TODO is it possible to overwrite group for sysfs attributes via udev? */ From 22d515723ff1d92eea4d7537a3f8d7674080422b Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Wed, 26 May 2010 20:51:28 +0200 Subject: [PATCH 02/16] HID: roccat: fix whitespace warning from checkpatch.pl Fixed the following warning of checkpatch.pl: WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h index d8aae0c1fa7e..09e864e9f79d 100644 --- a/drivers/hid/hid-roccat.h +++ b/drivers/hid/hid-roccat.h @@ -15,7 +15,7 @@ #include #include -#if defined(CONFIG_HID_ROCCAT) || defined (CONFIG_HID_ROCCAT_MODULE) +#if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE) int roccat_connect(struct hid_device *hid); void roccat_disconnect(int minor); int roccat_report_event(int minor, u8 const *data, int len); From 33ccbc320fc38094128c68b2ee0b305884965bd4 Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Wed, 26 May 2010 20:52:43 +0200 Subject: [PATCH 03/16] HID: roccat: change kone_driver_version to kone_abi_version Renamed the sysfs attribute kone_driver_version to kone_abi_version and simplified returned data to integer. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- .../ABI/testing/sysfs-driver-hid-roccat-kone | 7 +++---- drivers/hid/hid-roccat-kone.c | 12 ++++++------ drivers/hid/hid-roccat-kone.h | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone index 88340a23ce91..36bfa234f1e2 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone @@ -33,11 +33,10 @@ Description: When read, this file returns the raw integer version number of the left. E.g. a returned value of 138 means 1.38 This file is readonly. -What: /sys/bus/usb/devices/-:./kone_driver_version -Date: March 2010 +What: /sys/bus/usb/devices/-:./kone_abi_version +Date: May 2010 Contact: Stefan Achatz -Description: When read, this file returns the driver version. - The format of the string is "v..". +Description: When read, this file returns the abi version as an integer value. This attribute is used by the userland tools to find the sysfs- paths of installed kone-mice and determine the capabilites of the driver. Versions of this driver for old kernels replace diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 3e5b5534f2ed..0ab1df9d68ab 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -621,12 +621,12 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev, * This file is used by userland software to find devices that are handled by * this driver. This provides a consistent way for actual and older kernels * where this driver replaced usbhid instead of generic-usb. - * Driver capabilities are determined by version number. + * Driver capabilities are determined by returned number. */ -static ssize_t kone_sysfs_show_driver_version(struct device *dev, +static ssize_t kone_sysfs_show_abi_version(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, ROCCAT_KONE_DRIVER_VERSION "\n"); + return snprintf(buf, PAGE_SIZE, ROCCAT_KONE_ABI_VERSION "\n"); } /* @@ -666,8 +666,8 @@ static DEVICE_ATTR(startup_profile, 0660, kone_sysfs_show_startup_profile, kone_sysfs_set_startup_profile); -static DEVICE_ATTR(kone_driver_version, 0440, - kone_sysfs_show_driver_version, NULL); +static DEVICE_ATTR(kone_abi_version, 0440, + kone_sysfs_show_abi_version, NULL); static struct attribute *kone_attributes[] = { &dev_attr_actual_dpi.attr, @@ -676,7 +676,7 @@ static struct attribute *kone_attributes[] = { &dev_attr_firmware_version.attr, &dev_attr_tcu.attr, &dev_attr_startup_profile.attr, - &dev_attr_kone_driver_version.attr, + &dev_attr_kone_abi_version.attr, NULL }; diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 003e6f81c195..71b14fa40dce 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h @@ -14,7 +14,7 @@ #include -#define ROCCAT_KONE_DRIVER_VERSION "v0.3.1" +#define ROCCAT_KONE_ABI_VERSION "1" #pragma pack(push) #pragma pack(1) From dfe5c7b7e710d8ed885068b0fcfa6f66ab685592 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 1 Jun 2010 16:35:15 +0200 Subject: [PATCH 04/16] HID: roccat: introduce missing kfree Error handling code following a kmalloc should free the allocated data. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,f1,l; position p1,p2; expression *ptr != NULL; @@ x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S <... when != x when != if (...) { <+...x...+> } ( x->f1 = E | (x->f1 == NULL || ...) | f(...,x->f1,...) ) ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index e05d48edb66f..f6e80c7ca61e 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -168,7 +168,7 @@ static int roccat_open(struct inode *inode, struct file *file) printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", minor); error = -ENODEV; - goto exit_unlock; + goto exit_err; } if (!device->open++) { @@ -178,7 +178,7 @@ static int roccat_open(struct inode *inode, struct file *file) PM_HINT_FULLON); if (error < 0) { --device->open; - goto exit_unlock; + goto exit_err; } } error = device->hid->ll_driver->open(device->hid); @@ -187,7 +187,7 @@ static int roccat_open(struct inode *inode, struct file *file) device->hid->ll_driver->power(device->hid, PM_HINT_NORMAL); --device->open; - goto exit_unlock; + goto exit_err; } } @@ -202,6 +202,9 @@ exit_unlock: mutex_unlock(&device->readers_lock); mutex_unlock(&devices_lock); return error; +exit_err: + kfree(reader); + goto exit_unlock; } static int roccat_release(struct inode *inode, struct file *file) From ef566d30a702cc9b49d24edc4ad45c62208a4f5d Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Wed, 2 Jun 2010 10:28:25 -0400 Subject: [PATCH 05/16] HID: magicmouse: scroll on entire surface, not just middle of mouse Previously, scroll events only occurred when the user moved a touch along the middle of the touch surface. This is unintuitive for a normal user who is not aware of this. The device has a uniform surface, so the distinction is artificial. This change removes the touch area check for a scroll event, which replicates the OS X behavior. Signed-off-by: Chase Douglas Acked-by: Michael Poole Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index f10d56a15f21..cd706354496a 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -160,10 +160,9 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda msc->touches[id].size = misc & 63; /* If requested, emulate a scroll wheel by detecting small - * vertical touch motions along the middle of the mouse. + * vertical touch motions. */ - if (emulate_scroll_wheel && - middle_button_start < x && x < middle_button_stop) { + if (emulate_scroll_wheel) { static const int accel_profile[] = { 256, 228, 192, 160, 128, 96, 64, 32, }; From 9846f350ef4d4108c1154acfc125fe8d8630ef84 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Wed, 2 Jun 2010 10:28:27 -0400 Subject: [PATCH 06/16] HID: magicmouse: disable and add module param for scroll acceleration Scroll acceleration is unique to the magicmouse driver, and is unintuitive to a user who is unaware of the functionality. Thus, disable it by default, but add a module parameter to enable it for power users who want it. Signed-off-by: Chase Douglas Acked-by: Michael Poole Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index cd706354496a..4c4a79c760a2 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -30,6 +30,10 @@ static bool emulate_scroll_wheel = true; module_param(emulate_scroll_wheel, bool, 0644); MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); +static bool scroll_acceleration = false; +module_param(scroll_acceleration, bool, 0644); +MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); + static bool report_touches = true; module_param(report_touches, bool, 0644); MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)"); @@ -177,7 +181,9 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda switch (tdata[7] & TOUCH_STATE_MASK) { case TOUCH_STATE_START: msc->touches[id].scroll_y = y; - msc->scroll_accel = min_t(int, msc->scroll_accel + 1, + if (scroll_acceleration) + msc->scroll_accel = min_t(int, + msc->scroll_accel + 1, ARRAY_SIZE(accel_profile) - 1); break; case TOUCH_STATE_DRAG: From cab6b16aca4ac12f731a523fe14770add2f9394a Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Sun, 20 Jun 2010 19:19:06 +0200 Subject: [PATCH 07/16] HID: roccat: fix offset errors in bin_attribute read Fixing wrong calculated offsets in bin_attribute read functions. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat-kone.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 0ab1df9d68ab..2aef6e4caf43 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -272,7 +272,7 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, count = sizeof(struct kone_settings) - off; mutex_lock(&kone->kone_lock); - memcpy(buf, &kone->settings + off, count); + memcpy(buf, ((char const *)&kone->settings) + off, count); mutex_unlock(&kone->kone_lock); return count; @@ -332,7 +332,7 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj, count = sizeof(struct kone_profile) - off; mutex_lock(&kone->kone_lock); - memcpy(buf, &kone->profiles[number - 1], sizeof(struct kone_profile)); + memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count); mutex_unlock(&kone->kone_lock); return count; From 0b3fa399bef02f3658295f8dd334fc26a59c3a95 Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Fri, 18 Jun 2010 16:42:25 +0200 Subject: [PATCH 08/16] HID: roccat: remove obsolete kone_abi_version sysfs attribute The newest version of the accompanying userland tools cuts backward compatibility and uses libudev to find its devices superseding the quirky kone_abi_version sysfs attribute. Therefore it should be removed. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- .../ABI/testing/sysfs-driver-hid-roccat-kone | 12 ------------ drivers/hid/hid-roccat-kone.c | 16 ---------------- drivers/hid/hid-roccat-kone.h | 2 -- 3 files changed, 30 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone index 36bfa234f1e2..063bda7fe707 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone @@ -33,18 +33,6 @@ Description: When read, this file returns the raw integer version number of the left. E.g. a returned value of 138 means 1.38 This file is readonly. -What: /sys/bus/usb/devices/-:./kone_abi_version -Date: May 2010 -Contact: Stefan Achatz -Description: When read, this file returns the abi version as an integer value. - This attribute is used by the userland tools to find the sysfs- - paths of installed kone-mice and determine the capabilites of - the driver. Versions of this driver for old kernels replace - usbhid instead of generic-usb. The way to scan for this file - has been chosen to provide a consistent way for all supported - kernel versions. - This file is readonly. - What: /sys/bus/usb/devices/-:./profile[1-5] Date: March 2010 Contact: Stefan Achatz diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 2aef6e4caf43..f77695762cb5 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -617,18 +617,6 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev, return size; } -/* - * This file is used by userland software to find devices that are handled by - * this driver. This provides a consistent way for actual and older kernels - * where this driver replaced usbhid instead of generic-usb. - * Driver capabilities are determined by returned number. - */ -static ssize_t kone_sysfs_show_abi_version(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, ROCCAT_KONE_ABI_VERSION "\n"); -} - /* * Read actual dpi settings. * Returns raw value for further processing. Refer to enum kone_polling_rates to @@ -666,9 +654,6 @@ static DEVICE_ATTR(startup_profile, 0660, kone_sysfs_show_startup_profile, kone_sysfs_set_startup_profile); -static DEVICE_ATTR(kone_abi_version, 0440, - kone_sysfs_show_abi_version, NULL); - static struct attribute *kone_attributes[] = { &dev_attr_actual_dpi.attr, &dev_attr_actual_profile.attr, @@ -676,7 +661,6 @@ static struct attribute *kone_attributes[] = { &dev_attr_firmware_version.attr, &dev_attr_tcu.attr, &dev_attr_startup_profile.attr, - &dev_attr_kone_abi_version.attr, NULL }; diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 71b14fa40dce..130d6566ea82 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h @@ -14,8 +14,6 @@ #include -#define ROCCAT_KONE_ABI_VERSION "1" - #pragma pack(push) #pragma pack(1) From 8d93efb27ab8927ffc7a357f1b2d10039de50ed4 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Sun, 20 Jun 2010 21:32:29 -0400 Subject: [PATCH 09/16] HID: magicmouse: properly account for scroll movement in state Before this change, sequential scroll events would take a variable amount of movement due to incorrect accounting. This change ensures all scroll movements require a deterministic touch movement for an action to occur. Signed-off-by: Chase Douglas Acked-by: Michael Poole Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 4c4a79c760a2..f44aaf21e1e2 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -189,7 +189,8 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda case TOUCH_STATE_DRAG: step = step / accel_profile[msc->scroll_accel]; if (step != 0) { - msc->touches[id].scroll_y = y; + msc->touches[id].scroll_y -= + step * accel_profile[msc->scroll_accel]; msc->scroll_jiffies = now; input_report_rel(input, REL_WHEEL, step); } From 0b778e76c1e7ccf49f8980b594e72f984095fd26 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Sun, 20 Jun 2010 21:32:30 -0400 Subject: [PATCH 10/16] HID: magicmouse: add param for scroll speed The new scroll_speed param takes an integer value from 0 to 63, where 0 is slowest and 63 is fastest. The default of 32 remains the same. This parameter also affects scroll acceleration linearly. A second part of this change is a tightly coupled modification to the scroll acceleration. Previously, scroll acceleration could be reset without lifting the scroll finger. This is rather unintuitive and hard to control in the case where a user wants faster scrolling, but wants to hold the scroll touch for longer than a moment. Note that scroll acceleration levels are now 1-7, where 7 is slowest. In the previous implementation, there were 8 levels defined, but it was impossible to start at the slowest level. In order to keep the default scroll speed unchanged, only 7 levels are used now. Signed-off-by: Chase Douglas Acked-by: Michael Poole Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 43 +++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index f44aaf21e1e2..fe0c760d7e6e 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -30,6 +30,17 @@ static bool emulate_scroll_wheel = true; module_param(emulate_scroll_wheel, bool, 0644); MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel"); +static unsigned int scroll_speed = 32; +static int param_set_scroll_speed(const char *val, struct kernel_param *kp) { + unsigned long speed; + if (!val || strict_strtoul(val, 0, &speed) || speed > 63) + return -EINVAL; + scroll_speed = speed; + return 0; +} +module_param_call(scroll_speed, param_set_scroll_speed, param_get_uint, &scroll_speed, 0644); +MODULE_PARM_DESC(scroll_speed, "Scroll speed, value from 0 (slow) to 63 (fast)"); + static bool scroll_acceleration = false; module_param(scroll_acceleration, bool, 0644); MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); @@ -54,6 +65,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie #define TOUCH_STATE_START 0x30 #define TOUCH_STATE_DRAG 0x40 +#define SCROLL_ACCEL_DEFAULT 7 + /** * struct magicmouse_sc - Tracks Magic Mouse-specific data. * @input: Input device through which we report events. @@ -145,7 +158,7 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state) input_report_key(msc->input, BTN_RIGHT, state & 2); if (state != last_state) - msc->scroll_accel = 0; + msc->scroll_accel = SCROLL_ACCEL_DEFAULT; } static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) @@ -167,30 +180,28 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda * vertical touch motions. */ if (emulate_scroll_wheel) { - static const int accel_profile[] = { - 256, 228, 192, 160, 128, 96, 64, 32, - }; unsigned long now = jiffies; int step = msc->touches[id].scroll_y - y; - /* Reset acceleration after half a second. */ - if (time_after(now, msc->scroll_jiffies + HZ / 2)) - msc->scroll_accel = 0; - /* Calculate and apply the scroll motion. */ switch (tdata[7] & TOUCH_STATE_MASK) { case TOUCH_STATE_START: msc->touches[id].scroll_y = y; - if (scroll_acceleration) - msc->scroll_accel = min_t(int, - msc->scroll_accel + 1, - ARRAY_SIZE(accel_profile) - 1); + + /* Reset acceleration after half a second. */ + if (scroll_acceleration && time_before(now, + msc->scroll_jiffies + HZ / 2)) + msc->scroll_accel = max_t(int, + msc->scroll_accel - 1, 1); + else + msc->scroll_accel = SCROLL_ACCEL_DEFAULT; + break; case TOUCH_STATE_DRAG: - step = step / accel_profile[msc->scroll_accel]; + step /= (64 - (int)scroll_speed) * msc->scroll_accel; if (step != 0) { - msc->touches[id].scroll_y -= - step * accel_profile[msc->scroll_accel]; + msc->touches[id].scroll_y -= step * + (64 - scroll_speed) * msc->scroll_accel; msc->scroll_jiffies = now; input_report_rel(input, REL_WHEEL, step); } @@ -351,6 +362,8 @@ static int magicmouse_probe(struct hid_device *hdev, return -ENOMEM; } + msc->scroll_accel = SCROLL_ACCEL_DEFAULT; + msc->quirks = id->driver_data; hid_set_drvdata(hdev, msc); From c04266889b591165bdea396b20313bebb83c0fd6 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Sun, 20 Jun 2010 21:32:31 -0400 Subject: [PATCH 11/16] HID: magicmouse: enable horizontal scrolling Mimicks OS X behavior. Signed-off-by: Chase Douglas Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index fe0c760d7e6e..0b89c1cf9ec4 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -95,6 +95,7 @@ struct magicmouse_sc { struct { short x; short y; + short scroll_x; short scroll_y; u8 size; } touches[16]; @@ -181,11 +182,13 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda */ if (emulate_scroll_wheel) { unsigned long now = jiffies; - int step = msc->touches[id].scroll_y - y; + int step_x = msc->touches[id].scroll_x - x; + int step_y = msc->touches[id].scroll_y - y; /* Calculate and apply the scroll motion. */ switch (tdata[7] & TOUCH_STATE_MASK) { case TOUCH_STATE_START: + msc->touches[id].scroll_x = x; msc->touches[id].scroll_y = y; /* Reset acceleration after half a second. */ @@ -198,12 +201,20 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda break; case TOUCH_STATE_DRAG: - step /= (64 - (int)scroll_speed) * msc->scroll_accel; - if (step != 0) { - msc->touches[id].scroll_y -= step * + step_x /= (64 - (int)scroll_speed) * msc->scroll_accel; + if (step_x != 0) { + msc->touches[id].scroll_x -= step_x * (64 - scroll_speed) * msc->scroll_accel; msc->scroll_jiffies = now; - input_report_rel(input, REL_WHEEL, step); + input_report_rel(input, REL_HWHEEL, -step_x); + } + + step_y /= (64 - (int)scroll_speed) * msc->scroll_accel; + if (step_y != 0) { + msc->touches[id].scroll_y -= step_y * + (64 - scroll_speed) * msc->scroll_accel; + msc->scroll_jiffies = now; + input_report_rel(input, REL_WHEEL, step_y); } break; } @@ -318,8 +329,10 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h __set_bit(EV_REL, input->evbit); __set_bit(REL_X, input->relbit); __set_bit(REL_Y, input->relbit); - if (emulate_scroll_wheel) + if (emulate_scroll_wheel) { __set_bit(REL_WHEEL, input->relbit); + __set_bit(REL_HWHEEL, input->relbit); + } if (report_touches) { __set_bit(EV_ABS, input->evbit); From e3612e8669b8c15278058f8dd52e3dc6e7d26710 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Mon, 5 Jul 2010 09:57:52 -0400 Subject: [PATCH 12/16] HID: magicmouse: report last touch up The evdev multitouch protocol requires that a last MT sync event must be sent after all touches are up. This change adds the last MT sync event to the hid-magicmouse driver. Also, don't send events when a touch leaves. Signed-off-by: Chase Douglas Acked-by: Michael Poole Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 0b89c1cf9ec4..ee7878785955 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -98,6 +98,7 @@ struct magicmouse_sc { short scroll_x; short scroll_y; u8 size; + u8 down; } touches[16]; int tracking_ids[16]; }; @@ -170,6 +171,7 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda int id = (misc >> 6) & 15; int x = x_y << 12 >> 20; int y = -(x_y >> 20); + int down = (tdata[7] & TOUCH_STATE_MASK) != TOUCH_STATE_NONE; /* Store tracking ID and other fields. */ msc->tracking_ids[raw_id] = id; @@ -221,9 +223,11 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda } /* Generate the input events for this touch. */ - if (report_touches) { + if (report_touches && down) { int orientation = (misc >> 10) - 32; + msc->touches[id].down = 1; + input_report_abs(input, ABS_MT_TRACKING_ID, id); input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]); input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]); @@ -243,7 +247,7 @@ static int magicmouse_raw_event(struct hid_device *hdev, { struct magicmouse_sc *msc = hid_get_drvdata(hdev); struct input_dev *input = msc->input; - int x, y, ts, ii, clicks; + int x, y, ts, ii, clicks, last_up; switch (data[0]) { case 0x10: @@ -263,6 +267,20 @@ static int magicmouse_raw_event(struct hid_device *hdev, msc->ntouches = (size - 6) / 8; for (ii = 0; ii < msc->ntouches; ii++) magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); + + if (report_touches) { + last_up = 1; + for (ii = 0; ii < ARRAY_SIZE(msc->touches); ii++) { + if (msc->touches[ii].down) { + last_up = 0; + msc->touches[ii].down = 0; + } + } + if (last_up) { + input_mt_sync(input); + } + } + /* When emulating three-button mode, it is important * to have the current touch information before * generating a click event. From 7d876c05fa6cf82f0274f27276d981ed325697a5 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Mon, 5 Jul 2010 10:50:09 -0400 Subject: [PATCH 13/16] HID: magicmouse: Correct parsing of large X and Y motions. The X and Y values have two more significant bits in the same byte that contains click status. Include these in the reported value. Thanks to Iain Hibbert of NetBSD for pointing this out. Signed-off-by: Michael Poole Acked-by: Chase Douglas Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index ee7878785955..319b0e57ee41 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -285,8 +285,8 @@ static int magicmouse_raw_event(struct hid_device *hdev, * to have the current touch information before * generating a click event. */ - x = (signed char)data[1]; - y = (signed char)data[2]; + x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22; + y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22; clicks = data[3]; break; case 0x20: /* Theoretically battery status (0-100), but I have From fc99f22c5de2177431cada350417ac6e353380c7 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 12 Jul 2010 19:28:26 +0200 Subject: [PATCH 14/16] HID: hid-input.c: indentation fixes Signed-off-by: Daniel Mack Cc: Jiri Kosina Cc: Dmitry Torokhov Signed-off-by: Jiri Kosina --- drivers/hid/hid-input.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 7a0d2e4661a1..36c214877f77 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -199,11 +199,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_GD_MOUSE: case HID_GD_POINTER: code += 0x110; break; case HID_GD_JOYSTICK: - if (code <= 0xf) - code += BTN_JOYSTICK; - else - code += BTN_TRIGGER_HAPPY; - break; + if (code <= 0xf) + code += BTN_JOYSTICK; + else + code += BTN_TRIGGER_HAPPY; + break; case HID_GD_GAMEPAD: code += 0x130; break; default: switch (field->physical) { @@ -480,7 +480,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case HID_UP_LOGIVENDOR: goto ignore; - + case HID_UP_PID: switch (usage->hid & HID_USAGE) { case 0xa4: map_key_clear(BTN_DEAD); break; @@ -586,9 +586,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); - input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); - return; - } + input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); + return; + } if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); From 3a343ee4509c982552b35fbc99d3213f3bb1acde Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 12 Jul 2010 19:28:27 +0200 Subject: [PATCH 15/16] HID: add HID_QUIRK_HIDINPUT_FORCE For devices with exotic HID report descriptors, it might be necessary to make the HID core force the registration of an input device. Make that possible by introducing a new quirk type. Signed-off-by: Daniel Mack Cc: Jiri Kosina Cc: Dmitry Torokhov Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 ++ include/linux/hid.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 866e54ec5fb2..7ccee899b59e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1157,6 +1157,8 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); + if (hdev->quirks & HID_QUIRK_HIDINPUT_FORCE) + connect_mask |= HID_CONNECT_HIDINPUT_FORCE; if (hdev->bus != BUS_USB) connect_mask &= ~HID_CONNECT_HIDDEV; if (hid_hiddev(hdev)) diff --git a/include/linux/hid.h b/include/linux/hid.h index 895001f7f4b2..42a0f1d11365 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -311,6 +311,7 @@ struct hid_item { #define HID_QUIRK_HIDDEV_FORCE 0x00000010 #define HID_QUIRK_BADPAD 0x00000020 #define HID_QUIRK_MULTI_INPUT 0x00000040 +#define HID_QUIRK_HIDINPUT_FORCE 0x00000080 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 From 70c7c9c4438fc3ca573744c5448df90dbcc5e159 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 12 Jul 2010 19:28:28 +0200 Subject: [PATCH 16/16] HID: Force input registration for "VEC footpedal" These devices report a usage page of type "consumer" and a usage of "Programmable buttons". They are hence ignored by the hid-input layer. Force the registration of an input device by using the new quirk type HID_QUIRK_HIDINPUT_FORCE. Signed-off-by: Daniel Mack Cc: Jiri Kosina Cc: Dmitry Torokhov Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 2 ++ drivers/hid/usbhid/hid-quirks.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 31601eef25dd..d42c88fea90e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -526,5 +526,7 @@ #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 +#define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 +#define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff #endif diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 5f5aa39b3988..2643d3147621 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -75,6 +75,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, + { 0, 0 } };