nfc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /*
  2. *
  3. * Intel Management Engine Interface (Intel MEI) Linux driver
  4. * Copyright (c) 2003-2013, 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. */
  16. #include <linux/kernel.h>
  17. #include <linux/sched.h>
  18. #include <linux/module.h>
  19. #include <linux/moduleparam.h>
  20. #include <linux/device.h>
  21. #include <linux/slab.h>
  22. #include <linux/mei_cl_bus.h>
  23. #include "mei_dev.h"
  24. #include "client.h"
  25. struct mei_nfc_cmd {
  26. u8 command;
  27. u8 status;
  28. u16 req_id;
  29. u32 reserved;
  30. u16 data_size;
  31. u8 sub_command;
  32. u8 data[];
  33. } __packed;
  34. struct mei_nfc_reply {
  35. u8 command;
  36. u8 status;
  37. u16 req_id;
  38. u32 reserved;
  39. u16 data_size;
  40. u8 sub_command;
  41. u8 reply_status;
  42. u8 data[];
  43. } __packed;
  44. struct mei_nfc_if_version {
  45. u8 radio_version_sw[3];
  46. u8 reserved[3];
  47. u8 radio_version_hw[3];
  48. u8 i2c_addr;
  49. u8 fw_ivn;
  50. u8 vendor_id;
  51. u8 radio_type;
  52. } __packed;
  53. struct mei_nfc_connect {
  54. u8 fw_ivn;
  55. u8 vendor_id;
  56. } __packed;
  57. struct mei_nfc_connect_resp {
  58. u8 fw_ivn;
  59. u8 vendor_id;
  60. u16 me_major;
  61. u16 me_minor;
  62. u16 me_hotfix;
  63. u16 me_build;
  64. } __packed;
  65. struct mei_nfc_hci_hdr {
  66. u8 cmd;
  67. u8 status;
  68. u16 req_id;
  69. u32 reserved;
  70. u16 data_size;
  71. } __packed;
  72. #define MEI_NFC_CMD_MAINTENANCE 0x00
  73. #define MEI_NFC_CMD_HCI_SEND 0x01
  74. #define MEI_NFC_CMD_HCI_RECV 0x02
  75. #define MEI_NFC_SUBCMD_CONNECT 0x00
  76. #define MEI_NFC_SUBCMD_IF_VERSION 0x01
  77. #define MEI_NFC_HEADER_SIZE 10
  78. /**
  79. * struct mei_nfc_dev - NFC mei device
  80. *
  81. * @cl: NFC host client
  82. * @cl_info: NFC info host client
  83. * @init_work: perform connection to the info client
  84. * @send_wq: send completion wait queue
  85. * @fw_ivn: NFC Interface Version Number
  86. * @vendor_id: NFC manufacturer ID
  87. * @radio_type: NFC radio type
  88. * @bus_name: bus name
  89. *
  90. * @req_id: message counter
  91. * @recv_req_id: reception message counter
  92. */
  93. struct mei_nfc_dev {
  94. struct mei_cl *cl;
  95. struct mei_cl *cl_info;
  96. struct work_struct init_work;
  97. wait_queue_head_t send_wq;
  98. u8 fw_ivn;
  99. u8 vendor_id;
  100. u8 radio_type;
  101. char *bus_name;
  102. u16 req_id;
  103. u16 recv_req_id;
  104. };
  105. /* UUIDs for NFC F/W clients */
  106. const uuid_le mei_nfc_guid = UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50,
  107. 0x94, 0xd4, 0x50, 0x26,
  108. 0x67, 0x23, 0x77, 0x5c);
  109. static const uuid_le mei_nfc_info_guid = UUID_LE(0xd2de1625, 0x382d, 0x417d,
  110. 0x48, 0xa4, 0xef, 0xab,
  111. 0xba, 0x8a, 0x12, 0x06);
  112. /* Vendors */
  113. #define MEI_NFC_VENDOR_INSIDE 0x00
  114. #define MEI_NFC_VENDOR_NXP 0x01
  115. /* Radio types */
  116. #define MEI_NFC_VENDOR_INSIDE_UREAD 0x00
  117. #define MEI_NFC_VENDOR_NXP_PN544 0x01
  118. static void mei_nfc_free(struct mei_nfc_dev *ndev)
  119. {
  120. if (!ndev)
  121. return;
  122. if (ndev->cl) {
  123. list_del(&ndev->cl->device_link);
  124. mei_cl_unlink(ndev->cl);
  125. kfree(ndev->cl);
  126. }
  127. if (ndev->cl_info) {
  128. list_del(&ndev->cl_info->device_link);
  129. mei_cl_unlink(ndev->cl_info);
  130. kfree(ndev->cl_info);
  131. }
  132. kfree(ndev);
  133. }
  134. static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
  135. {
  136. struct mei_device *dev;
  137. if (!ndev->cl)
  138. return -ENODEV;
  139. dev = ndev->cl->dev;
  140. switch (ndev->vendor_id) {
  141. case MEI_NFC_VENDOR_INSIDE:
  142. switch (ndev->radio_type) {
  143. case MEI_NFC_VENDOR_INSIDE_UREAD:
  144. ndev->bus_name = "microread";
  145. return 0;
  146. default:
  147. dev_err(dev->dev, "Unknown radio type 0x%x\n",
  148. ndev->radio_type);
  149. return -EINVAL;
  150. }
  151. case MEI_NFC_VENDOR_NXP:
  152. switch (ndev->radio_type) {
  153. case MEI_NFC_VENDOR_NXP_PN544:
  154. ndev->bus_name = "pn544";
  155. return 0;
  156. default:
  157. dev_err(dev->dev, "Unknown radio type 0x%x\n",
  158. ndev->radio_type);
  159. return -EINVAL;
  160. }
  161. default:
  162. dev_err(dev->dev, "Unknown vendor ID 0x%x\n",
  163. ndev->vendor_id);
  164. return -EINVAL;
  165. }
  166. return 0;
  167. }
  168. static int mei_nfc_connect(struct mei_nfc_dev *ndev)
  169. {
  170. struct mei_device *dev;
  171. struct mei_cl *cl;
  172. struct mei_nfc_cmd *cmd, *reply;
  173. struct mei_nfc_connect *connect;
  174. struct mei_nfc_connect_resp *connect_resp;
  175. size_t connect_length, connect_resp_length;
  176. int bytes_recv, ret;
  177. cl = ndev->cl;
  178. dev = cl->dev;
  179. connect_length = sizeof(struct mei_nfc_cmd) +
  180. sizeof(struct mei_nfc_connect);
  181. connect_resp_length = sizeof(struct mei_nfc_cmd) +
  182. sizeof(struct mei_nfc_connect_resp);
  183. cmd = kzalloc(connect_length, GFP_KERNEL);
  184. if (!cmd)
  185. return -ENOMEM;
  186. connect = (struct mei_nfc_connect *)cmd->data;
  187. reply = kzalloc(connect_resp_length, GFP_KERNEL);
  188. if (!reply) {
  189. kfree(cmd);
  190. return -ENOMEM;
  191. }
  192. connect_resp = (struct mei_nfc_connect_resp *)reply->data;
  193. cmd->command = MEI_NFC_CMD_MAINTENANCE;
  194. cmd->data_size = 3;
  195. cmd->sub_command = MEI_NFC_SUBCMD_CONNECT;
  196. connect->fw_ivn = ndev->fw_ivn;
  197. connect->vendor_id = ndev->vendor_id;
  198. ret = __mei_cl_send(cl, (u8 *)cmd, connect_length);
  199. if (ret < 0) {
  200. dev_err(dev->dev, "Could not send connect cmd\n");
  201. goto err;
  202. }
  203. bytes_recv = __mei_cl_recv(cl, (u8 *)reply, connect_resp_length);
  204. if (bytes_recv < 0) {
  205. dev_err(dev->dev, "Could not read connect response\n");
  206. ret = bytes_recv;
  207. goto err;
  208. }
  209. dev_info(dev->dev, "IVN 0x%x Vendor ID 0x%x\n",
  210. connect_resp->fw_ivn, connect_resp->vendor_id);
  211. dev_info(dev->dev, "ME FW %d.%d.%d.%d\n",
  212. connect_resp->me_major, connect_resp->me_minor,
  213. connect_resp->me_hotfix, connect_resp->me_build);
  214. ret = 0;
  215. err:
  216. kfree(reply);
  217. kfree(cmd);
  218. return ret;
  219. }
  220. static int mei_nfc_if_version(struct mei_nfc_dev *ndev)
  221. {
  222. struct mei_device *dev;
  223. struct mei_cl *cl;
  224. struct mei_nfc_cmd cmd;
  225. struct mei_nfc_reply *reply = NULL;
  226. struct mei_nfc_if_version *version;
  227. size_t if_version_length;
  228. int bytes_recv, ret;
  229. cl = ndev->cl_info;
  230. dev = cl->dev;
  231. memset(&cmd, 0, sizeof(struct mei_nfc_cmd));
  232. cmd.command = MEI_NFC_CMD_MAINTENANCE;
  233. cmd.data_size = 1;
  234. cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
  235. ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd));
  236. if (ret < 0) {
  237. dev_err(dev->dev, "Could not send IF version cmd\n");
  238. return ret;
  239. }
  240. /* to be sure on the stack we alloc memory */
  241. if_version_length = sizeof(struct mei_nfc_reply) +
  242. sizeof(struct mei_nfc_if_version);
  243. reply = kzalloc(if_version_length, GFP_KERNEL);
  244. if (!reply)
  245. return -ENOMEM;
  246. bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
  247. if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
  248. dev_err(dev->dev, "Could not read IF version\n");
  249. ret = -EIO;
  250. goto err;
  251. }
  252. version = (struct mei_nfc_if_version *)reply->data;
  253. ndev->fw_ivn = version->fw_ivn;
  254. ndev->vendor_id = version->vendor_id;
  255. ndev->radio_type = version->radio_type;
  256. err:
  257. kfree(reply);
  258. return ret;
  259. }
  260. static int mei_nfc_enable(struct mei_cl_device *cldev)
  261. {
  262. struct mei_device *dev;
  263. struct mei_nfc_dev *ndev;
  264. int ret;
  265. ndev = (struct mei_nfc_dev *)cldev->priv_data;
  266. dev = ndev->cl->dev;
  267. ret = mei_nfc_connect(ndev);
  268. if (ret < 0) {
  269. dev_err(dev->dev, "Could not connect to NFC");
  270. return ret;
  271. }
  272. return 0;
  273. }
  274. static int mei_nfc_disable(struct mei_cl_device *cldev)
  275. {
  276. return 0;
  277. }
  278. static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
  279. {
  280. struct mei_device *dev;
  281. struct mei_nfc_dev *ndev;
  282. struct mei_nfc_hci_hdr *hdr;
  283. u8 *mei_buf;
  284. int err;
  285. ndev = (struct mei_nfc_dev *) cldev->priv_data;
  286. dev = ndev->cl->dev;
  287. err = -ENOMEM;
  288. mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL);
  289. if (!mei_buf)
  290. goto out;
  291. hdr = (struct mei_nfc_hci_hdr *) mei_buf;
  292. hdr->cmd = MEI_NFC_CMD_HCI_SEND;
  293. hdr->status = 0;
  294. hdr->req_id = ndev->req_id;
  295. hdr->reserved = 0;
  296. hdr->data_size = length;
  297. memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
  298. err = __mei_cl_send(ndev->cl, mei_buf, length + MEI_NFC_HEADER_SIZE);
  299. if (err < 0)
  300. goto out;
  301. if (!wait_event_interruptible_timeout(ndev->send_wq,
  302. ndev->recv_req_id == ndev->req_id, HZ)) {
  303. dev_err(dev->dev, "NFC MEI command timeout\n");
  304. err = -ETIME;
  305. } else {
  306. ndev->req_id++;
  307. }
  308. out:
  309. kfree(mei_buf);
  310. return err;
  311. }
  312. static int mei_nfc_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
  313. {
  314. struct mei_nfc_dev *ndev;
  315. struct mei_nfc_hci_hdr *hci_hdr;
  316. int received_length;
  317. ndev = (struct mei_nfc_dev *)cldev->priv_data;
  318. received_length = __mei_cl_recv(ndev->cl, buf, length);
  319. if (received_length < 0)
  320. return received_length;
  321. hci_hdr = (struct mei_nfc_hci_hdr *) buf;
  322. if (hci_hdr->cmd == MEI_NFC_CMD_HCI_SEND) {
  323. ndev->recv_req_id = hci_hdr->req_id;
  324. wake_up(&ndev->send_wq);
  325. return 0;
  326. }
  327. return received_length;
  328. }
  329. static struct mei_cl_ops nfc_ops = {
  330. .enable = mei_nfc_enable,
  331. .disable = mei_nfc_disable,
  332. .send = mei_nfc_send,
  333. .recv = mei_nfc_recv,
  334. };
  335. static void mei_nfc_init(struct work_struct *work)
  336. {
  337. struct mei_device *dev;
  338. struct mei_cl_device *cldev;
  339. struct mei_nfc_dev *ndev;
  340. struct mei_cl *cl_info;
  341. ndev = container_of(work, struct mei_nfc_dev, init_work);
  342. cl_info = ndev->cl_info;
  343. dev = cl_info->dev;
  344. mutex_lock(&dev->device_lock);
  345. if (mei_cl_connect(cl_info, NULL) < 0) {
  346. mutex_unlock(&dev->device_lock);
  347. dev_err(dev->dev, "Could not connect to the NFC INFO ME client");
  348. goto err;
  349. }
  350. mutex_unlock(&dev->device_lock);
  351. if (mei_nfc_if_version(ndev) < 0) {
  352. dev_err(dev->dev, "Could not get the NFC interface version");
  353. goto err;
  354. }
  355. dev_info(dev->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
  356. ndev->fw_ivn, ndev->vendor_id, ndev->radio_type);
  357. mutex_lock(&dev->device_lock);
  358. if (mei_cl_disconnect(cl_info) < 0) {
  359. mutex_unlock(&dev->device_lock);
  360. dev_err(dev->dev, "Could not disconnect the NFC INFO ME client");
  361. goto err;
  362. }
  363. mutex_unlock(&dev->device_lock);
  364. if (mei_nfc_build_bus_name(ndev) < 0) {
  365. dev_err(dev->dev, "Could not build the bus ID name\n");
  366. return;
  367. }
  368. cldev = mei_cl_add_device(dev, mei_nfc_guid, ndev->bus_name, &nfc_ops);
  369. if (!cldev) {
  370. dev_err(dev->dev, "Could not add the NFC device to the MEI bus\n");
  371. goto err;
  372. }
  373. cldev->priv_data = ndev;
  374. return;
  375. err:
  376. mutex_lock(&dev->device_lock);
  377. mei_nfc_free(ndev);
  378. mutex_unlock(&dev->device_lock);
  379. }
  380. int mei_nfc_host_init(struct mei_device *dev)
  381. {
  382. struct mei_nfc_dev *ndev;
  383. struct mei_cl *cl_info, *cl;
  384. struct mei_me_client *me_cl = NULL;
  385. int ret;
  386. /* in case of internal reset bail out
  387. * as the device is already setup
  388. */
  389. cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
  390. if (cl)
  391. return 0;
  392. ndev = kzalloc(sizeof(struct mei_nfc_dev), GFP_KERNEL);
  393. if (!ndev) {
  394. ret = -ENOMEM;
  395. goto err;
  396. }
  397. /* check for valid client id */
  398. me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
  399. if (!me_cl) {
  400. dev_info(dev->dev, "nfc: failed to find the client\n");
  401. ret = -ENOTTY;
  402. goto err;
  403. }
  404. cl_info = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
  405. if (IS_ERR(cl_info)) {
  406. ret = PTR_ERR(cl_info);
  407. goto err;
  408. }
  409. cl_info->me_client_id = me_cl->client_id;
  410. cl_info->cl_uuid = me_cl->props.protocol_name;
  411. mei_me_cl_put(me_cl);
  412. me_cl = NULL;
  413. list_add_tail(&cl_info->device_link, &dev->device_list);
  414. ndev->cl_info = cl_info;
  415. /* check for valid client id */
  416. me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
  417. if (!me_cl) {
  418. dev_info(dev->dev, "nfc: failed to find the client\n");
  419. ret = -ENOTTY;
  420. goto err;
  421. }
  422. cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
  423. if (IS_ERR(cl)) {
  424. ret = PTR_ERR(cl);
  425. goto err;
  426. }
  427. cl->me_client_id = me_cl->client_id;
  428. cl->cl_uuid = me_cl->props.protocol_name;
  429. mei_me_cl_put(me_cl);
  430. me_cl = NULL;
  431. list_add_tail(&cl->device_link, &dev->device_list);
  432. ndev->cl = cl;
  433. ndev->req_id = 1;
  434. INIT_WORK(&ndev->init_work, mei_nfc_init);
  435. init_waitqueue_head(&ndev->send_wq);
  436. schedule_work(&ndev->init_work);
  437. return 0;
  438. err:
  439. mei_me_cl_put(me_cl);
  440. mei_nfc_free(ndev);
  441. return ret;
  442. }
  443. void mei_nfc_host_exit(struct mei_device *dev)
  444. {
  445. struct mei_nfc_dev *ndev;
  446. struct mei_cl *cl;
  447. struct mei_cl_device *cldev;
  448. cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
  449. if (!cl)
  450. return;
  451. cldev = cl->device;
  452. if (!cldev)
  453. return;
  454. ndev = (struct mei_nfc_dev *)cldev->priv_data;
  455. if (ndev)
  456. cancel_work_sync(&ndev->init_work);
  457. cldev->priv_data = NULL;
  458. mutex_lock(&dev->device_lock);
  459. /* Need to remove the device here
  460. * since mei_nfc_free will unlink the clients
  461. */
  462. mei_cl_remove_device(cldev);
  463. mei_nfc_free(ndev);
  464. mutex_unlock(&dev->device_lock);
  465. }