aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/i2c-hid/i2c-hid.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 14:39:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 14:39:00 -0400
commit3366dd9fa887ebbda4872e9554f853eaeda764be (patch)
treed1bb553325b276e9d2a1bce99f3e64834b46866b /drivers/hid/i2c-hid/i2c-hid.c
parent697a067f1ec67f2f8dfafd0a1b95a46997a11f32 (diff)
parent21796b39c9e876a46a353a4a9ff9881766a7c176 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: - HID battery handling cleanup by David Herrmann - ELO 4000/4500 driver, which has been finally ported to be proper HID driver by Jiri Slaby - ps3remote driver functionality is now provided by generic sony driver, by Jiri Kosina - PS2/3 Buzz controllers support, by Colin Leitner - rework of wiimote driver including full extensions hotpluggin support, sub-device modularization and speaker support by David Herrmann * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (55 commits) HID: wacom: Intuos4 battery charging changes HID: i2c-hid: support sending HID output reports using the output register HID: kye: Add report fixup for Genius Gila Gaming mouse HID: wiimote: support Nintendo Wii U Pro Controller Input: make gamepad API keycodes more clear input: document gamepad API and add extra keycodes HID: explain out-of-range check better HID: fix false positive out of range values HID: wiimote: fix coccinelle warnings HID: roccat: check cdev_add return value HID: fold ps3remote driver into generic Sony driver HID: hyperv: convert alloc+memcpy to memdup HID: core: fix reporting of raw events HID: wiimote: discard invalid EXT data reports HID: wiimote: fix classic controller parsing HID: wiimote: init EXT/MP during device detection HID: wiimote: fix DRM debug-attr to correctly parse input HID: wiimote: add MP quirks HID: wiimote: remove old static extension support HID: wiimote: add "bboard_calib" attribute ...
Diffstat (limited to 'drivers/hid/i2c-hid/i2c-hid.c')
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 2b1799a3b212..879b0ed701a3 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -108,6 +108,7 @@ static const struct i2c_hid_cmd hid_reset_cmd = { I2C_HID_CMD(0x01),
108static const struct i2c_hid_cmd hid_get_report_cmd = { I2C_HID_CMD(0x02) }; 108static const struct i2c_hid_cmd hid_get_report_cmd = { I2C_HID_CMD(0x02) };
109static const struct i2c_hid_cmd hid_set_report_cmd = { I2C_HID_CMD(0x03) }; 109static const struct i2c_hid_cmd hid_set_report_cmd = { I2C_HID_CMD(0x03) };
110static const struct i2c_hid_cmd hid_set_power_cmd = { I2C_HID_CMD(0x08) }; 110static const struct i2c_hid_cmd hid_set_power_cmd = { I2C_HID_CMD(0x08) };
111static const struct i2c_hid_cmd hid_no_cmd = { .length = 0 };
111 112
112/* 113/*
113 * These definitions are not used here, but are defined by the spec. 114 * These definitions are not used here, but are defined by the spec.
@@ -259,8 +260,11 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
259{ 260{
260 struct i2c_hid *ihid = i2c_get_clientdata(client); 261 struct i2c_hid *ihid = i2c_get_clientdata(client);
261 u8 *args = ihid->argsbuf; 262 u8 *args = ihid->argsbuf;
263 const struct i2c_hid_cmd * hidcmd = &hid_set_report_cmd;
262 int ret; 264 int ret;
263 u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); 265 u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
266 u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister);
267 u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength);
264 268
265 /* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */ 269 /* hidraw already checked that data_len < HID_MAX_BUFFER_SIZE */
266 u16 size = 2 /* size */ + 270 u16 size = 2 /* size */ +
@@ -278,8 +282,18 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
278 reportID = 0x0F; 282 reportID = 0x0F;
279 } 283 }
280 284
281 args[index++] = dataRegister & 0xFF; 285 /*
282 args[index++] = dataRegister >> 8; 286 * use the data register for feature reports or if the device does not
287 * support the output register
288 */
289 if (reportType == 0x03 || maxOutputLength == 0) {
290 args[index++] = dataRegister & 0xFF;
291 args[index++] = dataRegister >> 8;
292 } else {
293 args[index++] = outputRegister & 0xFF;
294 args[index++] = outputRegister >> 8;
295 hidcmd = &hid_no_cmd;
296 }
283 297
284 args[index++] = size & 0xFF; 298 args[index++] = size & 0xFF;
285 args[index++] = size >> 8; 299 args[index++] = size >> 8;
@@ -289,7 +303,7 @@ static int i2c_hid_set_report(struct i2c_client *client, u8 reportType,
289 303
290 memcpy(&args[index], buf, data_len); 304 memcpy(&args[index], buf, data_len);
291 305
292 ret = __i2c_hid_command(client, &hid_set_report_cmd, reportID, 306 ret = __i2c_hid_command(client, hidcmd, reportID,
293 reportType, args, args_len, NULL, 0); 307 reportType, args, args_len, NULL, 0);
294 if (ret) { 308 if (ret) {
295 dev_err(&client->dev, "failed to set a report to device.\n"); 309 dev_err(&client->dev, "failed to set a report to device.\n");