1 // SPDX-License-Identifier: GPL-2.0-only
3 * ISHTP client driver for HID (ISH)
5 * Copyright (c) 2014-2016, Intel Corporation.
8 #include <linux/module.h>
10 #include <linux/intel-ish-client-if.h>
11 #include <linux/sched.h>
12 #include "ishtp-hid.h"
14 /* Rx ring buffer pool size */
15 #define HID_CL_RX_RING_SIZE 32
16 #define HID_CL_TX_RING_SIZE 16
18 #define cl_data_to_dev(client_data) ishtp_device(client_data->cl_device)
21 * report_bad_packets() - Report bad packets
22 * @hid_ishtp_cl: Client instance to get stats
23 * @recv_buf: Raw received host interface message
24 * @cur_pos: Current position index in payload
25 * @payload_len: Length of payload expected
27 * Dumps error in case bad packet is received
29 static void report_bad_packet(struct ishtp_cl
*hid_ishtp_cl
, void *recv_buf
,
30 size_t cur_pos
, size_t payload_len
)
32 struct hostif_msg
*recv_msg
= recv_buf
;
33 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
35 dev_err(cl_data_to_dev(client_data
), "[hid-ish]: BAD packet %02X\n"
36 "total_bad=%u cur_pos=%u\n"
37 "[%02X %02X %02X %02X]\n"
39 "multi_packet_cnt=%u\n"
41 recv_msg
->hdr
.command
, client_data
->bad_recv_cnt
,
42 (unsigned int)cur_pos
,
43 ((unsigned char *)recv_msg
)[0], ((unsigned char *)recv_msg
)[1],
44 ((unsigned char *)recv_msg
)[2], ((unsigned char *)recv_msg
)[3],
45 (unsigned int)payload_len
, client_data
->multi_packet_cnt
,
46 recv_msg
->hdr
.command
& ~CMD_MASK
);
50 * process_recv() - Received and parse incoming packet
51 * @hid_ishtp_cl: Client instance to get stats
52 * @recv_buf: Raw received host interface message
53 * @data_len: length of the message
55 * Parse the incoming packet. If it is a response packet then it will update
56 * per instance flags and wake up the caller waiting to for the response.
58 static void process_recv(struct ishtp_cl
*hid_ishtp_cl
, void *recv_buf
,
61 struct hostif_msg
*recv_msg
;
62 unsigned char *payload
;
63 struct device_info
*dev_info
;
65 size_t payload_len
, total_len
, cur_pos
, raw_len
;
67 struct report_list
*reports_list
;
70 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
71 int curr_hid_dev
= client_data
->cur_hid_dev
;
72 struct ishtp_hid_data
*hid_data
= NULL
;
73 struct hid_device
*hid
= NULL
;
75 payload
= recv_buf
+ sizeof(struct hostif_msg_hdr
);
80 if (cur_pos
+ sizeof(struct hostif_msg
) > total_len
) {
81 dev_err(cl_data_to_dev(client_data
),
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(ishtp_get_ishtp_device(hid_ishtp_cl
));
90 recv_msg
= (struct hostif_msg
*)(recv_buf
+ cur_pos
);
91 payload_len
= recv_msg
->hdr
.size
;
94 if (cur_pos
+ payload_len
+ sizeof(struct hostif_msg
) >
96 ++client_data
->bad_recv_cnt
;
97 report_bad_packet(hid_ishtp_cl
, recv_msg
, cur_pos
,
99 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
103 hid_ishtp_trace(client_data
, "%s %d\n",
104 __func__
, recv_msg
->hdr
.command
& CMD_MASK
);
106 switch (recv_msg
->hdr
.command
& CMD_MASK
) {
107 case HOSTIF_DM_ENUM_DEVICES
:
108 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
109 client_data
->init_done
)) {
110 ++client_data
->bad_recv_cnt
;
111 report_bad_packet(hid_ishtp_cl
, recv_msg
,
114 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
117 client_data
->hid_dev_count
= (unsigned int)*payload
;
118 if (!client_data
->hid_devices
)
119 client_data
->hid_devices
= devm_kcalloc(
120 cl_data_to_dev(client_data
),
121 client_data
->hid_dev_count
,
122 sizeof(struct device_info
),
124 if (!client_data
->hid_devices
) {
125 dev_err(cl_data_to_dev(client_data
),
126 "Mem alloc failed for hid device info\n");
127 wake_up_interruptible(&client_data
->init_wait
);
130 for (i
= 0; i
< client_data
->hid_dev_count
; ++i
) {
131 if (1 + sizeof(struct device_info
) * i
>=
133 dev_err(cl_data_to_dev(client_data
),
134 "[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
135 1 + sizeof(struct device_info
)
139 if (1 + sizeof(struct device_info
) * i
>=
143 dev_info
= (struct device_info
*)(payload
+ 1 +
144 sizeof(struct device_info
) * i
);
145 if (client_data
->hid_devices
)
146 memcpy(client_data
->hid_devices
+ i
,
148 sizeof(struct device_info
));
151 client_data
->enum_devices_done
= true;
152 wake_up_interruptible(&client_data
->init_wait
);
156 case HOSTIF_GET_HID_DESCRIPTOR
:
157 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
158 client_data
->init_done
)) {
159 ++client_data
->bad_recv_cnt
;
160 report_bad_packet(hid_ishtp_cl
, recv_msg
,
163 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
166 if (!client_data
->hid_descr
[curr_hid_dev
])
167 client_data
->hid_descr
[curr_hid_dev
] =
168 devm_kmalloc(cl_data_to_dev(client_data
),
169 payload_len
, GFP_KERNEL
);
170 if (client_data
->hid_descr
[curr_hid_dev
]) {
171 memcpy(client_data
->hid_descr
[curr_hid_dev
],
172 payload
, payload_len
);
173 client_data
->hid_descr_size
[curr_hid_dev
] =
175 client_data
->hid_descr_done
= true;
177 wake_up_interruptible(&client_data
->init_wait
);
181 case HOSTIF_GET_REPORT_DESCRIPTOR
:
182 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
183 client_data
->init_done
)) {
184 ++client_data
->bad_recv_cnt
;
185 report_bad_packet(hid_ishtp_cl
, recv_msg
,
188 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
191 if (!client_data
->report_descr
[curr_hid_dev
])
192 client_data
->report_descr
[curr_hid_dev
] =
193 devm_kmalloc(cl_data_to_dev(client_data
),
194 payload_len
, GFP_KERNEL
);
195 if (client_data
->report_descr
[curr_hid_dev
]) {
196 memcpy(client_data
->report_descr
[curr_hid_dev
],
199 client_data
->report_descr_size
[curr_hid_dev
] =
201 client_data
->report_descr_done
= true;
203 wake_up_interruptible(&client_data
->init_wait
);
207 case HOSTIF_GET_FEATURE_REPORT
:
208 report_type
= HID_FEATURE_REPORT
;
211 case HOSTIF_GET_INPUT_REPORT
:
212 report_type
= HID_INPUT_REPORT
;
214 /* Get index of device that matches this id */
215 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
216 if (recv_msg
->hdr
.device_id
==
217 client_data
->hid_devices
[i
].dev_id
) {
218 hid
= client_data
->hid_sensor_hubs
[i
];
222 hid_data
= hid
->driver_data
;
223 if (hid_data
->raw_get_req
) {
225 (hid_data
->raw_buf_size
<
227 hid_data
->raw_buf_size
:
230 memcpy(hid_data
->raw_buf
,
235 payload
, payload_len
,
239 ishtp_hid_wakeup(hid
);
245 case HOSTIF_SET_FEATURE_REPORT
:
246 /* Get index of device that matches this id */
247 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
248 if (recv_msg
->hdr
.device_id
==
249 client_data
->hid_devices
[i
].dev_id
)
250 if (client_data
->hid_sensor_hubs
[i
]) {
252 client_data
->hid_sensor_hubs
[
259 case HOSTIF_PUBLISH_INPUT_REPORT
:
260 report_type
= HID_INPUT_REPORT
;
261 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
)
262 if (recv_msg
->hdr
.device_id
==
263 client_data
->hid_devices
[i
].dev_id
)
264 if (client_data
->hid_sensor_hubs
[i
])
266 client_data
->hid_sensor_hubs
[
268 report_type
, payload
,
272 case HOSTIF_PUBLISH_INPUT_REPORT_LIST
:
273 report_type
= HID_INPUT_REPORT
;
274 reports_list
= (struct report_list
*)payload
;
275 reports
= (char *)reports_list
->reports
;
277 for (j
= 0; j
< reports_list
->num_of_reports
; j
++) {
278 recv_msg
= (struct hostif_msg
*)(reports
+
280 report_len
= *(uint16_t *)reports
;
281 payload
= reports
+ sizeof(uint16_t) +
282 sizeof(struct hostif_msg_hdr
);
283 payload_len
= report_len
-
284 sizeof(struct hostif_msg_hdr
);
286 for (i
= 0; i
< client_data
->num_hid_devices
;
288 if (recv_msg
->hdr
.device_id
==
289 client_data
->hid_devices
[i
].dev_id
&&
290 client_data
->hid_sensor_hubs
[i
]) {
292 client_data
->hid_sensor_hubs
[
295 payload
, payload_len
,
299 reports
+= sizeof(uint16_t) + report_len
;
303 ++client_data
->bad_recv_cnt
;
304 report_bad_packet(hid_ishtp_cl
, recv_msg
, cur_pos
,
306 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
311 if (!cur_pos
&& cur_pos
+ payload_len
+
312 sizeof(struct hostif_msg
) < total_len
)
313 ++client_data
->multi_packet_cnt
;
315 cur_pos
+= payload_len
+ sizeof(struct hostif_msg
);
316 payload
+= payload_len
+ sizeof(struct hostif_msg
);
318 } while (cur_pos
< total_len
);
322 * ish_cl_event_cb() - bus driver callback for incoming message/packet
323 * @device: Pointer to the the ishtp client device for which this message
326 * Remove the packet from the list and process the message by calling
329 static void ish_cl_event_cb(struct ishtp_cl_device
*device
)
331 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(device
);
332 struct ishtp_cl_rb
*rb_in_proc
;
338 while ((rb_in_proc
= ishtp_cl_rx_get_rb(hid_ishtp_cl
)) != NULL
) {
339 if (!rb_in_proc
->buffer
.data
)
342 r_length
= rb_in_proc
->buf_idx
;
344 /* decide what to do with received data */
345 process_recv(hid_ishtp_cl
, rb_in_proc
->buffer
.data
, r_length
);
347 ishtp_cl_io_rb_recycle(rb_in_proc
);
352 * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
353 * @hid: hid device instance for this request
354 * @buf: feature buffer
355 * @len: Length of feature buffer
356 * @report_id: Report id for the feature set request
358 * This is called from hid core .request() callback. This function doesn't wait
361 void hid_ishtp_set_feature(struct hid_device
*hid
, char *buf
, unsigned int len
,
364 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
365 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
366 struct hostif_msg
*msg
= (struct hostif_msg
*)buf
;
370 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
372 rv
= ishtp_hid_link_ready_wait(client_data
);
374 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
379 memset(msg
, 0, sizeof(struct hostif_msg
));
380 msg
->hdr
.command
= HOSTIF_SET_FEATURE_REPORT
;
381 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
382 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
384 client_data
->hid_devices
[i
].dev_id
;
389 if (i
== client_data
->num_hid_devices
)
392 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, buf
, len
);
394 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
399 * hid_ishtp_get_report() - request to get feature/input report
400 * @hid: hid device instance for this request
401 * @report_id: Report id for the get request
402 * @report_type: Report type for the this request
404 * This is called from hid core .request() callback. This function will send
405 * request to FW and return without waiting for response.
407 void hid_ishtp_get_report(struct hid_device
*hid
, int report_id
,
410 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
411 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
412 struct hostif_msg_to_sensor msg
= {};
416 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
417 rv
= ishtp_hid_link_ready_wait(client_data
);
419 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
424 msg
.hdr
.command
= (report_type
== HID_FEATURE_REPORT
) ?
425 HOSTIF_GET_FEATURE_REPORT
: HOSTIF_GET_INPUT_REPORT
;
426 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
427 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
429 client_data
->hid_devices
[i
].dev_id
;
434 if (i
== client_data
->num_hid_devices
)
437 msg
.report_id
= report_id
;
438 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, (uint8_t *)&msg
,
441 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
446 * ishtp_hid_link_ready_wait() - Wait for link ready
447 * @client_data: client data instance
449 * If the transport link started suspend process, then wait, till either
452 * Return: 0 on success, non zero on error
454 int ishtp_hid_link_ready_wait(struct ishtp_cl_data
*client_data
)
458 if (client_data
->suspended
) {
459 hid_ishtp_trace(client_data
, "wait for link ready\n");
460 rc
= wait_event_interruptible_timeout(
461 client_data
->ishtp_resume_wait
,
462 !client_data
->suspended
,
466 hid_ishtp_trace(client_data
, "link not ready\n");
469 hid_ishtp_trace(client_data
, "link ready\n");
476 * ishtp_enum_enum_devices() - Enumerate hid devices
477 * @hid_ishtp_cl: client instance
479 * Helper function to send request to firmware to enumerate HID devices
481 * Return: 0 on success, non zero on error
483 static int ishtp_enum_enum_devices(struct ishtp_cl
*hid_ishtp_cl
)
485 struct hostif_msg msg
;
486 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
490 /* Send HOSTIF_DM_ENUM_DEVICES */
491 memset(&msg
, 0, sizeof(struct hostif_msg
));
492 msg
.hdr
.command
= HOSTIF_DM_ENUM_DEVICES
;
493 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *)&msg
,
494 sizeof(struct hostif_msg
));
499 while (!client_data
->enum_devices_done
&&
501 wait_event_interruptible_timeout(client_data
->init_wait
,
502 client_data
->enum_devices_done
,
505 if (!client_data
->enum_devices_done
)
506 /* Send HOSTIF_DM_ENUM_DEVICES */
507 rv
= ishtp_cl_send(hid_ishtp_cl
,
508 (unsigned char *) &msg
,
509 sizeof(struct hostif_msg
));
511 if (!client_data
->enum_devices_done
) {
512 dev_err(cl_data_to_dev(client_data
),
513 "[hid-ish]: timed out waiting for enum_devices\n");
516 if (!client_data
->hid_devices
) {
517 dev_err(cl_data_to_dev(client_data
),
518 "[hid-ish]: failed to allocate HID dev structures\n");
522 client_data
->num_hid_devices
= client_data
->hid_dev_count
;
523 dev_info(ishtp_device(client_data
->cl_device
),
524 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
525 client_data
->num_hid_devices
);
531 * ishtp_get_hid_descriptor() - Get hid descriptor
532 * @hid_ishtp_cl: client instance
533 * @index: Index into the hid_descr array
535 * Helper function to send request to firmware get HID descriptor of a device
537 * Return: 0 on success, non zero on error
539 static int ishtp_get_hid_descriptor(struct ishtp_cl
*hid_ishtp_cl
, int index
)
541 struct hostif_msg msg
;
542 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
545 /* Get HID descriptor */
546 client_data
->hid_descr_done
= false;
547 memset(&msg
, 0, sizeof(struct hostif_msg
));
548 msg
.hdr
.command
= HOSTIF_GET_HID_DESCRIPTOR
;
549 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
550 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
551 sizeof(struct hostif_msg
));
555 if (!client_data
->hid_descr_done
) {
556 wait_event_interruptible_timeout(client_data
->init_wait
,
557 client_data
->hid_descr_done
,
559 if (!client_data
->hid_descr_done
) {
560 dev_err(cl_data_to_dev(client_data
),
561 "[hid-ish]: timed out for hid_descr_done\n");
565 if (!client_data
->hid_descr
[index
]) {
566 dev_err(cl_data_to_dev(client_data
),
567 "[hid-ish]: allocation HID desc fail\n");
576 * ishtp_get_report_descriptor() - Get report descriptor
577 * @hid_ishtp_cl: client instance
578 * @index: Index into the hid_descr array
580 * Helper function to send request to firmware get HID report descriptor of
583 * Return: 0 on success, non zero on error
585 static int ishtp_get_report_descriptor(struct ishtp_cl
*hid_ishtp_cl
,
588 struct hostif_msg msg
;
589 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
592 /* Get report descriptor */
593 client_data
->report_descr_done
= false;
594 memset(&msg
, 0, sizeof(struct hostif_msg
));
595 msg
.hdr
.command
= HOSTIF_GET_REPORT_DESCRIPTOR
;
596 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
597 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
598 sizeof(struct hostif_msg
));
602 if (!client_data
->report_descr_done
)
603 wait_event_interruptible_timeout(client_data
->init_wait
,
604 client_data
->report_descr_done
,
606 if (!client_data
->report_descr_done
) {
607 dev_err(cl_data_to_dev(client_data
),
608 "[hid-ish]: timed out for report descr\n");
611 if (!client_data
->report_descr
[index
]) {
612 dev_err(cl_data_to_dev(client_data
),
613 "[hid-ish]: failed to alloc report descr\n");
621 * hid_ishtp_cl_init() - Init function for ISHTP client
622 * @hid_ishtp_cl: ISHTP client instance
623 * @reset: true if called for init after reset
625 * This function complete the initializtion of the client. The summary of
627 * - Send request to enumerate the hid clients
628 * Get the HID descriptor for each enumearated device
629 * Get report description of each device
630 * Register each device wik hid core by calling ishtp_hid_probe
632 * Return: 0 on success, non zero on error
634 static int hid_ishtp_cl_init(struct ishtp_cl
*hid_ishtp_cl
, int reset
)
636 struct ishtp_device
*dev
;
637 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
638 struct ishtp_fw_client
*fw_client
;
642 dev_dbg(cl_data_to_dev(client_data
), "%s\n", __func__
);
643 hid_ishtp_trace(client_data
, "%s reset flag: %d\n", __func__
, reset
);
645 rv
= ishtp_cl_link(hid_ishtp_cl
);
647 dev_err(cl_data_to_dev(client_data
),
648 "ishtp_cl_link failed\n");
652 client_data
->init_done
= 0;
654 dev
= ishtp_get_ishtp_device(hid_ishtp_cl
);
656 /* Connect to FW client */
657 ishtp_set_tx_ring_size(hid_ishtp_cl
, HID_CL_TX_RING_SIZE
);
658 ishtp_set_rx_ring_size(hid_ishtp_cl
, HID_CL_RX_RING_SIZE
);
660 fw_client
= ishtp_fw_cl_get_client(dev
, &hid_ishtp_guid
);
662 dev_err(cl_data_to_dev(client_data
),
663 "ish client uuid not found\n");
666 ishtp_cl_set_fw_client_id(hid_ishtp_cl
,
667 ishtp_get_fw_client_id(fw_client
));
668 ishtp_set_connection_state(hid_ishtp_cl
, ISHTP_CL_CONNECTING
);
670 rv
= ishtp_cl_connect(hid_ishtp_cl
);
672 dev_err(cl_data_to_dev(client_data
),
673 "client connect fail\n");
677 hid_ishtp_trace(client_data
, "%s client connected\n", __func__
);
679 /* Register read callback */
680 ishtp_register_event_cb(client_data
->cl_device
, ish_cl_event_cb
);
682 rv
= ishtp_enum_enum_devices(hid_ishtp_cl
);
684 goto err_cl_disconnect
;
686 hid_ishtp_trace(client_data
, "%s enumerated device count %d\n",
687 __func__
, client_data
->num_hid_devices
);
689 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
690 client_data
->cur_hid_dev
= i
;
692 rv
= ishtp_get_hid_descriptor(hid_ishtp_cl
, i
);
694 goto err_cl_disconnect
;
696 rv
= ishtp_get_report_descriptor(hid_ishtp_cl
, i
);
698 goto err_cl_disconnect
;
701 rv
= ishtp_hid_probe(i
, client_data
);
703 dev_err(cl_data_to_dev(client_data
),
704 "[hid-ish]: HID probe for #%u failed: %d\n",
706 goto err_cl_disconnect
;
709 } /* for() on all hid devices */
711 client_data
->init_done
= 1;
712 client_data
->suspended
= false;
713 wake_up_interruptible(&client_data
->ishtp_resume_wait
);
714 hid_ishtp_trace(client_data
, "%s successful init\n", __func__
);
718 ishtp_set_connection_state(hid_ishtp_cl
, ISHTP_CL_DISCONNECTING
);
719 ishtp_cl_disconnect(hid_ishtp_cl
);
721 ishtp_cl_unlink(hid_ishtp_cl
);
726 * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
727 * @hid_ishtp_cl: ISHTP client instance
729 * Unlink and free hid client
731 static void hid_ishtp_cl_deinit(struct ishtp_cl
*hid_ishtp_cl
)
733 ishtp_cl_unlink(hid_ishtp_cl
);
734 ishtp_cl_flush_queues(hid_ishtp_cl
);
736 /* disband and free all Tx and Rx client-level rings */
737 ishtp_cl_free(hid_ishtp_cl
);
740 static void hid_ishtp_cl_reset_handler(struct work_struct
*work
)
742 struct ishtp_cl_data
*client_data
;
743 struct ishtp_cl
*hid_ishtp_cl
;
744 struct ishtp_cl_device
*cl_device
;
748 client_data
= container_of(work
, struct ishtp_cl_data
, work
);
750 hid_ishtp_cl
= client_data
->hid_ishtp_cl
;
751 cl_device
= client_data
->cl_device
;
753 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
755 dev_dbg(ishtp_device(client_data
->cl_device
), "%s\n", __func__
);
757 hid_ishtp_cl_deinit(hid_ishtp_cl
);
759 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
);
763 ishtp_set_drvdata(cl_device
, hid_ishtp_cl
);
764 ishtp_set_client_data(hid_ishtp_cl
, client_data
);
765 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
767 client_data
->num_hid_devices
= 0;
769 for (retry
= 0; retry
< 3; ++retry
) {
770 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 1);
773 dev_err(cl_data_to_dev(client_data
), "Retry reset init\n");
776 dev_err(cl_data_to_dev(client_data
), "Reset Failed\n");
777 hid_ishtp_trace(client_data
, "%s Failed hid_ishtp_cl %p\n",
778 __func__
, hid_ishtp_cl
);
782 void (*hid_print_trace
)(void *unused
, const char *format
, ...);
785 * hid_ishtp_cl_probe() - ISHTP client driver probe
786 * @cl_device: ISHTP client device instance
788 * This function gets called on device create on ISHTP bus
790 * Return: 0 on success, non zero on error
792 static int hid_ishtp_cl_probe(struct ishtp_cl_device
*cl_device
)
794 struct ishtp_cl
*hid_ishtp_cl
;
795 struct ishtp_cl_data
*client_data
;
801 client_data
= devm_kzalloc(ishtp_device(cl_device
),
802 sizeof(*client_data
),
807 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
);
811 ishtp_set_drvdata(cl_device
, hid_ishtp_cl
);
812 ishtp_set_client_data(hid_ishtp_cl
, client_data
);
813 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
814 client_data
->cl_device
= cl_device
;
816 init_waitqueue_head(&client_data
->init_wait
);
817 init_waitqueue_head(&client_data
->ishtp_resume_wait
);
819 INIT_WORK(&client_data
->work
, hid_ishtp_cl_reset_handler
);
821 hid_print_trace
= ishtp_trace_callback(cl_device
);
823 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 0);
825 ishtp_cl_free(hid_ishtp_cl
);
828 ishtp_get_device(cl_device
);
834 * hid_ishtp_cl_remove() - ISHTP client driver remove
835 * @cl_device: ISHTP client device instance
837 * This function gets called on device remove on ISHTP bus
841 static int hid_ishtp_cl_remove(struct ishtp_cl_device
*cl_device
)
843 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
844 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
846 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
849 dev_dbg(ishtp_device(cl_device
), "%s\n", __func__
);
850 ishtp_set_connection_state(hid_ishtp_cl
, ISHTP_CL_DISCONNECTING
);
851 ishtp_cl_disconnect(hid_ishtp_cl
);
852 ishtp_put_device(cl_device
);
853 ishtp_hid_remove(client_data
);
854 hid_ishtp_cl_deinit(hid_ishtp_cl
);
858 client_data
->num_hid_devices
= 0;
864 * hid_ishtp_cl_reset() - ISHTP client driver reset
865 * @cl_device: ISHTP client device instance
867 * This function gets called on device reset on ISHTP bus
871 static int hid_ishtp_cl_reset(struct ishtp_cl_device
*cl_device
)
873 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
874 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
876 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
879 schedule_work(&client_data
->work
);
885 * hid_ishtp_cl_suspend() - ISHTP client driver suspend
886 * @device: device instance
888 * This function gets called on system suspend
892 static int hid_ishtp_cl_suspend(struct device
*device
)
894 struct ishtp_cl_device
*cl_device
= ishtp_dev_to_cl_device(device
);
895 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
896 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
898 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
900 client_data
->suspended
= true;
906 * hid_ishtp_cl_resume() - ISHTP client driver resume
907 * @device: device instance
909 * This function gets called on system resume
913 static int hid_ishtp_cl_resume(struct device
*device
)
915 struct ishtp_cl_device
*cl_device
= ishtp_dev_to_cl_device(device
);
916 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
917 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
919 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
921 client_data
->suspended
= false;
925 static const struct dev_pm_ops hid_ishtp_pm_ops
= {
926 .suspend
= hid_ishtp_cl_suspend
,
927 .resume
= hid_ishtp_cl_resume
,
930 static struct ishtp_cl_driver hid_ishtp_cl_driver
= {
932 .guid
= &hid_ishtp_guid
,
933 .probe
= hid_ishtp_cl_probe
,
934 .remove
= hid_ishtp_cl_remove
,
935 .reset
= hid_ishtp_cl_reset
,
936 .driver
.pm
= &hid_ishtp_pm_ops
,
939 static int __init
ish_hid_init(void)
943 /* Register ISHTP client device driver with ISHTP Bus */
944 rv
= ishtp_cl_driver_register(&hid_ishtp_cl_driver
, THIS_MODULE
);
950 static void __exit
ish_hid_exit(void)
952 ishtp_cl_driver_unregister(&hid_ishtp_cl_driver
);
955 late_initcall(ish_hid_init
);
956 module_exit(ish_hid_exit
);
958 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
960 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
962 * Several modification for multi instance support
963 * suspend/resume and clean up
965 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
967 MODULE_LICENSE("GPL");
968 MODULE_ALIAS("ishtp:*");