diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2014-02-05 16:33:17 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-02-17 08:05:55 -0500 |
commit | 0e40d35637d68f654b66f4562c9a914be7d06bd1 (patch) | |
tree | 5a294dcfcdfd84d1d8c8b39f57efe978519fdf26 /drivers/hid/hid-logitech-dj.c | |
parent | b69d6536794c93dda362ab79c9f559382e3465be (diff) |
HID: logitech-dj: remove hidinput_input_event
hid-logitech-dj uses its own ->hidinput_input_event() instead of
the generic binding in hid-input.
Moving the handling of LEDs towards logi_dj_output_hidraw_report()
allows two things:
- remove hidinput_input_event in struct hid_device
- hidraw user space programs can also set the LEDs
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-logitech-dj.c')
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 106 |
1 files changed, 42 insertions, 64 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index f45279c3b11a..980ede54782d 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
@@ -44,14 +44,6 @@ static const char kbd_descriptor[] = { | |||
44 | 0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */ | 44 | 0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */ |
45 | 0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */ | 45 | 0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */ |
46 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ | 46 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ |
47 | 0x95, 0x05, /* REPORT COUNT (5) */ | ||
48 | 0x05, 0x08, /* USAGE PAGE (LED page) */ | ||
49 | 0x19, 0x01, /* USAGE MINIMUM (1) */ | ||
50 | 0x29, 0x05, /* USAGE MAXIMUM (5) */ | ||
51 | 0x91, 0x02, /* OUTPUT (Data, Variable, Absolute) */ | ||
52 | 0x95, 0x01, /* REPORT COUNT (1) */ | ||
53 | 0x75, 0x03, /* REPORT SIZE (3) */ | ||
54 | 0x91, 0x01, /* OUTPUT (Constant) */ | ||
55 | 0x95, 0x06, /* REPORT_COUNT (6) */ | 47 | 0x95, 0x06, /* REPORT_COUNT (6) */ |
56 | 0x75, 0x08, /* REPORT_SIZE (8) */ | 48 | 0x75, 0x08, /* REPORT_SIZE (8) */ |
57 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ | 49 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ |
@@ -60,6 +52,18 @@ static const char kbd_descriptor[] = { | |||
60 | 0x19, 0x00, /* USAGE_MINIMUM (no event) */ | 52 | 0x19, 0x00, /* USAGE_MINIMUM (no event) */ |
61 | 0x2A, 0xFF, 0x00, /* USAGE_MAXIMUM (reserved) */ | 53 | 0x2A, 0xFF, 0x00, /* USAGE_MAXIMUM (reserved) */ |
62 | 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ | 54 | 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ |
55 | 0x85, 0x0e, /* REPORT_ID (14) */ | ||
56 | 0x05, 0x08, /* USAGE PAGE (LED page) */ | ||
57 | 0x95, 0x05, /* REPORT COUNT (5) */ | ||
58 | 0x75, 0x01, /* REPORT SIZE (1) */ | ||
59 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ | ||
60 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ | ||
61 | 0x19, 0x01, /* USAGE MINIMUM (1) */ | ||
62 | 0x29, 0x05, /* USAGE MAXIMUM (5) */ | ||
63 | 0x91, 0x02, /* OUTPUT (Data, Variable, Absolute) */ | ||
64 | 0x95, 0x01, /* REPORT COUNT (1) */ | ||
65 | 0x75, 0x03, /* REPORT SIZE (3) */ | ||
66 | 0x91, 0x01, /* OUTPUT (Constant) */ | ||
63 | 0xC0 | 67 | 0xC0 |
64 | }; | 68 | }; |
65 | 69 | ||
@@ -544,10 +548,37 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, | |||
544 | size_t count, | 548 | size_t count, |
545 | unsigned char report_type) | 549 | unsigned char report_type) |
546 | { | 550 | { |
547 | /* Called by hid raw to send data */ | 551 | struct dj_device *djdev = hid->driver_data; |
548 | dbg_hid("%s\n", __func__); | 552 | struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev; |
553 | u8 *out_buf; | ||
554 | int ret; | ||
549 | 555 | ||
550 | return 0; | 556 | if (buf[0] != REPORT_TYPE_LEDS) |
557 | return -EINVAL; | ||
558 | |||
559 | out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC); | ||
560 | if (!out_buf) | ||
561 | return -ENOMEM; | ||
562 | |||
563 | if (count < DJREPORT_SHORT_LENGTH - 2) | ||
564 | count = DJREPORT_SHORT_LENGTH - 2; | ||
565 | |||
566 | out_buf[0] = REPORT_ID_DJ_SHORT; | ||
567 | out_buf[1] = djdev->device_index; | ||
568 | memcpy(out_buf + 2, buf, count); | ||
569 | |||
570 | /* | ||
571 | * hid-generic calls us with hid_output_raw_report(), but the LEDs | ||
572 | * are set through a SET_REPORT command. It works for USB-HID devices | ||
573 | * because usbhid either calls a SET_REPORT or directly send the output | ||
574 | * report depending if the device presents an urbout. | ||
575 | * Let be simple, send a SET_REPORT request. | ||
576 | */ | ||
577 | ret = hid_hw_raw_request(djrcv_dev->hdev, out_buf[0], out_buf, | ||
578 | DJREPORT_SHORT_LENGTH, report_type, HID_REQ_SET_REPORT); | ||
579 | |||
580 | kfree(out_buf); | ||
581 | return ret; | ||
551 | } | 582 | } |
552 | 583 | ||
553 | static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size) | 584 | static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size) |
@@ -613,58 +644,6 @@ static int logi_dj_ll_parse(struct hid_device *hid) | |||
613 | return retval; | 644 | return retval; |
614 | } | 645 | } |
615 | 646 | ||
616 | static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, | ||
617 | unsigned int code, int value) | ||
618 | { | ||
619 | /* Sent by the input layer to handle leds and Force Feedback */ | ||
620 | struct hid_device *dj_hiddev = input_get_drvdata(dev); | ||
621 | struct dj_device *dj_dev = dj_hiddev->driver_data; | ||
622 | |||
623 | struct dj_receiver_dev *djrcv_dev = | ||
624 | dev_get_drvdata(dj_hiddev->dev.parent); | ||
625 | struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev; | ||
626 | struct hid_report_enum *output_report_enum; | ||
627 | |||
628 | struct hid_field *field; | ||
629 | struct hid_report *report; | ||
630 | unsigned char *data; | ||
631 | int offset; | ||
632 | |||
633 | dbg_hid("%s: %s, type:%d | code:%d | value:%d\n", | ||
634 | __func__, dev->phys, type, code, value); | ||
635 | |||
636 | if (type != EV_LED) | ||
637 | return -1; | ||
638 | |||
639 | offset = hidinput_find_field(dj_hiddev, type, code, &field); | ||
640 | |||
641 | if (offset == -1) { | ||
642 | dev_warn(&dev->dev, "event field not found\n"); | ||
643 | return -1; | ||
644 | } | ||
645 | hid_set_field(field, offset, value); | ||
646 | |||
647 | data = hid_alloc_report_buf(field->report, GFP_ATOMIC); | ||
648 | if (!data) { | ||
649 | dev_warn(&dev->dev, "failed to allocate report buf memory\n"); | ||
650 | return -1; | ||
651 | } | ||
652 | |||
653 | hid_output_report(field->report, &data[0]); | ||
654 | |||
655 | output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT]; | ||
656 | report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; | ||
657 | hid_set_field(report->field[0], 0, dj_dev->device_index); | ||
658 | hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS); | ||
659 | hid_set_field(report->field[0], 2, data[1]); | ||
660 | |||
661 | hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT); | ||
662 | |||
663 | kfree(data); | ||
664 | |||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | static int logi_dj_ll_start(struct hid_device *hid) | 647 | static int logi_dj_ll_start(struct hid_device *hid) |
669 | { | 648 | { |
670 | dbg_hid("%s\n", __func__); | 649 | dbg_hid("%s\n", __func__); |
@@ -683,7 +662,6 @@ static struct hid_ll_driver logi_dj_ll_driver = { | |||
683 | .stop = logi_dj_ll_stop, | 662 | .stop = logi_dj_ll_stop, |
684 | .open = logi_dj_ll_open, | 663 | .open = logi_dj_ll_open, |
685 | .close = logi_dj_ll_close, | 664 | .close = logi_dj_ll_close, |
686 | .hidinput_input_event = logi_dj_ll_input_event, | ||
687 | }; | 665 | }; |
688 | 666 | ||
689 | 667 | ||