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 payload
= recv_buf
+ sizeof(struct hostif_msg_hdr
);
85 if (cur_pos
+ sizeof(struct hostif_msg
) > total_len
) {
86 dev_err(&client_data
->cl_device
->dev
,
87 "[hid-ish]: error, received %u which is less than data header %u\n",
88 (unsigned int)data_len
,
89 (unsigned int)sizeof(struct hostif_msg_hdr
));
90 ++client_data
->bad_recv_cnt
;
91 ish_hw_reset(hid_ishtp_cl
->dev
);
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_kcalloc(
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 %zu is bigger than payload_len %zu\n",
140 1 + sizeof(struct device_info
)
144 if (1 + sizeof(struct device_info
) * i
>=
148 dev_info
= (struct device_info
*)(payload
+ 1 +
149 sizeof(struct device_info
) * i
);
150 if (client_data
->hid_devices
)
151 memcpy(client_data
->hid_devices
+ i
,
153 sizeof(struct device_info
));
156 client_data
->enum_devices_done
= true;
157 wake_up_interruptible(&client_data
->init_wait
);
161 case HOSTIF_GET_HID_DESCRIPTOR
:
162 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
163 client_data
->init_done
)) {
164 ++client_data
->bad_recv_cnt
;
165 report_bad_packet(hid_ishtp_cl
, recv_msg
,
168 ish_hw_reset(hid_ishtp_cl
->dev
);
171 if (!client_data
->hid_descr
[curr_hid_dev
])
172 client_data
->hid_descr
[curr_hid_dev
] =
173 devm_kmalloc(&client_data
->cl_device
->dev
,
174 payload_len
, GFP_KERNEL
);
175 if (client_data
->hid_descr
[curr_hid_dev
]) {
176 memcpy(client_data
->hid_descr
[curr_hid_dev
],
177 payload
, payload_len
);
178 client_data
->hid_descr_size
[curr_hid_dev
] =
180 client_data
->hid_descr_done
= true;
182 wake_up_interruptible(&client_data
->init_wait
);
186 case HOSTIF_GET_REPORT_DESCRIPTOR
:
187 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
188 client_data
->init_done
)) {
189 ++client_data
->bad_recv_cnt
;
190 report_bad_packet(hid_ishtp_cl
, recv_msg
,
193 ish_hw_reset(hid_ishtp_cl
->dev
);
196 if (!client_data
->report_descr
[curr_hid_dev
])
197 client_data
->report_descr
[curr_hid_dev
] =
198 devm_kmalloc(&client_data
->cl_device
->dev
,
199 payload_len
, GFP_KERNEL
);
200 if (client_data
->report_descr
[curr_hid_dev
]) {
201 memcpy(client_data
->report_descr
[curr_hid_dev
],
204 client_data
->report_descr_size
[curr_hid_dev
] =
206 client_data
->report_descr_done
= true;
208 wake_up_interruptible(&client_data
->init_wait
);
212 case HOSTIF_GET_FEATURE_REPORT
:
213 report_type
= HID_FEATURE_REPORT
;
216 case HOSTIF_GET_INPUT_REPORT
:
217 report_type
= HID_INPUT_REPORT
;
219 /* Get index of device that matches this id */
220 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
221 if (recv_msg
->hdr
.device_id
==
222 client_data
->hid_devices
[i
].dev_id
)
223 if (client_data
->hid_sensor_hubs
[i
]) {
225 client_data
->hid_sensor_hubs
[
227 report_type
, payload
,
230 client_data
->hid_sensor_hubs
[
237 case HOSTIF_SET_FEATURE_REPORT
:
238 /* Get index of device that matches this id */
239 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
240 if (recv_msg
->hdr
.device_id
==
241 client_data
->hid_devices
[i
].dev_id
)
242 if (client_data
->hid_sensor_hubs
[i
]) {
244 client_data
->hid_sensor_hubs
[
251 case HOSTIF_PUBLISH_INPUT_REPORT
:
252 report_type
= HID_INPUT_REPORT
;
253 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
)
254 if (recv_msg
->hdr
.device_id
==
255 client_data
->hid_devices
[i
].dev_id
)
256 if (client_data
->hid_sensor_hubs
[i
])
258 client_data
->hid_sensor_hubs
[
260 report_type
, payload
,
264 case HOSTIF_PUBLISH_INPUT_REPORT_LIST
:
265 report_type
= HID_INPUT_REPORT
;
266 reports_list
= (struct report_list
*)payload
;
267 reports
= (char *)reports_list
->reports
;
269 for (j
= 0; j
< reports_list
->num_of_reports
; j
++) {
270 recv_msg
= (struct hostif_msg
*)(reports
+
272 report_len
= *(uint16_t *)reports
;
273 payload
= reports
+ sizeof(uint16_t) +
274 sizeof(struct hostif_msg_hdr
);
275 payload_len
= report_len
-
276 sizeof(struct hostif_msg_hdr
);
278 for (i
= 0; i
< client_data
->num_hid_devices
;
280 if (recv_msg
->hdr
.device_id
==
281 client_data
->hid_devices
[i
].dev_id
&&
282 client_data
->hid_sensor_hubs
[i
]) {
284 client_data
->hid_sensor_hubs
[
287 payload
, payload_len
,
291 reports
+= sizeof(uint16_t) + report_len
;
295 ++client_data
->bad_recv_cnt
;
296 report_bad_packet(hid_ishtp_cl
, recv_msg
, cur_pos
,
298 ish_hw_reset(hid_ishtp_cl
->dev
);
303 if (!cur_pos
&& cur_pos
+ payload_len
+
304 sizeof(struct hostif_msg
) < total_len
)
305 ++client_data
->multi_packet_cnt
;
307 cur_pos
+= payload_len
+ sizeof(struct hostif_msg
);
308 payload
+= payload_len
+ sizeof(struct hostif_msg
);
310 } while (cur_pos
< total_len
);
314 * ish_cl_event_cb() - bus driver callback for incoming message/packet
315 * @device: Pointer to the the ishtp client device for which this message
318 * Remove the packet from the list and process the message by calling
321 static void ish_cl_event_cb(struct ishtp_cl_device
*device
)
323 struct ishtp_cl
*hid_ishtp_cl
= device
->driver_data
;
324 struct ishtp_cl_rb
*rb_in_proc
;
331 spin_lock_irqsave(&hid_ishtp_cl
->in_process_spinlock
, flags
);
332 while (!list_empty(&hid_ishtp_cl
->in_process_list
.list
)) {
333 rb_in_proc
= list_entry(
334 hid_ishtp_cl
->in_process_list
.list
.next
,
335 struct ishtp_cl_rb
, list
);
336 list_del_init(&rb_in_proc
->list
);
337 spin_unlock_irqrestore(&hid_ishtp_cl
->in_process_spinlock
,
340 if (!rb_in_proc
->buffer
.data
)
343 r_length
= rb_in_proc
->buf_idx
;
345 /* decide what to do with received data */
346 process_recv(hid_ishtp_cl
, rb_in_proc
->buffer
.data
, r_length
);
348 ishtp_cl_io_rb_recycle(rb_in_proc
);
349 spin_lock_irqsave(&hid_ishtp_cl
->in_process_spinlock
, flags
);
351 spin_unlock_irqrestore(&hid_ishtp_cl
->in_process_spinlock
, flags
);
355 * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
356 * @hid: hid device instance for this request
357 * @buf: feature buffer
358 * @len: Length of feature buffer
359 * @report_id: Report id for the feature set request
361 * This is called from hid core .request() callback. This function doesn't wait
364 void hid_ishtp_set_feature(struct hid_device
*hid
, char *buf
, unsigned int len
,
367 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
368 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
369 struct hostif_msg
*msg
= (struct hostif_msg
*)buf
;
373 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
375 rv
= ishtp_hid_link_ready_wait(client_data
);
377 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
382 memset(msg
, 0, sizeof(struct hostif_msg
));
383 msg
->hdr
.command
= HOSTIF_SET_FEATURE_REPORT
;
384 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
385 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
387 client_data
->hid_devices
[i
].dev_id
;
392 if (i
== client_data
->num_hid_devices
)
395 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, buf
, len
);
397 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
402 * hid_ishtp_get_report() - request to get feature/input report
403 * @hid: hid device instance for this request
404 * @report_id: Report id for the get request
405 * @report_type: Report type for the this request
407 * This is called from hid core .request() callback. This function will send
408 * request to FW and return without waiting for response.
410 void hid_ishtp_get_report(struct hid_device
*hid
, int report_id
,
413 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
414 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
415 struct hostif_msg_to_sensor msg
= {};
419 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
420 rv
= ishtp_hid_link_ready_wait(client_data
);
422 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
427 msg
.hdr
.command
= (report_type
== HID_FEATURE_REPORT
) ?
428 HOSTIF_GET_FEATURE_REPORT
: HOSTIF_GET_INPUT_REPORT
;
429 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
430 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
432 client_data
->hid_devices
[i
].dev_id
;
437 if (i
== client_data
->num_hid_devices
)
440 msg
.report_id
= report_id
;
441 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, (uint8_t *)&msg
,
444 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
449 * ishtp_hid_link_ready_wait() - Wait for link ready
450 * @client_data: client data instance
452 * If the transport link started suspend process, then wait, till either
455 * Return: 0 on success, non zero on error
457 int ishtp_hid_link_ready_wait(struct ishtp_cl_data
*client_data
)
461 if (client_data
->suspended
) {
462 hid_ishtp_trace(client_data
, "wait for link ready\n");
463 rc
= wait_event_interruptible_timeout(
464 client_data
->ishtp_resume_wait
,
465 !client_data
->suspended
,
469 hid_ishtp_trace(client_data
, "link not ready\n");
472 hid_ishtp_trace(client_data
, "link ready\n");
479 * ishtp_enum_enum_devices() - Enumerate hid devices
480 * @hid_ishtp_cl: client instance
482 * Helper function to send request to firmware to enumerate HID devices
484 * Return: 0 on success, non zero on error
486 static int ishtp_enum_enum_devices(struct ishtp_cl
*hid_ishtp_cl
)
488 struct hostif_msg msg
;
489 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
493 /* Send HOSTIF_DM_ENUM_DEVICES */
494 memset(&msg
, 0, sizeof(struct hostif_msg
));
495 msg
.hdr
.command
= HOSTIF_DM_ENUM_DEVICES
;
496 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *)&msg
,
497 sizeof(struct hostif_msg
));
502 while (!client_data
->enum_devices_done
&&
504 wait_event_interruptible_timeout(client_data
->init_wait
,
505 client_data
->enum_devices_done
,
508 if (!client_data
->enum_devices_done
)
509 /* Send HOSTIF_DM_ENUM_DEVICES */
510 rv
= ishtp_cl_send(hid_ishtp_cl
,
511 (unsigned char *) &msg
,
512 sizeof(struct hostif_msg
));
514 if (!client_data
->enum_devices_done
) {
515 dev_err(&client_data
->cl_device
->dev
,
516 "[hid-ish]: timed out waiting for enum_devices\n");
519 if (!client_data
->hid_devices
) {
520 dev_err(&client_data
->cl_device
->dev
,
521 "[hid-ish]: failed to allocate HID dev structures\n");
525 client_data
->num_hid_devices
= client_data
->hid_dev_count
;
526 dev_info(&hid_ishtp_cl
->device
->dev
,
527 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
528 client_data
->num_hid_devices
);
534 * ishtp_get_hid_descriptor() - Get hid descriptor
535 * @hid_ishtp_cl: client instance
536 * @index: Index into the hid_descr array
538 * Helper function to send request to firmware get HID descriptor of a device
540 * Return: 0 on success, non zero on error
542 static int ishtp_get_hid_descriptor(struct ishtp_cl
*hid_ishtp_cl
, int index
)
544 struct hostif_msg msg
;
545 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
548 /* Get HID descriptor */
549 client_data
->hid_descr_done
= false;
550 memset(&msg
, 0, sizeof(struct hostif_msg
));
551 msg
.hdr
.command
= HOSTIF_GET_HID_DESCRIPTOR
;
552 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
553 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
554 sizeof(struct hostif_msg
));
558 if (!client_data
->hid_descr_done
) {
559 wait_event_interruptible_timeout(client_data
->init_wait
,
560 client_data
->hid_descr_done
,
562 if (!client_data
->hid_descr_done
) {
563 dev_err(&client_data
->cl_device
->dev
,
564 "[hid-ish]: timed out for hid_descr_done\n");
568 if (!client_data
->hid_descr
[index
]) {
569 dev_err(&client_data
->cl_device
->dev
,
570 "[hid-ish]: allocation HID desc fail\n");
579 * ishtp_get_report_descriptor() - Get report descriptor
580 * @hid_ishtp_cl: client instance
581 * @index: Index into the hid_descr array
583 * Helper function to send request to firmware get HID report descriptor of
586 * Return: 0 on success, non zero on error
588 static int ishtp_get_report_descriptor(struct ishtp_cl
*hid_ishtp_cl
,
591 struct hostif_msg msg
;
592 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
595 /* Get report descriptor */
596 client_data
->report_descr_done
= false;
597 memset(&msg
, 0, sizeof(struct hostif_msg
));
598 msg
.hdr
.command
= HOSTIF_GET_REPORT_DESCRIPTOR
;
599 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
600 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
601 sizeof(struct hostif_msg
));
605 if (!client_data
->report_descr_done
)
606 wait_event_interruptible_timeout(client_data
->init_wait
,
607 client_data
->report_descr_done
,
609 if (!client_data
->report_descr_done
) {
610 dev_err(&client_data
->cl_device
->dev
,
611 "[hid-ish]: timed out for report descr\n");
614 if (!client_data
->report_descr
[index
]) {
615 dev_err(&client_data
->cl_device
->dev
,
616 "[hid-ish]: failed to alloc report descr\n");
624 * hid_ishtp_cl_init() - Init function for ISHTP client
625 * @hid_ishtp_cl: ISHTP client instance
626 * @reset: true if called for init after reset
628 * This function complete the initializtion of the client. The summary of
630 * - Send request to enumerate the hid clients
631 * Get the HID descriptor for each enumearated device
632 * Get report description of each device
633 * Register each device wik hid core by calling ishtp_hid_probe
635 * Return: 0 on success, non zero on error
637 static int hid_ishtp_cl_init(struct ishtp_cl
*hid_ishtp_cl
, int reset
)
639 struct ishtp_device
*dev
;
641 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
645 dev_dbg(&client_data
->cl_device
->dev
, "%s\n", __func__
);
646 hid_ishtp_trace(client_data
, "%s reset flag: %d\n", __func__
, reset
);
648 rv
= ishtp_cl_link(hid_ishtp_cl
, ISHTP_HOST_CLIENT_ID_ANY
);
650 dev_err(&client_data
->cl_device
->dev
,
651 "ishtp_cl_link failed\n");
655 client_data
->init_done
= 0;
657 dev
= hid_ishtp_cl
->dev
;
659 /* Connect to FW client */
660 hid_ishtp_cl
->rx_ring_size
= HID_CL_RX_RING_SIZE
;
661 hid_ishtp_cl
->tx_ring_size
= HID_CL_TX_RING_SIZE
;
663 spin_lock_irqsave(&dev
->fw_clients_lock
, flags
);
664 i
= ishtp_fw_cl_by_uuid(dev
, &hid_ishtp_guid
);
666 spin_unlock_irqrestore(&dev
->fw_clients_lock
, flags
);
667 dev_err(&client_data
->cl_device
->dev
,
668 "ish client uuid not found\n");
671 hid_ishtp_cl
->fw_client_id
= dev
->fw_clients
[i
].client_id
;
672 spin_unlock_irqrestore(&dev
->fw_clients_lock
, flags
);
673 hid_ishtp_cl
->state
= ISHTP_CL_CONNECTING
;
675 rv
= ishtp_cl_connect(hid_ishtp_cl
);
677 dev_err(&client_data
->cl_device
->dev
,
678 "client connect fail\n");
682 hid_ishtp_trace(client_data
, "%s client connected\n", __func__
);
684 /* Register read callback */
685 ishtp_register_event_cb(hid_ishtp_cl
->device
, ish_cl_event_cb
);
687 rv
= ishtp_enum_enum_devices(hid_ishtp_cl
);
689 goto err_cl_disconnect
;
691 hid_ishtp_trace(client_data
, "%s enumerated device count %d\n",
692 __func__
, client_data
->num_hid_devices
);
694 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
695 client_data
->cur_hid_dev
= i
;
697 rv
= ishtp_get_hid_descriptor(hid_ishtp_cl
, i
);
699 goto err_cl_disconnect
;
701 rv
= ishtp_get_report_descriptor(hid_ishtp_cl
, i
);
703 goto err_cl_disconnect
;
706 rv
= ishtp_hid_probe(i
, client_data
);
708 dev_err(&client_data
->cl_device
->dev
,
709 "[hid-ish]: HID probe for #%u failed: %d\n",
711 goto err_cl_disconnect
;
714 } /* for() on all hid devices */
716 client_data
->init_done
= 1;
717 client_data
->suspended
= false;
718 wake_up_interruptible(&client_data
->ishtp_resume_wait
);
719 hid_ishtp_trace(client_data
, "%s successful init\n", __func__
);
723 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
724 ishtp_cl_disconnect(hid_ishtp_cl
);
726 ishtp_cl_unlink(hid_ishtp_cl
);
731 * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
732 * @hid_ishtp_cl: ISHTP client instance
734 * Unlink and free hid client
736 static void hid_ishtp_cl_deinit(struct ishtp_cl
*hid_ishtp_cl
)
738 ishtp_cl_unlink(hid_ishtp_cl
);
739 ishtp_cl_flush_queues(hid_ishtp_cl
);
741 /* disband and free all Tx and Rx client-level rings */
742 ishtp_cl_free(hid_ishtp_cl
);
745 static void hid_ishtp_cl_reset_handler(struct work_struct
*work
)
747 struct ishtp_cl_data
*client_data
;
748 struct ishtp_cl
*hid_ishtp_cl
;
749 struct ishtp_cl_device
*cl_device
;
753 client_data
= container_of(work
, struct ishtp_cl_data
, work
);
755 hid_ishtp_cl
= client_data
->hid_ishtp_cl
;
756 cl_device
= client_data
->cl_device
;
758 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
760 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
762 hid_ishtp_cl_deinit(hid_ishtp_cl
);
764 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
768 cl_device
->driver_data
= hid_ishtp_cl
;
769 hid_ishtp_cl
->client_data
= client_data
;
770 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
772 client_data
->num_hid_devices
= 0;
774 for (retry
= 0; retry
< 3; ++retry
) {
775 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 1);
778 dev_err(&client_data
->cl_device
->dev
, "Retry reset init\n");
781 dev_err(&client_data
->cl_device
->dev
, "Reset Failed\n");
782 hid_ishtp_trace(client_data
, "%s Failed hid_ishtp_cl %p\n",
783 __func__
, hid_ishtp_cl
);
788 * hid_ishtp_cl_probe() - ISHTP client driver probe
789 * @cl_device: ISHTP client device instance
791 * This function gets called on device create on ISHTP bus
793 * Return: 0 on success, non zero on error
795 static int hid_ishtp_cl_probe(struct ishtp_cl_device
*cl_device
)
797 struct ishtp_cl
*hid_ishtp_cl
;
798 struct ishtp_cl_data
*client_data
;
804 if (uuid_le_cmp(hid_ishtp_guid
,
805 cl_device
->fw_client
->props
.protocol_name
) != 0)
808 client_data
= devm_kzalloc(&cl_device
->dev
, sizeof(*client_data
),
813 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
817 cl_device
->driver_data
= hid_ishtp_cl
;
818 hid_ishtp_cl
->client_data
= client_data
;
819 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
820 client_data
->cl_device
= cl_device
;
822 init_waitqueue_head(&client_data
->init_wait
);
823 init_waitqueue_head(&client_data
->ishtp_resume_wait
);
825 INIT_WORK(&client_data
->work
, hid_ishtp_cl_reset_handler
);
827 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 0);
829 ishtp_cl_free(hid_ishtp_cl
);
832 ishtp_get_device(cl_device
);
838 * hid_ishtp_cl_remove() - ISHTP client driver remove
839 * @cl_device: ISHTP client device instance
841 * This function gets called on device remove on ISHTP bus
845 static int hid_ishtp_cl_remove(struct ishtp_cl_device
*cl_device
)
847 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
848 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
850 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
853 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
854 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
855 ishtp_cl_disconnect(hid_ishtp_cl
);
856 ishtp_put_device(cl_device
);
857 ishtp_hid_remove(client_data
);
858 hid_ishtp_cl_deinit(hid_ishtp_cl
);
862 client_data
->num_hid_devices
= 0;
868 * hid_ishtp_cl_reset() - ISHTP client driver reset
869 * @cl_device: ISHTP client device instance
871 * This function gets called on device reset on ISHTP bus
875 static int hid_ishtp_cl_reset(struct ishtp_cl_device
*cl_device
)
877 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
878 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
880 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
883 schedule_work(&client_data
->work
);
888 #define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev)
891 * hid_ishtp_cl_suspend() - ISHTP client driver suspend
892 * @device: device instance
894 * This function gets called on system suspend
898 static int hid_ishtp_cl_suspend(struct device
*device
)
900 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
901 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
902 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
904 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
906 client_data
->suspended
= true;
912 * hid_ishtp_cl_resume() - ISHTP client driver resume
913 * @device: device instance
915 * This function gets called on system resume
919 static int hid_ishtp_cl_resume(struct device
*device
)
921 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
922 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
923 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
925 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
927 client_data
->suspended
= false;
931 static const struct dev_pm_ops hid_ishtp_pm_ops
= {
932 .suspend
= hid_ishtp_cl_suspend
,
933 .resume
= hid_ishtp_cl_resume
,
936 static struct ishtp_cl_driver hid_ishtp_cl_driver
= {
938 .probe
= hid_ishtp_cl_probe
,
939 .remove
= hid_ishtp_cl_remove
,
940 .reset
= hid_ishtp_cl_reset
,
941 .driver
.pm
= &hid_ishtp_pm_ops
,
944 static int __init
ish_hid_init(void)
948 /* Register ISHTP client device driver with ISHTP Bus */
949 rv
= ishtp_cl_driver_register(&hid_ishtp_cl_driver
);
955 static void __exit
ish_hid_exit(void)
957 ishtp_cl_driver_unregister(&hid_ishtp_cl_driver
);
960 late_initcall(ish_hid_init
);
961 module_exit(ish_hid_exit
);
963 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
965 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
967 * Several modification for multi instance support
968 * suspend/resume and clean up
970 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
972 MODULE_LICENSE("GPL");
973 MODULE_ALIAS("ishtp:*");