aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/i2c-hid/i2c-hid.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2014-04-01 13:05:09 -0400
committerJiri Kosina <jkosina@suse.cz>2014-04-01 13:05:09 -0400
commitad295b6d5739ab24880a31be403bbc8fab62e177 (patch)
treecd760a18bcfa6e59b8b63fc71e333ba394b1cd9c /drivers/hid/i2c-hid/i2c-hid.c
parentba04a57b4acd05a764471b2accd02000f6641881 (diff)
parentc3d77fab51f40821de91a744e4b514e9e4e76a7c (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.c71
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
260static 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 */
269static 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
561static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, 574static 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
586static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, 599static 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
606static 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
616static int i2c_hid_parse(struct hid_device *hid) 622static 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
774static int i2c_hid_init_irq(struct i2c_client *client) 781static 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;