diff options
Diffstat (limited to 'drivers/hid/hid-magicmouse.c')
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 0ec91c18a42..08f5dc77397 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
@@ -81,6 +81,28 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie | |||
81 | #define NO_TOUCHES -1 | 81 | #define NO_TOUCHES -1 |
82 | #define SINGLE_TOUCH_UP -2 | 82 | #define SINGLE_TOUCH_UP -2 |
83 | 83 | ||
84 | /* Touch surface information. Dimension is in hundredths of a mm, min and max | ||
85 | * are in units. */ | ||
86 | #define MOUSE_DIMENSION_X (float)9056 | ||
87 | #define MOUSE_MIN_X -1100 | ||
88 | #define MOUSE_MAX_X 1258 | ||
89 | #define MOUSE_RES_X ((MOUSE_MAX_X - MOUSE_MIN_X) / (MOUSE_DIMENSION_X / 100)) | ||
90 | #define MOUSE_DIMENSION_Y (float)5152 | ||
91 | #define MOUSE_MIN_Y -1589 | ||
92 | #define MOUSE_MAX_Y 2047 | ||
93 | #define MOUSE_RES_Y ((MOUSE_MAX_Y - MOUSE_MIN_Y) / (MOUSE_DIMENSION_Y / 100)) | ||
94 | |||
95 | #define TRACKPAD_DIMENSION_X (float)13000 | ||
96 | #define TRACKPAD_MIN_X -2909 | ||
97 | #define TRACKPAD_MAX_X 3167 | ||
98 | #define TRACKPAD_RES_X \ | ||
99 | ((TRACKPAD_MAX_X - TRACKPAD_MIN_X) / (TRACKPAD_DIMENSION_X / 100)) | ||
100 | #define TRACKPAD_DIMENSION_Y (float)11000 | ||
101 | #define TRACKPAD_MIN_Y -2456 | ||
102 | #define TRACKPAD_MAX_Y 2565 | ||
103 | #define TRACKPAD_RES_Y \ | ||
104 | ((TRACKPAD_MAX_Y - TRACKPAD_MIN_Y) / (TRACKPAD_DIMENSION_Y / 100)) | ||
105 | |||
84 | /** | 106 | /** |
85 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. | 107 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. |
86 | * @input: Input device through which we report events. | 108 | * @input: Input device through which we report events. |
@@ -365,8 +387,10 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
365 | return 1; | 387 | return 1; |
366 | } | 388 | } |
367 | 389 | ||
368 | static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) | 390 | static int magicmouse_setup_input(struct hid_device *hdev, struct hid_input *hi) |
369 | { | 391 | { |
392 | struct input_dev *input = hi->input; | ||
393 | |||
370 | __set_bit(EV_KEY, input->evbit); | 394 | __set_bit(EV_KEY, input->evbit); |
371 | 395 | ||
372 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { | 396 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
@@ -406,17 +430,31 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
406 | * inverse of the reported Y. | 430 | * inverse of the reported Y. |
407 | */ | 431 | */ |
408 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { | 432 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
409 | input_set_abs_params(input, ABS_MT_POSITION_X, -1100, | 433 | input_set_abs_params(input, ABS_MT_POSITION_X, |
410 | 1358, 4, 0); | 434 | MOUSE_MIN_X, MOUSE_MAX_X, 4, 0); |
411 | input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, | 435 | input_set_abs_params(input, ABS_MT_POSITION_Y, |
412 | 2047, 4, 0); | 436 | MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0); |
437 | |||
438 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
439 | MOUSE_RES_X); | ||
440 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
441 | MOUSE_RES_Y); | ||
413 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | 442 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ |
414 | input_set_abs_params(input, ABS_X, -2909, 3167, 4, 0); | 443 | input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X, |
415 | input_set_abs_params(input, ABS_Y, -2456, 2565, 4, 0); | 444 | TRACKPAD_MAX_X, 4, 0); |
416 | input_set_abs_params(input, ABS_MT_POSITION_X, -2909, | 445 | input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y, |
417 | 3167, 4, 0); | 446 | TRACKPAD_MAX_Y, 4, 0); |
418 | input_set_abs_params(input, ABS_MT_POSITION_Y, -2456, | 447 | input_set_abs_params(input, ABS_MT_POSITION_X, |
419 | 2565, 4, 0); | 448 | TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0); |
449 | input_set_abs_params(input, ABS_MT_POSITION_Y, | ||
450 | TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0); | ||
451 | |||
452 | input_abs_set_res(input, ABS_X, TRACKPAD_RES_X); | ||
453 | input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y); | ||
454 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
455 | TRACKPAD_RES_X); | ||
456 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
457 | TRACKPAD_RES_Y); | ||
420 | } | 458 | } |
421 | 459 | ||
422 | input_set_events_per_packet(input, 60); | 460 | input_set_events_per_packet(input, 60); |
@@ -426,6 +464,8 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
426 | __set_bit(EV_MSC, input->evbit); | 464 | __set_bit(EV_MSC, input->evbit); |
427 | __set_bit(MSC_RAW, input->mscbit); | 465 | __set_bit(MSC_RAW, input->mscbit); |
428 | } | 466 | } |
467 | |||
468 | return 0; | ||
429 | } | 469 | } |
430 | 470 | ||
431 | static int magicmouse_input_mapping(struct hid_device *hdev, | 471 | static int magicmouse_input_mapping(struct hid_device *hdev, |
@@ -478,12 +518,6 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
478 | goto err_free; | 518 | goto err_free; |
479 | } | 519 | } |
480 | 520 | ||
481 | /* We do this after hid-input is done parsing reports so that | ||
482 | * hid-input uses the most natural button and axis IDs. | ||
483 | */ | ||
484 | if (msc->input) | ||
485 | magicmouse_setup_input(msc->input, hdev); | ||
486 | |||
487 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) | 521 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) |
488 | report = hid_register_report(hdev, HID_INPUT_REPORT, | 522 | report = hid_register_report(hdev, HID_INPUT_REPORT, |
489 | MOUSE_REPORT_ID); | 523 | MOUSE_REPORT_ID); |
@@ -501,9 +535,17 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
501 | } | 535 | } |
502 | report->size = 6; | 536 | report->size = 6; |
503 | 537 | ||
538 | /* | ||
539 | * Some devices repond with 'invalid report id' when feature | ||
540 | * report switching it into multitouch mode is sent to it. | ||
541 | * | ||
542 | * This results in -EIO from the _raw low-level transport callback, | ||
543 | * but there seems to be no other way of switching the mode. | ||
544 | * Thus the super-ugly hacky success check below. | ||
545 | */ | ||
504 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), | 546 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), |
505 | HID_FEATURE_REPORT); | 547 | HID_FEATURE_REPORT); |
506 | if (ret != sizeof(feature)) { | 548 | if (ret != -EIO && ret != sizeof(feature)) { |
507 | hid_err(hdev, "unable to request touch data (%d)\n", ret); | 549 | hid_err(hdev, "unable to request touch data (%d)\n", ret); |
508 | goto err_stop_hw; | 550 | goto err_stop_hw; |
509 | } | 551 | } |
@@ -540,6 +582,7 @@ static struct hid_driver magicmouse_driver = { | |||
540 | .remove = magicmouse_remove, | 582 | .remove = magicmouse_remove, |
541 | .raw_event = magicmouse_raw_event, | 583 | .raw_event = magicmouse_raw_event, |
542 | .input_mapping = magicmouse_input_mapping, | 584 | .input_mapping = magicmouse_input_mapping, |
585 | .input_register = magicmouse_setup_input, | ||
543 | }; | 586 | }; |
544 | 587 | ||
545 | static int __init magicmouse_init(void) | 588 | static int __init magicmouse_init(void) |