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/intel-ish-client-if.h>
19 #include <linux/sched.h>
20 #include "ishtp-hid.h"
22 /* Rx ring buffer pool size */
23 #define HID_CL_RX_RING_SIZE 32
24 #define HID_CL_TX_RING_SIZE 16
26 #define cl_data_to_dev(client_data) ishtp_device(client_data->cl_device)
29 * report_bad_packets() - Report bad packets
30 * @hid_ishtp_cl: Client instance to get stats
31 * @recv_buf: Raw received host interface message
32 * @cur_pos: Current position index in payload
33 * @payload_len: Length of payload expected
35 * Dumps error in case bad packet is received
37 static void report_bad_packet(struct ishtp_cl
*hid_ishtp_cl
, void *recv_buf
,
38 size_t cur_pos
, size_t payload_len
)
40 struct hostif_msg
*recv_msg
= recv_buf
;
41 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
43 dev_err(cl_data_to_dev(client_data
), "[hid-ish]: BAD packet %02X\n"
44 "total_bad=%u cur_pos=%u\n"
45 "[%02X %02X %02X %02X]\n"
47 "multi_packet_cnt=%u\n"
49 recv_msg
->hdr
.command
, client_data
->bad_recv_cnt
,
50 (unsigned int)cur_pos
,
51 ((unsigned char *)recv_msg
)[0], ((unsigned char *)recv_msg
)[1],
52 ((unsigned char *)recv_msg
)[2], ((unsigned char *)recv_msg
)[3],
53 (unsigned int)payload_len
, client_data
->multi_packet_cnt
,
54 recv_msg
->hdr
.command
& ~CMD_MASK
);
58 * process_recv() - Received and parse incoming packet
59 * @hid_ishtp_cl: Client instance to get stats
60 * @recv_buf: Raw received host interface message
61 * @data_len: length of the message
63 * Parse the incoming packet. If it is a response packet then it will update
64 * per instance flags and wake up the caller waiting to for the response.
66 static void process_recv(struct ishtp_cl
*hid_ishtp_cl
, void *recv_buf
,
69 struct hostif_msg
*recv_msg
;
70 unsigned char *payload
;
71 struct device_info
*dev_info
;
73 size_t payload_len
, total_len
, cur_pos
, raw_len
;
75 struct report_list
*reports_list
;
78 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
79 int curr_hid_dev
= client_data
->cur_hid_dev
;
80 struct ishtp_hid_data
*hid_data
= NULL
;
81 struct hid_device
*hid
= NULL
;
83 payload
= recv_buf
+ sizeof(struct hostif_msg_hdr
);
88 if (cur_pos
+ sizeof(struct hostif_msg
) > total_len
) {
89 dev_err(cl_data_to_dev(client_data
),
90 "[hid-ish]: error, received %u which is less than data header %u\n",
91 (unsigned int)data_len
,
92 (unsigned int)sizeof(struct hostif_msg_hdr
));
93 ++client_data
->bad_recv_cnt
;
94 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
98 recv_msg
= (struct hostif_msg
*)(recv_buf
+ cur_pos
);
99 payload_len
= recv_msg
->hdr
.size
;
102 if (cur_pos
+ payload_len
+ sizeof(struct hostif_msg
) >
104 ++client_data
->bad_recv_cnt
;
105 report_bad_packet(hid_ishtp_cl
, recv_msg
, cur_pos
,
107 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
111 hid_ishtp_trace(client_data
, "%s %d\n",
112 __func__
, recv_msg
->hdr
.command
& CMD_MASK
);
114 switch (recv_msg
->hdr
.command
& CMD_MASK
) {
115 case HOSTIF_DM_ENUM_DEVICES
:
116 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
117 client_data
->init_done
)) {
118 ++client_data
->bad_recv_cnt
;
119 report_bad_packet(hid_ishtp_cl
, recv_msg
,
122 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
125 client_data
->hid_dev_count
= (unsigned int)*payload
;
126 if (!client_data
->hid_devices
)
127 client_data
->hid_devices
= devm_kcalloc(
128 cl_data_to_dev(client_data
),
129 client_data
->hid_dev_count
,
130 sizeof(struct device_info
),
132 if (!client_data
->hid_devices
) {
133 dev_err(cl_data_to_dev(client_data
),
134 "Mem alloc failed for hid device info\n");
135 wake_up_interruptible(&client_data
->init_wait
);
138 for (i
= 0; i
< client_data
->hid_dev_count
; ++i
) {
139 if (1 + sizeof(struct device_info
) * i
>=
141 dev_err(cl_data_to_dev(client_data
),
142 "[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
143 1 + sizeof(struct device_info
)
147 if (1 + sizeof(struct device_info
) * i
>=
151 dev_info
= (struct device_info
*)(payload
+ 1 +
152 sizeof(struct device_info
) * i
);
153 if (client_data
->hid_devices
)
154 memcpy(client_data
->hid_devices
+ i
,
156 sizeof(struct device_info
));
159 client_data
->enum_devices_done
= true;
160 wake_up_interruptible(&client_data
->init_wait
);
164 case HOSTIF_GET_HID_DESCRIPTOR
:
165 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
166 client_data
->init_done
)) {
167 ++client_data
->bad_recv_cnt
;
168 report_bad_packet(hid_ishtp_cl
, recv_msg
,
171 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
174 if (!client_data
->hid_descr
[curr_hid_dev
])
175 client_data
->hid_descr
[curr_hid_dev
] =
176 devm_kmalloc(cl_data_to_dev(client_data
),
177 payload_len
, GFP_KERNEL
);
178 if (client_data
->hid_descr
[curr_hid_dev
]) {
179 memcpy(client_data
->hid_descr
[curr_hid_dev
],
180 payload
, payload_len
);
181 client_data
->hid_descr_size
[curr_hid_dev
] =
183 client_data
->hid_descr_done
= true;
185 wake_up_interruptible(&client_data
->init_wait
);
189 case HOSTIF_GET_REPORT_DESCRIPTOR
:
190 if ((!(recv_msg
->hdr
.command
& ~CMD_MASK
) ||
191 client_data
->init_done
)) {
192 ++client_data
->bad_recv_cnt
;
193 report_bad_packet(hid_ishtp_cl
, recv_msg
,
196 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
199 if (!client_data
->report_descr
[curr_hid_dev
])
200 client_data
->report_descr
[curr_hid_dev
] =
201 devm_kmalloc(cl_data_to_dev(client_data
),
202 payload_len
, GFP_KERNEL
);
203 if (client_data
->report_descr
[curr_hid_dev
]) {
204 memcpy(client_data
->report_descr
[curr_hid_dev
],
207 client_data
->report_descr_size
[curr_hid_dev
] =
209 client_data
->report_descr_done
= true;
211 wake_up_interruptible(&client_data
->init_wait
);
215 case HOSTIF_GET_FEATURE_REPORT
:
216 report_type
= HID_FEATURE_REPORT
;
219 case HOSTIF_GET_INPUT_REPORT
:
220 report_type
= HID_INPUT_REPORT
;
222 /* Get index of device that matches this id */
223 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
224 if (recv_msg
->hdr
.device_id
==
225 client_data
->hid_devices
[i
].dev_id
) {
226 hid
= client_data
->hid_sensor_hubs
[i
];
230 hid_data
= hid
->driver_data
;
231 if (hid_data
->raw_get_req
) {
233 (hid_data
->raw_buf_size
<
235 hid_data
->raw_buf_size
:
238 memcpy(hid_data
->raw_buf
,
243 payload
, payload_len
,
247 ishtp_hid_wakeup(hid
);
253 case HOSTIF_SET_FEATURE_REPORT
:
254 /* Get index of device that matches this id */
255 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
256 if (recv_msg
->hdr
.device_id
==
257 client_data
->hid_devices
[i
].dev_id
)
258 if (client_data
->hid_sensor_hubs
[i
]) {
260 client_data
->hid_sensor_hubs
[
267 case HOSTIF_PUBLISH_INPUT_REPORT
:
268 report_type
= HID_INPUT_REPORT
;
269 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
)
270 if (recv_msg
->hdr
.device_id
==
271 client_data
->hid_devices
[i
].dev_id
)
272 if (client_data
->hid_sensor_hubs
[i
])
274 client_data
->hid_sensor_hubs
[
276 report_type
, payload
,
280 case HOSTIF_PUBLISH_INPUT_REPORT_LIST
:
281 report_type
= HID_INPUT_REPORT
;
282 reports_list
= (struct report_list
*)payload
;
283 reports
= (char *)reports_list
->reports
;
285 for (j
= 0; j
< reports_list
->num_of_reports
; j
++) {
286 recv_msg
= (struct hostif_msg
*)(reports
+
288 report_len
= *(uint16_t *)reports
;
289 payload
= reports
+ sizeof(uint16_t) +
290 sizeof(struct hostif_msg_hdr
);
291 payload_len
= report_len
-
292 sizeof(struct hostif_msg_hdr
);
294 for (i
= 0; i
< client_data
->num_hid_devices
;
296 if (recv_msg
->hdr
.device_id
==
297 client_data
->hid_devices
[i
].dev_id
&&
298 client_data
->hid_sensor_hubs
[i
]) {
300 client_data
->hid_sensor_hubs
[
303 payload
, payload_len
,
307 reports
+= sizeof(uint16_t) + report_len
;
311 ++client_data
->bad_recv_cnt
;
312 report_bad_packet(hid_ishtp_cl
, recv_msg
, cur_pos
,
314 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl
));
319 if (!cur_pos
&& cur_pos
+ payload_len
+
320 sizeof(struct hostif_msg
) < total_len
)
321 ++client_data
->multi_packet_cnt
;
323 cur_pos
+= payload_len
+ sizeof(struct hostif_msg
);
324 payload
+= payload_len
+ sizeof(struct hostif_msg
);
326 } while (cur_pos
< total_len
);
330 * ish_cl_event_cb() - bus driver callback for incoming message/packet
331 * @device: Pointer to the the ishtp client device for which this message
334 * Remove the packet from the list and process the message by calling
337 static void ish_cl_event_cb(struct ishtp_cl_device
*device
)
339 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(device
);
340 struct ishtp_cl_rb
*rb_in_proc
;
346 while ((rb_in_proc
= ishtp_cl_rx_get_rb(hid_ishtp_cl
)) != NULL
) {
347 if (!rb_in_proc
->buffer
.data
)
350 r_length
= rb_in_proc
->buf_idx
;
352 /* decide what to do with received data */
353 process_recv(hid_ishtp_cl
, rb_in_proc
->buffer
.data
, r_length
);
355 ishtp_cl_io_rb_recycle(rb_in_proc
);
360 * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
361 * @hid: hid device instance for this request
362 * @buf: feature buffer
363 * @len: Length of feature buffer
364 * @report_id: Report id for the feature set request
366 * This is called from hid core .request() callback. This function doesn't wait
369 void hid_ishtp_set_feature(struct hid_device
*hid
, char *buf
, unsigned int len
,
372 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
373 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
374 struct hostif_msg
*msg
= (struct hostif_msg
*)buf
;
378 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
380 rv
= ishtp_hid_link_ready_wait(client_data
);
382 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
387 memset(msg
, 0, sizeof(struct hostif_msg
));
388 msg
->hdr
.command
= HOSTIF_SET_FEATURE_REPORT
;
389 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
390 if (hid
== client_data
->hid_sensor_hubs
[i
]) {
392 client_data
->hid_devices
[i
].dev_id
;
397 if (i
== client_data
->num_hid_devices
)
400 rv
= ishtp_cl_send(client_data
->hid_ishtp_cl
, buf
, len
);
402 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
407 * hid_ishtp_get_report() - request to get feature/input report
408 * @hid: hid device instance for this request
409 * @report_id: Report id for the get request
410 * @report_type: Report type for the this request
412 * This is called from hid core .request() callback. This function will send
413 * request to FW and return without waiting for response.
415 void hid_ishtp_get_report(struct hid_device
*hid
, int report_id
,
418 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
419 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
420 struct hostif_msg_to_sensor msg
= {};
424 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
425 rv
= ishtp_hid_link_ready_wait(client_data
);
427 hid_ishtp_trace(client_data
, "%s hid %p link not ready\n",
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
, (uint8_t *)&msg
,
449 hid_ishtp_trace(client_data
, "%s hid %p send failed\n",
454 * ishtp_hid_link_ready_wait() - Wait for link ready
455 * @client_data: client data instance
457 * If the transport link started suspend process, then wait, till either
460 * Return: 0 on success, non zero on error
462 int ishtp_hid_link_ready_wait(struct ishtp_cl_data
*client_data
)
466 if (client_data
->suspended
) {
467 hid_ishtp_trace(client_data
, "wait for link ready\n");
468 rc
= wait_event_interruptible_timeout(
469 client_data
->ishtp_resume_wait
,
470 !client_data
->suspended
,
474 hid_ishtp_trace(client_data
, "link not ready\n");
477 hid_ishtp_trace(client_data
, "link ready\n");
484 * ishtp_enum_enum_devices() - Enumerate hid devices
485 * @hid_ishtp_cl: client instance
487 * Helper function to send request to firmware to enumerate HID devices
489 * Return: 0 on success, non zero on error
491 static int ishtp_enum_enum_devices(struct ishtp_cl
*hid_ishtp_cl
)
493 struct hostif_msg msg
;
494 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
498 /* Send HOSTIF_DM_ENUM_DEVICES */
499 memset(&msg
, 0, sizeof(struct hostif_msg
));
500 msg
.hdr
.command
= HOSTIF_DM_ENUM_DEVICES
;
501 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *)&msg
,
502 sizeof(struct hostif_msg
));
507 while (!client_data
->enum_devices_done
&&
509 wait_event_interruptible_timeout(client_data
->init_wait
,
510 client_data
->enum_devices_done
,
513 if (!client_data
->enum_devices_done
)
514 /* Send HOSTIF_DM_ENUM_DEVICES */
515 rv
= ishtp_cl_send(hid_ishtp_cl
,
516 (unsigned char *) &msg
,
517 sizeof(struct hostif_msg
));
519 if (!client_data
->enum_devices_done
) {
520 dev_err(cl_data_to_dev(client_data
),
521 "[hid-ish]: timed out waiting for enum_devices\n");
524 if (!client_data
->hid_devices
) {
525 dev_err(cl_data_to_dev(client_data
),
526 "[hid-ish]: failed to allocate HID dev structures\n");
530 client_data
->num_hid_devices
= client_data
->hid_dev_count
;
531 dev_info(ishtp_device(client_data
->cl_device
),
532 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
533 client_data
->num_hid_devices
);
539 * ishtp_get_hid_descriptor() - Get hid descriptor
540 * @hid_ishtp_cl: client instance
541 * @index: Index into the hid_descr array
543 * Helper function to send request to firmware get HID descriptor of a device
545 * Return: 0 on success, non zero on error
547 static int ishtp_get_hid_descriptor(struct ishtp_cl
*hid_ishtp_cl
, int index
)
549 struct hostif_msg msg
;
550 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
553 /* Get HID descriptor */
554 client_data
->hid_descr_done
= false;
555 memset(&msg
, 0, sizeof(struct hostif_msg
));
556 msg
.hdr
.command
= HOSTIF_GET_HID_DESCRIPTOR
;
557 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
558 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
559 sizeof(struct hostif_msg
));
563 if (!client_data
->hid_descr_done
) {
564 wait_event_interruptible_timeout(client_data
->init_wait
,
565 client_data
->hid_descr_done
,
567 if (!client_data
->hid_descr_done
) {
568 dev_err(cl_data_to_dev(client_data
),
569 "[hid-ish]: timed out for hid_descr_done\n");
573 if (!client_data
->hid_descr
[index
]) {
574 dev_err(cl_data_to_dev(client_data
),
575 "[hid-ish]: allocation HID desc fail\n");
584 * ishtp_get_report_descriptor() - Get report descriptor
585 * @hid_ishtp_cl: client instance
586 * @index: Index into the hid_descr array
588 * Helper function to send request to firmware get HID report descriptor of
591 * Return: 0 on success, non zero on error
593 static int ishtp_get_report_descriptor(struct ishtp_cl
*hid_ishtp_cl
,
596 struct hostif_msg msg
;
597 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
600 /* Get report descriptor */
601 client_data
->report_descr_done
= false;
602 memset(&msg
, 0, sizeof(struct hostif_msg
));
603 msg
.hdr
.command
= HOSTIF_GET_REPORT_DESCRIPTOR
;
604 msg
.hdr
.device_id
= client_data
->hid_devices
[index
].dev_id
;
605 rv
= ishtp_cl_send(hid_ishtp_cl
, (unsigned char *) &msg
,
606 sizeof(struct hostif_msg
));
610 if (!client_data
->report_descr_done
)
611 wait_event_interruptible_timeout(client_data
->init_wait
,
612 client_data
->report_descr_done
,
614 if (!client_data
->report_descr_done
) {
615 dev_err(cl_data_to_dev(client_data
),
616 "[hid-ish]: timed out for report descr\n");
619 if (!client_data
->report_descr
[index
]) {
620 dev_err(cl_data_to_dev(client_data
),
621 "[hid-ish]: failed to alloc report descr\n");
629 * hid_ishtp_cl_init() - Init function for ISHTP client
630 * @hid_ishtp_cl: ISHTP client instance
631 * @reset: true if called for init after reset
633 * This function complete the initializtion of the client. The summary of
635 * - Send request to enumerate the hid clients
636 * Get the HID descriptor for each enumearated device
637 * Get report description of each device
638 * Register each device wik hid core by calling ishtp_hid_probe
640 * Return: 0 on success, non zero on error
642 static int hid_ishtp_cl_init(struct ishtp_cl
*hid_ishtp_cl
, int reset
)
644 struct ishtp_device
*dev
;
645 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
646 struct ishtp_fw_client
*fw_client
;
650 dev_dbg(cl_data_to_dev(client_data
), "%s\n", __func__
);
651 hid_ishtp_trace(client_data
, "%s reset flag: %d\n", __func__
, reset
);
653 rv
= ishtp_cl_link(hid_ishtp_cl
);
655 dev_err(cl_data_to_dev(client_data
),
656 "ishtp_cl_link failed\n");
660 client_data
->init_done
= 0;
662 dev
= ishtp_get_ishtp_device(hid_ishtp_cl
);
664 /* Connect to FW client */
665 ishtp_set_tx_ring_size(hid_ishtp_cl
, HID_CL_TX_RING_SIZE
);
666 ishtp_set_rx_ring_size(hid_ishtp_cl
, HID_CL_RX_RING_SIZE
);
668 fw_client
= ishtp_fw_cl_get_client(dev
, &hid_ishtp_guid
);
670 dev_err(cl_data_to_dev(client_data
),
671 "ish client uuid not found\n");
674 ishtp_cl_set_fw_client_id(hid_ishtp_cl
,
675 ishtp_get_fw_client_id(fw_client
));
676 ishtp_set_connection_state(hid_ishtp_cl
, ISHTP_CL_CONNECTING
);
678 rv
= ishtp_cl_connect(hid_ishtp_cl
);
680 dev_err(cl_data_to_dev(client_data
),
681 "client connect fail\n");
685 hid_ishtp_trace(client_data
, "%s client connected\n", __func__
);
687 /* Register read callback */
688 ishtp_register_event_cb(client_data
->cl_device
, ish_cl_event_cb
);
690 rv
= ishtp_enum_enum_devices(hid_ishtp_cl
);
692 goto err_cl_disconnect
;
694 hid_ishtp_trace(client_data
, "%s enumerated device count %d\n",
695 __func__
, client_data
->num_hid_devices
);
697 for (i
= 0; i
< client_data
->num_hid_devices
; ++i
) {
698 client_data
->cur_hid_dev
= i
;
700 rv
= ishtp_get_hid_descriptor(hid_ishtp_cl
, i
);
702 goto err_cl_disconnect
;
704 rv
= ishtp_get_report_descriptor(hid_ishtp_cl
, i
);
706 goto err_cl_disconnect
;
709 rv
= ishtp_hid_probe(i
, client_data
);
711 dev_err(cl_data_to_dev(client_data
),
712 "[hid-ish]: HID probe for #%u failed: %d\n",
714 goto err_cl_disconnect
;
717 } /* for() on all hid devices */
719 client_data
->init_done
= 1;
720 client_data
->suspended
= false;
721 wake_up_interruptible(&client_data
->ishtp_resume_wait
);
722 hid_ishtp_trace(client_data
, "%s successful init\n", __func__
);
726 ishtp_set_connection_state(hid_ishtp_cl
, ISHTP_CL_DISCONNECTING
);
727 ishtp_cl_disconnect(hid_ishtp_cl
);
729 ishtp_cl_unlink(hid_ishtp_cl
);
734 * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
735 * @hid_ishtp_cl: ISHTP client instance
737 * Unlink and free hid client
739 static void hid_ishtp_cl_deinit(struct ishtp_cl
*hid_ishtp_cl
)
741 ishtp_cl_unlink(hid_ishtp_cl
);
742 ishtp_cl_flush_queues(hid_ishtp_cl
);
744 /* disband and free all Tx and Rx client-level rings */
745 ishtp_cl_free(hid_ishtp_cl
);
748 static void hid_ishtp_cl_reset_handler(struct work_struct
*work
)
750 struct ishtp_cl_data
*client_data
;
751 struct ishtp_cl
*hid_ishtp_cl
;
752 struct ishtp_cl_device
*cl_device
;
756 client_data
= container_of(work
, struct ishtp_cl_data
, work
);
758 hid_ishtp_cl
= client_data
->hid_ishtp_cl
;
759 cl_device
= client_data
->cl_device
;
761 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
763 dev_dbg(ishtp_device(client_data
->cl_device
), "%s\n", __func__
);
765 hid_ishtp_cl_deinit(hid_ishtp_cl
);
767 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
);
771 ishtp_set_drvdata(cl_device
, hid_ishtp_cl
);
772 ishtp_set_client_data(hid_ishtp_cl
, client_data
);
773 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
775 client_data
->num_hid_devices
= 0;
777 for (retry
= 0; retry
< 3; ++retry
) {
778 rv
= hid_ishtp_cl_init(hid_ishtp_cl
, 1);
781 dev_err(cl_data_to_dev(client_data
), "Retry reset init\n");
784 dev_err(cl_data_to_dev(client_data
), "Reset Failed\n");
785 hid_ishtp_trace(client_data
, "%s Failed hid_ishtp_cl %p\n",
786 __func__
, hid_ishtp_cl
);
790 void (*hid_print_trace
)(void *unused
, const char *format
, ...);
793 * hid_ishtp_cl_probe() - ISHTP client driver probe
794 * @cl_device: ISHTP client device instance
796 * This function gets called on device create on ISHTP bus
798 * Return: 0 on success, non zero on error
800 static int hid_ishtp_cl_probe(struct ishtp_cl_device
*cl_device
)
802 struct ishtp_cl
*hid_ishtp_cl
;
803 struct ishtp_cl_data
*client_data
;
809 client_data
= devm_kzalloc(ishtp_device(cl_device
),
810 sizeof(*client_data
),
815 hid_ishtp_cl
= ishtp_cl_allocate(cl_device
);
819 ishtp_set_drvdata(cl_device
, hid_ishtp_cl
);
820 ishtp_set_client_data(hid_ishtp_cl
, client_data
);
821 client_data
->hid_ishtp_cl
= hid_ishtp_cl
;
822 client_data
->cl_device
= cl_device
;
824 init_waitqueue_head(&client_data
->init_wait
);
825 init_waitqueue_head(&client_data
->ishtp_resume_wait
);
827 INIT_WORK(&client_data
->work
, hid_ishtp_cl_reset_handler
);
829 hid_print_trace
= ishtp_trace_callback(cl_device
);
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
= ishtp_get_drvdata(cl_device
);
852 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
854 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
857 dev_dbg(ishtp_device(cl_device
), "%s\n", __func__
);
858 ishtp_set_connection_state(hid_ishtp_cl
, 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
= ishtp_get_drvdata(cl_device
);
882 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
884 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
887 schedule_work(&client_data
->work
);
893 * hid_ishtp_cl_suspend() - ISHTP client driver suspend
894 * @device: device instance
896 * This function gets called on system suspend
900 static int hid_ishtp_cl_suspend(struct device
*device
)
902 struct ishtp_cl_device
*cl_device
= dev_get_drvdata(device
);
903 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
904 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
906 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
908 client_data
->suspended
= true;
914 * hid_ishtp_cl_resume() - ISHTP client driver resume
915 * @device: device instance
917 * This function gets called on system resume
921 static int hid_ishtp_cl_resume(struct device
*device
)
923 struct ishtp_cl_device
*cl_device
= dev_get_drvdata(device
);
924 struct ishtp_cl
*hid_ishtp_cl
= ishtp_get_drvdata(cl_device
);
925 struct ishtp_cl_data
*client_data
= ishtp_get_client_data(hid_ishtp_cl
);
927 hid_ishtp_trace(client_data
, "%s hid_ishtp_cl %p\n", __func__
,
929 client_data
->suspended
= false;
933 static const struct dev_pm_ops hid_ishtp_pm_ops
= {
934 .suspend
= hid_ishtp_cl_suspend
,
935 .resume
= hid_ishtp_cl_resume
,
938 static struct ishtp_cl_driver hid_ishtp_cl_driver
= {
940 .guid
= &hid_ishtp_guid
,
941 .probe
= hid_ishtp_cl_probe
,
942 .remove
= hid_ishtp_cl_remove
,
943 .reset
= hid_ishtp_cl_reset
,
944 .driver
.pm
= &hid_ishtp_pm_ops
,
947 static int __init
ish_hid_init(void)
951 /* Register ISHTP client device driver with ISHTP Bus */
952 rv
= ishtp_cl_driver_register(&hid_ishtp_cl_driver
, THIS_MODULE
);
958 static void __exit
ish_hid_exit(void)
960 ishtp_cl_driver_unregister(&hid_ishtp_cl_driver
);
963 late_initcall(ish_hid_init
);
964 module_exit(ish_hid_exit
);
966 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
968 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
970 * Several modification for multi instance support
971 * suspend/resume and clean up
973 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
975 MODULE_LICENSE("GPL");
976 MODULE_ALIAS("ishtp:*");