From patchwork Mon Mar 4 20:48:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hyungwoo Yang X-Patchwork-Id: 10838591 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 540BE14DE for ; Mon, 4 Mar 2019 20:48:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3C8E828C5D for ; Mon, 4 Mar 2019 20:48:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2A5662A66A; Mon, 4 Mar 2019 20:48:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9DB4228C5D for ; Mon, 4 Mar 2019 20:48:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726393AbfCDUs4 (ORCPT ); Mon, 4 Mar 2019 15:48:56 -0500 Received: from mga06.intel.com ([134.134.136.31]:15007 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726054AbfCDUsz (ORCPT ); Mon, 4 Mar 2019 15:48:55 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Mar 2019 12:48:55 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,441,1544515200"; d="scan'208";a="279696112" Received: from hyungwoo-ubuntu.sc.intel.com ([10.3.62.78]) by orsmga004.jf.intel.com with ESMTP; 04 Mar 2019 12:48:55 -0800 From: Hyungwoo Yang To: srinivas.pandruvada@linux.intel.com Cc: jikos@kernel.org, benjamin.tissoires@redhat.com, linux-input@vger.kernel.org, hyungwoo.yang@intel.com Subject: [PATCH 1/1] HID: intel-ish: enable raw interface to HID devices on ISH Date: Mon, 4 Mar 2019 12:48:54 -0800 Message-Id: <1551732534-4937-1-git-send-email-hyungwoo.yang@intel.com> X-Mailer: git-send-email 1.9.1 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Acked-by: Srinivas Pandruvada --- drivers/hid/intel-ish-hid/ishtp-hid-client.c | 37 +++++++++++++++++------- drivers/hid/intel-ish-hid/ishtp-hid.c | 43 ++++++++++++++++++++++++++-- drivers/hid/intel-ish-hid/ishtp-hid.h | 8 ++++++ 3 files changed, 74 insertions(+), 14 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c index 30fe0c5..58773a3 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c +++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c @@ -69,13 +69,15 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, unsigned char *payload; struct device_info *dev_info; int i, j; - size_t payload_len, total_len, cur_pos; + size_t payload_len, total_len, cur_pos, raw_len; int report_type; struct report_list *reports_list; char *reports; size_t report_len; struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; int curr_hid_dev = client_data->cur_hid_dev; + struct ishtp_hid_data *hid_data = NULL; + struct hid_device *hid = NULL; payload = recv_buf + sizeof(struct hostif_msg_hdr); total_len = data_len; @@ -219,18 +221,31 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, /* Get index of device that matches this id */ for (i = 0; i < client_data->num_hid_devices; ++i) { if (recv_msg->hdr.device_id == - client_data->hid_devices[i].dev_id) - if (client_data->hid_sensor_hubs[i]) { - hid_input_report( - client_data->hid_sensor_hubs[ - i], - report_type, payload, - payload_len, 0); - ishtp_hid_wakeup( - client_data->hid_sensor_hubs[ - i]); + client_data->hid_devices[i].dev_id) { + hid = client_data->hid_sensor_hubs[i]; + if (!hid) break; + + hid_data = hid->driver_data; + if (hid_data->raw_get_req) { + raw_len = + (hid_data->raw_buf_size < + payload_len) ? + hid_data->raw_buf_size : + payload_len; + + memcpy(hid_data->raw_buf, + payload, raw_len); + } else { + hid_input_report + (hid, report_type, + payload, payload_len, + 0); } + + ishtp_hid_wakeup(hid); + break; + } } break; diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.c b/drivers/hid/intel-ish-hid/ishtp-hid.c index bc4c536..5c7e127 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: diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.h b/drivers/hid/intel-ish-hid/ishtp-hid.h index 1cd07a4..40663639 100644 --- a/drivers/hid/intel-ish-hid/ishtp-hid.h +++ b/drivers/hid/intel-ish-hid/ishtp-hid.h @@ -159,6 +159,9 @@ struct ishtp_cl_data { * @client_data: Link to the client instance * @hid_wait: Completion waitq * + * @raw_get_req: Flag indicating raw get request ongoing + * @raw_buf: raw request buffer filled on receiving get report + * @raw_buf_size: raw request buffer size * Used to tie hid hid->driver data to driver client instance */ struct ishtp_hid_data { @@ -166,6 +169,11 @@ struct ishtp_hid_data { bool request_done; struct ishtp_cl_data *client_data; wait_queue_head_t hid_wait; + + /* raw request */ + bool raw_get_req; + u8 *raw_buf; + size_t raw_buf_size; }; /* Interface functions between HID LL driver and ISH TP client */