HID: logitech-dj: remove hidinput_input_event
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Wed, 5 Feb 2014 21:33:17 +0000 (16:33 -0500)
committerJiri Kosina <jkosina@suse.cz>
Mon, 17 Feb 2014 13:05:55 +0000 (14:05 +0100)
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>
drivers/hid/hid-logitech-dj.c

index f45279c3b11a9f241f6b0f28d1565ef965c04587..980ede54782da0fefceb43c9556a2f9dc7484bb0 100644 (file)
@@ -44,14 +44,6 @@ static const char kbd_descriptor[] = {
        0x19, 0xE0,             /*   USAGE_MINIMUM (Left Control)   */
        0x29, 0xE7,             /*   USAGE_MAXIMUM (Right GUI)      */
        0x81, 0x02,             /*   INPUT (Data,Var,Abs)       */
-       0x95, 0x05,             /*   REPORT COUNT (5)           */
-       0x05, 0x08,             /*   USAGE PAGE (LED page)      */
-       0x19, 0x01,             /*   USAGE MINIMUM (1)          */
-       0x29, 0x05,             /*   USAGE MAXIMUM (5)          */
-       0x91, 0x02,             /*   OUTPUT (Data, Variable, Absolute)  */
-       0x95, 0x01,             /*   REPORT COUNT (1)           */
-       0x75, 0x03,             /*   REPORT SIZE (3)            */
-       0x91, 0x01,             /*   OUTPUT (Constant)          */
        0x95, 0x06,             /*   REPORT_COUNT (6)           */
        0x75, 0x08,             /*   REPORT_SIZE (8)            */
        0x15, 0x00,             /*   LOGICAL_MINIMUM (0)        */
@@ -60,6 +52,18 @@ static const char kbd_descriptor[] = {
        0x19, 0x00,             /*   USAGE_MINIMUM (no event)       */
        0x2A, 0xFF, 0x00,       /*   USAGE_MAXIMUM (reserved)       */
        0x81, 0x00,             /*   INPUT (Data,Ary,Abs)       */
+       0x85, 0x0e,             /* REPORT_ID (14)               */
+       0x05, 0x08,             /*   USAGE PAGE (LED page)      */
+       0x95, 0x05,             /*   REPORT COUNT (5)           */
+       0x75, 0x01,             /*   REPORT SIZE (1)            */
+       0x15, 0x00,             /*   LOGICAL_MINIMUM (0)        */
+       0x25, 0x01,             /*   LOGICAL_MAXIMUM (1)        */
+       0x19, 0x01,             /*   USAGE MINIMUM (1)          */
+       0x29, 0x05,             /*   USAGE MAXIMUM (5)          */
+       0x91, 0x02,             /*   OUTPUT (Data, Variable, Absolute)  */
+       0x95, 0x01,             /*   REPORT COUNT (1)           */
+       0x75, 0x03,             /*   REPORT SIZE (3)            */
+       0x91, 0x01,             /*   OUTPUT (Constant)          */
        0xC0
 };
 
@@ -544,10 +548,37 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
                                        size_t count,
                                        unsigned char report_type)
 {
-       /* Called by hid raw to send data */
-       dbg_hid("%s\n", __func__);
+       struct dj_device *djdev = hid->driver_data;
+       struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
+       u8 *out_buf;
+       int ret;
 
-       return 0;
+       if (buf[0] != REPORT_TYPE_LEDS)
+               return -EINVAL;
+
+       out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC);
+       if (!out_buf)
+               return -ENOMEM;
+
+       if (count < DJREPORT_SHORT_LENGTH - 2)
+               count = DJREPORT_SHORT_LENGTH - 2;
+
+       out_buf[0] = REPORT_ID_DJ_SHORT;
+       out_buf[1] = djdev->device_index;
+       memcpy(out_buf + 2, buf, count);
+
+       /*
+        * hid-generic calls us with hid_output_raw_report(), but the LEDs
+        * are set through a SET_REPORT command. It works for USB-HID devices
+        * because usbhid either calls a SET_REPORT or directly send the output
+        * report depending if the device presents an urbout.
+        * Let be simple, send a SET_REPORT request.
+        */
+       ret = hid_hw_raw_request(djrcv_dev->hdev, out_buf[0], out_buf,
+               DJREPORT_SHORT_LENGTH, report_type, HID_REQ_SET_REPORT);
+
+       kfree(out_buf);
+       return ret;
 }
 
 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)
        return retval;
 }
 
-static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
-                                 unsigned int code, int value)
-{
-       /* Sent by the input layer to handle leds and Force Feedback */
-       struct hid_device *dj_hiddev = input_get_drvdata(dev);
-       struct dj_device *dj_dev = dj_hiddev->driver_data;
-
-       struct dj_receiver_dev *djrcv_dev =
-           dev_get_drvdata(dj_hiddev->dev.parent);
-       struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
-       struct hid_report_enum *output_report_enum;
-
-       struct hid_field *field;
-       struct hid_report *report;
-       unsigned char *data;
-       int offset;
-
-       dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
-               __func__, dev->phys, type, code, value);
-
-       if (type != EV_LED)
-               return -1;
-
-       offset = hidinput_find_field(dj_hiddev, type, code, &field);
-
-       if (offset == -1) {
-               dev_warn(&dev->dev, "event field not found\n");
-               return -1;
-       }
-       hid_set_field(field, offset, value);
-
-       data = hid_alloc_report_buf(field->report, GFP_ATOMIC);
-       if (!data) {
-               dev_warn(&dev->dev, "failed to allocate report buf memory\n");
-               return -1;
-       }
-
-       hid_output_report(field->report, &data[0]);
-
-       output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
-       report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
-       hid_set_field(report->field[0], 0, dj_dev->device_index);
-       hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
-       hid_set_field(report->field[0], 2, data[1]);
-
-       hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
-
-       kfree(data);
-
-       return 0;
-}
-
 static int logi_dj_ll_start(struct hid_device *hid)
 {
        dbg_hid("%s\n", __func__);
@@ -683,7 +662,6 @@ static struct hid_ll_driver logi_dj_ll_driver = {
        .stop = logi_dj_ll_stop,
        .open = logi_dj_ll_open,
        .close = logi_dj_ll_close,
-       .hidinput_input_event = logi_dj_ll_input_event,
 };