adapter: Bypass the target layer
[platform/upstream/neard.git] / plugins / nfctype4.c
1 /*
2  *
3  *  neard - Near Field Communication manager
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdint.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <sys/socket.h>
31
32 #include <linux/socket.h>
33 #include <linux/nfc.h>
34
35 #include <near/plugin.h>
36 #include <near/log.h>
37 #include <near/types.h>
38 #include <near/adapter.h>
39 #include <near/target.h>
40 #include <near/tag.h>
41 #include <near/ndef.h>
42 #include <near/tlv.h>
43
44 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
45
46 #define NFC_STATUS              0
47 #define NFC_STATUS_BYTE_LEN     1
48
49 #define STATUS_WORD_1           1
50 #define STATUS_WORD_2           2
51 #define APDU_HEADER_LEN         5
52 #define APDU_OK                 0x9000
53 #define APDU_NOT_FOUND          0x6A82
54
55 #define T4_ALL_ACCESS           0x00
56 #define T4_READ_ONLY            0xFF
57
58 #define APDU_STATUS(a) (g_ntohs(*((uint16_t *)(a))))
59
60 /* Tag Type 4 version ID */
61 static uint8_t iso_appname_v1[] = { 0xd2, 0x76, 0x0, 0x0, 0x85, 0x01, 0x0 };
62 static uint8_t iso_appname_v2[] = { 0xd2, 0x76, 0x0, 0x0, 0x85, 0x01, 0x1 };
63
64 /* Tag T4 File ID */
65 static uint8_t iso_cc_fileid[] = { 0xe1, 0x03 };
66 #define LEN_ISO_CC_FILEID       2
67
68 #define LEN_ISO_CC_READ_SIZE    0x0F
69
70 #define CMD_HEADER_SIZE         5
71 struct type4_cmd {                      /* iso 7816 */
72         uint8_t class;
73         uint8_t instruction;
74         uint8_t param1;
75         uint8_t param2;
76         uint8_t data_length;
77         uint8_t data[];
78 } __attribute__((packed));
79
80 struct type4_NDEF_file_control_tlv {
81         uint8_t tag     ;               /* should be 4 */
82         uint8_t len     ;               /* should be 6 */
83         uint16_t file_id ;
84         uint16_t max_ndef_size ;
85         uint8_t read_access ;
86         uint8_t write_access ;
87 } __attribute__((packed));
88
89 struct type4_cc {                       /* Capability Container */
90         uint16_t CCLEN;
91         uint8_t mapping_version;
92         uint16_t max_R_apdu_data_size;
93         uint16_t max_C_apdu_data_size;
94         struct type4_NDEF_file_control_tlv tlv_fc ;
95         uint8_t tlv_blocks[];
96 } __attribute__((packed));
97
98 struct t4_cookie {
99         uint32_t adapter_idx;
100         uint32_t target_idx;
101         near_tag_io_cb cb;
102         struct near_tag *tag;
103         uint16_t read_data;
104         uint16_t r_apdu_max_size;
105         uint16_t c_apdu_max_size;
106         uint16_t max_ndef_size;
107         uint8_t write_access;
108         struct near_ndef_message *ndef;
109 };
110
111 /* ISO functions: This code prepares APDU */
112 static int ISO_send_cmd(uint8_t class,
113                         uint8_t instruction,
114                         uint8_t param1,
115                         uint8_t param2,
116                         uint8_t *cmd_data,
117                         uint8_t cmd_data_length,
118                         near_recv cb,
119                         void *in_data)
120 {
121         struct type4_cmd *cmd;
122         struct t4_cookie *in_rcv = in_data;
123         int err;
124
125         DBG("CLA:x%02x INS:x%02x P1:%02x P2:%02x",
126                         class, instruction, param1, param2);
127
128         cmd = g_try_malloc0(APDU_HEADER_LEN + cmd_data_length);
129         if (cmd == NULL) {
130                 DBG("Mem alloc failed");
131                 err = -ENOMEM;
132                 goto out_err;
133         }
134
135         cmd->class      =       class;
136         cmd->instruction =      instruction ;
137         cmd->param1     =       param1 ;
138         cmd->param2     =       param2 ;
139         cmd->data_length =      cmd_data_length;
140
141         if (cmd_data)
142                 memcpy(cmd->data, cmd_data, cmd_data_length);
143         else
144                 cmd_data_length = 0 ;
145
146         err =  near_adapter_send(in_rcv->adapter_idx, (uint8_t *)cmd,
147                         APDU_HEADER_LEN + cmd_data_length , cb, in_rcv);
148         if (err < 0)
149                 g_free(in_rcv);
150
151 out_err:
152         /* On exit, clean memory */
153         g_free(cmd);
154
155         return err;
156 }
157
158 /* ISO 7816 command: Select applications or files
159  * p1=0 select by "file id"
160  * P1=4 select by "DF name"
161  *  */
162 static int ISO_Select(uint8_t *filename, uint8_t fnamelen, uint8_t P1,
163                 near_recv cb, void *cookie)
164 {
165         DBG("");
166
167         return ISO_send_cmd(
168                         0x00,           /* CLA */
169                         0xA4,           /* INS: Select file */
170                         P1,             /* P1: select by name */
171                         0x00,           /* P2: First or only occurence */
172                         filename,       /* cmd_data */
173                         fnamelen,       /* uint8_t cmd_data_length*/
174                         cb,
175                         cookie);
176 }
177
178 /* ISO 7816 command: Read binary data from files */
179 static int ISO_ReadBinary(uint16_t offset, uint8_t readsize,
180                         near_recv cb, void *cookie)
181 {
182         DBG("");
183         return ISO_send_cmd(
184                         0x00,           /* CLA */
185                         0xB0,           /* INS: Select file */
186                         (uint8_t)((offset & 0xFF00)>>8),
187                         (uint8_t)(offset & 0xFF),
188                         0,              /* no data send */
189                         readsize,       /* bytes to read */
190                         cb,
191                         cookie);
192 }
193
194 /* ISO 7816 command: Update data */
195 static int ISO_Update(uint16_t offset, uint8_t nlen,
196                         uint8_t *data, near_recv cb, void *cookie)
197 {
198         DBG("");
199         return ISO_send_cmd(
200                         0x00,                   /* CLA */
201                         0xD6,                   /* INS: Select file */
202                         (uint8_t)((offset & 0xFF00) >> 8),
203                         (uint8_t)(offset & 0xFF),
204                         data,                   /* length of NDEF data */
205                         nlen,                   /* NLEN + NDEF data */
206                         cb,
207                         cookie);
208 }
209
210 static int t4_cookie_release(int err, struct t4_cookie *cookie)
211 {
212         if (cookie == NULL)
213                 return err;
214
215         if (err < 0 && cookie->cb)
216                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
217
218         if (cookie->ndef)
219                 g_free(cookie->ndef->data);
220
221         g_free(cookie->ndef);
222         g_free(cookie);
223
224         return err;
225 }
226
227
228 static int data_read_cb(uint8_t *resp, int length, void *data)
229 {
230         struct t4_cookie *cookie = data ;
231         uint8_t *nfc_data;
232         uint16_t data_length, length_read, current_length;
233         uint16_t remain_bytes;
234         int err = 0;
235
236         DBG("%d", length);
237
238         if (length < 0)
239                 return t4_cookie_release(err, cookie);
240
241         if (APDU_STATUS(resp + length - 2) != APDU_OK) {
242                 DBG("Fail read_cb SW:x%04x", APDU_STATUS(resp + length - 2));
243                 err = -EIO;
244                 return t4_cookie_release(err, cookie);
245         }
246
247         nfc_data = near_tag_get_data(cookie->tag, (size_t *)&data_length);
248
249         /* Remove SW1 / SW2  and NFC header */
250         length_read = length - NFC_HEADER_SIZE - 2 ;
251         length = length_read;
252
253         current_length = cookie->read_data;
254
255         if (current_length + (length_read) > data_length)
256                 length_read = data_length - current_length;
257
258         memcpy(nfc_data + current_length, resp + NFC_HEADER_SIZE, length_read);
259         if (current_length + length_read == data_length) {
260                 DBG("Done reading");
261
262                 near_ndef_parse(cookie->tag, nfc_data, data_length);
263                 /* Notify the change */
264                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
265
266                 err = 0;
267                 goto out_err;
268         }
269
270         cookie->read_data += length ;
271         remain_bytes = (data_length - cookie->read_data);
272
273         if (remain_bytes >= cookie->r_apdu_max_size)
274                 err = ISO_ReadBinary(cookie->read_data + 2,
275                                 cookie->r_apdu_max_size, data_read_cb, cookie);
276         else
277                 err = ISO_ReadBinary(cookie->read_data + 2,
278                                 (uint8_t)remain_bytes, data_read_cb, cookie);
279         if (err < 0)
280                 goto out_err;
281
282         return err;
283
284 out_err:
285         return t4_cookie_release(err, cookie);
286 }
287
288
289 static int t4_readbin_NDEF_ID(uint8_t *resp, int length, void *data)
290 {
291         struct t4_cookie *cookie = data ;
292         struct near_tag *tag;
293         int err = 0;
294
295         DBG("%d", length);
296
297         if (length < 0) {
298                 err = length;
299                 goto out_err;
300         }
301
302         if (APDU_STATUS(resp + length - 2) != APDU_OK) {
303                 DBG("Fail SW:x%04x", APDU_STATUS(resp + length - 2));
304                 err = -EIO;
305                 goto out_err;
306         }
307
308         /* Add data to the tag */
309         err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx, NULL,
310                                 g_ntohs(*((uint16_t *)(resp + NFC_STATUS_BYTE_LEN))));
311         if (err < 0)
312                 goto out_err;
313
314         tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
315         if (tag == NULL) {
316                 err = -ENOMEM;
317                 goto out_err;
318         }
319
320         near_tag_set_max_ndef_size(tag, cookie->max_ndef_size);
321         near_tag_set_c_apdu_max_size(tag, cookie->c_apdu_max_size);
322
323         /* save the tag */
324         cookie->tag = tag;
325
326         /* Set write conditions */
327         if (cookie->write_access == T4_READ_ONLY)
328                 near_tag_set_ro(tag, TRUE);
329         else
330                 near_tag_set_ro(tag, FALSE);
331
332         /* TODO: see how we can get the UID value:
333          *  near_tag_set_uid(tag, resp + NFC_HEADER_SIZE, 8);
334          *  */
335
336         /* Read 1st block */
337         err = ISO_ReadBinary(2, cookie->r_apdu_max_size - 2,
338                         data_read_cb, cookie);
339         if (err < 0)
340                 goto out_err;
341
342         return err;
343
344 out_err:
345         return t4_cookie_release(err, cookie);
346 }
347
348 static int t4_select_NDEF_ID(uint8_t *resp, int length, void *data)
349 {
350         struct t4_cookie *cookie = data;
351         int err = 0;
352
353         DBG("%d", length);
354
355         if (length < 0) {
356                 err = length;
357                 goto out_err;
358         }
359
360         /* Check for APDU error */
361         if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
362                 DBG("Fail SW:x%04x", APDU_STATUS(resp + STATUS_WORD_1));
363                 err = -EIO;
364                 goto out_err;
365         }
366
367         /* Read 0x0f bytes, to grab the NDEF msg length */
368         err = ISO_ReadBinary(0, LEN_ISO_CC_READ_SIZE,
369                                         t4_readbin_NDEF_ID, cookie);
370         if (err < 0)
371                 goto out_err;
372
373         return err;
374
375 out_err:
376         return t4_cookie_release(err, cookie);
377 }
378
379
380 static int t4_readbin_cc(uint8_t *resp, int length, void *data)
381 {
382         struct t4_cookie *cookie = data ;
383         struct type4_cc *read_cc ;
384         int err = 0;
385
386         DBG("%d", length);
387
388         if (length < 0) {
389                 err = length;
390                 goto out_err;
391         }
392
393         /* Check APDU error ( the two last bytes of the resp) */
394         if (APDU_STATUS(resp + length - 2) != APDU_OK) {
395                 DBG("Fail SW:x%04x", APDU_STATUS(resp + length - 2));
396                 err = -EIO;
397                 goto out_err;
398         }
399
400         /* -2 for status word and -1 is for NFC first byte... */
401         read_cc = g_try_malloc0(length - 2 - NFC_STATUS_BYTE_LEN);
402         if (read_cc == NULL) {
403                 DBG("Mem alloc failed");
404                 err = -ENOMEM;
405                 goto out_err;
406         }
407
408         memcpy(read_cc, &resp[1], length - 2 - NFC_STATUS_BYTE_LEN) ;
409
410         cookie->r_apdu_max_size = g_ntohs(read_cc->max_R_apdu_data_size) -
411                         APDU_HEADER_LEN ;
412         cookie->c_apdu_max_size = g_ntohs(read_cc->max_C_apdu_data_size);
413         cookie->max_ndef_size = g_ntohs(read_cc->tlv_fc.max_ndef_size);
414
415         /* TODO 5.1.1 :TLV blocks can be zero, one or more...  */
416         /* TODO 5.1.2 :Must ignore proprietary blocks (x05)...  */
417         if (read_cc->tlv_fc.tag  != 0x4) {
418                 DBG("NDEF File Control tag not found !") ;
419                 err = -EINVAL ;
420                 goto out_err ;
421         }
422
423         /* save rw conditions */
424         cookie->write_access = read_cc->tlv_fc.write_access;
425
426         err = ISO_Select((uint8_t *)&read_cc->tlv_fc.file_id,
427                         LEN_ISO_CC_FILEID, 0, t4_select_NDEF_ID, cookie);
428         if (err < 0)
429                 goto out_err;
430
431         return err;
432
433 out_err:
434         return t4_cookie_release(err, cookie);
435 }
436
437 static int t4_select_cc(uint8_t *resp, int length, void *data)
438 {
439         struct t4_cookie *cookie = data;
440         int err = 0;
441
442         DBG("%d", length);
443
444         if (length < 0) {
445                 err = length;
446                 goto out_err;
447         }
448
449         /* Check for APDU error */
450         if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
451                 DBG("Fail SW:x%04x", APDU_STATUS(resp + STATUS_WORD_1));
452                 err = -EIO;
453                 goto out_err;
454         }
455
456         err = ISO_ReadBinary(0, LEN_ISO_CC_READ_SIZE, t4_readbin_cc, cookie);
457         if (err < 0)
458                 goto out_err;
459
460         return err;
461
462 out_err:
463         return t4_cookie_release(err, cookie);
464 }
465
466
467 static int t4_select_file_by_name_v1(uint8_t *resp, int length, void *data)
468 {
469         struct t4_cookie *cookie = data;
470         int err = 0 ;
471
472         DBG("%d", length);
473
474         if (length < 0) {
475                 err = length;
476                 goto out_err;
477         }
478
479         /* Check for APDU error */
480         if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
481                 DBG("V1 Fail SW:x%04x", APDU_STATUS(resp + STATUS_WORD_1));
482                 err = -EIO;
483                 goto out_err;
484         }
485
486         if (resp[NFC_STATUS] != 0) {
487                 err = -EIO;
488                 goto out_err;
489         }
490
491         /* Jump to select phase */
492         err = ISO_Select(iso_cc_fileid, LEN_ISO_CC_FILEID, 0,
493                                 t4_select_cc, cookie);
494         if (err < 0)
495                 goto out_err;
496
497         return err;
498
499 out_err:
500         return t4_cookie_release(err, cookie);
501 }
502
503
504 static int t4_select_file_by_name_v2(uint8_t *resp, int length, void *data)
505 {
506         struct t4_cookie *cookie = data;
507         int err = 0 ;
508
509         DBG("%d", length);
510
511         if (length < 0) {
512                 err = length;
513                 goto out_err;
514         }
515
516         /* Check for APDU error - Not found */
517         if (APDU_STATUS(resp + STATUS_WORD_1) == APDU_NOT_FOUND) {
518                 DBG("Fallback to V1");
519                 err = ISO_Select(iso_appname_v1, ARRAY_SIZE(iso_appname_v1),
520                                 0x4, t4_select_file_by_name_v1, cookie);
521                 if (err < 0)
522                         goto out_err;
523
524                 return err;
525         }
526
527         if (APDU_STATUS(resp + STATUS_WORD_1) != APDU_OK) {
528                 DBG("V2 Fail SW:x%04x", APDU_STATUS(resp + STATUS_WORD_1));
529                 err = -EIO;
530                 goto out_err;
531         }
532
533         if (resp[NFC_STATUS] != 0) {
534                 err = -EIO;
535                 goto out_err;
536         }
537
538         /* Jump to select phase */
539         err = ISO_Select(iso_cc_fileid, LEN_ISO_CC_FILEID, 0,
540                         t4_select_cc, cookie);
541         if (err < 0)
542                 goto out_err;
543
544         return err;
545
546 out_err:
547         return t4_cookie_release(err, cookie);
548 }
549
550 static int nfctype4_read_tag(uint32_t adapter_idx,
551                 uint32_t target_idx, near_tag_io_cb cb)
552 {
553         struct t4_cookie *cookie;
554         int err = 0;
555
556         DBG("");
557
558         cookie = g_try_malloc0(sizeof(struct t4_cookie));
559         if (cookie == NULL) {
560                 err = -ENOMEM;
561                 goto out_err;
562         }
563
564         cookie->adapter_idx = adapter_idx;
565         cookie->target_idx = target_idx;
566         cookie->cb = cb;
567         cookie->tag = NULL;
568         cookie->read_data = 0;;
569
570         /* Check for V2 type 4 tag */
571         err = ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2),
572                         0x4, t4_select_file_by_name_v2, cookie);
573         if (err < 0)
574                 goto out_err;
575
576         return err;
577
578 out_err:
579         return t4_cookie_release(err, cookie);
580 }
581
582 static int data_write_cb(uint8_t *resp, int length, void *data)
583 {
584         struct t4_cookie *cookie = data;
585         int err = 0;
586
587         DBG("%d", length);
588
589         if (length < 0)
590                 return t4_cookie_release(err, cookie);
591
592         if (APDU_STATUS(resp + length - 2) != APDU_OK) {
593                 near_error("write failed SWx%04x",
594                                 APDU_STATUS(resp + length - 2));
595                 err = -EIO;
596
597                 return t4_cookie_release(err, cookie);
598         }
599
600         if (cookie->ndef->offset >= cookie->ndef->length) {
601                 DBG("Done writing");
602                 near_adapter_disconnect(cookie->adapter_idx);
603
604                 return t4_cookie_release(0, cookie);
605         }
606
607         if ((cookie->ndef->length - cookie->ndef->offset) >
608                         cookie->c_apdu_max_size) {
609                 err = ISO_Update(cookie->ndef->offset,
610                                 cookie->c_apdu_max_size,
611                                 cookie->ndef->data + cookie->ndef->offset,
612                                 data_write_cb, cookie);
613                 cookie->ndef->offset += cookie->c_apdu_max_size;
614         } else {
615                 err = ISO_Update(cookie->ndef->offset,
616                                 cookie->ndef->length - cookie->ndef->offset,
617                                 cookie->ndef->data + cookie->ndef->offset,
618                                 data_write_cb, cookie);
619                 cookie->ndef->offset = cookie->ndef->length;
620         }
621
622         if (err < 0)
623                 return t4_cookie_release(err, cookie);
624
625         return err;
626 }
627
628 static int data_write(uint32_t adapter_idx, uint32_t target_idx,
629                                 struct near_ndef_message *ndef,
630                                 struct near_tag *tag, near_tag_io_cb cb)
631 {
632         struct t4_cookie *cookie;
633         int err;
634
635         cookie = g_try_malloc0(sizeof(struct t4_cookie));
636         if (cookie == NULL) {
637                 err = -ENOMEM;
638                 goto out;
639         }
640
641         cookie->adapter_idx = adapter_idx;
642         cookie->target_idx = target_idx;
643         cookie->cb = cb;
644         cookie->tag = NULL;
645         cookie->read_data = 0;
646         cookie->max_ndef_size = near_tag_get_max_ndef_size(tag);
647         cookie->c_apdu_max_size = near_tag_get_c_apdu_max_size(tag);
648         cookie->ndef = ndef;
649
650         if (cookie->max_ndef_size < cookie->ndef->length) {
651                 near_error("not enough space on tag to write data");
652                 err = -ENOMEM;
653                 goto out;
654         }
655
656         if ((cookie->ndef->length - cookie->ndef->offset) >
657                         cookie->c_apdu_max_size) {
658                 err = ISO_Update(cookie->ndef->offset,
659                                 cookie->c_apdu_max_size,
660                                 cookie->ndef->data,
661                                 data_write_cb, cookie);
662                 cookie->ndef->offset += cookie->c_apdu_max_size;
663         } else {
664                 err = ISO_Update(cookie->ndef->offset,
665                                 cookie->ndef->length,
666                                 cookie->ndef->data,
667                                 data_write_cb, cookie);
668                 cookie->ndef->offset = cookie->ndef->length;
669         }
670
671         if (err < 0)
672                 goto out;
673
674         return 0;
675
676 out:
677         t4_cookie_release(err, cookie);
678
679         return err;
680 }
681
682 static int nfctype4_write_tag(uint32_t adapter_idx, uint32_t target_idx,
683                         struct near_ndef_message *ndef, near_tag_io_cb cb)
684 {
685         struct near_tag *tag;
686
687         DBG("");
688
689         if (ndef == NULL || cb == NULL)
690                 return -EINVAL;
691
692         tag = near_tag_get_tag(adapter_idx, target_idx);
693         if (tag == NULL)
694                 return -EINVAL;
695
696         if (near_tag_get_ro(tag) == TRUE) {
697                 DBG("tag is read-only");
698                 return -EPERM;
699         }
700
701         return data_write(adapter_idx, target_idx, ndef, tag, cb);
702 }
703
704 static int check_presence(uint8_t *resp, int length, void *data)
705 {
706         struct t4_cookie *cookie = data;
707         int err = 0;
708
709         DBG("%d", length);
710
711         if (length < 0)
712                 err = -EIO;
713
714         if (cookie->cb)
715                 cookie->cb(cookie->adapter_idx,
716                                 cookie->target_idx, err);
717
718         return t4_cookie_release(err, cookie);
719 }
720
721 static int nfctype4_check_presence(uint32_t adapter_idx,
722                 uint32_t target_idx, near_tag_io_cb cb)
723 {
724         struct t4_cookie *cookie;
725         int err = 0;
726
727         DBG("");
728
729         cookie = g_try_malloc0(sizeof(struct t4_cookie));
730         if (cookie == NULL) {
731                 err = -ENOMEM;
732                 goto out_err;
733         }
734
735         cookie->adapter_idx = adapter_idx;
736         cookie->target_idx = target_idx;
737         cookie->cb = cb;
738         cookie->tag = NULL;
739         cookie->read_data = 0;;
740
741         /* Check for V2 type 4 tag */
742         err = ISO_Select(iso_appname_v2, ARRAY_SIZE(iso_appname_v2),
743                         0x4, check_presence, cookie);
744         if (err < 0)
745                 goto out_err;
746
747         return err;
748
749 out_err:
750         return t4_cookie_release(err, cookie);
751 }
752
753 static struct near_tag_driver type4_driver = {
754         .type           = NFC_PROTO_ISO14443,
755         .priority       = NEAR_TAG_PRIORITY_DEFAULT,
756         .read_tag       = nfctype4_read_tag,
757         .add_ndef       = nfctype4_write_tag,
758         .check_presence = nfctype4_check_presence,
759 };
760
761 static int nfctype4_init(void)
762 {
763         DBG("");
764
765         return near_tag_driver_register(&type4_driver);
766 }
767
768 static void nfctype4_exit(void)
769 {
770         DBG("");
771
772         near_tag_driver_unregister(&type4_driver);
773 }
774
775 NEAR_PLUGIN_DEFINE(nfctype4, "NFC Forum Type 4 tags support", VERSION,
776                 NEAR_PLUGIN_PRIORITY_HIGH, nfctype4_init, nfctype4_exit)