diff options
author | Hyungwoo Yang <hyungwoo.yang@intel.com> | 2019-03-04 12:48:54 -0800 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2019-03-18 14:46:20 +0100 |
commit | e19595fcabb5d09071b9ddb302be98715b77b1b9 (patch) | |
tree | 3151170f6e1e1c523a84dc7aa095041b314d0ba5 /drivers/hid/intel-ish-hid/ishtp-hid.c | |
parent | c6400e5cef5eafc259e649ceedc4c7eecc9069d8 (diff) |
HID: intel-ish: enable raw interface to HID devices on ISH
Raw interface is often used to update firmwares in HID devices.
We are enabling the interface to support in-field firmware update
for the HID devices attached to ISH.
Signed-off-by: Hyungwoo Yang <hyungwoo.yang@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/intel-ish-hid/ishtp-hid.c')
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp-hid.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.c b/drivers/hid/intel-ish-hid/ishtp-hid.c index bc4c536f3c0d..5c7e127b0483 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid.c +++ b/drivers/hid/intel-ish-hid/ishtp-hid.c @@ -59,10 +59,46 @@ static void ishtp_hid_close(struct hid_device *hid) { } -static int ishtp_raw_request(struct hid_device *hdev, unsigned char reportnum, - __u8 *buf, size_t len, unsigned char rtype, int reqtype) +static int ishtp_raw_request(struct hid_device *hid, unsigned char reportnum, + __u8 *buf, size_t len, unsigned char rtype, + int reqtype) { - return 0; + struct ishtp_hid_data *hid_data = hid->driver_data; + char *ishtp_buf = NULL; + size_t ishtp_buf_len; + unsigned int header_size = sizeof(struct hostif_msg); + + if (rtype == HID_OUTPUT_REPORT) + return -EINVAL; + + hid_data->request_done = false; + switch (reqtype) { + case HID_REQ_GET_REPORT: + hid_data->raw_buf = buf; + hid_data->raw_buf_size = len; + hid_data->raw_get_req = true; + + hid_ishtp_get_report(hid, reportnum, rtype); + break; + case HID_REQ_SET_REPORT: + /* + * Spare 7 bytes for 64b accesses through + * get/put_unaligned_le64() + */ + ishtp_buf_len = len + header_size; + ishtp_buf = kzalloc(ishtp_buf_len + 7, GFP_KERNEL); + if (!ishtp_buf) + return -ENOMEM; + + memcpy(ishtp_buf + header_size, buf, len); + hid_ishtp_set_feature(hid, ishtp_buf, ishtp_buf_len, reportnum); + kfree(ishtp_buf); + break; + } + + hid_hw_wait(hid); + + return len; } /** @@ -87,6 +123,7 @@ static void ishtp_hid_request(struct hid_device *hid, struct hid_report *rep, hid_data->request_done = false; switch (reqtype) { case HID_REQ_GET_REPORT: + hid_data->raw_get_req = false; hid_ishtp_get_report(hid, rep->id, rep->type); break; case HID_REQ_SET_REPORT: |