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
= ishtp_get_drvdata(device
);
324 struct ishtp_cl_rb
*rb_in_proc
;
330 while ((rb_in_proc
= ishtp_cl_rx_get_rb(hid_ishtp_cl
)) != NULL
) {
331 if (!rb_in_proc
->buffer
.data
)
334 r_length
= rb_in_proc
->buf_idx
;
336 /* decide what to do with received data */
337 process_recv(hid_ishtp_cl
, rb_in_proc
->buffer
.data
, r_length
);
339 ishtp_cl_io_rb_recycle(rb_in_proc
);
344 * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
345 * @hid: hid device instance for this request
346 * @buf: feature buffer
347 * @len: Length of feature buffer
348 * @report_id: Report id for the feature set request
350 * This is called from hid core .request() callback. This function doesn't wait
353 void hid_ishtp_set_feature(struct hid_device
*hid
, char *buf
, unsigned int len
,
356 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
357 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
358 struct hostif_msg
*msg
= (struct hostif_msg
*)buf
;
362 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
364 rv
= ishtp_hid_link_ready_wait(client_data
);
366 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
371 memset(msg
, 0, sizeof(struct hostif_msg
));
372 msg
->hdr
.command
= HOSTIF_SET_FEATURE_REPORT
;
373 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
374 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
376 client_data
->hid_devices
[i
].dev_id
;
381 if (i
== client_data
->num_hid_devices
)
384 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, buf
, len
);
386 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
391 * hid_ishtp_get_report() - request to get feature/input report
392 * @hid: hid device instance for this request
393 * @report_id: Report id for the get request
394 * @report_type: Report type for the this request
396 * This is called from hid core .request() callback. This function will send
397 * request to FW and return without waiting for response.
399 void hid_ishtp_get_report(struct hid_device
*hid
, int report_id
,
402 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
403 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
404 struct hostif_msg_to_sensor msg
= {};
408 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
409 rv
= ishtp_hid_link_ready_wait(client_data
);
411 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
416 msg
.hdr
.command
= (report_type
== HID_FEATURE_REPORT
) ?
417 HOSTIF_GET_FEATURE_REPORT
: HOSTIF_GET_INPUT_REPORT
;
418 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
419 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
421 client_data
->hid_devices
[i
].dev_id
;
426 if (i
== client_data
->num_hid_devices
)
429 msg
.report_id
= report_id
;
430 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, (uint8_t *)&msg
,
433 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
438 * ishtp_hid_link_ready_wait() - Wait for link ready
439 * @client_data: client data instance
441 * If the transport link started suspend process, then wait, till either
444 * Return: 0 on success, non zero on error
446 int ishtp_hid_link_ready_wait(struct ishtp_cl_data
*client_data
)
450 if (client_data
->suspended
) {
451 hid_ishtp_trace(client_data
, "wait for link ready\n");
452 rc
= wait_event_interruptible_timeout(
453 client_data
->ishtp_resume_wait
,
454 !client_data
->suspended
,
458 hid_ishtp_trace(client_data
, "link not ready\n");
461 hid_ishtp_trace(client_data
, "link ready\n");
468 * ishtp_enum_enum_devices() - Enumerate hid devices
469 * @hid_ishtp_cl: client instance
471 * Helper function to send request to firmware to enumerate HID devices
473 * Return: 0 on success, non zero on error
475 static int ishtp_enum_enum_devices(struct ishtp_cl
*hid_ishtp_cl
)
477 struct hostif_msg msg
;
478 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
482 /* Send HOSTIF_DM_ENUM_DEVICES */
483 memset(&msg
, 0, sizeof(struct hostif_msg
));
484 msg
.hdr
.command
= HOSTIF_DM_ENUM_DEVICES
;
485 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *)&msg
,
486 sizeof(struct hostif_msg
));
491 while (!client_data
->enum_devices_done
&&
493 wait_event_interruptible_timeout(client_data
->init_wait
,
494 client_data
->enum_devices_done
,
497 if (!client_data
->enum_devices_done
)
498 /* Send HOSTIF_DM_ENUM_DEVICES */
499 rv
= ishtp_cl_send(hid_ishtp_cl
,
500 (unsigned char *) &msg
,
501 sizeof(struct hostif_msg
));
503 if (!client_data
->enum_devices_done
) {
504 dev_err(&client_data
->cl_device
->dev
,
505 "[hid-ish]: timed out waiting for enum_devices\n");
508 if (!client_data
->hid_devices
) {
509 dev_err(&client_data
->cl_device
->dev
,
510 "[hid-ish]: failed to allocate HID dev structures\n");
514 client_data
->num_hid_devices
= client_data
->hid_dev_count
;
515 dev_info(&hid_ishtp_cl
->device
->dev
,
516 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
517 client_data
->num_hid_devices
);
523 * ishtp_get_hid_descriptor() - Get hid descriptor
524 * @hid_ishtp_cl: client instance
525 * @index: Index into the hid_descr array
527 * Helper function to send request to firmware get HID descriptor of a device
529 * Return: 0 on success, non zero on error
531 static int ishtp_get_hid_descriptor(struct ishtp_cl
*hid_ishtp_cl
, int index
)
533 struct hostif_msg msg
;
534 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
537 /* Get HID descriptor */
538 client_data
->hid_descr_done
= false;
539 memset(&msg
, 0, sizeof(struct hostif_msg
));
540 msg
.hdr
.command
= HOSTIF_GET_HID_DESCRIPTOR
;
541 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
542 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
543 sizeof(struct hostif_msg
));
547 if (!client_data
->hid_descr_done
) {
548 wait_event_interruptible_timeout(client_data
->init_wait
,
549 client_data
->hid_descr_done
,
551 if (!client_data
->hid_descr_done
) {
552 dev_err(&client_data
->cl_device
->dev
,
553 "[hid-ish]: timed out for hid_descr_done\n");
557 if (!client_data
->hid_descr
[index
]) {
558 dev_err(&client_data
->cl_device
->dev
,
559 "[hid-ish]: allocation HID desc fail\n");
568 * ishtp_get_report_descriptor() - Get report descriptor
569 * @hid_ishtp_cl: client instance
570 * @index: Index into the hid_descr array
572 * Helper function to send request to firmware get HID report descriptor of
575 * Return: 0 on success, non zero on error
577 static int ishtp_get_report_descriptor(struct ishtp_cl
*hid_ishtp_cl
,
580 struct hostif_msg msg
;
581 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
584 /* Get report descriptor */
585 client_data
->report_descr_done
= false;
586 memset(&msg
, 0, sizeof(struct hostif_msg
));
587 msg
.hdr
.command
= HOSTIF_GET_REPORT_DESCRIPTOR
;
588 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
589 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
590 sizeof(struct hostif_msg
));
594 if (!client_data
->report_descr_done
)
595 wait_event_interruptible_timeout(client_data
->init_wait
,
596 client_data
->report_descr_done
,
598 if (!client_data
->report_descr_done
) {
599 dev_err(&client_data
->cl_device
->dev
,
600 "[hid-ish]: timed out for report descr\n");
603 if (!client_data
->report_descr
[index
]) {
604 dev_err(&client_data
->cl_device
->dev
,
605 "[hid-ish]: failed to alloc report descr\n");
613 * hid_ishtp_cl_init() - Init function for ISHTP client
614 * @hid_ishtp_cl: ISHTP client instance
615 * @reset: true if called for init after reset
617 * This function complete the initializtion of the client. The summary of
619 * - Send request to enumerate the hid clients
620 * Get the HID descriptor for each enumearated device
621 * Get report description of each device
622 * Register each device wik hid core by calling ishtp_hid_probe
624 * Return: 0 on success, non zero on error
626 static int hid_ishtp_cl_init(struct ishtp_cl
*hid_ishtp_cl
, int reset
)
628 struct ishtp_device
*dev
;
629 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
630 struct ishtp_fw_client
*fw_client
;
634 dev_dbg(&client_data
->cl_device
->dev
, "%s\n", __func__
);
635 hid_ishtp_trace(client_data
, "%s reset flag: %d\n", __func__
, reset
);
637 rv
= ishtp_cl_link(hid_ishtp_cl
, ISHTP_HOST_CLIENT_ID_ANY
);
639 dev_err(&client_data
->cl_device
->dev
,
640 "ishtp_cl_link failed\n");
644 client_data
->init_done
= 0;
646 dev
= hid_ishtp_cl
->dev
;
648 /* Connect to FW client */
649 hid_ishtp_cl
->rx_ring_size
= HID_CL_RX_RING_SIZE
;
650 hid_ishtp_cl
->tx_ring_size
= HID_CL_TX_RING_SIZE
;
652 fw_client
= ishtp_fw_cl_get_client(dev
, &hid_ishtp_guid
);
654 dev_err(&client_data
->cl_device
->dev
,
655 "ish client uuid not found\n");
659 hid_ishtp_cl
->fw_client_id
= fw_client
->client_id
;
660 hid_ishtp_cl
->state
= ISHTP_CL_CONNECTING
;
662 rv
= ishtp_cl_connect(hid_ishtp_cl
);
664 dev_err(&client_data
->cl_device
->dev
,
665 "client connect fail\n");
669 hid_ishtp_trace(client_data
, "%s client connected\n", __func__
);
671 /* Register read callback */
672 ishtp_register_event_cb(hid_ishtp_cl
->device
, ish_cl_event_cb
);
674 rv
= ishtp_enum_enum_devices(hid_ishtp_cl
);
676 goto err_cl_disconnect
;
678 hid_ishtp_trace(client_data
, "%s enumerated device count %d\n",
679 __func__
, client_data
->num_hid_devices
);
681 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
682 client_data
->cur_hid_dev
= i
;
684 rv
= ishtp_get_hid_descriptor(hid_ishtp_cl
, i
);
686 goto err_cl_disconnect
;
688 rv
= ishtp_get_report_descriptor(hid_ishtp_cl
, i
);
690 goto err_cl_disconnect
;
693 rv
= ishtp_hid_probe(i
, client_data
);
695 dev_err(&client_data
->cl_device
->dev
,
696 "[hid-ish]: HID probe for #%u failed: %d\n",
698 goto err_cl_disconnect
;
701 } /* for() on all hid devices */
703 client_data
->init_done
= 1;
704 client_data
->suspended
= false;
705 wake_up_interruptible(&client_data
->ishtp_resume_wait
);
706 hid_ishtp_trace(client_data
, "%s successful init\n", __func__
);
710 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
711 ishtp_cl_disconnect(hid_ishtp_cl
);
713 ishtp_cl_unlink(hid_ishtp_cl
);
718 * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
719 * @hid_ishtp_cl: ISHTP client instance
721 * Unlink and free hid client
723 static void hid_ishtp_cl_deinit(struct ishtp_cl
*hid_ishtp_cl
)
725 ishtp_cl_unlink(hid_ishtp_cl
);
726 ishtp_cl_flush_queues(hid_ishtp_cl
);
728 /* disband and free all Tx and Rx client-level rings */
729 ishtp_cl_free(hid_ishtp_cl
);
732 static void hid_ishtp_cl_reset_handler(struct work_struct
*work
)
734 struct ishtp_cl_data
*client_data
;
735 struct ishtp_cl
*hid_ishtp_cl
;
736 struct ishtp_cl_device
*cl_device
;
740 client_data
= container_of(work
, struct ishtp_cl_data
, work
);
742 hid_ishtp_cl
= client_data
->hid_ishtp_cl
;
743 cl_device
= client_data
->cl_device
;
745 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
747 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
749 hid_ishtp_cl_deinit(hid_ishtp_cl
);
751 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
755 ishtp_set_drvdata(cl_device
, hid_ishtp_cl
);
756 hid_ishtp_cl
->client_data
= client_data
;
757 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
759 client_data
->num_hid_devices
= 0;
761 for (retry
= 0; retry
< 3; ++retry
) {
762 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 1);
765 dev_err(&client_data
->cl_device
->dev
, "Retry reset init\n");
768 dev_err(&client_data
->cl_device
->dev
, "Reset Failed\n");
769 hid_ishtp_trace(client_data
, "%s Failed hid_ishtp_cl %p\n",
770 __func__
, hid_ishtp_cl
);
775 * hid_ishtp_cl_probe() - ISHTP client driver probe
776 * @cl_device: ISHTP client device instance
778 * This function gets called on device create on ISHTP bus
780 * Return: 0 on success, non zero on error
782 static int hid_ishtp_cl_probe(struct ishtp_cl_device
*cl_device
)
784 struct ishtp_cl
*hid_ishtp_cl
;
785 struct ishtp_cl_data
*client_data
;
791 if (!guid_equal(&hid_ishtp_guid
,
792 &cl_device
->fw_client
->props
.protocol_name
))
795 client_data
= devm_kzalloc(&cl_device
->dev
, sizeof(*client_data
),
800 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
->ishtp_dev
);
804 ishtp_set_drvdata(cl_device
, hid_ishtp_cl
);
805 hid_ishtp_cl
->client_data
= client_data
;
806 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
807 client_data
->cl_device
= cl_device
;
809 init_waitqueue_head(&client_data
->init_wait
);
810 init_waitqueue_head(&client_data
->ishtp_resume_wait
);
812 INIT_WORK(&client_data
->work
, hid_ishtp_cl_reset_handler
);
814 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 0);
816 ishtp_cl_free(hid_ishtp_cl
);
819 ishtp_get_device(cl_device
);
825 * hid_ishtp_cl_remove() - ISHTP client driver remove
826 * @cl_device: ISHTP client device instance
828 * This function gets called on device remove on ISHTP bus
832 static int hid_ishtp_cl_remove(struct ishtp_cl_device
*cl_device
)
834 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
835 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
837 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
840 dev_dbg(&cl_device
->dev
, "%s\n", __func__
);
841 hid_ishtp_cl
->state
= ISHTP_CL_DISCONNECTING
;
842 ishtp_cl_disconnect(hid_ishtp_cl
);
843 ishtp_put_device(cl_device
);
844 ishtp_hid_remove(client_data
);
845 hid_ishtp_cl_deinit(hid_ishtp_cl
);
849 client_data
->num_hid_devices
= 0;
855 * hid_ishtp_cl_reset() - ISHTP client driver reset
856 * @cl_device: ISHTP client device instance
858 * This function gets called on device reset on ISHTP bus
862 static int hid_ishtp_cl_reset(struct ishtp_cl_device
*cl_device
)
864 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
865 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
867 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
870 schedule_work(&client_data
->work
);
875 #define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev)
878 * hid_ishtp_cl_suspend() - ISHTP client driver suspend
879 * @device: device instance
881 * This function gets called on system suspend
885 static int hid_ishtp_cl_suspend(struct device
*device
)
887 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
888 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
889 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
891 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
893 client_data
->suspended
= true;
899 * hid_ishtp_cl_resume() - ISHTP client driver resume
900 * @device: device instance
902 * This function gets called on system resume
906 static int hid_ishtp_cl_resume(struct device
*device
)
908 struct ishtp_cl_device
*cl_device
= to_ishtp_cl_device(device
);
909 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
910 struct ishtp_cl_data
*client_data
= hid_ishtp_cl
->client_data
;
912 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
914 client_data
->suspended
= false;
918 static const struct dev_pm_ops hid_ishtp_pm_ops
= {
919 .suspend
= hid_ishtp_cl_suspend
,
920 .resume
= hid_ishtp_cl_resume
,
923 static struct ishtp_cl_driver hid_ishtp_cl_driver
= {
925 .probe
= hid_ishtp_cl_probe
,
926 .remove
= hid_ishtp_cl_remove
,
927 .reset
= hid_ishtp_cl_reset
,
928 .driver
.pm
= &hid_ishtp_pm_ops
,
931 static int __init
ish_hid_init(void)
935 /* Register ISHTP client device driver with ISHTP Bus */
936 rv
= ishtp_cl_driver_register(&hid_ishtp_cl_driver
);
942 static void __exit
ish_hid_exit(void)
944 ishtp_cl_driver_unregister(&hid_ishtp_cl_driver
);
947 late_initcall(ish_hid_init
);
948 module_exit(ish_hid_exit
);
950 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
952 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
954 * Several modification for multi instance support
955 * suspend/resume and clean up
957 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
959 MODULE_LICENSE("GPL");
960 MODULE_ALIAS("ishtp:*");