Commit 3371ac4b authored by Jiri Kosina's avatar Jiri Kosina

Merge branch 'for-3.15/hid-core-ll-transport-cleanup' into for-3.15/sony

parents 7db7504a 6fad42d5
This diff is collapsed.
...@@ -350,9 +350,9 @@ static int hidinput_get_battery_property(struct power_supply *psy, ...@@ -350,9 +350,9 @@ static int hidinput_get_battery_property(struct power_supply *psy,
ret = -ENOMEM; ret = -ENOMEM;
break; break;
} }
ret = dev->hid_get_raw_report(dev, dev->battery_report_id, ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
buf, 2, dev->battery_report_type,
dev->battery_report_type); HID_REQ_GET_REPORT);
if (ret != 2) { if (ret != 2) {
ret = -ENODATA; ret = -ENODATA;
...@@ -1184,7 +1184,7 @@ static void hidinput_led_worker(struct work_struct *work) ...@@ -1184,7 +1184,7 @@ static void hidinput_led_worker(struct work_struct *work)
hid_output_report(report, buf); hid_output_report(report, buf);
/* synchronous output report */ /* 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); kfree(buf);
} }
...@@ -1263,9 +1263,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) ...@@ -1263,9 +1263,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
} }
input_set_drvdata(input_dev, hid); input_set_drvdata(input_dev, hid);
if (hid->ll_driver->hidinput_input_event) if (hid->ll_driver->request || hid->hid_output_raw_report)
input_dev->event = hid->ll_driver->hidinput_input_event;
else if (hid->ll_driver->request || hid->hid_output_raw_report)
input_dev->event = hidinput_input_event; input_dev->event = hidinput_input_event;
input_dev->open = hidinput_open; input_dev->open = hidinput_open;
input_dev->close = hidinput_close; input_dev->close = hidinput_close;
......
...@@ -692,7 +692,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -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) { if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 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) { if (ret >= 0) {
/* insert a little delay of 10 jiffies ~ 40ms */ /* 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) ...@@ -704,7 +705,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
buf[1] = 0xB2; buf[1] = 0xB2;
get_random_bytes(&buf[2], 2); 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);
} }
} }
......
...@@ -44,14 +44,6 @@ static const char kbd_descriptor[] = { ...@@ -44,14 +44,6 @@ static const char kbd_descriptor[] = {
0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */ 0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */
0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */ 0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */
0x81, 0x02, /* INPUT (Data,Var,Abs) */ 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) */ 0x95, 0x06, /* REPORT_COUNT (6) */
0x75, 0x08, /* REPORT_SIZE (8) */ 0x75, 0x08, /* REPORT_SIZE (8) */
0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
...@@ -60,6 +52,18 @@ static const char kbd_descriptor[] = { ...@@ -60,6 +52,18 @@ static const char kbd_descriptor[] = {
0x19, 0x00, /* USAGE_MINIMUM (no event) */ 0x19, 0x00, /* USAGE_MINIMUM (no event) */
0x2A, 0xFF, 0x00, /* USAGE_MAXIMUM (reserved) */ 0x2A, 0xFF, 0x00, /* USAGE_MAXIMUM (reserved) */
0x81, 0x00, /* INPUT (Data,Ary,Abs) */ 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 0xC0
}; };
...@@ -544,10 +548,37 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, ...@@ -544,10 +548,37 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
size_t count, size_t count,
unsigned char report_type) unsigned char report_type)
{ {
/* Called by hid raw to send data */ struct dj_device *djdev = hid->driver_data;
dbg_hid("%s\n", __func__); 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) 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,58 +644,6 @@ static int logi_dj_ll_parse(struct hid_device *hid)
return retval; 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) static int logi_dj_ll_start(struct hid_device *hid)
{ {
dbg_hid("%s\n", __func__); dbg_hid("%s\n", __func__);
...@@ -683,7 +662,6 @@ static struct hid_ll_driver logi_dj_ll_driver = { ...@@ -683,7 +662,6 @@ static struct hid_ll_driver logi_dj_ll_driver = {
.stop = logi_dj_ll_stop, .stop = logi_dj_ll_stop,
.open = logi_dj_ll_open, .open = logi_dj_ll_open,
.close = logi_dj_ll_close, .close = logi_dj_ll_close,
.hidinput_input_event = logi_dj_ll_input_event,
}; };
......
...@@ -538,7 +538,7 @@ static int magicmouse_probe(struct hid_device *hdev, ...@@ -538,7 +538,7 @@ static int magicmouse_probe(struct hid_device *hdev,
* but there seems to be no other way of switching the mode. * but there seems to be no other way of switching the mode.
* Thus the super-ugly hacky success check below. * 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); HID_FEATURE_REPORT);
if (ret != -EIO && ret != sizeof(feature)) { if (ret != -EIO && ret != sizeof(feature)) {
hid_err(hdev, "unable to request touch data (%d)\n", ret); hid_err(hdev, "unable to request touch data (%d)\n", ret);
......
...@@ -810,7 +810,8 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) ...@@ -810,7 +810,8 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
if (!buf) if (!buf)
return -ENOMEM; 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) if (ret < 0)
hid_err(hdev, "can't set operational mode\n"); hid_err(hdev, "can't set operational mode\n");
...@@ -823,7 +824,8 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) ...@@ -823,7 +824,8 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
static int sixaxis_set_operational_bt(struct hid_device *hdev) static int sixaxis_set_operational_bt(struct hid_device *hdev)
{ {
unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; 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) 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) ...@@ -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[2] << 3;
buf[10] |= sc->led_state[3] << 4; buf[10] |= sc->led_state[3] << 4;
sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf), hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT);
HID_OUTPUT_REPORT);
} }
static void dualshock4_state_worker(struct work_struct *work) static void dualshock4_state_worker(struct work_struct *work)
......
...@@ -48,8 +48,8 @@ static int blink1_send_command(struct blink1_data *data, ...@@ -48,8 +48,8 @@ static int blink1_send_command(struct blink1_data *data,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[0], buf[1], buf[2], buf[3], buf[4],
buf[5], buf[6], buf[7], buf[8]); buf[5], buf[6], buf[7], buf[8]);
ret = data->hdev->hid_output_raw_report(data->hdev, buf, ret = hid_output_raw_report(data->hdev, buf, BLINK1_CMD_SIZE,
BLINK1_CMD_SIZE, HID_FEATURE_REPORT); HID_FEATURE_REPORT);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
......
...@@ -128,8 +128,7 @@ static void wacom_set_image(struct hid_device *hdev, const char *image, ...@@ -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[0] = WAC_CMD_ICON_START_STOP;
rep_data[1] = 0; rep_data[1] = 0;
ret = hdev->hid_output_raw_report(hdev, rep_data, 2, ret = hid_output_raw_report(hdev, rep_data, 2, HID_FEATURE_REPORT);
HID_FEATURE_REPORT);
if (ret < 0) if (ret < 0)
goto err; goto err;
...@@ -143,15 +142,14 @@ static void wacom_set_image(struct hid_device *hdev, const char *image, ...@@ -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[j + 3] = p[(i << 6) + j];
rep_data[2] = i; 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); HID_FEATURE_REPORT);
} }
rep_data[0] = WAC_CMD_ICON_START_STOP; rep_data[0] = WAC_CMD_ICON_START_STOP;
rep_data[1] = 0; rep_data[1] = 0;
ret = hdev->hid_output_raw_report(hdev, rep_data, 2, ret = hid_output_raw_report(hdev, rep_data, 2, HID_FEATURE_REPORT);
HID_FEATURE_REPORT);
err: err:
return; return;
...@@ -183,7 +181,7 @@ static void wacom_leds_set_brightness(struct led_classdev *led_dev, ...@@ -183,7 +181,7 @@ static void wacom_leds_set_brightness(struct led_classdev *led_dev,
buf[3] = value; buf[3] = value;
/* use fixed brightness for OLEDs */ /* use fixed brightness for OLEDs */
buf[4] = 0x08; 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); kfree(buf);
} }
...@@ -339,7 +337,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed) ...@@ -339,7 +337,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed)
rep_data[0] = 0x03 ; rep_data[1] = 0x00; rep_data[0] = 0x03 ; rep_data[1] = 0x00;
limit = 3; limit = 3;
do { do {
ret = hdev->hid_output_raw_report(hdev, rep_data, 2, ret = hid_output_raw_report(hdev, rep_data, 2,
HID_FEATURE_REPORT); HID_FEATURE_REPORT);
} while (ret < 0 && limit-- > 0); } while (ret < 0 && limit-- > 0);
...@@ -352,7 +350,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed) ...@@ -352,7 +350,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed)
rep_data[1] = 0x00; rep_data[1] = 0x00;
limit = 3; limit = 3;
do { do {
ret = hdev->hid_output_raw_report(hdev, ret = hid_output_raw_report(hdev,
rep_data, 2, HID_FEATURE_REPORT); rep_data, 2, HID_FEATURE_REPORT);
} while (ret < 0 && limit-- > 0); } while (ret < 0 && limit-- > 0);
...@@ -378,7 +376,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed) ...@@ -378,7 +376,7 @@ static void wacom_set_features(struct hid_device *hdev, u8 speed)
rep_data[0] = 0x03; rep_data[0] = 0x03;
rep_data[1] = wdata->features; 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); HID_FEATURE_REPORT);
if (ret >= 0) if (ret >= 0)
wdata->high_speed = speed; wdata->high_speed = speed;
......
...@@ -35,7 +35,7 @@ static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, ...@@ -35,7 +35,7 @@ static int wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
if (!buf) if (!buf)
return -ENOMEM; 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); kfree(buf);
return ret; return ret;
......
...@@ -153,7 +153,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, ...@@ -153,7 +153,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
goto out_free; 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: out_free:
kfree(buf); kfree(buf);
out: out:
...@@ -189,7 +189,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t ...@@ -189,7 +189,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
dev = hidraw_table[minor]->hid; dev = hidraw_table[minor]->hid;
if (!dev->hid_get_raw_report) { if (!dev->ll_driver->raw_request) {
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
...@@ -216,14 +216,15 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t ...@@ -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, * 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)) { if (copy_from_user(&report_number, buffer, 1)) {
ret = -EFAULT; ret = -EFAULT;
goto out_free; 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) if (ret < 0)
goto out_free; goto out_free;
......
...@@ -1005,7 +1005,6 @@ static int i2c_hid_probe(struct i2c_client *client, ...@@ -1005,7 +1005,6 @@ static int i2c_hid_probe(struct i2c_client *client,
hid->driver_data = client; hid->driver_data = client;
hid->ll_driver = &i2c_hid_ll_driver; 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->hid_output_raw_report = i2c_hid_output_raw_report;
hid->dev.parent = &client->dev; hid->dev.parent = &client->dev;
ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev)); ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev));
......
...@@ -244,12 +244,39 @@ static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count, ...@@ -244,12 +244,39 @@ static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
return 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 = { static struct hid_ll_driver uhid_hid_driver = {
.start = uhid_hid_start, .start = uhid_hid_start,
.stop = uhid_hid_stop, .stop = uhid_hid_stop,
.open = uhid_hid_open, .open = uhid_hid_open,
.close = uhid_hid_close, .close = uhid_hid_close,
.parse = uhid_hid_parse, .parse = uhid_hid_parse,
.output_report = uhid_hid_output_report,
}; };
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -377,7 +404,6 @@ static int uhid_dev_create(struct uhid_device *uhid, ...@@ -377,7 +404,6 @@ static int uhid_dev_create(struct uhid_device *uhid,
hid->uniq[63] = 0; hid->uniq[63] = 0;
hid->ll_driver = &uhid_hid_driver; 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->hid_output_raw_report = uhid_hid_output_raw;
hid->bus = ev->u.create.bus; hid->bus = ev->u.create.bus;
hid->vendor = ev->u.create.vendor; hid->vendor = ev->u.create.vendor;
......
...@@ -884,58 +884,78 @@ static int usbhid_get_raw_report(struct hid_device *hid, ...@@ -884,58 +884,78 @@ static int usbhid_get_raw_report(struct hid_device *hid,
return ret; return ret;
} }
static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, static int usbhid_set_raw_report(struct hid_device *hid, unsigned int reportnum,
unsigned char report_type) __u8 *buf, size_t count, unsigned char rtype)
{ {
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
struct usb_device *dev = hid_to_usb_dev(hid); struct usb_device *dev = hid_to_usb_dev(hid);
struct usb_interface *intf = usbhid->intf; struct usb_interface *intf = usbhid->intf;
struct usb_host_interface *interface = intf->cur_altsetting; struct usb_host_interface *interface = intf->cur_altsetting;
int ret; int ret, skipped_report_id = 0;
if (usbhid->urbout && report_type != HID_FEATURE_REPORT) { /* Byte 0 is the report number. Report data starts at byte 1.*/
int actual_length; buf[0] = reportnum;
int skipped_report_id = 0; if (buf[0] == 0x0) {
/* Don't send the Report ID */
buf++;
count--;
skipped_report_id = 1;
}
if (buf[0] == 0x0) { ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
/* 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),
HID_REQ_SET_REPORT, HID_REQ_SET_REPORT,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
((report_type + 1) << 8) | report_id, ((rtype + 1) << 8) | reportnum,
interface->desc.bInterfaceNumber, buf, count, interface->desc.bInterfaceNumber, buf, count,
USB_CTRL_SET_TIMEOUT); USB_CTRL_SET_TIMEOUT);
/* count also the report id, if this was a numbered report. */ /* count also the report id, if this was a numbered report. */
if (ret > 0 && skipped_report_id) 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++; ret++;
} }
return 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) static void usbhid_restart_queues(struct usbhid_device *usbhid)
{ {
if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)) 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 ...@@ -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, static int usbhid_idle(struct hid_device *hid, int report, int idle,
int reqtype) int reqtype)
{ {
...@@ -1223,6 +1257,8 @@ static struct hid_ll_driver usb_hid_driver = { ...@@ -1223,6 +1257,8 @@ static struct hid_ll_driver usb_hid_driver = {
.power = usbhid_power, .power = usbhid_power,
.request = usbhid_request, .request = usbhid_request,
.wait = usbhid_wait_io, .wait = usbhid_wait_io,
.raw_request = usbhid_raw_request,
.output_report = usbhid_output_report,
.idle = usbhid_idle, .idle = usbhid_idle,
}; };
...@@ -1253,7 +1289,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * ...@@ -1253,7 +1289,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
usb_set_intfdata(intf, hid); usb_set_intfdata(intf, hid);
hid->ll_driver = &usb_hid_driver; 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->hid_output_raw_report = usbhid_output_raw_report;
hid->ff_init = hid_pidff_init; hid->ff_init = hid_pidff_init;
#ifdef CONFIG_USB_HIDDEV #ifdef CONFIG_USB_HIDDEV
......
...@@ -508,9 +508,6 @@ struct hid_device { /* device report descriptor */ ...@@ -508,9 +508,6 @@ struct hid_device { /* device report descriptor */
struct hid_usage *, __s32); struct hid_usage *, __s32);
void (*hiddev_report_event) (struct hid_device *, struct hid_report *); void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
/* handler for raw input (Get_Report) data, used by hidraw */
int (*hid_get_raw_report) (struct hid_device *, unsigned char, __u8 *, size_t, unsigned char);
/* handler for raw output data, used by hidraw */ /* handler for raw output data, used by hidraw */
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char); int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
...@@ -675,11 +672,12 @@ struct hid_driver { ...@@ -675,11 +672,12 @@ struct hid_driver {
* @stop: called on remove * @stop: called on remove
* @open: called by input layer on open * @open: called by input layer on open
* @close: called by input layer on close * @close: called by input layer on close
* @hidinput_input_event: event input event (e.g. ff or leds)
* @parse: this method is called only once to parse the device data, * @parse: this method is called only once to parse the device data,
* shouldn't allocate anything to not leak memory * shouldn't allocate anything to not leak memory
* @request: send report request to device (e.g. feature report) * @request: send report request to device (e.g. feature report)
* @wait: wait for buffered io to complete (send/recv reports) * @wait: wait for buffered io to complete (send/recv reports)
* @raw_request: send raw report request to device (e.g. feature report)
* @output_report: send output report to device
* @idle: send idle request to device * @idle: send idle request to device
*/ */
struct hid_ll_driver { struct hid_ll_driver {
...@@ -691,17 +689,20 @@ struct hid_ll_driver { ...@@ -691,17 +689,20 @@ struct hid_ll_driver {
int (*power)(struct hid_device *hdev, int level); int (*power)(struct hid_device *hdev, int level);
int (*hidinput_input_event) (struct input_dev *idev, unsigned int type,
unsigned int code, int value);
int (*parse)(struct hid_device *hdev); int (*parse)(struct hid_device *hdev);
void (*request)(struct hid_device *hdev, void (*request)(struct hid_device *hdev,
struct hid_report *report, int reqtype); struct hid_report *report, int reqtype);
int (*wait)(struct hid_device *hdev); int (*wait)(struct hid_device *hdev);
int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
__u8 *buf, size_t len, unsigned char rtype,
int reqtype);
int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len);
int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
}; };
#define PM_HINT_FULLON 1<<5 #define PM_HINT_FULLON 1<<5
...@@ -967,6 +968,65 @@ static inline void hid_hw_request(struct hid_device *hdev, ...@@ -967,6 +968,65 @@ static inline void hid_hw_request(struct hid_device *hdev,
hdev->ll_driver->request(hdev, report, reqtype); hdev->ll_driver->request(hdev, report, reqtype);
} }
/**
* hid_hw_raw_request - send report request to device
*
* @hdev: hid device
* @reportnum: report ID
* @buf: in/out data to transfer
* @len: length of buf
* @rtype: HID report type
* @reqtype: HID_REQ_GET_REPORT or HID_REQ_SET_REPORT
*
* @return: count of data transfered, negative if error
*
* Same behavior as hid_hw_request, but with raw buffers instead.
*/
static inline int hid_hw_raw_request(struct hid_device *hdev,
unsigned char reportnum, __u8 *buf,
size_t len, unsigned char rtype, int reqtype)
{
if (hdev->ll_driver->raw_request)
return hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
rtype, reqtype);
return -ENOSYS;
}
/**
* hid_hw_output_report - send output report to device
*
* @hdev: hid device
* @buf: raw data to transfer
* @len: length of buf
*
* @return: count of data transfered, negative if error
*/
static inline int hid_hw_output_report(struct hid_device *hdev, __u8 *buf,
size_t len)
{
if (hdev->ll_driver->output_report)
return hdev->ll_driver->output_report(hdev, buf, len);
return -ENOSYS;
}
/**
* hid_output_raw_report - send an output or a feature report to the device
*
* @hdev: hid device
* @buf: raw data to transfer
* @len: length of buf
* @report_type: HID_FEATURE_REPORT or HID_OUTPUT_REPORT
*
* @return: count of data transfered, negative if error
*/
static inline int hid_output_raw_report(struct hid_device *hdev, __u8 *buf,
size_t len, unsigned char report_type)
{
return hdev->hid_output_raw_report(hdev, buf, len, report_type);
}
/** /**
* hid_hw_idle - send idle request to device * hid_hw_idle - send idle request to device
* *
......
...@@ -223,51 +223,6 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) ...@@ -223,51 +223,6 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_sync(dev); input_sync(dev);
} }
static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
{
unsigned char hdr;
u8 *buf;
int rsize, ret;
buf = hid_alloc_report_buf(report, GFP_ATOMIC);
if (!buf)
return -EIO;
hid_output_report(report, buf);
hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
ret = hidp_send_intr_message(session, hdr, buf, rsize);
kfree(buf);
return ret;
}
static int hidp_hidinput_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value)
{
struct hid_device *hid = input_get_drvdata(dev);
struct hidp_session *session = hid->driver_data;
struct hid_field *field;
int offset;
BT_DBG("session %p type %d code %d value %d",
session, type, code, value);
if (type != EV_LED)
return -1;
offset = hidinput_find_field(hid, type, code, &field);
if (offset == -1) {
hid_warn(dev, "event field not found\n");
return -1;
}
hid_set_field(field, offset, value);
return hidp_send_report(session, field->report);
}
static int hidp_get_raw_report(struct hid_device *hid, static int hidp_get_raw_report(struct hid_device *hid,
unsigned char report_number, unsigned char report_number,
unsigned char *data, size_t count, unsigned char *data, size_t count,
...@@ -353,17 +308,24 @@ static int hidp_get_raw_report(struct hid_device *hid, ...@@ -353,17 +308,24 @@ static int hidp_get_raw_report(struct hid_device *hid,
return ret; return ret;
} }
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count, static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum,
unsigned char report_type) unsigned char *data, size_t count,
unsigned char report_type)
{ {
struct hidp_session *session = hid->driver_data; struct hidp_session *session = hid->driver_data;
int ret; int ret;
if (report_type == HID_OUTPUT_REPORT) { switch (report_type) {
report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; case HID_FEATURE_REPORT:
return hidp_send_intr_message(session, report_type, report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
data, count); break;
} else if (report_type != HID_FEATURE_REPORT) { case HID_INPUT_REPORT:
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_INPUT;
break;
case HID_OUTPUT_REPORT:
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
break;
default:
return -EINVAL; return -EINVAL;
} }
...@@ -371,8 +333,8 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s ...@@ -371,8 +333,8 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
return -ERESTARTSYS; return -ERESTARTSYS;
/* Set up our wait, and send the report request to the device. */ /* Set up our wait, and send the report request to the device. */
data[0] = reportnum;
set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
ret = hidp_send_ctrl_message(session, report_type, data, count); ret = hidp_send_ctrl_message(session, report_type, data, count);
if (ret) if (ret)
goto err; goto err;
...@@ -411,6 +373,41 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s ...@@ -411,6 +373,41 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
return ret; return ret;
} }
static int hidp_output_report(struct hid_device *hid, __u8 *data, size_t count)
{
struct hidp_session *session = hid->driver_data;
return hidp_send_intr_message(session,
HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT,
data, count);
}
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data,
size_t count, unsigned char report_type)
{
if (report_type == HID_OUTPUT_REPORT) {
return hidp_output_report(hid, data, count);
} else if (report_type != HID_FEATURE_REPORT) {
return -EINVAL;
}
return hidp_set_raw_report(hid, data[0], data, count, report_type);
}
static int hidp_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 hidp_get_raw_report(hid, reportnum, buf, len, rtype);
case HID_REQ_SET_REPORT:
return hidp_set_raw_report(hid, reportnum, buf, len, rtype);
default:
return -EIO;
}
}
static void hidp_idle_timeout(unsigned long arg) static void hidp_idle_timeout(unsigned long arg)
{ {
struct hidp_session *session = (struct hidp_session *) arg; struct hidp_session *session = (struct hidp_session *) arg;
...@@ -727,7 +724,8 @@ static struct hid_ll_driver hidp_hid_driver = { ...@@ -727,7 +724,8 @@ static struct hid_ll_driver hidp_hid_driver = {
.stop = hidp_stop, .stop = hidp_stop,
.open = hidp_open, .open = hidp_open,
.close = hidp_close, .close = hidp_close,
.hidinput_input_event = hidp_hidinput_event, .raw_request = hidp_raw_request,
.output_report = hidp_output_report,
}; };
/* This function sets up the hid device. It does not add it /* This function sets up the hid device. It does not add it
...@@ -775,7 +773,6 @@ static int hidp_setup_hid(struct hidp_session *session, ...@@ -775,7 +773,6 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->dev.parent = &session->conn->hcon->dev; hid->dev.parent = &session->conn->hcon->dev;
hid->ll_driver = &hidp_hid_driver; hid->ll_driver = &hidp_hid_driver;
hid->hid_get_raw_report = hidp_get_raw_report;
hid->hid_output_raw_report = hidp_output_raw_report; hid->hid_output_raw_report = hidp_output_raw_report;
/* True if device is blacklisted in drivers/hid/hid-core.c */ /* True if device is blacklisted in drivers/hid/hid-core.c */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment