summaryrefslogtreecommitdiff
path: root/drivers/hid/hid-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r--drivers/hid/hid-core.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 4741ff626771..b31b8a2fd540 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1883,9 +1883,12 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
/*
* 7 extra bytes are necessary to achieve proper functionality
* of implement() working on 8 byte chunks
+ * 1 extra byte for the report ID if it is null (not used) so
+ * we can reserve that extra byte in the first position of the buffer
+ * when sending it to .raw_request()
*/
- u32 len = hid_report_len(report) + 7;
+ u32 len = hid_report_len(report) + 7 + (report->id == 0);
return kzalloc(len, flags);
}
@@ -1973,7 +1976,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
int __hid_request(struct hid_device *hid, struct hid_report *report,
enum hid_class_request reqtype)
{
- char *buf;
+ char *buf, *data_buf;
int ret;
u32 len;
@@ -1981,13 +1984,19 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
if (!buf)
return -ENOMEM;
+ data_buf = buf;
len = hid_report_len(report);
+ if (report->id == 0) {
+ /* reserve the first byte for the report ID */
+ data_buf++;
+ len++;
+ }
+
if (reqtype == HID_REQ_SET_REPORT)
- hid_output_report(report, buf);
+ hid_output_report(report, data_buf);
- ret = hid->ll_driver->raw_request(hid, report->id, buf, len,
- report->type, reqtype);
+ ret = hid_hw_raw_request(hid, report->id, buf, len, report->type, reqtype);
if (ret < 0) {
dbg_hid("unable to complete request: %d\n", ret);
goto out;
@@ -2396,6 +2405,9 @@ int hid_hw_open(struct hid_device *hdev)
ret = hdev->ll_driver->open(hdev);
if (ret)
hdev->ll_open_count--;
+
+ if (hdev->driver->on_hid_hw_open)
+ hdev->driver->on_hid_hw_open(hdev);
}
mutex_unlock(&hdev->ll_open_lock);
@@ -2415,8 +2427,12 @@ EXPORT_SYMBOL_GPL(hid_hw_open);
void hid_hw_close(struct hid_device *hdev)
{
mutex_lock(&hdev->ll_open_lock);
- if (!--hdev->ll_open_count)
+ if (!--hdev->ll_open_count) {
hdev->ll_driver->close(hdev);
+
+ if (hdev->driver->on_hid_hw_close)
+ hdev->driver->on_hid_hw_close(hdev);
+ }
mutex_unlock(&hdev->ll_open_lock);
}
EXPORT_SYMBOL_GPL(hid_hw_close);