aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/i2c-hid/i2c-hid.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-02-10 12:58:49 -0500
committerJiri Kosina <jkosina@suse.cz>2014-02-17 08:53:09 -0500
commit9b5a9ae88573884224a26fda0e3eb6a6ec48686d (patch)
tree073210d6f79259918a9fd76ff8fe91c2d2ddd3d4 /drivers/hid/i2c-hid/i2c-hid.c
parent4fa5a7f76cc7b6ac87f57741edd2b124851d119f (diff)
HID: i2c-hid: implement ll_driver transport-layer callbacks
Add output_report and raw_request to i2c-hid. The current implementation of i2c_hid_output_raw_report decides by itself if it should use a direct send of the output report or use the data register (SET_REPORT). Split that by reimplement the logic in __i2c_hid_output_raw_report() which will be dropped soon. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/i2c-hid/i2c-hid.c')
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c69
1 files changed, 60 insertions, 9 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index f4ea7343e823..b48f49d1f0dd 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -256,12 +256,21 @@ static int i2c_hid_get_report(struct i2c_client *client, u8 reportType,
256 return 0; 256 return 0;
257} 257}
258 258
259static int i2c_hid_set_report(struct i2c_client *client, u8 reportType, 259/**
260 u8 reportID, unsigned char *buf, size_t data_len) 260 * i2c_hid_set_or_send_report: forward an incoming report to the device
261 * @client: the i2c_client of the device
262 * @reportType: 0x03 for HID_FEATURE_REPORT ; 0x02 for HID_OUTPUT_REPORT
263 * @reportID: the report ID
264 * @buf: the actual data to transfer, without the report ID
265 * @len: size of buf
266 * @use_data: true: use SET_REPORT HID command, false: send plain OUTPUT report
267 */
268static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType,
269 u8 reportID, unsigned char *buf, size_t data_len, bool use_data)
261{ 270{
262 struct i2c_hid *ihid = i2c_get_clientdata(client); 271 struct i2c_hid *ihid = i2c_get_clientdata(client);
263 u8 *args = ihid->argsbuf; 272 u8 *args = ihid->argsbuf;
264 const struct i2c_hid_cmd * hidcmd = &hid_set_report_cmd; 273 const struct i2c_hid_cmd *hidcmd;
265 int ret; 274 int ret;
266 u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); 275 u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
267 u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); 276 u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister);
@@ -278,6 +287,9 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
278 287
279 i2c_hid_dbg(ihid, "%s\n", __func__); 288 i2c_hid_dbg(ihid, "%s\n", __func__);
280 289
290 if (!use_data && maxOutputLength == 0)
291 return -ENOSYS;
292
281 if (reportID >= 0x0F) { 293 if (reportID >= 0x0F) {
282 args[index++] = reportID; 294 args[index++] = reportID;
283 reportID = 0x0F; 295 reportID = 0x0F;
@@ -287,9 +299,10 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
287 * use the data register for feature reports or if the device does not 299 * use the data register for feature reports or if the device does not
288 * support the output register 300 * support the output register
289 */ 301 */
290 if (reportType == 0x03 || maxOutputLength == 0) { 302 if (use_data) {
291 args[index++] = dataRegister & 0xFF; 303 args[index++] = dataRegister & 0xFF;
292 args[index++] = dataRegister >> 8; 304 args[index++] = dataRegister >> 8;
305 hidcmd = &hid_set_report_cmd;
293 } else { 306 } else {
294 args[index++] = outputRegister & 0xFF; 307 args[index++] = outputRegister & 0xFF;
295 args[index++] = outputRegister >> 8; 308 args[index++] = outputRegister >> 8;
@@ -550,7 +563,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid,
550} 563}
551 564
552static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, 565static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
553 size_t count, unsigned char report_type) 566 size_t count, unsigned char report_type, bool use_data)
554{ 567{
555 struct i2c_client *client = hid->driver_data; 568 struct i2c_client *client = hid->driver_data;
556 int report_id = buf[0]; 569 int report_id = buf[0];
@@ -564,9 +577,9 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
564 count--; 577 count--;
565 } 578 }
566 579
567 ret = i2c_hid_set_report(client, 580 ret = i2c_hid_set_or_send_report(client,
568 report_type == HID_FEATURE_REPORT ? 0x03 : 0x02, 581 report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
569 report_id, buf, count); 582 report_id, buf, count, use_data);
570 583
571 if (report_id && ret >= 0) 584 if (report_id && ret >= 0)
572 ret++; /* add report_id to the number of transfered bytes */ 585 ret++; /* add report_id to the number of transfered bytes */
@@ -574,6 +587,42 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
574 return ret; 587 return ret;
575} 588}
576 589
590static int __i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
591 size_t count, unsigned char report_type)
592{
593 struct i2c_client *client = hid->driver_data;
594 struct i2c_hid *ihid = i2c_get_clientdata(client);
595 bool data = true; /* SET_REPORT */
596
597 if (report_type == HID_OUTPUT_REPORT)
598 data = le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0;
599
600 return i2c_hid_output_raw_report(hid, buf, count, report_type, data);
601}
602
603static int i2c_hid_output_report(struct hid_device *hid, __u8 *buf,
604 size_t count)
605{
606 return i2c_hid_output_raw_report(hid, buf, count, HID_OUTPUT_REPORT,
607 false);
608}
609
610static int i2c_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
611 __u8 *buf, size_t len, unsigned char rtype,
612 int reqtype)
613{
614 switch (reqtype) {
615 case HID_REQ_GET_REPORT:
616 return i2c_hid_get_raw_report(hid, reportnum, buf, len, rtype);
617 case HID_REQ_SET_REPORT:
618 if (buf[0] != reportnum)
619 return -EINVAL;
620 return i2c_hid_output_raw_report(hid, buf, len, rtype, true);
621 default:
622 return -EIO;
623 }
624}
625
577static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, 626static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
578 int reqtype) 627 int reqtype)
579{ 628{
@@ -597,7 +646,7 @@ static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
597 break; 646 break;
598 case HID_REQ_SET_REPORT: 647 case HID_REQ_SET_REPORT:
599 hid_output_report(rep, buf); 648 hid_output_report(rep, buf);
600 i2c_hid_output_raw_report(hid, buf, len, rep->type); 649 i2c_hid_output_raw_report(hid, buf, len, rep->type, true);
601 break; 650 break;
602 } 651 }
603 652
@@ -761,6 +810,8 @@ static struct hid_ll_driver i2c_hid_ll_driver = {
761 .close = i2c_hid_close, 810 .close = i2c_hid_close,
762 .power = i2c_hid_power, 811 .power = i2c_hid_power,
763 .request = i2c_hid_request, 812 .request = i2c_hid_request,
813 .output_report = i2c_hid_output_report,
814 .raw_request = i2c_hid_raw_request,
764}; 815};
765 816
766static int i2c_hid_init_irq(struct i2c_client *client) 817static int i2c_hid_init_irq(struct i2c_client *client)
@@ -1005,7 +1056,7 @@ static int i2c_hid_probe(struct i2c_client *client,
1005 1056
1006 hid->driver_data = client; 1057 hid->driver_data = client;
1007 hid->ll_driver = &i2c_hid_ll_driver; 1058 hid->ll_driver = &i2c_hid_ll_driver;
1008 hid->hid_output_raw_report = i2c_hid_output_raw_report; 1059 hid->hid_output_raw_report = __i2c_hid_output_raw_report;
1009 hid->dev.parent = &client->dev; 1060 hid->dev.parent = &client->dev;
1010 ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev)); 1061 ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev));
1011 hid->bus = BUS_I2C; 1062 hid->bus = BUS_I2C;