diff options
author | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 13:05:09 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-04-01 13:05:09 -0400 |
commit | ad295b6d5739ab24880a31be403bbc8fab62e177 (patch) | |
tree | cd760a18bcfa6e59b8b63fc71e333ba394b1cd9c /drivers/hid/i2c-hid/i2c-hid.c | |
parent | ba04a57b4acd05a764471b2accd02000f6641881 (diff) | |
parent | c3d77fab51f40821de91a744e4b514e9e4e76a7c (diff) |
Merge branch 'for-3.15/hid-core-ll-transport-cleanup' into for-linus
Conflicts:
drivers/hid/hid-ids.h
drivers/hid/hid-sony.c
drivers/hid/i2c-hid/i2c-hid.c
Diffstat (limited to 'drivers/hid/i2c-hid/i2c-hid.c')
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index c121990c6beb..8c52a07d5652 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
@@ -257,18 +257,27 @@ static int i2c_hid_get_report(struct i2c_client *client, u8 reportType, | |||
257 | return 0; | 257 | return 0; |
258 | } | 258 | } |
259 | 259 | ||
260 | static int i2c_hid_set_report(struct i2c_client *client, u8 reportType, | 260 | /** |
261 | u8 reportID, unsigned char *buf, size_t data_len) | 261 | * i2c_hid_set_or_send_report: forward an incoming report to the device |
262 | * @client: the i2c_client of the device | ||
263 | * @reportType: 0x03 for HID_FEATURE_REPORT ; 0x02 for HID_OUTPUT_REPORT | ||
264 | * @reportID: the report ID | ||
265 | * @buf: the actual data to transfer, without the report ID | ||
266 | * @len: size of buf | ||
267 | * @use_data: true: use SET_REPORT HID command, false: send plain OUTPUT report | ||
268 | */ | ||
269 | static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType, | ||
270 | u8 reportID, unsigned char *buf, size_t data_len, bool use_data) | ||
262 | { | 271 | { |
263 | struct i2c_hid *ihid = i2c_get_clientdata(client); | 272 | struct i2c_hid *ihid = i2c_get_clientdata(client); |
264 | u8 *args = ihid->argsbuf; | 273 | u8 *args = ihid->argsbuf; |
265 | const struct i2c_hid_cmd * hidcmd = &hid_set_report_cmd; | 274 | const struct i2c_hid_cmd *hidcmd; |
266 | int ret; | 275 | int ret; |
267 | u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); | 276 | u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); |
268 | u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); | 277 | u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); |
269 | u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength); | 278 | u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength); |
270 | 279 | ||
271 | /* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */ | 280 | /* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */ |
272 | u16 size = 2 /* size */ + | 281 | u16 size = 2 /* size */ + |
273 | (reportID ? 1 : 0) /* reportID */ + | 282 | (reportID ? 1 : 0) /* reportID */ + |
274 | data_len /* buf */; | 283 | data_len /* buf */; |
@@ -279,6 +288,9 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType, | |||
279 | 288 | ||
280 | i2c_hid_dbg(ihid, "%s\n", __func__); | 289 | i2c_hid_dbg(ihid, "%s\n", __func__); |
281 | 290 | ||
291 | if (!use_data && maxOutputLength == 0) | ||
292 | return -ENOSYS; | ||
293 | |||
282 | if (reportID >= 0x0F) { | 294 | if (reportID >= 0x0F) { |
283 | args[index++] = reportID; | 295 | args[index++] = reportID; |
284 | reportID = 0x0F; | 296 | reportID = 0x0F; |
@@ -288,9 +300,10 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType, | |||
288 | * use the data register for feature reports or if the device does not | 300 | * use the data register for feature reports or if the device does not |
289 | * support the output register | 301 | * support the output register |
290 | */ | 302 | */ |
291 | if (reportType == 0x03 || maxOutputLength == 0) { | 303 | if (use_data) { |
292 | args[index++] = dataRegister & 0xFF; | 304 | args[index++] = dataRegister & 0xFF; |
293 | args[index++] = dataRegister >> 8; | 305 | args[index++] = dataRegister >> 8; |
306 | hidcmd = &hid_set_report_cmd; | ||
294 | } else { | 307 | } else { |
295 | args[index++] = outputRegister & 0xFF; | 308 | args[index++] = outputRegister & 0xFF; |
296 | args[index++] = outputRegister >> 8; | 309 | args[index++] = outputRegister >> 8; |
@@ -559,7 +572,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, | |||
559 | } | 572 | } |
560 | 573 | ||
561 | static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, | 574 | static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, |
562 | size_t count, unsigned char report_type) | 575 | size_t count, unsigned char report_type, bool use_data) |
563 | { | 576 | { |
564 | struct i2c_client *client = hid->driver_data; | 577 | struct i2c_client *client = hid->driver_data; |
565 | int report_id = buf[0]; | 578 | int report_id = buf[0]; |
@@ -573,9 +586,9 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, | |||
573 | count--; | 586 | count--; |
574 | } | 587 | } |
575 | 588 | ||
576 | ret = i2c_hid_set_report(client, | 589 | ret = i2c_hid_set_or_send_report(client, |
577 | report_type == HID_FEATURE_REPORT ? 0x03 : 0x02, | 590 | report_type == HID_FEATURE_REPORT ? 0x03 : 0x02, |
578 | report_id, buf, count); | 591 | report_id, buf, count, use_data); |
579 | 592 | ||
580 | if (report_id && ret >= 0) | 593 | if (report_id && ret >= 0) |
581 | ret++; /* add report_id to the number of transfered bytes */ | 594 | ret++; /* add report_id to the number of transfered bytes */ |
@@ -583,34 +596,27 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, | |||
583 | return ret; | 596 | return ret; |
584 | } | 597 | } |
585 | 598 | ||
586 | static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, | 599 | static int i2c_hid_output_report(struct hid_device *hid, __u8 *buf, |
587 | int reqtype) | 600 | size_t count) |
588 | { | 601 | { |
589 | struct i2c_client *client = hid->driver_data; | 602 | return i2c_hid_output_raw_report(hid, buf, count, HID_OUTPUT_REPORT, |
590 | char *buf; | 603 | false); |
591 | int ret; | 604 | } |
592 | int len = i2c_hid_get_report_length(rep) - 2; | ||
593 | |||
594 | buf = hid_alloc_report_buf(rep, GFP_KERNEL); | ||
595 | if (!buf) | ||
596 | return; | ||
597 | 605 | ||
606 | static int i2c_hid_raw_request(struct hid_device *hid, unsigned char reportnum, | ||
607 | __u8 *buf, size_t len, unsigned char rtype, | ||
608 | int reqtype) | ||
609 | { | ||
598 | switch (reqtype) { | 610 | switch (reqtype) { |
599 | case HID_REQ_GET_REPORT: | 611 | case HID_REQ_GET_REPORT: |
600 | ret = i2c_hid_get_raw_report(hid, rep->id, buf, len, rep->type); | 612 | return i2c_hid_get_raw_report(hid, reportnum, buf, len, rtype); |
601 | if (ret < 0) | ||
602 | dev_err(&client->dev, "%s: unable to get report: %d\n", | ||
603 | __func__, ret); | ||
604 | else | ||
605 | hid_input_report(hid, rep->type, buf, ret, 0); | ||
606 | break; | ||
607 | case HID_REQ_SET_REPORT: | 613 | case HID_REQ_SET_REPORT: |
608 | hid_output_report(rep, buf); | 614 | if (buf[0] != reportnum) |
609 | i2c_hid_output_raw_report(hid, buf, len, rep->type); | 615 | return -EINVAL; |
610 | break; | 616 | return i2c_hid_output_raw_report(hid, buf, len, rtype, true); |
617 | default: | ||
618 | return -EIO; | ||
611 | } | 619 | } |
612 | |||
613 | kfree(buf); | ||
614 | } | 620 | } |
615 | 621 | ||
616 | static int i2c_hid_parse(struct hid_device *hid) | 622 | static int i2c_hid_parse(struct hid_device *hid) |
@@ -768,7 +774,8 @@ static struct hid_ll_driver i2c_hid_ll_driver = { | |||
768 | .open = i2c_hid_open, | 774 | .open = i2c_hid_open, |
769 | .close = i2c_hid_close, | 775 | .close = i2c_hid_close, |
770 | .power = i2c_hid_power, | 776 | .power = i2c_hid_power, |
771 | .request = i2c_hid_request, | 777 | .output_report = i2c_hid_output_report, |
778 | .raw_request = i2c_hid_raw_request, | ||
772 | }; | 779 | }; |
773 | 780 | ||
774 | static int i2c_hid_init_irq(struct i2c_client *client) | 781 | static int i2c_hid_init_irq(struct i2c_client *client) |
@@ -1017,8 +1024,6 @@ static int i2c_hid_probe(struct i2c_client *client, | |||
1017 | 1024 | ||
1018 | hid->driver_data = client; | 1025 | hid->driver_data = client; |
1019 | hid->ll_driver = &i2c_hid_ll_driver; | 1026 | hid->ll_driver = &i2c_hid_ll_driver; |
1020 | hid->hid_get_raw_report = i2c_hid_get_raw_report; | ||
1021 | hid->hid_output_raw_report = i2c_hid_output_raw_report; | ||
1022 | hid->dev.parent = &client->dev; | 1027 | hid->dev.parent = &client->dev; |
1023 | ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev)); | 1028 | ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev)); |
1024 | hid->bus = BUS_I2C; | 1029 | hid->bus = BUS_I2C; |