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