@@ -163,14 +163,26 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state)
msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
}
+/* Function shamelessly borrowed from hid-core.c. */
+
+static s32 snto32(__u32 value, unsigned n)
+{
+ switch (n) {
+ case 8: return ((__s8)value);
+ case 16: return ((__s16)value);
+ case 32: return ((__s32)value);
+ }
+ return value & (1 << (n - 1)) ? value | (-1 << n) : value;
+}
+
static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata)
{
struct input_dev *input = msc->input;
__s32 x_y = tdata[0] << 8 | tdata[1] << 16 | tdata[2] << 24;
int misc = tdata[5] | tdata[6] << 8;
int id = (misc >> 6) & 15;
- int x = x_y << 12 >> 20;
- int y = -(x_y >> 20);
+ int x = snto32((x_y >> 8) & 4095, 12);
+ int y = snto32(x_y >> 20, 12);
int down = (tdata[7] & TOUCH_STATE_MASK) != TOUCH_STATE_NONE;
/* Store tracking ID and other fields. */
@@ -285,8 +297,8 @@ static int magicmouse_raw_event(struct hid_device *hdev,
* to have the current touch information before
* generating a click event.
*/
- x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22;
- y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22;
+ x = snto32(((data[3] & 0x0c) << 6) | data[1], 10);
+ y = snto32(((data[3] & 0x30) << 4) | data[2], 10);
clicks = data[3];
break;
case 0x20: /* Theoretically battery status (0-100), but I have