ishtp-hid.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * ISHTP-HID glue driver.
  3. *
  4. * Copyright (c) 2012-2016, Intel Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. */
  15. #include <linux/hid.h>
  16. #include <uapi/linux/input.h>
  17. #include "ishtp/client.h"
  18. #include "ishtp-hid.h"
  19. /**
  20. * ishtp_hid_parse() - hid-core .parse() callback
  21. * @hid: hid device instance
  22. *
  23. * This function gets called during call to hid_add_device
  24. *
  25. * Return: 0 on success and non zero on error
  26. */
  27. static int ishtp_hid_parse(struct hid_device *hid)
  28. {
  29. struct ishtp_hid_data *hid_data = hid->driver_data;
  30. struct ishtp_cl_data *client_data = hid_data->client_data;
  31. int rv;
  32. rv = hid_parse_report(hid, client_data->report_descr[hid_data->index],
  33. client_data->report_descr_size[hid_data->index]);
  34. if (rv)
  35. return rv;
  36. return 0;
  37. }
  38. /* Empty callbacks with success return code */
  39. static int ishtp_hid_start(struct hid_device *hid)
  40. {
  41. return 0;
  42. }
  43. static void ishtp_hid_stop(struct hid_device *hid)
  44. {
  45. }
  46. static int ishtp_hid_open(struct hid_device *hid)
  47. {
  48. return 0;
  49. }
  50. static void ishtp_hid_close(struct hid_device *hid)
  51. {
  52. }
  53. static int ishtp_raw_request(struct hid_device *hdev, unsigned char reportnum,
  54. __u8 *buf, size_t len, unsigned char rtype, int reqtype)
  55. {
  56. return 0;
  57. }
  58. /**
  59. * ishtp_hid_request() - hid-core .request() callback
  60. * @hid: hid device instance
  61. * @rep: pointer to hid_report
  62. * @reqtype: type of req. [GET|SET]_REPORT
  63. *
  64. * This function is used to set/get feaure/input report.
  65. */
  66. static void ishtp_hid_request(struct hid_device *hid, struct hid_report *rep,
  67. int reqtype)
  68. {
  69. struct ishtp_hid_data *hid_data = hid->driver_data;
  70. /* the specific report length, just HID part of it */
  71. unsigned int len = ((rep->size - 1) >> 3) + 1 + (rep->id > 0);
  72. char *buf;
  73. unsigned int header_size = sizeof(struct hostif_msg);
  74. len += header_size;
  75. hid_data->request_done = false;
  76. switch (reqtype) {
  77. case HID_REQ_GET_REPORT:
  78. hid_ishtp_get_report(hid, rep->id, rep->type);
  79. break;
  80. case HID_REQ_SET_REPORT:
  81. /*
  82. * Spare 7 bytes for 64b accesses through
  83. * get/put_unaligned_le64()
  84. */
  85. buf = kzalloc(len + 7, GFP_KERNEL);
  86. if (!buf)
  87. return;
  88. hid_output_report(rep, buf + header_size);
  89. hid_ishtp_set_feature(hid, buf, len, rep->id);
  90. kfree(buf);
  91. break;
  92. }
  93. }
  94. /**
  95. * ishtp_wait_for_response() - hid-core .wait() callback
  96. * @hid: hid device instance
  97. *
  98. * This function is used to wait after get feaure/input report.
  99. *
  100. * Return: 0 on success and non zero on error
  101. */
  102. static int ishtp_wait_for_response(struct hid_device *hid)
  103. {
  104. struct ishtp_hid_data *hid_data = hid->driver_data;
  105. struct ishtp_cl_data *client_data = hid_data->client_data;
  106. int rv;
  107. hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid);
  108. rv = ishtp_hid_link_ready_wait(hid_data->client_data);
  109. if (rv)
  110. return rv;
  111. if (!hid_data->request_done)
  112. wait_event_interruptible_timeout(hid_data->hid_wait,
  113. hid_data->request_done, 3 * HZ);
  114. if (!hid_data->request_done) {
  115. hid_err(hid,
  116. "timeout waiting for response from ISHTP device\n");
  117. return -ETIMEDOUT;
  118. }
  119. hid_ishtp_trace(client_data, "%s hid %p done\n", __func__, hid);
  120. hid_data->request_done = false;
  121. return 0;
  122. }
  123. /**
  124. * ishtp_hid_wakeup() - Wakeup caller
  125. * @hid: hid device instance
  126. *
  127. * This function will wakeup caller waiting for Get/Set feature report
  128. */
  129. void ishtp_hid_wakeup(struct hid_device *hid)
  130. {
  131. struct ishtp_hid_data *hid_data = hid->driver_data;
  132. hid_data->request_done = true;
  133. wake_up_interruptible(&hid_data->hid_wait);
  134. }
  135. static struct hid_ll_driver ishtp_hid_ll_driver = {
  136. .parse = ishtp_hid_parse,
  137. .start = ishtp_hid_start,
  138. .stop = ishtp_hid_stop,
  139. .open = ishtp_hid_open,
  140. .close = ishtp_hid_close,
  141. .request = ishtp_hid_request,
  142. .wait = ishtp_wait_for_response,
  143. .raw_request = ishtp_raw_request
  144. };
  145. /**
  146. * ishtp_hid_probe() - hid register ll driver
  147. * @cur_hid_dev: Index of hid device calling to register
  148. * @client_data: Client data pointer
  149. *
  150. * This function is used to allocate and add HID device.
  151. *
  152. * Return: 0 on success, non zero on error
  153. */
  154. int ishtp_hid_probe(unsigned int cur_hid_dev,
  155. struct ishtp_cl_data *client_data)
  156. {
  157. int rv;
  158. struct hid_device *hid;
  159. struct ishtp_hid_data *hid_data;
  160. hid = hid_allocate_device();
  161. if (IS_ERR(hid)) {
  162. rv = PTR_ERR(hid);
  163. return -ENOMEM;
  164. }
  165. hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);
  166. if (!hid_data) {
  167. rv = -ENOMEM;
  168. goto err_hid_data;
  169. }
  170. hid_data->index = cur_hid_dev;
  171. hid_data->client_data = client_data;
  172. init_waitqueue_head(&hid_data->hid_wait);
  173. hid->driver_data = hid_data;
  174. client_data->hid_sensor_hubs[cur_hid_dev] = hid;
  175. hid->ll_driver = &ishtp_hid_ll_driver;
  176. hid->bus = BUS_INTEL_ISHTP;
  177. hid->dev.parent = &client_data->cl_device->dev;
  178. hid->version = le16_to_cpu(ISH_HID_VERSION);
  179. hid->vendor = le16_to_cpu(ISH_HID_VENDOR);
  180. hid->product = le16_to_cpu(ISH_HID_PRODUCT);
  181. snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", "hid-ishtp",
  182. hid->vendor, hid->product);
  183. rv = hid_add_device(hid);
  184. if (rv)
  185. goto err_hid_device;
  186. hid_ishtp_trace(client_data, "%s allocated hid %p\n", __func__, hid);
  187. return 0;
  188. err_hid_device:
  189. kfree(hid_data);
  190. err_hid_data:
  191. kfree(hid);
  192. return rv;
  193. }
  194. /**
  195. * ishtp_hid_probe() - Remove registered hid device
  196. * @client_data: client data pointer
  197. *
  198. * This function is used to destroy allocatd HID device.
  199. */
  200. void ishtp_hid_remove(struct ishtp_cl_data *client_data)
  201. {
  202. int i;
  203. for (i = 0; i < client_data->num_hid_devices; ++i) {
  204. if (client_data->hid_sensor_hubs[i]) {
  205. kfree(client_data->hid_sensor_hubs[i]->driver_data);
  206. hid_destroy_device(client_data->hid_sensor_hubs[i]);
  207. client_data->hid_sensor_hubs[i] = NULL;
  208. }
  209. }
  210. }