Re: [PATCH 1/1] HID: intel-ish: enable raw interface to HID devices on ISH

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2019-03-04 at 12:48 -0800, Hyungwoo Yang wrote:
> 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@xxxxxxxxx>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx>

But this is a new feature, so it can only go to v5.2+ kernel.

Thanks,
Srinivas

> ---
>  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 */




[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux