0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/hid.h>
0010 #include <linux/intel-ish-client-if.h>
0011 #include <linux/sched.h>
0012 #include "ishtp-hid.h"
0013
0014
0015 static const struct ishtp_device_id hid_ishtp_id_table[] = {
0016 { .guid = GUID_INIT(0x33AECD58, 0xB679, 0x4E54,
0017 0x9B, 0xD9, 0xA0, 0x4D, 0x34, 0xF0, 0xC2, 0x26), },
0018 { }
0019 };
0020 MODULE_DEVICE_TABLE(ishtp, hid_ishtp_id_table);
0021
0022
0023 #define HID_CL_RX_RING_SIZE 32
0024 #define HID_CL_TX_RING_SIZE 16
0025
0026 #define cl_data_to_dev(client_data) ishtp_device(client_data->cl_device)
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 static void report_bad_packet(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
0038 size_t cur_pos, size_t payload_len)
0039 {
0040 struct hostif_msg *recv_msg = recv_buf;
0041 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0042
0043 dev_err(cl_data_to_dev(client_data), "[hid-ish]: BAD packet %02X\n"
0044 "total_bad=%u cur_pos=%u\n"
0045 "[%02X %02X %02X %02X]\n"
0046 "payload_len=%u\n"
0047 "multi_packet_cnt=%u\n"
0048 "is_response=%02X\n",
0049 recv_msg->hdr.command, client_data->bad_recv_cnt,
0050 (unsigned int)cur_pos,
0051 ((unsigned char *)recv_msg)[0], ((unsigned char *)recv_msg)[1],
0052 ((unsigned char *)recv_msg)[2], ((unsigned char *)recv_msg)[3],
0053 (unsigned int)payload_len, client_data->multi_packet_cnt,
0054 recv_msg->hdr.command & ~CMD_MASK);
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
0067 size_t data_len)
0068 {
0069 struct hostif_msg *recv_msg;
0070 unsigned char *payload;
0071 struct device_info *dev_info;
0072 int i, j;
0073 size_t payload_len, total_len, cur_pos, raw_len;
0074 int report_type;
0075 struct report_list *reports_list;
0076 char *reports;
0077 size_t report_len;
0078 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0079 int curr_hid_dev = client_data->cur_hid_dev;
0080 struct ishtp_hid_data *hid_data = NULL;
0081 struct hid_device *hid = NULL;
0082
0083 payload = recv_buf + sizeof(struct hostif_msg_hdr);
0084 total_len = data_len;
0085 cur_pos = 0;
0086
0087 do {
0088 if (cur_pos + sizeof(struct hostif_msg) > total_len) {
0089 dev_err(cl_data_to_dev(client_data),
0090 "[hid-ish]: error, received %u which is less than data header %u\n",
0091 (unsigned int)data_len,
0092 (unsigned int)sizeof(struct hostif_msg_hdr));
0093 ++client_data->bad_recv_cnt;
0094 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
0095 break;
0096 }
0097
0098 recv_msg = (struct hostif_msg *)(recv_buf + cur_pos);
0099 payload_len = recv_msg->hdr.size;
0100
0101
0102 if (cur_pos + payload_len + sizeof(struct hostif_msg) >
0103 total_len) {
0104 ++client_data->bad_recv_cnt;
0105 report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
0106 payload_len);
0107 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
0108 break;
0109 }
0110
0111 hid_ishtp_trace(client_data, "%s %d\n",
0112 __func__, recv_msg->hdr.command & CMD_MASK);
0113
0114 switch (recv_msg->hdr.command & CMD_MASK) {
0115 case HOSTIF_DM_ENUM_DEVICES:
0116 if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
0117 client_data->init_done)) {
0118 ++client_data->bad_recv_cnt;
0119 report_bad_packet(hid_ishtp_cl, recv_msg,
0120 cur_pos,
0121 payload_len);
0122 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
0123 break;
0124 }
0125 client_data->hid_dev_count = (unsigned int)*payload;
0126 if (!client_data->hid_devices)
0127 client_data->hid_devices = devm_kcalloc(
0128 cl_data_to_dev(client_data),
0129 client_data->hid_dev_count,
0130 sizeof(struct device_info),
0131 GFP_KERNEL);
0132 if (!client_data->hid_devices) {
0133 dev_err(cl_data_to_dev(client_data),
0134 "Mem alloc failed for hid device info\n");
0135 wake_up_interruptible(&client_data->init_wait);
0136 break;
0137 }
0138 for (i = 0; i < client_data->hid_dev_count; ++i) {
0139 if (1 + sizeof(struct device_info) * i >=
0140 payload_len) {
0141 dev_err(cl_data_to_dev(client_data),
0142 "[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
0143 1 + sizeof(struct device_info)
0144 * i, payload_len);
0145 }
0146
0147 if (1 + sizeof(struct device_info) * i >=
0148 data_len)
0149 break;
0150
0151 dev_info = (struct device_info *)(payload + 1 +
0152 sizeof(struct device_info) * i);
0153 if (client_data->hid_devices)
0154 memcpy(client_data->hid_devices + i,
0155 dev_info,
0156 sizeof(struct device_info));
0157 }
0158
0159 client_data->enum_devices_done = true;
0160 wake_up_interruptible(&client_data->init_wait);
0161
0162 break;
0163
0164 case HOSTIF_GET_HID_DESCRIPTOR:
0165 if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
0166 client_data->init_done)) {
0167 ++client_data->bad_recv_cnt;
0168 report_bad_packet(hid_ishtp_cl, recv_msg,
0169 cur_pos,
0170 payload_len);
0171 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
0172 break;
0173 }
0174 if (!client_data->hid_descr[curr_hid_dev])
0175 client_data->hid_descr[curr_hid_dev] =
0176 devm_kmalloc(cl_data_to_dev(client_data),
0177 payload_len, GFP_KERNEL);
0178 if (client_data->hid_descr[curr_hid_dev]) {
0179 memcpy(client_data->hid_descr[curr_hid_dev],
0180 payload, payload_len);
0181 client_data->hid_descr_size[curr_hid_dev] =
0182 payload_len;
0183 client_data->hid_descr_done = true;
0184 }
0185 wake_up_interruptible(&client_data->init_wait);
0186
0187 break;
0188
0189 case HOSTIF_GET_REPORT_DESCRIPTOR:
0190 if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
0191 client_data->init_done)) {
0192 ++client_data->bad_recv_cnt;
0193 report_bad_packet(hid_ishtp_cl, recv_msg,
0194 cur_pos,
0195 payload_len);
0196 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
0197 break;
0198 }
0199 if (!client_data->report_descr[curr_hid_dev])
0200 client_data->report_descr[curr_hid_dev] =
0201 devm_kmalloc(cl_data_to_dev(client_data),
0202 payload_len, GFP_KERNEL);
0203 if (client_data->report_descr[curr_hid_dev]) {
0204 memcpy(client_data->report_descr[curr_hid_dev],
0205 payload,
0206 payload_len);
0207 client_data->report_descr_size[curr_hid_dev] =
0208 payload_len;
0209 client_data->report_descr_done = true;
0210 }
0211 wake_up_interruptible(&client_data->init_wait);
0212
0213 break;
0214
0215 case HOSTIF_GET_FEATURE_REPORT:
0216 report_type = HID_FEATURE_REPORT;
0217 goto do_get_report;
0218
0219 case HOSTIF_GET_INPUT_REPORT:
0220 report_type = HID_INPUT_REPORT;
0221 do_get_report:
0222
0223 for (i = 0; i < client_data->num_hid_devices; ++i) {
0224 if (recv_msg->hdr.device_id ==
0225 client_data->hid_devices[i].dev_id) {
0226 hid = client_data->hid_sensor_hubs[i];
0227 if (!hid)
0228 break;
0229
0230 hid_data = hid->driver_data;
0231 if (hid_data->raw_get_req) {
0232 raw_len =
0233 (hid_data->raw_buf_size <
0234 payload_len) ?
0235 hid_data->raw_buf_size :
0236 payload_len;
0237
0238 memcpy(hid_data->raw_buf,
0239 payload, raw_len);
0240 } else {
0241 hid_input_report
0242 (hid, report_type,
0243 payload, payload_len,
0244 0);
0245 }
0246
0247 ishtp_hid_wakeup(hid);
0248 break;
0249 }
0250 }
0251 break;
0252
0253 case HOSTIF_SET_FEATURE_REPORT:
0254
0255 for (i = 0; i < client_data->num_hid_devices; ++i) {
0256 if (recv_msg->hdr.device_id ==
0257 client_data->hid_devices[i].dev_id)
0258 if (client_data->hid_sensor_hubs[i]) {
0259 ishtp_hid_wakeup(
0260 client_data->hid_sensor_hubs[
0261 i]);
0262 break;
0263 }
0264 }
0265 break;
0266
0267 case HOSTIF_PUBLISH_INPUT_REPORT:
0268 report_type = HID_INPUT_REPORT;
0269 for (i = 0; i < client_data->num_hid_devices; ++i)
0270 if (recv_msg->hdr.device_id ==
0271 client_data->hid_devices[i].dev_id)
0272 if (client_data->hid_sensor_hubs[i])
0273 hid_input_report(
0274 client_data->hid_sensor_hubs[
0275 i],
0276 report_type, payload,
0277 payload_len, 0);
0278 break;
0279
0280 case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
0281 report_type = HID_INPUT_REPORT;
0282 reports_list = (struct report_list *)payload;
0283 reports = (char *)reports_list->reports;
0284
0285 for (j = 0; j < reports_list->num_of_reports; j++) {
0286 recv_msg = (struct hostif_msg *)(reports +
0287 sizeof(uint16_t));
0288 report_len = *(uint16_t *)reports;
0289 payload = reports + sizeof(uint16_t) +
0290 sizeof(struct hostif_msg_hdr);
0291 payload_len = report_len -
0292 sizeof(struct hostif_msg_hdr);
0293
0294 for (i = 0; i < client_data->num_hid_devices;
0295 ++i)
0296 if (recv_msg->hdr.device_id ==
0297 client_data->hid_devices[i].dev_id &&
0298 client_data->hid_sensor_hubs[i]) {
0299 hid_input_report(
0300 client_data->hid_sensor_hubs[
0301 i],
0302 report_type,
0303 payload, payload_len,
0304 0);
0305 }
0306
0307 reports += sizeof(uint16_t) + report_len;
0308 }
0309 break;
0310 default:
0311 ++client_data->bad_recv_cnt;
0312 report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
0313 payload_len);
0314 ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
0315 break;
0316
0317 }
0318
0319 if (!cur_pos && cur_pos + payload_len +
0320 sizeof(struct hostif_msg) < total_len)
0321 ++client_data->multi_packet_cnt;
0322
0323 cur_pos += payload_len + sizeof(struct hostif_msg);
0324 payload += payload_len + sizeof(struct hostif_msg);
0325
0326 } while (cur_pos < total_len);
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337 static void ish_cl_event_cb(struct ishtp_cl_device *device)
0338 {
0339 struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(device);
0340 struct ishtp_cl_rb *rb_in_proc;
0341 size_t r_length;
0342
0343 if (!hid_ishtp_cl)
0344 return;
0345
0346 while ((rb_in_proc = ishtp_cl_rx_get_rb(hid_ishtp_cl)) != NULL) {
0347 if (!rb_in_proc->buffer.data)
0348 return;
0349
0350 r_length = rb_in_proc->buf_idx;
0351
0352
0353 process_recv(hid_ishtp_cl, rb_in_proc->buffer.data, r_length);
0354
0355 ishtp_cl_io_rb_recycle(rb_in_proc);
0356 }
0357 }
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len,
0370 int report_id)
0371 {
0372 struct ishtp_hid_data *hid_data = hid->driver_data;
0373 struct ishtp_cl_data *client_data = hid_data->client_data;
0374 struct hostif_msg *msg = (struct hostif_msg *)buf;
0375 int rv;
0376 int i;
0377
0378 hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid);
0379
0380 rv = ishtp_hid_link_ready_wait(client_data);
0381 if (rv) {
0382 hid_ishtp_trace(client_data, "%s hid %p link not ready\n",
0383 __func__, hid);
0384 return;
0385 }
0386
0387 memset(msg, 0, sizeof(struct hostif_msg));
0388 msg->hdr.command = HOSTIF_SET_FEATURE_REPORT;
0389 for (i = 0; i < client_data->num_hid_devices; ++i) {
0390 if (hid == client_data->hid_sensor_hubs[i]) {
0391 msg->hdr.device_id =
0392 client_data->hid_devices[i].dev_id;
0393 break;
0394 }
0395 }
0396
0397 if (i == client_data->num_hid_devices)
0398 return;
0399
0400 rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len);
0401 if (rv)
0402 hid_ishtp_trace(client_data, "%s hid %p send failed\n",
0403 __func__, hid);
0404 }
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415 void hid_ishtp_get_report(struct hid_device *hid, int report_id,
0416 int report_type)
0417 {
0418 struct ishtp_hid_data *hid_data = hid->driver_data;
0419 struct ishtp_cl_data *client_data = hid_data->client_data;
0420 struct hostif_msg_to_sensor msg = {};
0421 int rv;
0422 int i;
0423
0424 hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid);
0425 rv = ishtp_hid_link_ready_wait(client_data);
0426 if (rv) {
0427 hid_ishtp_trace(client_data, "%s hid %p link not ready\n",
0428 __func__, hid);
0429 return;
0430 }
0431
0432 msg.hdr.command = (report_type == HID_FEATURE_REPORT) ?
0433 HOSTIF_GET_FEATURE_REPORT : HOSTIF_GET_INPUT_REPORT;
0434 for (i = 0; i < client_data->num_hid_devices; ++i) {
0435 if (hid == client_data->hid_sensor_hubs[i]) {
0436 msg.hdr.device_id =
0437 client_data->hid_devices[i].dev_id;
0438 break;
0439 }
0440 }
0441
0442 if (i == client_data->num_hid_devices)
0443 return;
0444
0445 msg.report_id = report_id;
0446 rv = ishtp_cl_send(client_data->hid_ishtp_cl, (uint8_t *)&msg,
0447 sizeof(msg));
0448 if (rv)
0449 hid_ishtp_trace(client_data, "%s hid %p send failed\n",
0450 __func__, hid);
0451 }
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462 int ishtp_hid_link_ready_wait(struct ishtp_cl_data *client_data)
0463 {
0464 int rc;
0465
0466 if (client_data->suspended) {
0467 hid_ishtp_trace(client_data, "wait for link ready\n");
0468 rc = wait_event_interruptible_timeout(
0469 client_data->ishtp_resume_wait,
0470 !client_data->suspended,
0471 5 * HZ);
0472
0473 if (rc == 0) {
0474 hid_ishtp_trace(client_data, "link not ready\n");
0475 return -EIO;
0476 }
0477 hid_ishtp_trace(client_data, "link ready\n");
0478 }
0479
0480 return 0;
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491 static int ishtp_enum_enum_devices(struct ishtp_cl *hid_ishtp_cl)
0492 {
0493 struct hostif_msg msg;
0494 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0495 int retry_count;
0496 int rv;
0497
0498
0499 memset(&msg, 0, sizeof(struct hostif_msg));
0500 msg.hdr.command = HOSTIF_DM_ENUM_DEVICES;
0501 rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *)&msg,
0502 sizeof(struct hostif_msg));
0503 if (rv)
0504 return rv;
0505
0506 retry_count = 0;
0507 while (!client_data->enum_devices_done &&
0508 retry_count < 10) {
0509 wait_event_interruptible_timeout(client_data->init_wait,
0510 client_data->enum_devices_done,
0511 3 * HZ);
0512 ++retry_count;
0513 if (!client_data->enum_devices_done)
0514
0515 rv = ishtp_cl_send(hid_ishtp_cl,
0516 (unsigned char *) &msg,
0517 sizeof(struct hostif_msg));
0518 }
0519 if (!client_data->enum_devices_done) {
0520 dev_err(cl_data_to_dev(client_data),
0521 "[hid-ish]: timed out waiting for enum_devices\n");
0522 return -ETIMEDOUT;
0523 }
0524 if (!client_data->hid_devices) {
0525 dev_err(cl_data_to_dev(client_data),
0526 "[hid-ish]: failed to allocate HID dev structures\n");
0527 return -ENOMEM;
0528 }
0529
0530 client_data->num_hid_devices = client_data->hid_dev_count;
0531 dev_info(ishtp_device(client_data->cl_device),
0532 "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
0533 client_data->num_hid_devices);
0534
0535 return 0;
0536 }
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547 static int ishtp_get_hid_descriptor(struct ishtp_cl *hid_ishtp_cl, int index)
0548 {
0549 struct hostif_msg msg;
0550 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0551 int rv;
0552
0553
0554 client_data->hid_descr_done = false;
0555 memset(&msg, 0, sizeof(struct hostif_msg));
0556 msg.hdr.command = HOSTIF_GET_HID_DESCRIPTOR;
0557 msg.hdr.device_id = client_data->hid_devices[index].dev_id;
0558 rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
0559 sizeof(struct hostif_msg));
0560 if (rv)
0561 return rv;
0562
0563 if (!client_data->hid_descr_done) {
0564 wait_event_interruptible_timeout(client_data->init_wait,
0565 client_data->hid_descr_done,
0566 3 * HZ);
0567 if (!client_data->hid_descr_done) {
0568 dev_err(cl_data_to_dev(client_data),
0569 "[hid-ish]: timed out for hid_descr_done\n");
0570 return -EIO;
0571 }
0572
0573 if (!client_data->hid_descr[index]) {
0574 dev_err(cl_data_to_dev(client_data),
0575 "[hid-ish]: allocation HID desc fail\n");
0576 return -ENOMEM;
0577 }
0578 }
0579
0580 return 0;
0581 }
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593 static int ishtp_get_report_descriptor(struct ishtp_cl *hid_ishtp_cl,
0594 int index)
0595 {
0596 struct hostif_msg msg;
0597 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0598 int rv;
0599
0600
0601 client_data->report_descr_done = false;
0602 memset(&msg, 0, sizeof(struct hostif_msg));
0603 msg.hdr.command = HOSTIF_GET_REPORT_DESCRIPTOR;
0604 msg.hdr.device_id = client_data->hid_devices[index].dev_id;
0605 rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
0606 sizeof(struct hostif_msg));
0607 if (rv)
0608 return rv;
0609
0610 if (!client_data->report_descr_done)
0611 wait_event_interruptible_timeout(client_data->init_wait,
0612 client_data->report_descr_done,
0613 3 * HZ);
0614 if (!client_data->report_descr_done) {
0615 dev_err(cl_data_to_dev(client_data),
0616 "[hid-ish]: timed out for report descr\n");
0617 return -EIO;
0618 }
0619 if (!client_data->report_descr[index]) {
0620 dev_err(cl_data_to_dev(client_data),
0621 "[hid-ish]: failed to alloc report descr\n");
0622 return -ENOMEM;
0623 }
0624
0625 return 0;
0626 }
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642 static int hid_ishtp_cl_init(struct ishtp_cl *hid_ishtp_cl, int reset)
0643 {
0644 struct ishtp_device *dev;
0645 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0646 struct ishtp_fw_client *fw_client;
0647 int i;
0648 int rv;
0649
0650 dev_dbg(cl_data_to_dev(client_data), "%s\n", __func__);
0651 hid_ishtp_trace(client_data, "%s reset flag: %d\n", __func__, reset);
0652
0653 rv = ishtp_cl_link(hid_ishtp_cl);
0654 if (rv) {
0655 dev_err(cl_data_to_dev(client_data),
0656 "ishtp_cl_link failed\n");
0657 return -ENOMEM;
0658 }
0659
0660 client_data->init_done = 0;
0661
0662 dev = ishtp_get_ishtp_device(hid_ishtp_cl);
0663
0664
0665 ishtp_set_tx_ring_size(hid_ishtp_cl, HID_CL_TX_RING_SIZE);
0666 ishtp_set_rx_ring_size(hid_ishtp_cl, HID_CL_RX_RING_SIZE);
0667
0668 fw_client = ishtp_fw_cl_get_client(dev, &hid_ishtp_id_table[0].guid);
0669 if (!fw_client) {
0670 dev_err(cl_data_to_dev(client_data),
0671 "ish client uuid not found\n");
0672 return -ENOENT;
0673 }
0674 ishtp_cl_set_fw_client_id(hid_ishtp_cl,
0675 ishtp_get_fw_client_id(fw_client));
0676 ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_CONNECTING);
0677
0678 rv = ishtp_cl_connect(hid_ishtp_cl);
0679 if (rv) {
0680 dev_err(cl_data_to_dev(client_data),
0681 "client connect fail\n");
0682 goto err_cl_unlink;
0683 }
0684
0685 hid_ishtp_trace(client_data, "%s client connected\n", __func__);
0686
0687
0688 ishtp_register_event_cb(client_data->cl_device, ish_cl_event_cb);
0689
0690 rv = ishtp_enum_enum_devices(hid_ishtp_cl);
0691 if (rv)
0692 goto err_cl_disconnect;
0693
0694 hid_ishtp_trace(client_data, "%s enumerated device count %d\n",
0695 __func__, client_data->num_hid_devices);
0696
0697 for (i = 0; i < client_data->num_hid_devices; ++i) {
0698 client_data->cur_hid_dev = i;
0699
0700 rv = ishtp_get_hid_descriptor(hid_ishtp_cl, i);
0701 if (rv)
0702 goto err_cl_disconnect;
0703
0704 rv = ishtp_get_report_descriptor(hid_ishtp_cl, i);
0705 if (rv)
0706 goto err_cl_disconnect;
0707
0708 if (!reset) {
0709 rv = ishtp_hid_probe(i, client_data);
0710 if (rv) {
0711 dev_err(cl_data_to_dev(client_data),
0712 "[hid-ish]: HID probe for #%u failed: %d\n",
0713 i, rv);
0714 goto err_cl_disconnect;
0715 }
0716 }
0717 }
0718
0719 client_data->init_done = 1;
0720 client_data->suspended = false;
0721 wake_up_interruptible(&client_data->ishtp_resume_wait);
0722 hid_ishtp_trace(client_data, "%s successful init\n", __func__);
0723 return 0;
0724
0725 err_cl_disconnect:
0726 ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_DISCONNECTING);
0727 ishtp_cl_disconnect(hid_ishtp_cl);
0728 err_cl_unlink:
0729 ishtp_cl_unlink(hid_ishtp_cl);
0730 return rv;
0731 }
0732
0733
0734
0735
0736
0737
0738
0739 static void hid_ishtp_cl_deinit(struct ishtp_cl *hid_ishtp_cl)
0740 {
0741 ishtp_cl_unlink(hid_ishtp_cl);
0742 ishtp_cl_flush_queues(hid_ishtp_cl);
0743
0744
0745 ishtp_cl_free(hid_ishtp_cl);
0746 }
0747
0748 static void hid_ishtp_cl_reset_handler(struct work_struct *work)
0749 {
0750 struct ishtp_cl_data *client_data;
0751 struct ishtp_cl *hid_ishtp_cl;
0752 struct ishtp_cl_device *cl_device;
0753 int retry;
0754 int rv;
0755
0756 client_data = container_of(work, struct ishtp_cl_data, work);
0757
0758 hid_ishtp_cl = client_data->hid_ishtp_cl;
0759 cl_device = client_data->cl_device;
0760
0761 hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
0762 hid_ishtp_cl);
0763 dev_dbg(ishtp_device(client_data->cl_device), "%s\n", __func__);
0764
0765 hid_ishtp_cl_deinit(hid_ishtp_cl);
0766
0767 hid_ishtp_cl = ishtp_cl_allocate(cl_device);
0768 if (!hid_ishtp_cl)
0769 return;
0770
0771 ishtp_set_drvdata(cl_device, hid_ishtp_cl);
0772 ishtp_set_client_data(hid_ishtp_cl, client_data);
0773 client_data->hid_ishtp_cl = hid_ishtp_cl;
0774
0775 client_data->num_hid_devices = 0;
0776
0777 for (retry = 0; retry < 3; ++retry) {
0778 rv = hid_ishtp_cl_init(hid_ishtp_cl, 1);
0779 if (!rv)
0780 break;
0781 dev_err(cl_data_to_dev(client_data), "Retry reset init\n");
0782 }
0783 if (rv) {
0784 dev_err(cl_data_to_dev(client_data), "Reset Failed\n");
0785 hid_ishtp_trace(client_data, "%s Failed hid_ishtp_cl %p\n",
0786 __func__, hid_ishtp_cl);
0787 }
0788 }
0789
0790 static void hid_ishtp_cl_resume_handler(struct work_struct *work)
0791 {
0792 struct ishtp_cl_data *client_data = container_of(work, struct ishtp_cl_data, resume_work);
0793 struct ishtp_cl *hid_ishtp_cl = client_data->hid_ishtp_cl;
0794
0795 if (ishtp_wait_resume(ishtp_get_ishtp_device(hid_ishtp_cl))) {
0796 client_data->suspended = false;
0797 wake_up_interruptible(&client_data->ishtp_resume_wait);
0798 }
0799 }
0800
0801 ishtp_print_log ishtp_hid_print_trace;
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811 static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
0812 {
0813 struct ishtp_cl *hid_ishtp_cl;
0814 struct ishtp_cl_data *client_data;
0815 int rv;
0816
0817 if (!cl_device)
0818 return -ENODEV;
0819
0820 client_data = devm_kzalloc(ishtp_device(cl_device),
0821 sizeof(*client_data),
0822 GFP_KERNEL);
0823 if (!client_data)
0824 return -ENOMEM;
0825
0826 hid_ishtp_cl = ishtp_cl_allocate(cl_device);
0827 if (!hid_ishtp_cl)
0828 return -ENOMEM;
0829
0830 ishtp_set_drvdata(cl_device, hid_ishtp_cl);
0831 ishtp_set_client_data(hid_ishtp_cl, client_data);
0832 client_data->hid_ishtp_cl = hid_ishtp_cl;
0833 client_data->cl_device = cl_device;
0834
0835 init_waitqueue_head(&client_data->init_wait);
0836 init_waitqueue_head(&client_data->ishtp_resume_wait);
0837
0838 INIT_WORK(&client_data->work, hid_ishtp_cl_reset_handler);
0839 INIT_WORK(&client_data->resume_work, hid_ishtp_cl_resume_handler);
0840
0841
0842 ishtp_hid_print_trace = ishtp_trace_callback(cl_device);
0843
0844 rv = hid_ishtp_cl_init(hid_ishtp_cl, 0);
0845 if (rv) {
0846 ishtp_cl_free(hid_ishtp_cl);
0847 return rv;
0848 }
0849 ishtp_get_device(cl_device);
0850
0851 return 0;
0852 }
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862 static void hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
0863 {
0864 struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
0865 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0866
0867 hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
0868 hid_ishtp_cl);
0869
0870 dev_dbg(ishtp_device(cl_device), "%s\n", __func__);
0871 ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_DISCONNECTING);
0872 ishtp_cl_disconnect(hid_ishtp_cl);
0873 ishtp_put_device(cl_device);
0874 ishtp_hid_remove(client_data);
0875 hid_ishtp_cl_deinit(hid_ishtp_cl);
0876
0877 hid_ishtp_cl = NULL;
0878
0879 client_data->num_hid_devices = 0;
0880 }
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890 static int hid_ishtp_cl_reset(struct ishtp_cl_device *cl_device)
0891 {
0892 struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
0893 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0894
0895 hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
0896 hid_ishtp_cl);
0897
0898 schedule_work(&client_data->work);
0899
0900 return 0;
0901 }
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911 static int hid_ishtp_cl_suspend(struct device *device)
0912 {
0913 struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
0914 struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
0915 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0916
0917 hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
0918 hid_ishtp_cl);
0919 client_data->suspended = true;
0920
0921 return 0;
0922 }
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932 static int hid_ishtp_cl_resume(struct device *device)
0933 {
0934 struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
0935 struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
0936 struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
0937
0938 hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
0939 hid_ishtp_cl);
0940 schedule_work(&client_data->resume_work);
0941 return 0;
0942 }
0943
0944 static const struct dev_pm_ops hid_ishtp_pm_ops = {
0945 .suspend = hid_ishtp_cl_suspend,
0946 .resume = hid_ishtp_cl_resume,
0947 };
0948
0949 static struct ishtp_cl_driver hid_ishtp_cl_driver = {
0950 .name = "ish-hid",
0951 .id = hid_ishtp_id_table,
0952 .probe = hid_ishtp_cl_probe,
0953 .remove = hid_ishtp_cl_remove,
0954 .reset = hid_ishtp_cl_reset,
0955 .driver.pm = &hid_ishtp_pm_ops,
0956 };
0957
0958 static int __init ish_hid_init(void)
0959 {
0960 int rv;
0961
0962
0963 rv = ishtp_cl_driver_register(&hid_ishtp_cl_driver, THIS_MODULE);
0964
0965 return rv;
0966
0967 }
0968
0969 static void __exit ish_hid_exit(void)
0970 {
0971 ishtp_cl_driver_unregister(&hid_ishtp_cl_driver);
0972 }
0973
0974 late_initcall(ish_hid_init);
0975 module_exit(ish_hid_exit);
0976
0977 MODULE_DESCRIPTION("ISH ISHTP HID client driver");
0978
0979 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
0980
0981
0982
0983
0984 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
0985
0986 MODULE_LICENSE("GPL");