• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Texas Instrument's NFC Driver For Shared Transport.
3  *
4  *  NFC Driver acts as interface between NCI core and
5  *  TI Shared Transport Layer.
6  *
7  *  Copyright (C) 2011 Texas Instruments, Inc.
8  *
9  *  Written by Ilan Elias <ilane@ti.com>
10  *
11  *  Acknowledgements:
12  *  This file is based on btwilink.c, which was written
13  *  by Raja Mani and Pavan Savoy.
14  *
15  *  This program is free software; you can redistribute it and/or modify
16  *  it under the terms of the GNU General Public License version 2 as
17  *  published by the Free Software Foundation.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28  */
29 #include <linux/platform_device.h>
30 #include <linux/module.h>
31 #include <linux/types.h>
32 #include <linux/firmware.h>
33 #include <linux/nfc.h>
34 #include <net/nfc/nci.h>
35 #include <net/nfc/nci_core.h>
36 #include <linux/ti_wilink_st.h>
37 
38 #define NFCWILINK_CHNL			12
39 #define NFCWILINK_OPCODE		7
40 #define NFCWILINK_MAX_FRAME_SIZE	300
41 #define NFCWILINK_HDR_LEN		4
42 #define NFCWILINK_OFFSET_LEN_IN_HDR	1
43 #define NFCWILINK_LEN_SIZE		2
44 #define NFCWILINK_REGISTER_TIMEOUT	8000	/* 8 sec */
45 #define NFCWILINK_CMD_TIMEOUT		5000	/* 5 sec */
46 
47 #define BTS_FILE_NAME_MAX_SIZE		40
48 #define BTS_FILE_HDR_MAGIC		0x42535442
49 #define BTS_FILE_CMD_MAX_LEN		0xff
50 #define BTS_FILE_ACTION_TYPE_SEND_CMD	1
51 
52 #define NCI_VS_NFCC_INFO_CMD_GID	0x2f
53 #define NCI_VS_NFCC_INFO_CMD_OID	0x12
54 #define NCI_VS_NFCC_INFO_RSP_GID	0x4f
55 #define NCI_VS_NFCC_INFO_RSP_OID	0x12
56 
57 struct nfcwilink_hdr {
58 	__u8 chnl;
59 	__u8 opcode;
60 	__le16 len;
61 } __packed;
62 
63 struct nci_vs_nfcc_info_cmd {
64 	__u8 gid;
65 	__u8 oid;
66 	__u8 plen;
67 } __packed;
68 
69 struct nci_vs_nfcc_info_rsp {
70 	__u8 gid;
71 	__u8 oid;
72 	__u8 plen;
73 	__u8 status;
74 	__u8 hw_id;
75 	__u8 sw_ver_x;
76 	__u8 sw_ver_z;
77 	__u8 patch_id;
78 } __packed;
79 
80 struct bts_file_hdr {
81 	__le32 magic;
82 	__le32 ver;
83 	__u8 rfu[24];
84 	__u8 actions[0];
85 } __packed;
86 
87 struct bts_file_action {
88 	__le16 type;
89 	__le16 len;
90 	__u8 data[0];
91 } __packed;
92 
93 struct nfcwilink {
94 	struct platform_device		*pdev;
95 	struct nci_dev			*ndev;
96 	unsigned long			flags;
97 
98 	char				st_register_cb_status;
99 	long				(*st_write) (struct sk_buff *);
100 
101 	struct completion		completed;
102 
103 	struct nci_vs_nfcc_info_rsp	nfcc_info;
104 };
105 
106 /* NFCWILINK driver flags */
107 enum {
108 	NFCWILINK_RUNNING,
109 	NFCWILINK_FW_DOWNLOAD,
110 };
111 
112 static int nfcwilink_send(struct sk_buff *skb);
113 
nfcwilink_skb_alloc(unsigned int len,gfp_t how)114 static inline struct sk_buff *nfcwilink_skb_alloc(unsigned int len, gfp_t how)
115 {
116 	struct sk_buff *skb;
117 
118 	skb = alloc_skb(len + NFCWILINK_HDR_LEN, how);
119 	if (skb)
120 		skb_reserve(skb, NFCWILINK_HDR_LEN);
121 
122 	return skb;
123 }
124 
nfcwilink_fw_download_receive(struct nfcwilink * drv,struct sk_buff * skb)125 static void nfcwilink_fw_download_receive(struct nfcwilink *drv,
126 						struct sk_buff *skb)
127 {
128 	struct nci_vs_nfcc_info_rsp *rsp = (void *)skb->data;
129 
130 	/* Detect NCI_VS_NFCC_INFO_RSP and store the result */
131 	if ((skb->len > 3) && (rsp->gid == NCI_VS_NFCC_INFO_RSP_GID) &&
132 		(rsp->oid == NCI_VS_NFCC_INFO_RSP_OID)) {
133 		memcpy(&drv->nfcc_info, rsp,
134 			sizeof(struct nci_vs_nfcc_info_rsp));
135 	}
136 
137 	kfree_skb(skb);
138 
139 	complete(&drv->completed);
140 }
141 
nfcwilink_get_bts_file_name(struct nfcwilink * drv,char * file_name)142 static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name)
143 {
144 	struct nci_vs_nfcc_info_cmd *cmd;
145 	struct sk_buff *skb;
146 	unsigned long comp_ret;
147 	int rc;
148 
149 	nfc_dev_dbg(&drv->pdev->dev, "get_bts_file_name entry");
150 
151 	skb = nfcwilink_skb_alloc(sizeof(struct nci_vs_nfcc_info_cmd),
152 					GFP_KERNEL);
153 	if (!skb) {
154 		nfc_dev_err(&drv->pdev->dev,
155 				"no memory for nci_vs_nfcc_info_cmd");
156 		return -ENOMEM;
157 	}
158 
159 	skb->dev = (void *)drv->ndev;
160 
161 	cmd = (struct nci_vs_nfcc_info_cmd *)
162 			skb_put(skb, sizeof(struct nci_vs_nfcc_info_cmd));
163 	cmd->gid = NCI_VS_NFCC_INFO_CMD_GID;
164 	cmd->oid = NCI_VS_NFCC_INFO_CMD_OID;
165 	cmd->plen = 0;
166 
167 	drv->nfcc_info.plen = 0;
168 
169 	rc = nfcwilink_send(skb);
170 	if (rc)
171 		return rc;
172 
173 	comp_ret = wait_for_completion_timeout(&drv->completed,
174 				msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT));
175 	nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld",
176 			comp_ret);
177 	if (comp_ret == 0) {
178 		nfc_dev_err(&drv->pdev->dev,
179 				"timeout on wait_for_completion_timeout");
180 		return -ETIMEDOUT;
181 	}
182 
183 	nfc_dev_dbg(&drv->pdev->dev, "nci_vs_nfcc_info_rsp: plen %d, status %d",
184 			drv->nfcc_info.plen,
185 			drv->nfcc_info.status);
186 
187 	if ((drv->nfcc_info.plen != 5) || (drv->nfcc_info.status != 0)) {
188 		nfc_dev_err(&drv->pdev->dev,
189 				"invalid nci_vs_nfcc_info_rsp");
190 		return -EINVAL;
191 	}
192 
193 	snprintf(file_name, BTS_FILE_NAME_MAX_SIZE,
194 			"TINfcInit_%d.%d.%d.%d.bts",
195 			drv->nfcc_info.hw_id,
196 			drv->nfcc_info.sw_ver_x,
197 			drv->nfcc_info.sw_ver_z,
198 			drv->nfcc_info.patch_id);
199 
200 	nfc_dev_info(&drv->pdev->dev, "nfcwilink FW file name: %s", file_name);
201 
202 	return 0;
203 }
204 
nfcwilink_send_bts_cmd(struct nfcwilink * drv,__u8 * data,int len)205 static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len)
206 {
207 	struct nfcwilink_hdr *hdr = (struct nfcwilink_hdr *)data;
208 	struct sk_buff *skb;
209 	unsigned long comp_ret;
210 	int rc;
211 
212 	nfc_dev_dbg(&drv->pdev->dev, "send_bts_cmd entry");
213 
214 	/* verify valid cmd for the NFC channel */
215 	if ((len <= sizeof(struct nfcwilink_hdr)) ||
216 		(len > BTS_FILE_CMD_MAX_LEN) ||
217 		(hdr->chnl != NFCWILINK_CHNL) ||
218 		(hdr->opcode != NFCWILINK_OPCODE)) {
219 		nfc_dev_err(&drv->pdev->dev,
220 			"ignoring invalid bts cmd, len %d, chnl %d, opcode %d",
221 			len, hdr->chnl, hdr->opcode);
222 		return 0;
223 	}
224 
225 	/* remove the ST header */
226 	len -= sizeof(struct nfcwilink_hdr);
227 	data += sizeof(struct nfcwilink_hdr);
228 
229 	skb = nfcwilink_skb_alloc(len, GFP_KERNEL);
230 	if (!skb) {
231 		nfc_dev_err(&drv->pdev->dev, "no memory for bts cmd");
232 		return -ENOMEM;
233 	}
234 
235 	skb->dev = (void *)drv->ndev;
236 
237 	memcpy(skb_put(skb, len), data, len);
238 
239 	rc = nfcwilink_send(skb);
240 	if (rc)
241 		return rc;
242 
243 	comp_ret = wait_for_completion_timeout(&drv->completed,
244 				msecs_to_jiffies(NFCWILINK_CMD_TIMEOUT));
245 	nfc_dev_dbg(&drv->pdev->dev, "wait_for_completion_timeout returned %ld",
246 			comp_ret);
247 	if (comp_ret == 0) {
248 		nfc_dev_err(&drv->pdev->dev,
249 				"timeout on wait_for_completion_timeout");
250 		return -ETIMEDOUT;
251 	}
252 
253 	return 0;
254 }
255 
nfcwilink_download_fw(struct nfcwilink * drv)256 static int nfcwilink_download_fw(struct nfcwilink *drv)
257 {
258 	unsigned char file_name[BTS_FILE_NAME_MAX_SIZE];
259 	const struct firmware *fw;
260 	__u16 action_type, action_len;
261 	__u8 *ptr;
262 	int len, rc;
263 
264 	nfc_dev_dbg(&drv->pdev->dev, "download_fw entry");
265 
266 	set_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags);
267 
268 	rc = nfcwilink_get_bts_file_name(drv, file_name);
269 	if (rc)
270 		goto exit;
271 
272 	rc = request_firmware(&fw, file_name, &drv->pdev->dev);
273 	if (rc) {
274 		nfc_dev_err(&drv->pdev->dev, "request_firmware failed %d", rc);
275 
276 		/* if the file is not found, don't exit with failure */
277 		if (rc == -ENOENT)
278 			rc = 0;
279 
280 		goto exit;
281 	}
282 
283 	len = fw->size;
284 	ptr = (__u8 *)fw->data;
285 
286 	if ((len == 0) || (ptr == NULL)) {
287 		nfc_dev_dbg(&drv->pdev->dev,
288 				"request_firmware returned size %d", len);
289 		goto release_fw;
290 	}
291 
292 	if (__le32_to_cpu(((struct bts_file_hdr *)ptr)->magic) !=
293 			BTS_FILE_HDR_MAGIC) {
294 		nfc_dev_err(&drv->pdev->dev, "wrong bts magic number");
295 		rc = -EINVAL;
296 		goto release_fw;
297 	}
298 
299 	/* remove the BTS header */
300 	len -= sizeof(struct bts_file_hdr);
301 	ptr += sizeof(struct bts_file_hdr);
302 
303 	while (len > 0) {
304 		action_type =
305 			__le16_to_cpu(((struct bts_file_action *)ptr)->type);
306 		action_len =
307 			__le16_to_cpu(((struct bts_file_action *)ptr)->len);
308 
309 		nfc_dev_dbg(&drv->pdev->dev, "bts_file_action type %d, len %d",
310 				action_type, action_len);
311 
312 		switch (action_type) {
313 		case BTS_FILE_ACTION_TYPE_SEND_CMD:
314 			rc = nfcwilink_send_bts_cmd(drv,
315 					((struct bts_file_action *)ptr)->data,
316 					action_len);
317 			if (rc)
318 				goto release_fw;
319 			break;
320 		}
321 
322 		/* advance to the next action */
323 		len -= (sizeof(struct bts_file_action) + action_len);
324 		ptr += (sizeof(struct bts_file_action) + action_len);
325 	}
326 
327 release_fw:
328 	release_firmware(fw);
329 
330 exit:
331 	clear_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags);
332 	return rc;
333 }
334 
335 /* Called by ST when registration is complete */
nfcwilink_register_complete(void * priv_data,char data)336 static void nfcwilink_register_complete(void *priv_data, char data)
337 {
338 	struct nfcwilink *drv = priv_data;
339 
340 	nfc_dev_dbg(&drv->pdev->dev, "register_complete entry");
341 
342 	/* store ST registration status */
343 	drv->st_register_cb_status = data;
344 
345 	/* complete the wait in nfc_st_open() */
346 	complete(&drv->completed);
347 }
348 
349 /* Called by ST when receive data is available */
nfcwilink_receive(void * priv_data,struct sk_buff * skb)350 static long nfcwilink_receive(void *priv_data, struct sk_buff *skb)
351 {
352 	struct nfcwilink *drv = priv_data;
353 	int rc;
354 
355 	if (!skb)
356 		return -EFAULT;
357 
358 	if (!drv) {
359 		kfree_skb(skb);
360 		return -EFAULT;
361 	}
362 
363 	nfc_dev_dbg(&drv->pdev->dev, "receive entry, len %d", skb->len);
364 
365 	/* strip the ST header
366 	(apart for the chnl byte, which is not received in the hdr) */
367 	skb_pull(skb, (NFCWILINK_HDR_LEN-1));
368 
369 	if (test_bit(NFCWILINK_FW_DOWNLOAD, &drv->flags)) {
370 		nfcwilink_fw_download_receive(drv, skb);
371 		return 0;
372 	}
373 
374 	skb->dev = (void *) drv->ndev;
375 
376 	/* Forward skb to NCI core layer */
377 	rc = nci_recv_frame(skb);
378 	if (rc < 0) {
379 		nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc);
380 		return rc;
381 	}
382 
383 	return 0;
384 }
385 
386 /* protocol structure registered with ST */
387 static struct st_proto_s nfcwilink_proto = {
388 	.chnl_id = NFCWILINK_CHNL,
389 	.max_frame_size = NFCWILINK_MAX_FRAME_SIZE,
390 	.hdr_len = (NFCWILINK_HDR_LEN-1),	/* not including chnl byte */
391 	.offset_len_in_hdr = NFCWILINK_OFFSET_LEN_IN_HDR,
392 	.len_size = NFCWILINK_LEN_SIZE,
393 	.reserve = 0,
394 	.recv = nfcwilink_receive,
395 	.reg_complete_cb = nfcwilink_register_complete,
396 	.write = NULL,
397 };
398 
nfcwilink_open(struct nci_dev * ndev)399 static int nfcwilink_open(struct nci_dev *ndev)
400 {
401 	struct nfcwilink *drv = nci_get_drvdata(ndev);
402 	unsigned long comp_ret;
403 	int rc;
404 
405 	nfc_dev_dbg(&drv->pdev->dev, "open entry");
406 
407 	if (test_and_set_bit(NFCWILINK_RUNNING, &drv->flags)) {
408 		rc = -EBUSY;
409 		goto exit;
410 	}
411 
412 	nfcwilink_proto.priv_data = drv;
413 
414 	init_completion(&drv->completed);
415 	drv->st_register_cb_status = -EINPROGRESS;
416 
417 	rc = st_register(&nfcwilink_proto);
418 	if (rc < 0) {
419 		if (rc == -EINPROGRESS) {
420 			comp_ret = wait_for_completion_timeout(
421 			&drv->completed,
422 			msecs_to_jiffies(NFCWILINK_REGISTER_TIMEOUT));
423 
424 			nfc_dev_dbg(&drv->pdev->dev,
425 			"wait_for_completion_timeout returned %ld",
426 			comp_ret);
427 
428 			if (comp_ret == 0) {
429 				/* timeout */
430 				rc = -ETIMEDOUT;
431 				goto clear_exit;
432 			} else if (drv->st_register_cb_status != 0) {
433 				rc = drv->st_register_cb_status;
434 				nfc_dev_err(&drv->pdev->dev,
435 				"st_register_cb failed %d", rc);
436 				goto clear_exit;
437 			}
438 		} else {
439 			nfc_dev_err(&drv->pdev->dev,
440 				"st_register failed %d", rc);
441 			goto clear_exit;
442 		}
443 	}
444 
445 	/* st_register MUST fill the write callback */
446 	BUG_ON(nfcwilink_proto.write == NULL);
447 	drv->st_write = nfcwilink_proto.write;
448 
449 	if (nfcwilink_download_fw(drv)) {
450 		nfc_dev_err(&drv->pdev->dev, "nfcwilink_download_fw failed %d",
451 				rc);
452 		/* open should succeed, even if the FW download failed */
453 	}
454 
455 	goto exit;
456 
457 clear_exit:
458 	clear_bit(NFCWILINK_RUNNING, &drv->flags);
459 
460 exit:
461 	return rc;
462 }
463 
nfcwilink_close(struct nci_dev * ndev)464 static int nfcwilink_close(struct nci_dev *ndev)
465 {
466 	struct nfcwilink *drv = nci_get_drvdata(ndev);
467 	int rc;
468 
469 	nfc_dev_dbg(&drv->pdev->dev, "close entry");
470 
471 	if (!test_and_clear_bit(NFCWILINK_RUNNING, &drv->flags))
472 		return 0;
473 
474 	rc = st_unregister(&nfcwilink_proto);
475 	if (rc)
476 		nfc_dev_err(&drv->pdev->dev, "st_unregister failed %d", rc);
477 
478 	drv->st_write = NULL;
479 
480 	return rc;
481 }
482 
nfcwilink_send(struct sk_buff * skb)483 static int nfcwilink_send(struct sk_buff *skb)
484 {
485 	struct nci_dev *ndev = (struct nci_dev *)skb->dev;
486 	struct nfcwilink *drv = nci_get_drvdata(ndev);
487 	struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000};
488 	long len;
489 
490 	nfc_dev_dbg(&drv->pdev->dev, "send entry, len %d", skb->len);
491 
492 	if (!test_bit(NFCWILINK_RUNNING, &drv->flags)) {
493 		kfree_skb(skb);
494 		return -EINVAL;
495 	}
496 
497 	/* add the ST hdr to the start of the buffer */
498 	hdr.len = cpu_to_le16(skb->len);
499 	memcpy(skb_push(skb, NFCWILINK_HDR_LEN), &hdr, NFCWILINK_HDR_LEN);
500 
501 	/* Insert skb to shared transport layer's transmit queue.
502 	 * Freeing skb memory is taken care in shared transport layer,
503 	 * so don't free skb memory here.
504 	 */
505 	len = drv->st_write(skb);
506 	if (len < 0) {
507 		kfree_skb(skb);
508 		nfc_dev_err(&drv->pdev->dev, "st_write failed %ld", len);
509 		return -EFAULT;
510 	}
511 
512 	return 0;
513 }
514 
515 static struct nci_ops nfcwilink_ops = {
516 	.open = nfcwilink_open,
517 	.close = nfcwilink_close,
518 	.send = nfcwilink_send,
519 };
520 
nfcwilink_probe(struct platform_device * pdev)521 static int nfcwilink_probe(struct platform_device *pdev)
522 {
523 	static struct nfcwilink *drv;
524 	int rc;
525 	__u32 protocols;
526 
527 	nfc_dev_dbg(&pdev->dev, "probe entry");
528 
529 	drv = devm_kzalloc(&pdev->dev, sizeof(struct nfcwilink), GFP_KERNEL);
530 	if (!drv) {
531 		rc = -ENOMEM;
532 		goto exit;
533 	}
534 
535 	drv->pdev = pdev;
536 
537 	protocols = NFC_PROTO_JEWEL_MASK
538 		| NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK
539 		| NFC_PROTO_ISO14443_MASK
540 		| NFC_PROTO_ISO14443_B_MASK
541 		| NFC_PROTO_NFC_DEP_MASK;
542 
543 	drv->ndev = nci_allocate_device(&nfcwilink_ops,
544 					protocols,
545 					NFC_SE_NONE,
546 					NFCWILINK_HDR_LEN,
547 					0);
548 	if (!drv->ndev) {
549 		nfc_dev_err(&pdev->dev, "nci_allocate_device failed");
550 		rc = -ENOMEM;
551 		goto exit;
552 	}
553 
554 	nci_set_parent_dev(drv->ndev, &pdev->dev);
555 	nci_set_drvdata(drv->ndev, drv);
556 
557 	rc = nci_register_device(drv->ndev);
558 	if (rc < 0) {
559 		nfc_dev_err(&pdev->dev, "nci_register_device failed %d", rc);
560 		goto free_dev_exit;
561 	}
562 
563 	dev_set_drvdata(&pdev->dev, drv);
564 
565 	goto exit;
566 
567 free_dev_exit:
568 	nci_free_device(drv->ndev);
569 
570 exit:
571 	return rc;
572 }
573 
nfcwilink_remove(struct platform_device * pdev)574 static int nfcwilink_remove(struct platform_device *pdev)
575 {
576 	struct nfcwilink *drv = dev_get_drvdata(&pdev->dev);
577 	struct nci_dev *ndev;
578 
579 	nfc_dev_dbg(&pdev->dev, "remove entry");
580 
581 	if (!drv)
582 		return -EFAULT;
583 
584 	ndev = drv->ndev;
585 
586 	nci_unregister_device(ndev);
587 	nci_free_device(ndev);
588 
589 	dev_set_drvdata(&pdev->dev, NULL);
590 
591 	return 0;
592 }
593 
594 static struct platform_driver nfcwilink_driver = {
595 	.probe = nfcwilink_probe,
596 	.remove = nfcwilink_remove,
597 	.driver = {
598 		.name = "nfcwilink",
599 		.owner = THIS_MODULE,
600 	},
601 };
602 
603 module_platform_driver(nfcwilink_driver);
604 
605 /* ------ Module Info ------ */
606 
607 MODULE_AUTHOR("Ilan Elias <ilane@ti.com>");
608 MODULE_DESCRIPTION("NFC Driver for TI Shared Transport");
609 MODULE_LICENSE("GPL");
610