diff options
author | Jiri Kosina <jkosina@suse.cz> | 2014-02-17 14:07:35 +0100 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-02-17 14:07:35 +0100 |
commit | 3371ac4b3b8b7d56928949ba7cfa6fc6274445e9 (patch) | |
tree | f7cd1dbb974d5ac7fc8af611dc6522a76b68b4cf /drivers/hid | |
parent | HID: hid-sony: report actual brightness value when reading LED (diff) | |
parent | HID: Add HID transport driver documentation (diff) | |
download | linux-3371ac4b3b8b7d56928949ba7cfa6fc6274445e9.tar.xz linux-3371ac4b3b8b7d56928949ba7cfa6fc6274445e9.zip |
Merge branch 'for-3.15/hid-core-ll-transport-cleanup' into for-3.15/sony
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-input.c | 12 | ||||
-rw-r--r-- | drivers/hid/hid-lg.c | 6 | ||||
-rw-r--r-- | drivers/hid/hid-logitech-dj.c | 106 | ||||
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-sony.c | 9 | ||||
-rw-r--r-- | drivers/hid/hid-thingm.c | 4 | ||||
-rw-r--r-- | drivers/hid/hid-wacom.c | 16 | ||||
-rw-r--r-- | drivers/hid/hid-wiimote-core.c | 2 | ||||
-rw-r--r-- | drivers/hid/hidraw.c | 9 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 1 | ||||
-rw-r--r-- | drivers/hid/uhid.c | 28 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 107 |
12 files changed, 170 insertions, 132 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d50e7313b171..15959fbae268 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -350,9 +350,9 @@ static int hidinput_get_battery_property(struct power_supply *psy, ret = -ENOMEM; break; } - ret = dev->hid_get_raw_report(dev, dev->battery_report_id, - buf, 2, - dev->battery_report_type); + ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2, + dev->battery_report_type, + HID_REQ_GET_REPORT); if (ret != 2) { ret = -ENODATA; @@ -1184,7 +1184,7 @@ static void hidinput_led_worker(struct work_struct *work) hid_output_report(report, buf); /* synchronous output report */ - hid->hid_output_raw_report(hid, buf, len, HID_OUTPUT_REPORT); + hid_output_raw_report(hid, buf, len, HID_OUTPUT_REPORT); kfree(buf); } @@ -1263,9 +1263,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) } input_set_drvdata(input_dev, hid); - if (hid->ll_driver->hidinput_input_event) - input_dev->event = hid->ll_driver->hidinput_input_event; - else if (hid->ll_driver->request || hid->hid_output_raw_report) + if (hid->ll_driver->request || hid->hid_output_raw_report) input_dev->event = hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 9fe9d4ac3114..76ed7e512dcf 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -692,7 +692,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); + ret = hid_output_raw_report(hdev, buf, sizeof(buf), + HID_FEATURE_REPORT); if (ret >= 0) { /* insert a little delay of 10 jiffies ~ 40ms */ @@ -704,7 +705,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) buf[1] = 0xB2; get_random_bytes(&buf[2], 2); - ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); + ret = hid_output_raw_report(hdev, buf, sizeof(buf), + HID_FEATURE_REPORT); } } 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[] = { 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, }; diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 3b43d1cfa936..cb5db3afc690 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -538,7 +538,7 @@ static int magicmouse_probe(struct hid_device *hdev, * but there seems to be no other way of switching the mode. * Thus the super-ugly hacky success check below. */ - ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), + ret = hid_output_raw_report(hdev, feature, sizeof(feature), HID_FEATURE_REPORT); if (ret != -EIO && ret != sizeof(feature)) { hid_err(hdev, "unable to request touch data (%d)\n", ret); diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index be0d38611598..e6995bf9f95a 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -810,7 +810,8 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) if (!buf) return -ENOMEM; - ret = hdev->hid_get_raw_report(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT); + ret = hid_hw_raw_request(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); if (ret < 0) hid_err(hdev, "can't set operational mode\n"); @@ -823,7 +824,8 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) static int sixaxis_set_operational_bt(struct hid_device *hdev) { unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; - return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); + return hid_output_raw_report(hdev, buf, sizeof(buf), + HID_FEATURE_REPORT); } static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds) @@ -1042,8 +1044,7 @@ static void sixaxis_state_worker(struct work_struct *work) buf[10] |= sc->led_state[2] << 3; buf[10] |= sc->led_state[3] << 4; - sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), - HID_OUTPUT_REPORT); + hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT); } static void dualshock4_state_worker(struct work_struct *work) diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c index 99342cfa0ea2..7dd3197f3b3e 100644 --- a/drivers/hid/hid-thingm.c +++ b/drivers/hid/hid-thingm.c @@ -48,8 +48,8 @@ static int blink1_send_command(struct blink1_data *data, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]); - ret = data->hdev->hid_output_raw_report(data->hdev, buf, - BLINK1_CMD_SIZE, HID_FEATURE_REPORT); + ret = hid_output_raw_report(data->hdev, buf, BLINK1_CMD_SIZE, + HID_FEATURE_REPORT); return ret < 0 ? ret : 0; } diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 60c75dcbbdb8..c720db912edb 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -128,8 +128,7 @@ static void wacom_set_image(struct hid_device *hdev, const char *image, rep_data[0] = WAC_CMD_ICON_START_STOP; rep_data[1] = 0; - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); + ret = hid_output_raw_report(hdev, rep_data, 2, HID_FEATURE_REPORT); if (ret < 0) goto err; @@ -143,15 +142,14 @@ static void wacom_set_image(struct hid_device *hdev, const char *image, rep_data[j + 3] = p[(i << 6) + j]; rep_data[2] = i; - ret = hdev->hid_output_raw_report(hdev, rep_data, 67, + ret = hid_output_raw_report(hdev, rep_data, 67, HID_FEATURE_REPORT); } rep_data[0] = WAC_CMD_ICON_START_STOP; rep_data[1] = 0; - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, - HID_FEATURE_REPORT); + ret = hid_output_raw_report(hdev, rep_data, 2, HID_FEATURE_REPORT); err: return; @@ -183,7 +181,7 @@ static void wacom_leds_set_brightness(struct led_classdev *led_dev, buf[3] = value; /* use fixed brightness for OLEDs */ buf[4] = 0x08; - hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT); + hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT); kfree(buf); } @@ -339,7 +337,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed) rep_data[0] = 0x03 ; rep_data[1] = 0x00; limit = 3; do { - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, + ret = hid_output_raw_report(hdev, rep_data, 2, HID_FEATURE_REPORT); } while (ret < 0 && limit-- > 0); @@ -352,7 +350,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed) rep_data[1] = 0x00; limit = 3; do { - ret = hdev->hid_output_raw_report(hdev, + ret = hid_output_raw_report(hdev, rep_data, 2, HID_FEATURE_REPORT); } while (ret < 0 && limit-- > 0); @@ -378,7 +376,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed) rep_data[0] = 0x03; rep_data[1] = wdata->features; - ret = hdev->hid_output_raw_report(hdev, rep_data, 2, + ret = hid_output_raw_report(hdev, rep_data, 2, HID_FEATURE_REPORT); if (ret >= 0) wdata->high_speed = speed; diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index abb20db2b443..d7dc6c5bc244 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -35,7 +35,7 @@ static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, if (!buf) return -ENOMEM; - ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT); + ret = hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT); kfree(buf); return ret; diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index cb0137b3718d..f8708c93f85c 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -153,7 +153,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, goto out_free; } - ret = dev->hid_output_raw_report(dev, buf, count, report_type); + ret = hid_output_raw_report(dev, buf, count, report_type); out_free: kfree(buf); out: @@ -189,7 +189,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t dev = hidraw_table[minor]->hid; - if (!dev->hid_get_raw_report) { + if (!dev->ll_driver->raw_request) { ret = -ENODEV; goto out; } @@ -216,14 +216,15 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t /* * Read the first byte from the user. This is the report number, - * which is passed to dev->hid_get_raw_report(). + * which is passed to hid_hw_raw_request(). */ if (copy_from_user(&report_number, buffer, 1)) { ret = -EFAULT; goto out_free; } - ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type); + ret = hid_hw_raw_request(dev, report_number, buf, count, report_type, + HID_REQ_GET_REPORT); if (ret < 0) goto out_free; diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index e914f2755491..f4ea7343e823 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1005,7 +1005,6 @@ static int i2c_hid_probe(struct i2c_client *client, hid->driver_data = client; hid->ll_driver = &i2c_hid_ll_driver; - hid->hid_get_raw_report = i2c_hid_get_raw_report; hid->hid_output_raw_report = i2c_hid_output_raw_report; hid->dev.parent = &client->dev; ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev)); diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index cedc6da93c19..12439e1eeae2 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -244,12 +244,39 @@ static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count, return count; } +static int uhid_hid_output_report(struct hid_device *hid, __u8 *buf, + size_t count) +{ + struct uhid_device *uhid = hid->driver_data; + unsigned long flags; + struct uhid_event *ev; + + if (count < 1 || count > UHID_DATA_MAX) + return -EINVAL; + + ev = kzalloc(sizeof(*ev), GFP_KERNEL); + if (!ev) + return -ENOMEM; + + ev->type = UHID_OUTPUT; + ev->u.output.size = count; + ev->u.output.rtype = UHID_OUTPUT_REPORT; + memcpy(ev->u.output.data, buf, count); + + spin_lock_irqsave(&uhid->qlock, flags); + uhid_queue(uhid, ev); + spin_unlock_irqrestore(&uhid->qlock, flags); + + return count; +} + static struct hid_ll_driver uhid_hid_driver = { .start = uhid_hid_start, .stop = uhid_hid_stop, .open = uhid_hid_open, .close = uhid_hid_close, .parse = uhid_hid_parse, + .output_report = uhid_hid_output_report, }; #ifdef CONFIG_COMPAT @@ -377,7 +404,6 @@ static int uhid_dev_create(struct uhid_device *uhid, hid->uniq[63] = 0; hid->ll_driver = &uhid_hid_driver; - hid->hid_get_raw_report = uhid_hid_get_raw; hid->hid_output_raw_report = uhid_hid_output_raw; hid->bus = ev->u.create.bus; hid->vendor = ev->u.create.vendor; diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 44df131d390a..b9a770f4d7ae 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -884,58 +884,78 @@ static int usbhid_get_raw_report(struct hid_device *hid, return ret; } -static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, - unsigned char report_type) +static int usbhid_set_raw_report(struct hid_device *hid, unsigned int reportnum, + __u8 *buf, size_t count, unsigned char rtype) { struct usbhid_device *usbhid = hid->driver_data; struct usb_device *dev = hid_to_usb_dev(hid); struct usb_interface *intf = usbhid->intf; struct usb_host_interface *interface = intf->cur_altsetting; - int ret; + int ret, skipped_report_id = 0; - if (usbhid->urbout && report_type != HID_FEATURE_REPORT) { - int actual_length; - int skipped_report_id = 0; + /* Byte 0 is the report number. Report data starts at byte 1.*/ + buf[0] = reportnum; + if (buf[0] == 0x0) { + /* Don't send the Report ID */ + buf++; + count--; + skipped_report_id = 1; + } - if (buf[0] == 0x0) { - /* Don't send the Report ID */ - buf++; - count--; - skipped_report_id = 1; - } - ret = usb_interrupt_msg(dev, usbhid->urbout->pipe, - buf, count, &actual_length, - USB_CTRL_SET_TIMEOUT); - /* return the number of bytes transferred */ - if (ret == 0) { - ret = actual_length; - /* count also the report id */ - if (skipped_report_id) - ret++; - } - } else { - int skipped_report_id = 0; - int report_id = buf[0]; - if (buf[0] == 0x0) { - /* Don't send the Report ID */ - buf++; - count--; - skipped_report_id = 1; - } - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), HID_REQ_SET_REPORT, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | report_id, + ((rtype + 1) << 8) | reportnum, interface->desc.bInterfaceNumber, buf, count, USB_CTRL_SET_TIMEOUT); - /* count also the report id, if this was a numbered report. */ - if (ret > 0 && skipped_report_id) + /* count also the report id, if this was a numbered report. */ + if (ret > 0 && skipped_report_id) + ret++; + + return ret; +} + +static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count) +{ + struct usbhid_device *usbhid = hid->driver_data; + struct usb_device *dev = hid_to_usb_dev(hid); + int actual_length, skipped_report_id = 0, ret; + + if (!usbhid->urbout) + return -EIO; + + if (buf[0] == 0x0) { + /* Don't send the Report ID */ + buf++; + count--; + skipped_report_id = 1; + } + + ret = usb_interrupt_msg(dev, usbhid->urbout->pipe, + buf, count, &actual_length, + USB_CTRL_SET_TIMEOUT); + /* return the number of bytes transferred */ + if (ret == 0) { + ret = actual_length; + /* count also the report id */ + if (skipped_report_id) ret++; } return ret; } +static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, + size_t count, unsigned char report_type) +{ + struct usbhid_device *usbhid = hid->driver_data; + + if (usbhid->urbout && report_type != HID_FEATURE_REPORT) + return usbhid_output_report(hid, buf, count); + + return usbhid_set_raw_report(hid, buf[0], buf, count, report_type); +} + static void usbhid_restart_queues(struct usbhid_device *usbhid) { if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)) @@ -1200,6 +1220,20 @@ static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int r } } +static int usbhid_raw_request(struct hid_device *hid, unsigned char reportnum, + __u8 *buf, size_t len, unsigned char rtype, + int reqtype) +{ + switch (reqtype) { + case HID_REQ_GET_REPORT: + return usbhid_get_raw_report(hid, reportnum, buf, len, rtype); + case HID_REQ_SET_REPORT: + return usbhid_set_raw_report(hid, reportnum, buf, len, rtype); + default: + return -EIO; + } +} + static int usbhid_idle(struct hid_device *hid, int report, int idle, int reqtype) { @@ -1223,6 +1257,8 @@ static struct hid_ll_driver usb_hid_driver = { .power = usbhid_power, .request = usbhid_request, .wait = usbhid_wait_io, + .raw_request = usbhid_raw_request, + .output_report = usbhid_output_report, .idle = usbhid_idle, }; @@ -1253,7 +1289,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * usb_set_intfdata(intf, hid); hid->ll_driver = &usb_hid_driver; - hid->hid_get_raw_report = usbhid_get_raw_report; hid->hid_output_raw_report = usbhid_output_raw_report; hid->ff_init = hid_pidff_init; #ifdef CONFIG_USB_HIDDEV |