summaryrefslogtreecommitdiffstats
path: root/drivers/hid/intel-ish-hid/ishtp-hid.c
diff options
context:
space:
mode:
authorHyungwoo Yang <hyungwoo.yang@intel.com>2019-03-04 12:48:54 -0800
committerJiri Kosina <jkosina@suse.cz>2019-03-18 14:46:20 +0100
commite19595fcabb5d09071b9ddb302be98715b77b1b9 (patch)
tree3151170f6e1e1c523a84dc7aa095041b314d0ba5 /drivers/hid/intel-ish-hid/ishtp-hid.c
parentc6400e5cef5eafc259e649ceedc4c7eecc9069d8 (diff)
downloadlinux-stable-e19595fcabb5d09071b9ddb302be98715b77b1b9.tar.gz
linux-stable-e19595fcabb5d09071b9ddb302be98715b77b1b9.tar.bz2
linux-stable-e19595fcabb5d09071b9ddb302be98715b77b1b9.zip
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.c43
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: