Commit e19595fc authored by Hyungwoo Yang's avatar Hyungwoo Yang Committed by Jiri Kosina
Browse files

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: default avatarHyungwoo Yang <hyungwoo.yang@intel.com>
Acked-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent c6400e5c
Loading
Loading
Loading
Loading
+26 −11
Original line number Diff line number Diff line
@@ -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,16 +221,29 @@ do_get_report:
			/* 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;
				}
			}
+40 −3
Original line number Diff line number Diff line
@@ -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:
+8 −0
Original line number Diff line number Diff line
@@ -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 */