2 * ISHTP client driver for HID (ISH)
4 * Copyright (c) 2014-2016, Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 #include <linux/module.h>
17 #include <linux/hid.h>
18 #include <linux/sched.h>
19 #include "ishtp/ishtp-dev.h"
20 #include "ishtp/client.h"
21 #include "ishtp-hid.h"
23 /* Rx ring buffer pool size */
24 #define HID_CL_RX_RING_SIZE 32
25 #define HID_CL_TX_RING_SIZE 16
28 * report_bad_packets() - Report bad packets
29 * @hid_ishtp_cl: Client instance to get stats
30 * @recv_buf: Raw received host interface message
31 * @cur_pos: Current position index in payload
32 * @payload_len: Length of payload expected
34 * Dumps error in case bad packet is received
36 static void report_bad_packet(struct ishtp_cl
*hid_ishtp_cl
, void *recv_buf
,
37 size_t cur_pos
, size_t payload_len
)
39 struct hostif_msg
*recv_msg
= recv_buf
;
40 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
42 dev_err(&client_data
->cl_device
->dev
, "[hid-ish]: BAD packet %02X\n"
43 "total_bad=%u cur_pos=%u\n"
44 "[%02X %02X %02X %02X]\n"
46 "multi_packet_cnt=%u\n"
48 recv_msg
->hdr
.command
, client_data
->bad_recv_cnt
,
49 (unsigned int)cur_pos
,
50 ((unsigned char *)recv_msg
)[0], ((unsigned char *)recv_msg
)[1],
51 ((unsigned char *)recv_msg
)[2], ((unsigned char *)recv_msg
)[3],
52 (unsigned int)payload_len
, client_data
->multi_packet_cnt
,
53 recv_msg
->hdr
.command
& ~CMD_MASK
);
57 * process_recv() - Received and parse incoming packet
58 * @hid_ishtp_cl: Client instance to get stats
59 * @recv_buf: Raw received host interface message
60 * @data_len: length of the message
62 * Parse the incoming packet. If it is a response packet then it will update
63 * per instance flags and wake up the caller waiting to for the response.
65 static void process_recv(struct ishtp_cl
*hid_ishtp_cl
, void *recv_buf
,
68 struct hostif_msg
*recv_msg
;
69 unsigned char *payload
;
70 struct device_info
*dev_info
;
72 size_t payload_len
, total_len
, cur_pos
;
74 struct report_list
*reports_list
;
77 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
78 int curr_hid_dev
= client_data
->cur_hid_dev
;
80 if (data_len
< sizeof(struct hostif_msg_hdr
)) {
81 dev_err(&client_data
->cl_device
->dev
,
82 "[hid-ish]: error, received %u which is less than data header %u\n",
83 (unsigned int)data_len
,
84 (unsigned int)sizeof(struct hostif_msg_hdr
));
85 ++client_data
->bad_recv_cnt
;
86 ish_hw_reset(hid_ishtp_cl
->dev
);
90 payload
= recv_buf
+ sizeof(struct hostif_msg_hdr
);
95 recv_msg
= (struct hostif_msg
*)(recv_buf
+ cur_pos
);
96 payload_len
= recv_msg
->hdr
.size
;
99 if (cur_pos
+ payload_len
+ sizeof(struct hostif_msg
) >
101 ++client_data
->bad_recv_cnt
;
102 report_bad_packet(hid_ishtp_cl
, recv_msg
, cur_pos
,
104 ish_hw_reset(hid_ishtp_cl
->dev
);
108 hid_ishtp_trace(client_data
, "%s %d\n",
109 __func__
, recv_msg
->hdr
.command
& CMD_MASK
);
111 switch (recv_msg
->hdr
.command
& CMD_MASK
) {
112 case HOSTIF_DM_ENUM_DEVICES
:
113 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
114 client_data
->init_done
)) {
115 ++client_data
->bad_recv_cnt
;
116 report_bad_packet(hid_ishtp_cl
, recv_msg
,
119 ish_hw_reset(hid_ishtp_cl
->dev
);
122 client_data
->hid_dev_count
= (unsigned int)*payload
;
123 if (!client_data
->hid_devices
)
124 client_data
->hid_devices
= devm_kzalloc(
125 &client_data
->cl_device
->dev
,
126 client_data
->hid_dev_count
*
127 sizeof(struct device_info
),
129 if (!client_data
->hid_devices
) {
130 dev_err(&client_data
->cl_device
->dev
,
131 "Mem alloc failed for hid device info\n");
132 wake_up_interruptible(&client_data
->init_wait
);
135 for (i
= 0; i
< client_data
->hid_dev_count
; ++i
) {
136 if (1 + sizeof(struct device_info
) * i
>=
138 dev_err(&client_data
->cl_device
->dev
,
139 "[hid-ish]: [ENUM_DEVICES]: content size %lu is bigger than payload_len %u\n",
140 1 + sizeof(struct device_info
)
142 (unsigned int)payload_len
);
145 if (1 + sizeof(struct device_info
) * i
>=
149 dev_info
= (struct device_info
*)(payload
+ 1 +
150 sizeof(struct device_info
) * i
);
151 if (client_data
->hid_devices
)
152 memcpy(client_data
->hid_devices
+ i
,
154 sizeof(struct device_info
));
157 client_data
->enum_devices_done
= true;
158 wake_up_interruptible(&client_data
->init_wait
);
162 case HOSTIF_GET_HID_DESCRIPTOR
:
163 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
164 client_data
->init_done
)) {
165 ++client_data
->bad_recv_cnt
;
166 report_bad_packet(hid_ishtp_cl
, recv_msg
,
169 ish_hw_reset(hid_ishtp_cl
->dev
);
172 if (!client_data
->hid_descr
[curr_hid_dev
])
173 client_data
->hid_descr
[curr_hid_dev
] =
174 devm_kmalloc(&client_data
->cl_device
->dev
,
175 payload_len
, GFP_KERNEL
);
176 if (client_data
->hid_descr
[curr_hid_dev
]) {
177 memcpy(client_data
->hid_descr
[curr_hid_dev
],
178 payload
, payload_len
);
179 client_data
->hid_descr_size
[curr_hid_dev
] =
181 client_data
->hid_descr_done
= true;
183 wake_up_interruptible(&client_data
->init_wait
);
187 case HOSTIF_GET_REPORT_DESCRIPTOR
:
188 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
189 client_data
->init_done
)) {
190 ++client_data
->bad_recv_cnt
;
191 report_bad_packet(hid_ishtp_cl
, recv_msg
,
194 ish_hw_reset(hid_ishtp_cl
->dev
);
197 if (!client_data
->report_descr
[curr_hid_dev
])
198 client_data
->report_descr
[curr_hid_dev
] =
199 devm_kmalloc(&client_data
->cl_device
->dev
,
200 payload_len
, GFP_KERNEL
);
201 if (client_data
->report_descr
[curr_hid_dev
]) {
202 memcpy(client_data
->report_descr
[curr_hid_dev
],
205 client_data
->report_descr_size
[curr_hid_dev
] =
207 client_data
->report_descr_done
= true;
209 wake_up_interruptible(&client_data
->init_wait
);
213 case HOSTIF_GET_FEATURE_REPORT
:
214 report_type
= HID_FEATURE_REPORT
;
217 case HOSTIF_GET_INPUT_REPORT
:
218 report_type
= HID_INPUT_REPORT
;
220 /* Get index of device that matches this id */
221 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
222 if (recv_msg
->hdr
.device_id
==
223 client_data
->hid_devices
[i
].dev_id
)
224 if (client_data
->hid_sensor_hubs
[i
]) {
226 client_data
->hid_sensor_hubs
[
228 report_type
, payload
,
231 client_data
->hid_sensor_hubs
[
238 case HOSTIF_SET_FEATURE_REPORT
:
239 /* Get index of device that matches this id */
240 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
241 if (recv_msg
->hdr
.device_id
==
242 client_data
->hid_devices
[i
].dev_id
)
243 if (client_data
->hid_sensor_hubs
[i
]) {
245 client_data
->hid_sensor_hubs
[
252 case HOSTIF_PUBLISH_INPUT_REPORT
:
253 report_type
= HID_INPUT_REPORT
;
254 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
)
255 if (recv_msg
->hdr
.device_id
==
256 client_data
->hid_devices
[i
].dev_id
)
257 if (client_data
->hid_sensor_hubs
[i
])
259 client_data
->hid_sensor_hubs
[
261 report_type
, payload
,
265 case HOSTIF_PUBLISH_INPUT_REPORT_LIST
:
266 report_type
= HID_INPUT_REPORT
;
267 reports_list
= (struct report_list
*)payload
;
268 reports
= (char *)reports_list
->reports
;
270 for (j
= 0; j
< reports_list
->num_of_reports
; j
++) {
271 recv_msg
= (struct hostif_msg
*)(reports
+
273 report_len
= *(uint16_t *)reports
;
274 payload
= reports
+ sizeof(uint16_t) +
275 sizeof(struct hostif_msg_hdr
);
276 payload_len
= report_len
-
277 sizeof(struct hostif_msg_hdr
);
279 for (i
= 0; i
< client_data
->num_hid_devices
;
281 if (recv_msg
->hdr
.device_id
==
282 client_data
->hid_devices
[i
].dev_id
&&
283 client_data
->hid_sensor_hubs
[i
]) {
285 client_data
->hid_sensor_hubs
[
288 payload
, payload_len
,
292 reports
+= sizeof(uint16_t) + report_len
;
296 ++client_data
->bad_recv_cnt
;
297 report_bad_packet(hid_ishtp_cl
, recv_msg
, cur_pos
,
299 ish_hw_reset(hid_ishtp_cl
->dev
);
304 if (!cur_pos
&& cur_pos
+ payload_len
+
305 sizeof(struct hostif_msg
) < total_len
)
306 ++client_data
->multi_packet_cnt
;
308 cur_pos
+= payload_len
+ sizeof(struct hostif_msg
);
309 payload
+= payload_len
+ sizeof(struct hostif_msg
);
311 } while (cur_pos
< total_len
);
315 * ish_cl_event_cb() - bus driver callback for incoming message/packet
316 * @device: Pointer to the the ishtp client device for which this message
319 * Remove the packet from the list and process the message by calling
322 static void ish_cl_event_cb(struct ishtp_cl_device
*device
)
324 struct ishtp_cl
*hid_ishtp_cl
= device
->driver_data
;
325 struct ishtp_cl_rb
*rb_in_proc
;
332 spin_lock_irqsave(&hid_ishtp_cl
->in_process_spinlock
, flags
);
333 while (!list_empty(&hid_ishtp_cl
->in_process_list
.list
)) {
334 rb_in_proc
= list_entry(
335 hid_ishtp_cl
->in_process_list
.list
.next
,
336 struct ishtp_cl_rb
, list
);
337 list_del_init(&rb_in_proc
->list
);
338 spin_unlock_irqrestore(&hid_ishtp_cl
->in_process_spinlock
,
341 if (!rb_in_proc
->buffer
.data
)
344 r_length
= rb_in_proc
->buf_idx
;
346 /* decide what to do with received data */
347 process_recv(hid_ishtp_cl
, rb_in_proc
->buffer
.data
, r_length
);
349 ishtp_cl_io_rb_recycle(rb_in_proc
);
350 spin_lock_irqsave(&hid_ishtp_cl
->in_process_spinlock
, flags
);
352 spin_unlock_irqrestore(&hid_ishtp_cl
->in_process_spinlock
, flags
);
356 * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
357 * @hid: hid device instance for this request
358 * @buf: feature buffer
359 * @len: Length of feature buffer
360 * @report_id: Report id for the feature set request
362 * This is called from hid core .request() callback. This function doesn't wait
365 void hid_ishtp_set_feature(struct hid_device
*hid
, char *buf
, unsigned int len
,
368 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
369 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
370 struct hostif_msg
*msg
= (struct hostif_msg
*)buf
;
374 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
376 rv
= ishtp_hid_link_ready_wait(client_data
);
378 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
383 memset(msg
, 0, sizeof(struct hostif_msg
));
384 msg
->hdr
.command
= HOSTIF_SET_FEATURE_REPORT
;
385 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
386 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
388 client_data
->hid_devices
[i
].dev_id
;
393 if (i
== client_data
->num_hid_devices
)
396 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, buf
, len
);
398 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
403 * hid_ishtp_get_report() - request to get feature/input report
404 * @hid: hid device instance for this request
405 * @report_id: Report id for the get request
406 * @report_type: Report type for the this request
408 * This is called from hid core .request() callback. This function will send
409 * request to FW and return without waiting for response.
411 void hid_ishtp_get_report(struct hid_device
*hid
, int report_id
,
414 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
415 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
416 static unsigned char buf
[10];
418 struct hostif_msg_to_sensor
*msg
= (struct hostif_msg_to_sensor
*)buf
;
422 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
423 rv
= ishtp_hid_link_ready_wait(client_data
);
425 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
430 len
= sizeof(struct hostif_msg_to_sensor
);
432 memset(msg
, 0, sizeof(struct hostif_msg_to_sensor
));
433 msg
->hdr
.command
= (report_type
== HID_FEATURE_REPORT
) ?
434 HOSTIF_GET_FEATURE_REPORT
: HOSTIF_GET_INPUT_REPORT
;
435 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
436 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
438 client_data
->hid_devices
[i
].dev_id
;
443 if (i
== client_data
->num_hid_devices
)
446 msg
->report_id
= report_id
;
447 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, buf
, len
);
449 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
454 * ishtp_hid_link_ready_wait() - Wait for link ready
455 * @client_data: client data instance
457 * If the transport link started suspend process, then wait, till either
460 * Return: 0 on success, non zero on error
462 int ishtp_hid_link_ready_wait(struct ishtp_cl_data
*client_data
)
466 if (client_data
->suspended
) {
467 hid_ishtp_trace(client_data
, "wait for link ready\n");
468 rc
= wait_event_interruptible_timeout(
469 client_data
->ishtp_resume_wait
,
470 !client_data
->suspended
,
474 hid_ishtp_trace(client_data
, "link not ready\n");
477 hid_ishtp_trace(client_data
, "link ready\n");
484 * ishtp_enum_enum_devices() - Enumerate hid devices
485 * @hid_ishtp_cl: client instance
487 * Helper function to send request to firmware to enumerate HID devices
489 * Return: 0 on success, non zero on error
491 static int ishtp_enum_enum_devices(struct ishtp_cl
*hid_ishtp_cl
)
493 struct hostif_msg msg
;
494 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
498 /* Send HOSTIF_DM_ENUM_DEVICES */
499 memset(&msg
, 0, sizeof(struct hostif_msg
));
500 msg
.hdr
.command
= HOSTIF_DM_ENUM_DEVICES
;
501 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *)&msg
,
502 sizeof(struct hostif_msg
));
507 while (!client_data
->enum_devices_done
&&
509 wait_event_interruptible_timeout(client_data
->init_wait
,
510 client_data
->enum_devices_done
,
513 if (!client_data
->enum_devices_done
)
514 /* Send HOSTIF_DM_ENUM_DEVICES */
515 rv
= ishtp_cl_send(hid_ishtp_cl
,
516 (unsigned char *) &msg
,
517 sizeof(struct hostif_msg
));
519 if (!client_data
->enum_devices_done
) {
520 dev_err(&client_data
->cl_device
->dev
,
521 "[hid-ish]: timed out waiting for enum_devices\n");
524 if (!client_data
->hid_devices
) {
525 dev_err(&client_data
->cl_device
->dev
,
526 "[hid-ish]: failed to allocate HID dev structures\n");
530 client_data
->num_hid_devices
= client_data
->hid_dev_count
;
531 dev_info(&hid_ishtp_cl
->device
->dev
,
532 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
533 client_data
->num_hid_devices
);
539 * ishtp_get_hid_descriptor() - Get hid descriptor
540 * @hid_ishtp_cl: client instance
541 * @index: Index into the hid_descr array
543 * Helper function to send request to firmware get HID descriptor of a device
545 * Return: 0 on success, non zero on error
547 static int ishtp_get_hid_descriptor(struct ishtp_cl
*hid_ishtp_cl
, int index
)
549 struct hostif_msg msg
;
550 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
553 /* Get HID descriptor */
554 client_data
->hid_descr_done
= false;
555 memset(&msg
, 0, sizeof(struct hostif_msg
));
556 msg
.hdr
.command
= HOSTIF_GET_HID_DESCRIPTOR
;
557 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
558 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
559 sizeof(struct hostif_msg
));
563 if (!client_data
->hid_descr_done
) {
564 wait_event_interruptible_timeout(client_data
->init_wait
,
565 client_data
->hid_descr_done
,
567 if (!client_data
->hid_descr_done
) {
568 dev_err(&client_data
->cl_device
->dev
,
569 "[hid-ish]: timed out for hid_descr_done\n");
573 if (!client_data
->hid_descr
[index
]) {
574 dev_err(&client_data
->cl_device
->dev
,
575 "[hid-ish]: allocation HID desc fail\n");
584 * ishtp_get_report_descriptor() - Get report descriptor
585 * @hid_ishtp_cl: client instance
586 * @index: Index into the hid_descr array
588 * Helper function to send request to firmware get HID report descriptor of
591 * Return: 0 on success, non zero on error
593 static int ishtp_get_report_descriptor(struct ishtp_cl
*hid_ishtp_cl
,
596 struct hostif_msg msg
;
597 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
600 /* Get report descriptor */
601 client_data
->report_descr_done
= false;
602 memset(&msg
, 0, sizeof(struct hostif_msg
));
603 msg
.hdr
.command
= HOSTIF_GET_REPORT_DESCRIPTOR
;
604 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
605 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
606 sizeof(struct hostif_msg
));
610 if (!client_data
->report_descr_done
)
611 wait_event_interruptible_timeout(client_data
->init_wait
,
612 client_data
->report_descr_done
,
614 if (!client_data
->report_descr_done
) {
615 dev_err(&client_data
->cl_device
->dev
,
616 "[hid-ish]: timed out for report descr\n");
619 if (!client_data
->report_descr
[index
]) {
620 dev_err(&client_data
->cl_device
->dev
,
621 "[hid-ish]: failed to alloc report descr\n");
629 * hid_ishtp_cl_init() - Init function for ISHTP client
630 * @hid_ishtp_cl: ISHTP client instance
631 * @reset: true if called for init after reset
633 * This function complete the initializtion of the client. The summary of
635 * - Send request to enumerate the hid clients
636 * Get the HID descriptor for each enumearated device
637 * Get report description of each device
638 * Register each device wik hid core by calling ishtp_hid_probe
640 * Return: 0 on success, non zero on error
642 static int hid_ishtp_cl_init(struct ishtp_cl
*hid_ishtp_cl
, int reset
)
644 struct ishtp_device
*dev
;
646 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
650 dev_dbg(&client_data
->cl_device
->dev
, "%s\n", __func__
);
651 hid_ishtp_trace(client_data
, "%s reset flag: %d\n", __func__
, reset
);
653 rv
= ishtp_cl_link(hid_ishtp_cl
, ISHTP_HOST_CLIENT_ID_ANY
);
655 dev_err(&client_data
->cl_device
->dev
,
656 "ishtp_cl_link failed\n");
660 client_data
->init_done
= 0;
662 dev
= hid_ishtp_cl
->dev
;
664 /* Connect to FW client */
665 hid_ishtp_cl
->rx_ring_size
= HID_CL_RX_RING_SIZE
;
666 hid_ishtp_cl
->tx_ring_size
= HID_CL_TX_RING_SIZE
;
668 spin_lock_irqsave(&dev
->fw_clients_lock
, flags
);
669 i
= ishtp_fw_cl_by_uuid(dev
, &hid_ishtp_guid
);
671 spin_unlock_irqrestore(&dev
->fw_clients_lock
, flags
);
672 dev_err(&client_data
->cl_device
->dev
,
673 "ish client uuid not found\n");
676 hid_ishtp_cl
->fw_client_id
= dev
->fw_clients
[i
].client_id
;
677 spin_unlock_irqrestore(&dev
->fw_clients_lock
, flags
);
678 hid_ishtp_cl
->state
= ISHTP_CL_CONNECTING
;
680 rv
= ishtp_cl_connect(hid_ishtp_cl
);
682 dev_err(&client_data
->cl_device
->dev
,
683 "client connect fail\n");
687 hid_ishtp_trace(client_data
, "%s client connected\n", __func__
);
689 /* Register read callback */
690 ishtp_register_event_cb(hid_ishtp_cl
->device
, ish_cl_event_cb
);
692 rv
= ishtp_enum_enum_devices(hid_ishtp_cl
);
694 goto err_cl_disconnect
;
696 hid_ishtp_trace(client_data
, "%s enumerated device count %d\n",
697 __func__
, client_data
->num_hid_devices
);
699 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
700 client_data
->cur_hid_dev
= i
;
702 rv
= ishtp_get_hid_descriptor(hid_ishtp_cl
, i
);
704 goto err_cl_disconnect
;
706 rv
= ishtp_get_report_descriptor(hid_ishtp_cl
, i
);
708 goto err_cl_disconnect
;
711 rv
= ishtp_hid_probe(i
, client_data
);
713 dev_err(&client_data
->cl_device
->dev
,
714 "[hid-ish]: HID probe for #%u failed: %d\n",
716 goto err_cl_disconnect
;
719 } /* for() on all hid devices */
721 client_data
->init_done
= 1;
722 client_data
->suspended
= false;
723 wake_up_interruptible(&client_data
->ishtp_resume_wait
);
724 hid_ishtp_trace(client_data
, "%s successful init\n", __func__
);
728 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
729 ishtp_cl_disconnect(hid_ishtp_cl
);
731 ishtp_cl_unlink(hid_ishtp_cl
);
736 * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
737 * @hid_ishtp_cl: ISHTP client instance
739 * Unlink and free hid client
741 static void hid_ishtp_cl_deinit(struct ishtp_cl
*hid_ishtp_cl
)
743 ishtp_cl_unlink(hid_ishtp_cl
);
744 ishtp_cl_flush_queues(hid_ishtp_cl
);
746 /* disband and free all Tx and Rx client-level rings */
747 ishtp_cl_free(hid_ishtp_cl
);
750 static void hid_ishtp_cl_reset_handler(struct work_struct
*work
)
752 struct ishtp_cl_data
*client_data
;
753 struct ishtp_cl
*hid_ishtp_cl
;
754 struct ishtp_cl_device
*cl_device
;
758 client_data
= container_of(work
, struct ishtp_cl_data
, work
);
760 hid_ishtp_cl
= client_data
->hid_ishtp_cl
;
761 cl_device
= client_data
->cl_device
;
763 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
765 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
767 hid_ishtp_cl_deinit(hid_ishtp_cl
);
769 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
773 cl_device
->driver_data
= hid_ishtp_cl
;
774 hid_ishtp_cl
->client_data
= client_data
;
775 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
777 client_data
->num_hid_devices
= 0;
779 for (retry
= 0; retry
< 3; ++retry
) {
780 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 1);
783 dev_err(&client_data
->cl_device
->dev
, "Retry reset init\n");
786 dev_err(&client_data
->cl_device
->dev
, "Reset Failed\n");
787 hid_ishtp_trace(client_data
, "%s Failed hid_ishtp_cl %p\n",
788 __func__
, hid_ishtp_cl
);
793 * hid_ishtp_cl_probe() - ISHTP client driver probe
794 * @cl_device: ISHTP client device instance
796 * This function gets called on device create on ISHTP bus
798 * Return: 0 on success, non zero on error
800 static int hid_ishtp_cl_probe(struct ishtp_cl_device
*cl_device
)
802 struct ishtp_cl
*hid_ishtp_cl
;
803 struct ishtp_cl_data
*client_data
;
809 if (uuid_le_cmp(hid_ishtp_guid
,
810 cl_device
->fw_client
->props
.protocol_name
) != 0)
813 client_data
= devm_kzalloc(&cl_device
->dev
, sizeof(*client_data
),
818 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
822 cl_device
->driver_data
= hid_ishtp_cl
;
823 hid_ishtp_cl
->client_data
= client_data
;
824 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
825 client_data
->cl_device
= cl_device
;
827 init_waitqueue_head(&client_data
->init_wait
);
828 init_waitqueue_head(&client_data
->ishtp_resume_wait
);
830 INIT_WORK(&client_data
->work
, hid_ishtp_cl_reset_handler
);
832 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 0);
834 ishtp_cl_free(hid_ishtp_cl
);
837 ishtp_get_device(cl_device
);
843 * hid_ishtp_cl_remove() - ISHTP client driver remove
844 * @cl_device: ISHTP client device instance
846 * This function gets called on device remove on ISHTP bus
850 static int hid_ishtp_cl_remove(struct ishtp_cl_device
*cl_device
)
852 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
853 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
855 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
858 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
859 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
860 ishtp_cl_disconnect(hid_ishtp_cl
);
861 ishtp_put_device(cl_device
);
862 ishtp_hid_remove(client_data
);
863 hid_ishtp_cl_deinit(hid_ishtp_cl
);
867 client_data
->num_hid_devices
= 0;
873 * hid_ishtp_cl_reset() - ISHTP client driver reset
874 * @cl_device: ISHTP client device instance
876 * This function gets called on device reset on ISHTP bus
880 static int hid_ishtp_cl_reset(struct ishtp_cl_device
*cl_device
)
882 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
883 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
885 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
888 schedule_work(&client_data
->work
);
893 #define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev)
896 * hid_ishtp_cl_suspend() - ISHTP client driver suspend
897 * @device: device instance
899 * This function gets called on system suspend
903 static int hid_ishtp_cl_suspend(struct device
*device
)
905 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
906 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
907 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
909 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
911 client_data
->suspended
= true;
917 * hid_ishtp_cl_resume() - ISHTP client driver resume
918 * @device: device instance
920 * This function gets called on system resume
924 static int hid_ishtp_cl_resume(struct device
*device
)
926 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
927 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
928 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
930 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
932 client_data
->suspended
= false;
936 static const struct dev_pm_ops hid_ishtp_pm_ops
= {
937 .suspend
= hid_ishtp_cl_suspend
,
938 .resume
= hid_ishtp_cl_resume
,
941 static struct ishtp_cl_driver hid_ishtp_cl_driver
= {
943 .probe
= hid_ishtp_cl_probe
,
944 .remove
= hid_ishtp_cl_remove
,
945 .reset
= hid_ishtp_cl_reset
,
946 .driver
.pm
= &hid_ishtp_pm_ops
,
949 static int __init
ish_hid_init(void)
953 /* Register ISHTP client device driver with ISHTP Bus */
954 rv
= ishtp_cl_driver_register(&hid_ishtp_cl_driver
);
960 static void __exit
ish_hid_exit(void)
962 ishtp_cl_driver_unregister(&hid_ishtp_cl_driver
);
965 late_initcall(ish_hid_init
);
966 module_exit(ish_hid_exit
);
968 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
970 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
972 * Several modification for multi instance support
973 * suspend/resume and clean up
975 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
977 MODULE_LICENSE("GPL");
978 MODULE_ALIAS("ishtp:*");