aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-logitech-dj.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-02-05 16:33:17 -0500
committerJiri Kosina <jkosina@suse.cz>2014-02-17 08:05:55 -0500
commit0e40d35637d68f654b66f4562c9a914be7d06bd1 (patch)
tree5a294dcfcdfd84d1d8c8b39f57efe978519fdf26 /drivers/hid/hid-logitech-dj.c
parentb69d6536794c93dda362ab79c9f559382e3465be (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.c106
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
553static void rdcat(char *rdesc, unsigned int *rsize, const char *data, unsigned int size) 584static 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
616static 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
668static int logi_dj_ll_start(struct hid_device *hid) 647static 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