Merge branches 'magicmouse', 'roccat' and 'vec-pedal' into for-linus

Conflicts:
	drivers/hid/hid-ids.h
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
index 88340a2..063bda7 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
@@ -33,19 +33,6 @@
 		left. E.g. a returned value of 138 means 1.38
 		This file is readonly.
 
-What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/kone_driver_version
-Date:		March 2010
-Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:	When read, this file returns the driver version.
-		The format of the string is "v<major>.<minor>.<patchlevel>".
-		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/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index e13d803..f4f04e4 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1157,6 +1157,8 @@
 
 	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/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 08b6ac6..fa053ab 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -439,6 +439,9 @@
 #define USB_VENDOR_ID_PHILIPS		0x0471
 #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
 
+#define USB_VENDOR_ID_PI_ENGINEERING	0x05f3
+#define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL	0xff
+
 #define USB_VENDOR_ID_PLAYDOTCOM	0x0b43
 #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII	0x0003
 
@@ -533,5 +536,4 @@
 #define USB_VENDOR_ID_ZYDACRON	0x13EC
 #define USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL	0x0006
 
-
 #endif
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 6b10e5a..d8cc790 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -199,11 +199,11 @@
 		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) {
@@ -483,7 +483,7 @@
 
 	case HID_UP_LOGIVENDOR:
 		goto ignore;
-	
+
 	case HID_UP_PID:
 		switch (usage->hid & HID_USAGE) {
 		case 0xa4: map_key_clear(BTN_DEAD);	break;
@@ -589,9 +589,9 @@
 			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);
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index f10d56a..319b0e5 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -30,6 +30,21 @@
 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");
+
 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)");
@@ -50,6 +65,8 @@
 #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.
@@ -78,8 +95,10 @@
 	struct {
 		short x;
 		short y;
+		short scroll_x;
 		short scroll_y;
 		u8 size;
+		u8 down;
 	} touches[16];
 	int tracking_ids[16];
 };
@@ -141,7 +160,7 @@
 	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)
@@ -152,6 +171,7 @@
 	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;
@@ -160,42 +180,54 @@
 	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) {
-		static const int accel_profile[] = {
-			256, 228, 192, 160, 128, 96, 64, 32,
-		};
+	if (emulate_scroll_wheel) {
 		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;
+		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;
-			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];
-			if (step != 0) {
-				msc->touches[id].scroll_y = y;
+			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;
 		}
 	}
 
 	/* 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]);
@@ -215,7 +247,7 @@
 {
 	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:
@@ -235,12 +267,26 @@
 		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.
 		 */
-		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
@@ -301,8 +347,10 @@
 	__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);
@@ -345,6 +393,8 @@
 		return -ENOMEM;
 	}
 
+	msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
+
 	msc->quirks = id->driver_data;
 	hid_set_drvdata(hdev, msc);
 
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 17f2dc0..f776957 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?
  */
 
@@ -277,7 +272,7 @@
 		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;
@@ -337,7 +332,7 @@
 		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;
@@ -623,18 +618,6 @@
 }
 
 /*
- * 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.
- */
-static ssize_t kone_sysfs_show_driver_version(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, ROCCAT_KONE_DRIVER_VERSION "\n");
-}
-
-/*
  * Read actual dpi settings.
  * Returns raw value for further processing. Refer to enum kone_polling_rates to
  * get real value.
@@ -671,9 +654,6 @@
 		kone_sysfs_show_startup_profile,
 		kone_sysfs_set_startup_profile);
 
-static DEVICE_ATTR(kone_driver_version, 0440,
-		kone_sysfs_show_driver_version, NULL);
-
 static struct attribute *kone_attributes[] = {
 		&dev_attr_actual_dpi.attr,
 		&dev_attr_actual_profile.attr,
@@ -681,7 +661,6 @@
 		&dev_attr_firmware_version.attr,
 		&dev_attr_tcu.attr,
 		&dev_attr_startup_profile.attr,
-		&dev_attr_kone_driver_version.attr,
 		NULL
 };
 
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h
index 003e6f8..130d656 100644
--- a/drivers/hid/hid-roccat-kone.h
+++ b/drivers/hid/hid-roccat-kone.h
@@ -14,8 +14,6 @@
 
 #include <linux/types.h>
 
-#define ROCCAT_KONE_DRIVER_VERSION "v0.3.1"
-
 #pragma pack(push)
 #pragma pack(1)
 
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index e05d48e..f6e80c7 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -168,7 +168,7 @@
 		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 @@
 					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 @@
 				device->hid->ll_driver->power(device->hid,
 						PM_HINT_NORMAL);
 			--device->open;
-			goto exit_unlock;
+			goto exit_err;
 		}
 	}
 
@@ -202,6 +202,9 @@
 	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)
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h
index d8aae0c..09e864e 100644
--- a/drivers/hid/hid-roccat.h
+++ b/drivers/hid/hid-roccat.h
@@ -15,7 +15,7 @@
 #include <linux/hid.h>
 #include <linux/types.h>
 
-#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);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 5f5aa39..2643d31 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -75,6 +75,8 @@
 	{ 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 }
 };
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 895001f..42a0f1d 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -311,6 +311,7 @@
 #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