ishtp-hid-client.c 27 KB

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