include:libata: fix boolreturn.cocci warnings
[linux-2.6-microblaze.git] / drivers / hid / intel-ish-hid / ishtp-hid-client.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ISHTP client driver for HID (ISH)
4  *
5  * Copyright (c) 2014-2016, Intel Corporation.
6  */
7
8 #include <linux/module.h>
9 #include <linux/hid.h>
10 #include <linux/intel-ish-client-if.h>
11 #include <linux/sched.h>
12 #include "ishtp-hid.h"
13
14 /* ISH Transport protocol (ISHTP in short) GUID */
15 static const guid_t hid_ishtp_guid =
16         GUID_INIT(0x33AECD58, 0xB679, 0x4E54,
17                   0x9B, 0xD9, 0xA0, 0x4D, 0x34, 0xF0, 0xC2, 0x26);
18
19 /* Rx ring buffer pool size */
20 #define HID_CL_RX_RING_SIZE     32
21 #define HID_CL_TX_RING_SIZE     16
22
23 #define cl_data_to_dev(client_data) ishtp_device(client_data->cl_device)
24
25 /**
26  * report_bad_packet() - Report bad packets
27  * @hid_ishtp_cl:       Client instance to get stats
28  * @recv_buf:           Raw received host interface message
29  * @cur_pos:            Current position index in payload
30  * @payload_len:        Length of payload expected
31  *
32  * Dumps error in case bad packet is received
33  */
34 static void report_bad_packet(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
35                               size_t cur_pos,  size_t payload_len)
36 {
37         struct hostif_msg *recv_msg = recv_buf;
38         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
39
40         dev_err(cl_data_to_dev(client_data), "[hid-ish]: BAD packet %02X\n"
41                 "total_bad=%u cur_pos=%u\n"
42                 "[%02X %02X %02X %02X]\n"
43                 "payload_len=%u\n"
44                 "multi_packet_cnt=%u\n"
45                 "is_response=%02X\n",
46                 recv_msg->hdr.command, client_data->bad_recv_cnt,
47                 (unsigned int)cur_pos,
48                 ((unsigned char *)recv_msg)[0], ((unsigned char *)recv_msg)[1],
49                 ((unsigned char *)recv_msg)[2], ((unsigned char *)recv_msg)[3],
50                 (unsigned int)payload_len, client_data->multi_packet_cnt,
51                 recv_msg->hdr.command & ~CMD_MASK);
52 }
53
54 /**
55  * process_recv() - Received and parse incoming packet
56  * @hid_ishtp_cl:       Client instance to get stats
57  * @recv_buf:           Raw received host interface message
58  * @data_len:           length of the message
59  *
60  * Parse the incoming packet. If it is a response packet then it will update
61  * per instance flags and wake up the caller waiting to for the response.
62  */
63 static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
64                          size_t data_len)
65 {
66         struct hostif_msg *recv_msg;
67         unsigned char *payload;
68         struct device_info *dev_info;
69         int i, j;
70         size_t  payload_len, total_len, cur_pos, raw_len;
71         int report_type;
72         struct report_list *reports_list;
73         char *reports;
74         size_t report_len;
75         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
76         int curr_hid_dev = client_data->cur_hid_dev;
77         struct ishtp_hid_data *hid_data = NULL;
78         struct hid_device *hid = NULL;
79
80         payload = recv_buf + sizeof(struct hostif_msg_hdr);
81         total_len = data_len;
82         cur_pos = 0;
83
84         do {
85                 if (cur_pos + sizeof(struct hostif_msg) > total_len) {
86                         dev_err(cl_data_to_dev(client_data),
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(ishtp_get_ishtp_device(hid_ishtp_cl));
92                         break;
93                 }
94
95                 recv_msg = (struct hostif_msg *)(recv_buf + cur_pos);
96                 payload_len = recv_msg->hdr.size;
97
98                 /* Sanity checks */
99                 if (cur_pos + payload_len + sizeof(struct hostif_msg) >
100                                 total_len) {
101                         ++client_data->bad_recv_cnt;
102                         report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
103                                           payload_len);
104                         ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
105                         break;
106                 }
107
108                 hid_ishtp_trace(client_data,  "%s %d\n",
109                                 __func__, recv_msg->hdr.command & CMD_MASK);
110
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,
117                                                   cur_pos,
118                                                   payload_len);
119                                 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
120                                 break;
121                         }
122                         client_data->hid_dev_count = (unsigned int)*payload;
123                         if (!client_data->hid_devices)
124                                 client_data->hid_devices = devm_kcalloc(
125                                                 cl_data_to_dev(client_data),
126                                                 client_data->hid_dev_count,
127                                                 sizeof(struct device_info),
128                                                 GFP_KERNEL);
129                         if (!client_data->hid_devices) {
130                                 dev_err(cl_data_to_dev(client_data),
131                                 "Mem alloc failed for hid device info\n");
132                                 wake_up_interruptible(&client_data->init_wait);
133                                 break;
134                         }
135                         for (i = 0; i < client_data->hid_dev_count; ++i) {
136                                 if (1 + sizeof(struct device_info) * i >=
137                                                 payload_len) {
138                                         dev_err(cl_data_to_dev(client_data),
139                                                 "[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
140                                                 1 + sizeof(struct device_info)
141                                                 * i, payload_len);
142                                 }
143
144                                 if (1 + sizeof(struct device_info) * i >=
145                                                 data_len)
146                                         break;
147
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,
152                                                dev_info,
153                                                sizeof(struct device_info));
154                         }
155
156                         client_data->enum_devices_done = true;
157                         wake_up_interruptible(&client_data->init_wait);
158
159                         break;
160
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,
166                                                   cur_pos,
167                                                   payload_len);
168                                 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
169                                 break;
170                         }
171                         if (!client_data->hid_descr[curr_hid_dev])
172                                 client_data->hid_descr[curr_hid_dev] =
173                                 devm_kmalloc(cl_data_to_dev(client_data),
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] =
179                                         payload_len;
180                                 client_data->hid_descr_done = true;
181                         }
182                         wake_up_interruptible(&client_data->init_wait);
183
184                         break;
185
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,
191                                                   cur_pos,
192                                                   payload_len);
193                                 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
194                                 break;
195                         }
196                         if (!client_data->report_descr[curr_hid_dev])
197                                 client_data->report_descr[curr_hid_dev] =
198                                 devm_kmalloc(cl_data_to_dev(client_data),
199                                              payload_len, GFP_KERNEL);
200                         if (client_data->report_descr[curr_hid_dev])  {
201                                 memcpy(client_data->report_descr[curr_hid_dev],
202                                        payload,
203                                        payload_len);
204                                 client_data->report_descr_size[curr_hid_dev] =
205                                         payload_len;
206                                 client_data->report_descr_done = true;
207                         }
208                         wake_up_interruptible(&client_data->init_wait);
209
210                         break;
211
212                 case HOSTIF_GET_FEATURE_REPORT:
213                         report_type = HID_FEATURE_REPORT;
214                         goto    do_get_report;
215
216                 case HOSTIF_GET_INPUT_REPORT:
217                         report_type = HID_INPUT_REPORT;
218 do_get_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                                         hid = client_data->hid_sensor_hubs[i];
224                                         if (!hid)
225                                                 break;
226
227                                         hid_data = hid->driver_data;
228                                         if (hid_data->raw_get_req) {
229                                                 raw_len =
230                                                   (hid_data->raw_buf_size <
231                                                                 payload_len) ?
232                                                   hid_data->raw_buf_size :
233                                                   payload_len;
234
235                                                 memcpy(hid_data->raw_buf,
236                                                        payload, raw_len);
237                                         } else {
238                                                 hid_input_report
239                                                         (hid, report_type,
240                                                          payload, payload_len,
241                                                          0);
242                                         }
243
244                                         ishtp_hid_wakeup(hid);
245                                         break;
246                                 }
247                         }
248                         break;
249
250                 case HOSTIF_SET_FEATURE_REPORT:
251                         /* Get index of device that matches this id */
252                         for (i = 0; i < client_data->num_hid_devices; ++i) {
253                                 if (recv_msg->hdr.device_id ==
254                                         client_data->hid_devices[i].dev_id)
255                                         if (client_data->hid_sensor_hubs[i]) {
256                                                 ishtp_hid_wakeup(
257                                                 client_data->hid_sensor_hubs[
258                                                         i]);
259                                                 break;
260                                         }
261                         }
262                         break;
263
264                 case HOSTIF_PUBLISH_INPUT_REPORT:
265                         report_type = HID_INPUT_REPORT;
266                         for (i = 0; i < client_data->num_hid_devices; ++i)
267                                 if (recv_msg->hdr.device_id ==
268                                         client_data->hid_devices[i].dev_id)
269                                         if (client_data->hid_sensor_hubs[i])
270                                                 hid_input_report(
271                                                 client_data->hid_sensor_hubs[
272                                                                         i],
273                                                 report_type, payload,
274                                                 payload_len, 0);
275                         break;
276
277                 case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
278                         report_type = HID_INPUT_REPORT;
279                         reports_list = (struct report_list *)payload;
280                         reports = (char *)reports_list->reports;
281
282                         for (j = 0; j < reports_list->num_of_reports; j++) {
283                                 recv_msg = (struct hostif_msg *)(reports +
284                                         sizeof(uint16_t));
285                                 report_len = *(uint16_t *)reports;
286                                 payload = reports + sizeof(uint16_t) +
287                                         sizeof(struct hostif_msg_hdr);
288                                 payload_len = report_len -
289                                         sizeof(struct hostif_msg_hdr);
290
291                                 for (i = 0; i < client_data->num_hid_devices;
292                                      ++i)
293                                         if (recv_msg->hdr.device_id ==
294                                         client_data->hid_devices[i].dev_id &&
295                                         client_data->hid_sensor_hubs[i]) {
296                                                 hid_input_report(
297                                                 client_data->hid_sensor_hubs[
298                                                                         i],
299                                                 report_type,
300                                                 payload, payload_len,
301                                                 0);
302                                         }
303
304                                 reports += sizeof(uint16_t) + report_len;
305                         }
306                         break;
307                 default:
308                         ++client_data->bad_recv_cnt;
309                         report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
310                                           payload_len);
311                         ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
312                         break;
313
314                 }
315
316                 if (!cur_pos && cur_pos + payload_len +
317                                 sizeof(struct hostif_msg) < total_len)
318                         ++client_data->multi_packet_cnt;
319
320                 cur_pos += payload_len + sizeof(struct hostif_msg);
321                 payload += payload_len + sizeof(struct hostif_msg);
322
323         } while (cur_pos < total_len);
324 }
325
326 /**
327  * ish_cl_event_cb() - bus driver callback for incoming message/packet
328  * @device:     Pointer to the the ishtp client device for which this message
329  *              is targeted
330  *
331  * Remove the packet from the list and process the message by calling
332  * process_recv
333  */
334 static void ish_cl_event_cb(struct ishtp_cl_device *device)
335 {
336         struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(device);
337         struct ishtp_cl_rb *rb_in_proc;
338         size_t r_length;
339
340         if (!hid_ishtp_cl)
341                 return;
342
343         while ((rb_in_proc = ishtp_cl_rx_get_rb(hid_ishtp_cl)) != NULL) {
344                 if (!rb_in_proc->buffer.data)
345                         return;
346
347                 r_length = rb_in_proc->buf_idx;
348
349                 /* decide what to do with received data */
350                 process_recv(hid_ishtp_cl, rb_in_proc->buffer.data, r_length);
351
352                 ishtp_cl_io_rb_recycle(rb_in_proc);
353         }
354 }
355
356 /**
357  * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
358  * @hid:        hid device instance for this request
359  * @buf:        feature buffer
360  * @len:        Length of feature buffer
361  * @report_id:  Report id for the feature set request
362  *
363  * This is called from hid core .request() callback. This function doesn't wait
364  * for response.
365  */
366 void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len,
367                            int report_id)
368 {
369         struct ishtp_hid_data *hid_data =  hid->driver_data;
370         struct ishtp_cl_data *client_data = hid_data->client_data;
371         struct hostif_msg *msg = (struct hostif_msg *)buf;
372         int     rv;
373         int     i;
374
375         hid_ishtp_trace(client_data,  "%s hid %p\n", __func__, hid);
376
377         rv = ishtp_hid_link_ready_wait(client_data);
378         if (rv) {
379                 hid_ishtp_trace(client_data,  "%s hid %p link not ready\n",
380                                 __func__, hid);
381                 return;
382         }
383
384         memset(msg, 0, sizeof(struct hostif_msg));
385         msg->hdr.command = HOSTIF_SET_FEATURE_REPORT;
386         for (i = 0; i < client_data->num_hid_devices; ++i) {
387                 if (hid == client_data->hid_sensor_hubs[i]) {
388                         msg->hdr.device_id =
389                                 client_data->hid_devices[i].dev_id;
390                         break;
391                 }
392         }
393
394         if (i == client_data->num_hid_devices)
395                 return;
396
397         rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len);
398         if (rv)
399                 hid_ishtp_trace(client_data,  "%s hid %p send failed\n",
400                                 __func__, hid);
401 }
402
403 /**
404  * hid_ishtp_get_report() - request to get feature/input report
405  * @hid:        hid device instance for this request
406  * @report_id:  Report id for the get request
407  * @report_type:        Report type for the this request
408  *
409  * This is called from hid core .request() callback. This function will send
410  * request to FW and return without waiting for response.
411  */
412 void hid_ishtp_get_report(struct hid_device *hid, int report_id,
413                           int report_type)
414 {
415         struct ishtp_hid_data *hid_data =  hid->driver_data;
416         struct ishtp_cl_data *client_data = hid_data->client_data;
417         struct hostif_msg_to_sensor msg = {};
418         int     rv;
419         int     i;
420
421         hid_ishtp_trace(client_data,  "%s hid %p\n", __func__, hid);
422         rv = ishtp_hid_link_ready_wait(client_data);
423         if (rv) {
424                 hid_ishtp_trace(client_data,  "%s hid %p link not ready\n",
425                                 __func__, hid);
426                 return;
427         }
428
429         msg.hdr.command = (report_type == HID_FEATURE_REPORT) ?
430                 HOSTIF_GET_FEATURE_REPORT : HOSTIF_GET_INPUT_REPORT;
431         for (i = 0; i < client_data->num_hid_devices; ++i) {
432                 if (hid == client_data->hid_sensor_hubs[i]) {
433                         msg.hdr.device_id =
434                                 client_data->hid_devices[i].dev_id;
435                         break;
436                 }
437         }
438
439         if (i == client_data->num_hid_devices)
440                 return;
441
442         msg.report_id = report_id;
443         rv = ishtp_cl_send(client_data->hid_ishtp_cl, (uint8_t *)&msg,
444                             sizeof(msg));
445         if (rv)
446                 hid_ishtp_trace(client_data,  "%s hid %p send failed\n",
447                                 __func__, hid);
448 }
449
450 /**
451  * ishtp_hid_link_ready_wait() - Wait for link ready
452  * @client_data:        client data instance
453  *
454  * If the transport link started suspend process, then wait, till either
455  * resumed or timeout
456  *
457  * Return: 0 on success, non zero on error
458  */
459 int ishtp_hid_link_ready_wait(struct ishtp_cl_data *client_data)
460 {
461         int rc;
462
463         if (client_data->suspended) {
464                 hid_ishtp_trace(client_data,  "wait for link ready\n");
465                 rc = wait_event_interruptible_timeout(
466                                         client_data->ishtp_resume_wait,
467                                         !client_data->suspended,
468                                         5 * HZ);
469
470                 if (rc == 0) {
471                         hid_ishtp_trace(client_data,  "link not ready\n");
472                         return -EIO;
473                 }
474                 hid_ishtp_trace(client_data,  "link ready\n");
475         }
476
477         return 0;
478 }
479
480 /**
481  * ishtp_enum_enum_devices() - Enumerate hid devices
482  * @hid_ishtp_cl:       client instance
483  *
484  * Helper function to send request to firmware to enumerate HID devices
485  *
486  * Return: 0 on success, non zero on error
487  */
488 static int ishtp_enum_enum_devices(struct ishtp_cl *hid_ishtp_cl)
489 {
490         struct hostif_msg msg;
491         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
492         int retry_count;
493         int rv;
494
495         /* Send HOSTIF_DM_ENUM_DEVICES */
496         memset(&msg, 0, sizeof(struct hostif_msg));
497         msg.hdr.command = HOSTIF_DM_ENUM_DEVICES;
498         rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *)&msg,
499                            sizeof(struct hostif_msg));
500         if (rv)
501                 return rv;
502
503         retry_count = 0;
504         while (!client_data->enum_devices_done &&
505                retry_count < 10) {
506                 wait_event_interruptible_timeout(client_data->init_wait,
507                                          client_data->enum_devices_done,
508                                          3 * HZ);
509                 ++retry_count;
510                 if (!client_data->enum_devices_done)
511                         /* Send HOSTIF_DM_ENUM_DEVICES */
512                         rv = ishtp_cl_send(hid_ishtp_cl,
513                                            (unsigned char *) &msg,
514                                            sizeof(struct hostif_msg));
515         }
516         if (!client_data->enum_devices_done) {
517                 dev_err(cl_data_to_dev(client_data),
518                         "[hid-ish]: timed out waiting for enum_devices\n");
519                 return -ETIMEDOUT;
520         }
521         if (!client_data->hid_devices) {
522                 dev_err(cl_data_to_dev(client_data),
523                         "[hid-ish]: failed to allocate HID dev structures\n");
524                 return -ENOMEM;
525         }
526
527         client_data->num_hid_devices = client_data->hid_dev_count;
528         dev_info(ishtp_device(client_data->cl_device),
529                 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
530                 client_data->num_hid_devices);
531
532         return  0;
533 }
534
535 /**
536  * ishtp_get_hid_descriptor() - Get hid descriptor
537  * @hid_ishtp_cl:       client instance
538  * @index:              Index into the hid_descr array
539  *
540  * Helper function to send request to firmware get HID descriptor of a device
541  *
542  * Return: 0 on success, non zero on error
543  */
544 static int ishtp_get_hid_descriptor(struct ishtp_cl *hid_ishtp_cl, int index)
545 {
546         struct hostif_msg msg;
547         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
548         int rv;
549
550         /* Get HID descriptor */
551         client_data->hid_descr_done = false;
552         memset(&msg, 0, sizeof(struct hostif_msg));
553         msg.hdr.command = HOSTIF_GET_HID_DESCRIPTOR;
554         msg.hdr.device_id = client_data->hid_devices[index].dev_id;
555         rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
556                            sizeof(struct hostif_msg));
557         if (rv)
558                 return rv;
559
560         if (!client_data->hid_descr_done) {
561                 wait_event_interruptible_timeout(client_data->init_wait,
562                                                  client_data->hid_descr_done,
563                                                  3 * HZ);
564                 if (!client_data->hid_descr_done) {
565                         dev_err(cl_data_to_dev(client_data),
566                                 "[hid-ish]: timed out for hid_descr_done\n");
567                         return -EIO;
568                 }
569
570                 if (!client_data->hid_descr[index]) {
571                         dev_err(cl_data_to_dev(client_data),
572                                 "[hid-ish]: allocation HID desc fail\n");
573                         return -ENOMEM;
574                 }
575         }
576
577         return 0;
578 }
579
580 /**
581  * ishtp_get_report_descriptor() - Get report descriptor
582  * @hid_ishtp_cl:       client instance
583  * @index:              Index into the hid_descr array
584  *
585  * Helper function to send request to firmware get HID report descriptor of
586  * a device
587  *
588  * Return: 0 on success, non zero on error
589  */
590 static int ishtp_get_report_descriptor(struct ishtp_cl *hid_ishtp_cl,
591                                        int index)
592 {
593         struct hostif_msg msg;
594         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
595         int rv;
596
597         /* Get report descriptor */
598         client_data->report_descr_done = false;
599         memset(&msg, 0, sizeof(struct hostif_msg));
600         msg.hdr.command = HOSTIF_GET_REPORT_DESCRIPTOR;
601         msg.hdr.device_id = client_data->hid_devices[index].dev_id;
602         rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
603                            sizeof(struct hostif_msg));
604         if (rv)
605                 return rv;
606
607         if (!client_data->report_descr_done)
608                 wait_event_interruptible_timeout(client_data->init_wait,
609                                          client_data->report_descr_done,
610                                          3 * HZ);
611         if (!client_data->report_descr_done) {
612                 dev_err(cl_data_to_dev(client_data),
613                                 "[hid-ish]: timed out for report descr\n");
614                 return -EIO;
615         }
616         if (!client_data->report_descr[index]) {
617                 dev_err(cl_data_to_dev(client_data),
618                         "[hid-ish]: failed to alloc report descr\n");
619                 return -ENOMEM;
620         }
621
622         return 0;
623 }
624
625 /**
626  * hid_ishtp_cl_init() - Init function for ISHTP client
627  * @hid_ishtp_cl:       ISHTP client instance
628  * @reset:              true if called for init after reset
629  *
630  * This function complete the initializtion of the client. The summary of
631  * processing:
632  * - Send request to enumerate the hid clients
633  *      Get the HID descriptor for each enumearated device
634  *      Get report description of each device
635  *      Register each device wik hid core by calling ishtp_hid_probe
636  *
637  * Return: 0 on success, non zero on error
638  */
639 static int hid_ishtp_cl_init(struct ishtp_cl *hid_ishtp_cl, int reset)
640 {
641         struct ishtp_device *dev;
642         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
643         struct ishtp_fw_client *fw_client;
644         int i;
645         int rv;
646
647         dev_dbg(cl_data_to_dev(client_data), "%s\n", __func__);
648         hid_ishtp_trace(client_data,  "%s reset flag: %d\n", __func__, reset);
649
650         rv = ishtp_cl_link(hid_ishtp_cl);
651         if (rv) {
652                 dev_err(cl_data_to_dev(client_data),
653                         "ishtp_cl_link failed\n");
654                 return  -ENOMEM;
655         }
656
657         client_data->init_done = 0;
658
659         dev = ishtp_get_ishtp_device(hid_ishtp_cl);
660
661         /* Connect to FW client */
662         ishtp_set_tx_ring_size(hid_ishtp_cl, HID_CL_TX_RING_SIZE);
663         ishtp_set_rx_ring_size(hid_ishtp_cl, HID_CL_RX_RING_SIZE);
664
665         fw_client = ishtp_fw_cl_get_client(dev, &hid_ishtp_guid);
666         if (!fw_client) {
667                 dev_err(cl_data_to_dev(client_data),
668                         "ish client uuid not found\n");
669                 return -ENOENT;
670         }
671         ishtp_cl_set_fw_client_id(hid_ishtp_cl,
672                                   ishtp_get_fw_client_id(fw_client));
673         ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_CONNECTING);
674
675         rv = ishtp_cl_connect(hid_ishtp_cl);
676         if (rv) {
677                 dev_err(cl_data_to_dev(client_data),
678                         "client connect fail\n");
679                 goto err_cl_unlink;
680         }
681
682         hid_ishtp_trace(client_data,  "%s client connected\n", __func__);
683
684         /* Register read callback */
685         ishtp_register_event_cb(client_data->cl_device, ish_cl_event_cb);
686
687         rv = ishtp_enum_enum_devices(hid_ishtp_cl);
688         if (rv)
689                 goto err_cl_disconnect;
690
691         hid_ishtp_trace(client_data,  "%s enumerated device count %d\n",
692                         __func__, client_data->num_hid_devices);
693
694         for (i = 0; i < client_data->num_hid_devices; ++i) {
695                 client_data->cur_hid_dev = i;
696
697                 rv = ishtp_get_hid_descriptor(hid_ishtp_cl, i);
698                 if (rv)
699                         goto err_cl_disconnect;
700
701                 rv = ishtp_get_report_descriptor(hid_ishtp_cl, i);
702                 if (rv)
703                         goto err_cl_disconnect;
704
705                 if (!reset) {
706                         rv = ishtp_hid_probe(i, client_data);
707                         if (rv) {
708                                 dev_err(cl_data_to_dev(client_data),
709                                 "[hid-ish]: HID probe for #%u failed: %d\n",
710                                 i, rv);
711                                 goto err_cl_disconnect;
712                         }
713                 }
714         } /* for() on all hid devices */
715
716         client_data->init_done = 1;
717         client_data->suspended = false;
718         wake_up_interruptible(&client_data->ishtp_resume_wait);
719         hid_ishtp_trace(client_data,  "%s successful init\n", __func__);
720         return 0;
721
722 err_cl_disconnect:
723         ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_DISCONNECTING);
724         ishtp_cl_disconnect(hid_ishtp_cl);
725 err_cl_unlink:
726         ishtp_cl_unlink(hid_ishtp_cl);
727         return rv;
728 }
729
730 /**
731  * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
732  * @hid_ishtp_cl:       ISHTP client instance
733  *
734  * Unlink and free hid client
735  */
736 static void hid_ishtp_cl_deinit(struct ishtp_cl *hid_ishtp_cl)
737 {
738         ishtp_cl_unlink(hid_ishtp_cl);
739         ishtp_cl_flush_queues(hid_ishtp_cl);
740
741         /* disband and free all Tx and Rx client-level rings */
742         ishtp_cl_free(hid_ishtp_cl);
743 }
744
745 static void hid_ishtp_cl_reset_handler(struct work_struct *work)
746 {
747         struct ishtp_cl_data *client_data;
748         struct ishtp_cl *hid_ishtp_cl;
749         struct ishtp_cl_device *cl_device;
750         int retry;
751         int rv;
752
753         client_data = container_of(work, struct ishtp_cl_data, work);
754
755         hid_ishtp_cl = client_data->hid_ishtp_cl;
756         cl_device = client_data->cl_device;
757
758         hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
759                         hid_ishtp_cl);
760         dev_dbg(ishtp_device(client_data->cl_device), "%s\n", __func__);
761
762         hid_ishtp_cl_deinit(hid_ishtp_cl);
763
764         hid_ishtp_cl = ishtp_cl_allocate(cl_device);
765         if (!hid_ishtp_cl)
766                 return;
767
768         ishtp_set_drvdata(cl_device, hid_ishtp_cl);
769         ishtp_set_client_data(hid_ishtp_cl, client_data);
770         client_data->hid_ishtp_cl = hid_ishtp_cl;
771
772         client_data->num_hid_devices = 0;
773
774         for (retry = 0; retry < 3; ++retry) {
775                 rv = hid_ishtp_cl_init(hid_ishtp_cl, 1);
776                 if (!rv)
777                         break;
778                 dev_err(cl_data_to_dev(client_data), "Retry reset init\n");
779         }
780         if (rv) {
781                 dev_err(cl_data_to_dev(client_data), "Reset Failed\n");
782                 hid_ishtp_trace(client_data, "%s Failed hid_ishtp_cl %p\n",
783                                 __func__, hid_ishtp_cl);
784         }
785 }
786
787 ishtp_print_log ishtp_hid_print_trace;
788
789 /**
790  * hid_ishtp_cl_probe() - ISHTP client driver probe
791  * @cl_device:          ISHTP client device instance
792  *
793  * This function gets called on device create on ISHTP bus
794  *
795  * Return: 0 on success, non zero on error
796  */
797 static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
798 {
799         struct ishtp_cl *hid_ishtp_cl;
800         struct ishtp_cl_data *client_data;
801         int rv;
802
803         if (!cl_device)
804                 return  -ENODEV;
805
806         client_data = devm_kzalloc(ishtp_device(cl_device),
807                                    sizeof(*client_data),
808                                    GFP_KERNEL);
809         if (!client_data)
810                 return -ENOMEM;
811
812         hid_ishtp_cl = ishtp_cl_allocate(cl_device);
813         if (!hid_ishtp_cl)
814                 return -ENOMEM;
815
816         ishtp_set_drvdata(cl_device, hid_ishtp_cl);
817         ishtp_set_client_data(hid_ishtp_cl, client_data);
818         client_data->hid_ishtp_cl = hid_ishtp_cl;
819         client_data->cl_device = cl_device;
820
821         init_waitqueue_head(&client_data->init_wait);
822         init_waitqueue_head(&client_data->ishtp_resume_wait);
823
824         INIT_WORK(&client_data->work, hid_ishtp_cl_reset_handler);
825
826         ishtp_hid_print_trace = ishtp_trace_callback(cl_device);
827
828         rv = hid_ishtp_cl_init(hid_ishtp_cl, 0);
829         if (rv) {
830                 ishtp_cl_free(hid_ishtp_cl);
831                 return rv;
832         }
833         ishtp_get_device(cl_device);
834
835         return 0;
836 }
837
838 /**
839  * hid_ishtp_cl_remove() - ISHTP client driver remove
840  * @cl_device:          ISHTP client device instance
841  *
842  * This function gets called on device remove on ISHTP bus
843  *
844  * Return: 0
845  */
846 static void hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
847 {
848         struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
849         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
850
851         hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
852                         hid_ishtp_cl);
853
854         dev_dbg(ishtp_device(cl_device), "%s\n", __func__);
855         ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_DISCONNECTING);
856         ishtp_cl_disconnect(hid_ishtp_cl);
857         ishtp_put_device(cl_device);
858         ishtp_hid_remove(client_data);
859         hid_ishtp_cl_deinit(hid_ishtp_cl);
860
861         hid_ishtp_cl = NULL;
862
863         client_data->num_hid_devices = 0;
864 }
865
866 /**
867  * hid_ishtp_cl_reset() - ISHTP client driver reset
868  * @cl_device:          ISHTP client device instance
869  *
870  * This function gets called on device reset on ISHTP bus
871  *
872  * Return: 0
873  */
874 static int hid_ishtp_cl_reset(struct ishtp_cl_device *cl_device)
875 {
876         struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
877         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
878
879         hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
880                         hid_ishtp_cl);
881
882         schedule_work(&client_data->work);
883
884         return 0;
885 }
886
887 /**
888  * hid_ishtp_cl_suspend() - ISHTP client driver suspend
889  * @device:     device instance
890  *
891  * This function gets called on system suspend
892  *
893  * Return: 0
894  */
895 static int hid_ishtp_cl_suspend(struct device *device)
896 {
897         struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
898         struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
899         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
900
901         hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
902                         hid_ishtp_cl);
903         client_data->suspended = true;
904
905         return 0;
906 }
907
908 /**
909  * hid_ishtp_cl_resume() - ISHTP client driver resume
910  * @device:     device instance
911  *
912  * This function gets called on system resume
913  *
914  * Return: 0
915  */
916 static int hid_ishtp_cl_resume(struct device *device)
917 {
918         struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
919         struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
920         struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
921
922         hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
923                         hid_ishtp_cl);
924         client_data->suspended = false;
925         return 0;
926 }
927
928 static const struct dev_pm_ops hid_ishtp_pm_ops = {
929         .suspend = hid_ishtp_cl_suspend,
930         .resume = hid_ishtp_cl_resume,
931 };
932
933 static struct ishtp_cl_driver   hid_ishtp_cl_driver = {
934         .name = "ish-hid",
935         .guid = &hid_ishtp_guid,
936         .probe = hid_ishtp_cl_probe,
937         .remove = hid_ishtp_cl_remove,
938         .reset = hid_ishtp_cl_reset,
939         .driver.pm = &hid_ishtp_pm_ops,
940 };
941
942 static int __init ish_hid_init(void)
943 {
944         int     rv;
945
946         /* Register ISHTP client device driver with ISHTP Bus */
947         rv = ishtp_cl_driver_register(&hid_ishtp_cl_driver, THIS_MODULE);
948
949         return rv;
950
951 }
952
953 static void __exit ish_hid_exit(void)
954 {
955         ishtp_cl_driver_unregister(&hid_ishtp_cl_driver);
956 }
957
958 late_initcall(ish_hid_init);
959 module_exit(ish_hid_exit);
960
961 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
962 /* Primary author */
963 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
964 /*
965  * Several modification for multi instance support
966  * suspend/resume and clean up
967  */
968 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
969
970 MODULE_LICENSE("GPL");
971 MODULE_ALIAS("ishtp:*");