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 %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 static unsigned char buf
[10];
417 struct hostif_msg_to_sensor
*msg
= (struct hostif_msg_to_sensor
*)buf
;
421 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
422 rv
= ishtp_hid_link_ready_wait(client_data
);
424 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
429 len
= sizeof(struct hostif_msg_to_sensor
);
431 memset(msg
, 0, sizeof(struct hostif_msg_to_sensor
));
432 msg
->hdr
.command
= (report_type
== HID_FEATURE_REPORT
) ?
433 HOSTIF_GET_FEATURE_REPORT
: HOSTIF_GET_INPUT_REPORT
;
434 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
435 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
437 client_data
->hid_devices
[i
].dev_id
;
442 if (i
== client_data
->num_hid_devices
)
445 msg
->report_id
= report_id
;
446 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, buf
, len
);
448 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
453 * ishtp_hid_link_ready_wait() - Wait for link ready
454 * @client_data: client data instance
456 * If the transport link started suspend process, then wait, till either
459 * Return: 0 on success, non zero on error
461 int ishtp_hid_link_ready_wait(struct ishtp_cl_data
*client_data
)
465 if (client_data
->suspended
) {
466 hid_ishtp_trace(client_data
, "wait for link ready\n");
467 rc
= wait_event_interruptible_timeout(
468 client_data
->ishtp_resume_wait
,
469 !client_data
->suspended
,
473 hid_ishtp_trace(client_data
, "link not ready\n");
476 hid_ishtp_trace(client_data
, "link ready\n");
483 * ishtp_enum_enum_devices() - Enumerate hid devices
484 * @hid_ishtp_cl: client instance
486 * Helper function to send request to firmware to enumerate HID devices
488 * Return: 0 on success, non zero on error
490 static int ishtp_enum_enum_devices(struct ishtp_cl
*hid_ishtp_cl
)
492 struct hostif_msg msg
;
493 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
497 /* Send HOSTIF_DM_ENUM_DEVICES */
498 memset(&msg
, 0, sizeof(struct hostif_msg
));
499 msg
.hdr
.command
= HOSTIF_DM_ENUM_DEVICES
;
500 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *)&msg
,
501 sizeof(struct hostif_msg
));
506 while (!client_data
->enum_devices_done
&&
508 wait_event_interruptible_timeout(client_data
->init_wait
,
509 client_data
->enum_devices_done
,
512 if (!client_data
->enum_devices_done
)
513 /* Send HOSTIF_DM_ENUM_DEVICES */
514 rv
= ishtp_cl_send(hid_ishtp_cl
,
515 (unsigned char *) &msg
,
516 sizeof(struct hostif_msg
));
518 if (!client_data
->enum_devices_done
) {
519 dev_err(&client_data
->cl_device
->dev
,
520 "[hid-ish]: timed out waiting for enum_devices\n");
523 if (!client_data
->hid_devices
) {
524 dev_err(&client_data
->cl_device
->dev
,
525 "[hid-ish]: failed to allocate HID dev structures\n");
529 client_data
->num_hid_devices
= client_data
->hid_dev_count
;
530 dev_info(&hid_ishtp_cl
->device
->dev
,
531 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
532 client_data
->num_hid_devices
);
538 * ishtp_get_hid_descriptor() - Get hid descriptor
539 * @hid_ishtp_cl: client instance
540 * @index: Index into the hid_descr array
542 * Helper function to send request to firmware get HID descriptor of a device
544 * Return: 0 on success, non zero on error
546 static int ishtp_get_hid_descriptor(struct ishtp_cl
*hid_ishtp_cl
, int index
)
548 struct hostif_msg msg
;
549 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
552 /* Get HID descriptor */
553 client_data
->hid_descr_done
= false;
554 memset(&msg
, 0, sizeof(struct hostif_msg
));
555 msg
.hdr
.command
= HOSTIF_GET_HID_DESCRIPTOR
;
556 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
557 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
558 sizeof(struct hostif_msg
));
562 if (!client_data
->hid_descr_done
) {
563 wait_event_interruptible_timeout(client_data
->init_wait
,
564 client_data
->hid_descr_done
,
566 if (!client_data
->hid_descr_done
) {
567 dev_err(&client_data
->cl_device
->dev
,
568 "[hid-ish]: timed out for hid_descr_done\n");
572 if (!client_data
->hid_descr
[index
]) {
573 dev_err(&client_data
->cl_device
->dev
,
574 "[hid-ish]: allocation HID desc fail\n");
583 * ishtp_get_report_descriptor() - Get report descriptor
584 * @hid_ishtp_cl: client instance
585 * @index: Index into the hid_descr array
587 * Helper function to send request to firmware get HID report descriptor of
590 * Return: 0 on success, non zero on error
592 static int ishtp_get_report_descriptor(struct ishtp_cl
*hid_ishtp_cl
,
595 struct hostif_msg msg
;
596 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
599 /* Get report descriptor */
600 client_data
->report_descr_done
= false;
601 memset(&msg
, 0, sizeof(struct hostif_msg
));
602 msg
.hdr
.command
= HOSTIF_GET_REPORT_DESCRIPTOR
;
603 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
604 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
605 sizeof(struct hostif_msg
));
609 if (!client_data
->report_descr_done
)
610 wait_event_interruptible_timeout(client_data
->init_wait
,
611 client_data
->report_descr_done
,
613 if (!client_data
->report_descr_done
) {
614 dev_err(&client_data
->cl_device
->dev
,
615 "[hid-ish]: timed out for report descr\n");
618 if (!client_data
->report_descr
[index
]) {
619 dev_err(&client_data
->cl_device
->dev
,
620 "[hid-ish]: failed to alloc report descr\n");
628 * hid_ishtp_cl_init() - Init function for ISHTP client
629 * @hid_ishtp_cl: ISHTP client instance
630 * @reset: true if called for init after reset
632 * This function complete the initializtion of the client. The summary of
634 * - Send request to enumerate the hid clients
635 * Get the HID descriptor for each enumearated device
636 * Get report description of each device
637 * Register each device wik hid core by calling ishtp_hid_probe
639 * Return: 0 on success, non zero on error
641 static int hid_ishtp_cl_init(struct ishtp_cl
*hid_ishtp_cl
, int reset
)
643 struct ishtp_device
*dev
;
645 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
649 dev_dbg(&client_data
->cl_device
->dev
, "%s\n", __func__
);
650 hid_ishtp_trace(client_data
, "%s reset flag: %d\n", __func__
, reset
);
652 rv
= ishtp_cl_link(hid_ishtp_cl
, ISHTP_HOST_CLIENT_ID_ANY
);
654 dev_err(&client_data
->cl_device
->dev
,
655 "ishtp_cl_link failed\n");
659 client_data
->init_done
= 0;
661 dev
= hid_ishtp_cl
->dev
;
663 /* Connect to FW client */
664 hid_ishtp_cl
->rx_ring_size
= HID_CL_RX_RING_SIZE
;
665 hid_ishtp_cl
->tx_ring_size
= HID_CL_TX_RING_SIZE
;
667 spin_lock_irqsave(&dev
->fw_clients_lock
, flags
);
668 i
= ishtp_fw_cl_by_uuid(dev
, &hid_ishtp_guid
);
670 spin_unlock_irqrestore(&dev
->fw_clients_lock
, flags
);
671 dev_err(&client_data
->cl_device
->dev
,
672 "ish client uuid not found\n");
675 hid_ishtp_cl
->fw_client_id
= dev
->fw_clients
[i
].client_id
;
676 spin_unlock_irqrestore(&dev
->fw_clients_lock
, flags
);
677 hid_ishtp_cl
->state
= ISHTP_CL_CONNECTING
;
679 rv
= ishtp_cl_connect(hid_ishtp_cl
);
681 dev_err(&client_data
->cl_device
->dev
,
682 "client connect fail\n");
686 hid_ishtp_trace(client_data
, "%s client connected\n", __func__
);
688 /* Register read callback */
689 ishtp_register_event_cb(hid_ishtp_cl
->device
, ish_cl_event_cb
);
691 rv
= ishtp_enum_enum_devices(hid_ishtp_cl
);
693 goto err_cl_disconnect
;
695 hid_ishtp_trace(client_data
, "%s enumerated device count %d\n",
696 __func__
, client_data
->num_hid_devices
);
698 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
699 client_data
->cur_hid_dev
= i
;
701 rv
= ishtp_get_hid_descriptor(hid_ishtp_cl
, i
);
703 goto err_cl_disconnect
;
705 rv
= ishtp_get_report_descriptor(hid_ishtp_cl
, i
);
707 goto err_cl_disconnect
;
710 rv
= ishtp_hid_probe(i
, client_data
);
712 dev_err(&client_data
->cl_device
->dev
,
713 "[hid-ish]: HID probe for #%u failed: %d\n",
715 goto err_cl_disconnect
;
718 } /* for() on all hid devices */
720 client_data
->init_done
= 1;
721 client_data
->suspended
= false;
722 wake_up_interruptible(&client_data
->ishtp_resume_wait
);
723 hid_ishtp_trace(client_data
, "%s successful init\n", __func__
);
727 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
728 ishtp_cl_disconnect(hid_ishtp_cl
);
730 ishtp_cl_unlink(hid_ishtp_cl
);
735 * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
736 * @hid_ishtp_cl: ISHTP client instance
738 * Unlink and free hid client
740 static void hid_ishtp_cl_deinit(struct ishtp_cl
*hid_ishtp_cl
)
742 ishtp_cl_unlink(hid_ishtp_cl
);
743 ishtp_cl_flush_queues(hid_ishtp_cl
);
745 /* disband and free all Tx and Rx client-level rings */
746 ishtp_cl_free(hid_ishtp_cl
);
749 static void hid_ishtp_cl_reset_handler(struct work_struct
*work
)
751 struct ishtp_cl_data
*client_data
;
752 struct ishtp_cl
*hid_ishtp_cl
;
753 struct ishtp_cl_device
*cl_device
;
757 client_data
= container_of(work
, struct ishtp_cl_data
, work
);
759 hid_ishtp_cl
= client_data
->hid_ishtp_cl
;
760 cl_device
= client_data
->cl_device
;
762 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
764 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
766 hid_ishtp_cl_deinit(hid_ishtp_cl
);
768 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
772 cl_device
->driver_data
= hid_ishtp_cl
;
773 hid_ishtp_cl
->client_data
= client_data
;
774 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
776 client_data
->num_hid_devices
= 0;
778 for (retry
= 0; retry
< 3; ++retry
) {
779 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 1);
782 dev_err(&client_data
->cl_device
->dev
, "Retry reset init\n");
785 dev_err(&client_data
->cl_device
->dev
, "Reset Failed\n");
786 hid_ishtp_trace(client_data
, "%s Failed hid_ishtp_cl %p\n",
787 __func__
, hid_ishtp_cl
);
792 * hid_ishtp_cl_probe() - ISHTP client driver probe
793 * @cl_device: ISHTP client device instance
795 * This function gets called on device create on ISHTP bus
797 * Return: 0 on success, non zero on error
799 static int hid_ishtp_cl_probe(struct ishtp_cl_device
*cl_device
)
801 struct ishtp_cl
*hid_ishtp_cl
;
802 struct ishtp_cl_data
*client_data
;
808 if (uuid_le_cmp(hid_ishtp_guid
,
809 cl_device
->fw_client
->props
.protocol_name
) != 0)
812 client_data
= devm_kzalloc(&cl_device
->dev
, sizeof(*client_data
),
817 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
821 cl_device
->driver_data
= hid_ishtp_cl
;
822 hid_ishtp_cl
->client_data
= client_data
;
823 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
824 client_data
->cl_device
= cl_device
;
826 init_waitqueue_head(&client_data
->init_wait
);
827 init_waitqueue_head(&client_data
->ishtp_resume_wait
);
829 INIT_WORK(&client_data
->work
, hid_ishtp_cl_reset_handler
);
831 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 0);
833 ishtp_cl_free(hid_ishtp_cl
);
836 ishtp_get_device(cl_device
);
842 * hid_ishtp_cl_remove() - ISHTP client driver remove
843 * @cl_device: ISHTP client device instance
845 * This function gets called on device remove on ISHTP bus
849 static int hid_ishtp_cl_remove(struct ishtp_cl_device
*cl_device
)
851 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
852 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
854 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
857 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
858 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
859 ishtp_cl_disconnect(hid_ishtp_cl
);
860 ishtp_put_device(cl_device
);
861 ishtp_hid_remove(client_data
);
862 hid_ishtp_cl_deinit(hid_ishtp_cl
);
866 client_data
->num_hid_devices
= 0;
872 * hid_ishtp_cl_reset() - ISHTP client driver reset
873 * @cl_device: ISHTP client device instance
875 * This function gets called on device reset on ISHTP bus
879 static int hid_ishtp_cl_reset(struct ishtp_cl_device
*cl_device
)
881 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
882 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
884 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
887 schedule_work(&client_data
->work
);
892 #define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev)
895 * hid_ishtp_cl_suspend() - ISHTP client driver suspend
896 * @device: device instance
898 * This function gets called on system suspend
902 static int hid_ishtp_cl_suspend(struct device
*device
)
904 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
905 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
906 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
908 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
910 client_data
->suspended
= true;
916 * hid_ishtp_cl_resume() - ISHTP client driver resume
917 * @device: device instance
919 * This function gets called on system resume
923 static int hid_ishtp_cl_resume(struct device
*device
)
925 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
926 struct ishtp_cl
*hid_ishtp_cl
= cl_device
->driver_data
;
927 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
929 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
931 client_data
->suspended
= false;
935 static const struct dev_pm_ops hid_ishtp_pm_ops
= {
936 .suspend
= hid_ishtp_cl_suspend
,
937 .resume
= hid_ishtp_cl_resume
,
940 static struct ishtp_cl_driver hid_ishtp_cl_driver
= {
942 .probe
= hid_ishtp_cl_probe
,
943 .remove
= hid_ishtp_cl_remove
,
944 .reset
= hid_ishtp_cl_reset
,
945 .driver
.pm
= &hid_ishtp_pm_ops
,
948 static int __init
ish_hid_init(void)
952 /* Register ISHTP client device driver with ISHTP Bus */
953 rv
= ishtp_cl_driver_register(&hid_ishtp_cl_driver
);
959 static void __exit
ish_hid_exit(void)
961 ishtp_cl_driver_unregister(&hid_ishtp_cl_driver
);
964 late_initcall(ish_hid_init
);
965 module_exit(ish_hid_exit
);
967 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
969 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
971 * Several modification for multi instance support
972 * suspend/resume and clean up
974 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
976 MODULE_LICENSE("GPL");
977 MODULE_ALIAS("ishtp:*");