diff options
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 20 |
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), | |||
108 | static const struct i2c_hid_cmd hid_get_report_cmd = { I2C_HID_CMD(0x02) }; | 108 | static const struct i2c_hid_cmd hid_get_report_cmd = { I2C_HID_CMD(0x02) }; |
109 | static const struct i2c_hid_cmd hid_set_report_cmd = { I2C_HID_CMD(0x03) }; | 109 | static const struct i2c_hid_cmd hid_set_report_cmd = { I2C_HID_CMD(0x03) }; |
110 | static const struct i2c_hid_cmd hid_set_power_cmd = { I2C_HID_CMD(0x08) }; | 110 | static const struct i2c_hid_cmd hid_set_power_cmd = { I2C_HID_CMD(0x08) }; |
111 | static 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"); |