2858f24cd98cf8c2b5ab81a86c7dafac4bb84e3a
[profile/ivi/neard.git] / plugins / nfctype2.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 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdint.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <sys/socket.h>
30
31 #include <linux/socket.h>
32 #include <linux/nfc.h>
33
34 #include <near/plugin.h>
35 #include <near/log.h>
36 #include <near/types.h>
37 #include <near/adapter.h>
38 #include <near/tag.h>
39 #include <near/ndef.h>
40 #include <near/tlv.h>
41
42 extern int mifare_read(uint32_t adapter_idx, uint32_t target_idx,
43                 near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype);
44
45 #define CMD_READ         0x30
46 #define CMD_READ_SIZE    0x02
47
48 #define CMD_WRITE        0xA2
49
50 #define READ_SIZE  16
51 #define BLOCK_SIZE 4
52
53 #define META_BLOCK_START 0
54 #define DATA_BLOCK_START 4
55 #define TYPE2_MAGIC 0xe1
56
57 #define TAG_DATA_CC(data) ((data) + 12)
58 #define TAG_DATA_LENGTH(cc) ((cc)[2] * 8)
59 #define TAG_DATA_NFC(cc) ((cc)[0] & TYPE2_MAGIC)
60
61 #define TYPE2_NOWRITE_ACCESS    0x0F
62 #define TYPE2_READWRITE_ACCESS  0x00
63 #define TAG_T2_WRITE_FLAG(cc) ((cc)[3] & TYPE2_NOWRITE_ACCESS)
64
65 #define NDEF_MAX_SIZE   0x30
66
67 #define CC_BLOCK_START 3
68 #define TYPE2_TAG_VER_1_0  0x10
69 #define TYPE2_DATA_SIZE_48 0x6
70
71 struct type2_cmd {
72         uint8_t cmd;
73         uint8_t block;
74         uint8_t data[BLOCK_SIZE];
75 } __attribute__((packed));
76
77 struct type2_tag {
78         uint32_t adapter_idx;
79         uint16_t current_block;
80
81         near_tag_io_cb cb;
82         struct near_tag *tag;
83 };
84
85 struct t2_cookie {
86         uint32_t adapter_idx;
87         uint32_t target_idx;
88         uint8_t current_block;
89         struct near_ndef_message *ndef;
90         near_tag_io_cb cb;
91 };
92
93 struct type2_cc {
94         uint8_t magic;
95         uint8_t version;
96         uint8_t mem_size;
97         uint8_t read_write;
98 };
99
100 static void t2_cookie_release(struct t2_cookie *cookie)
101 {
102         if (cookie == NULL)
103                 return;
104
105         if (cookie->ndef)
106                 g_free(cookie->ndef->data);
107
108         g_free(cookie->ndef);
109         g_free(cookie);
110         cookie = NULL;
111 }
112
113 static int data_recv(uint8_t *resp, int length, void *data)
114 {
115         struct type2_tag *tag = data;
116         struct type2_cmd cmd;
117         uint8_t *nfc_data;
118         size_t current_length, length_read, data_length;
119         uint32_t adapter_idx;
120         int read_blocks;
121
122         DBG("%d", length);
123
124         if (length < 0) {
125                 g_free(tag);
126
127                 return  length;
128         }
129
130         nfc_data = near_tag_get_data(tag->tag, &data_length);
131         adapter_idx = near_tag_get_adapter_idx(tag->tag);
132
133         length_read = length - NFC_HEADER_SIZE;
134         current_length = tag->current_block * BLOCK_SIZE;
135         if (current_length + length - NFC_HEADER_SIZE > data_length)
136                 length_read = data_length - current_length;
137
138         memcpy(nfc_data + current_length, resp + NFC_HEADER_SIZE, length_read);
139
140         if (current_length + length_read == data_length) {
141                 GList *records;
142
143                 /* TODO parse tag->data for NDEFS, and notify target.c */
144                 tag->current_block = 0;
145
146                 DBG("Done reading");
147
148                 records = near_tlv_parse(nfc_data, data_length);
149                 near_tag_add_records(tag->tag, records, tag->cb, 0);
150
151                 g_free(tag);
152
153                 return 0;
154         }
155
156         read_blocks = length / BLOCK_SIZE;
157         tag->current_block += read_blocks;
158
159         cmd.cmd = CMD_READ;
160         cmd.block = DATA_BLOCK_START + tag->current_block;
161
162         DBG("adapter %d", adapter_idx);
163
164         return near_adapter_send(adapter_idx,
165                                 (uint8_t *)&cmd, CMD_READ_SIZE,
166                                         data_recv, tag);
167 }
168
169 static int data_read(struct type2_tag *tag)
170 {
171         struct type2_cmd cmd;
172         uint32_t adapter_idx;
173
174         DBG("");
175
176         tag->current_block = 0;
177
178         cmd.cmd = CMD_READ;
179         cmd.block = DATA_BLOCK_START;
180
181         adapter_idx = near_tag_get_adapter_idx(tag->tag);
182
183         return near_adapter_send(adapter_idx,
184                                 (uint8_t *)&cmd, CMD_READ_SIZE,
185                                         data_recv, tag);
186 }
187
188 static int meta_recv(uint8_t *resp, int length, void *data)
189 {
190         struct t2_cookie *cookie = data;
191         struct near_tag *tag;
192         struct type2_tag *t2_tag;
193         uint8_t *cc;
194         int err;
195
196         DBG("%d", length);
197
198         if (length < 0) {
199                 err = length;
200                 goto out;
201         }
202
203         if (resp[0] != 0) {
204                 err = -EIO;
205                 goto out;
206         }
207
208         cc = TAG_DATA_CC(resp + NFC_HEADER_SIZE);
209
210         /* Default to 48 bytes data size in case of blank tag */
211         err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx,
212                         NULL, (TAG_DATA_LENGTH(cc) ? TAG_DATA_LENGTH(cc) :
213                         TYPE2_DATA_SIZE_48 << 3));
214
215         if (err < 0)
216                 goto out;
217
218         tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
219         if (tag == NULL) {
220                 err = -ENOMEM;
221                 goto out;
222         }
223
224         t2_tag = g_try_malloc0(sizeof(struct type2_tag));
225         if (t2_tag == NULL) {
226                 err = -ENOMEM;
227                 goto out;
228         }
229
230         t2_tag->adapter_idx = cookie->adapter_idx;
231         t2_tag->cb = cookie->cb;
232         t2_tag->tag = tag;
233
234         /* Set the ReadWrite flag */
235         if (TAG_T2_WRITE_FLAG(cc) == TYPE2_NOWRITE_ACCESS)
236                 near_tag_set_ro(tag, TRUE);
237         else
238                 near_tag_set_ro(tag, FALSE);
239
240         near_tag_set_memory_layout(tag, NEAR_TAG_MEMORY_STATIC);
241
242         if (TAG_DATA_NFC(cc) == 0) {
243                 DBG("Mark as blank tag");
244                 near_tag_set_blank(tag, TRUE);
245         } else {
246                 near_tag_set_blank(tag, FALSE);
247         }
248
249         err = data_read(t2_tag);
250         if (err < 0)
251                 goto out;
252
253         t2_cookie_release(cookie);
254
255         return 0;
256
257 out:
258         if (err < 0 && cookie->cb)
259                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
260
261         t2_cookie_release(cookie);
262
263         return err;
264 }
265
266 static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx,
267                                                         near_tag_io_cb cb)
268 {
269         struct type2_cmd cmd;
270         struct t2_cookie *cookie;
271         int err;
272
273         DBG("");
274
275         cmd.cmd = CMD_READ;
276         cmd.block = META_BLOCK_START;
277
278         cookie = g_try_malloc0(sizeof(struct t2_cookie));
279         if (cookie == NULL)
280                 return -ENOMEM;
281
282         cookie->adapter_idx = adapter_idx;
283         cookie->target_idx = target_idx;
284         cookie->cb = cb;
285
286         err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, CMD_READ_SIZE,
287                                                         meta_recv, cookie);
288         if (err < 0)
289                 g_free(cookie);
290
291         return err;
292 }
293
294 static int nfctype2_read(uint32_t adapter_idx,
295                                 uint32_t target_idx, near_tag_io_cb cb)
296 {
297         int err;
298         enum near_tag_sub_type tgt_subtype;
299
300         DBG("");
301
302         tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx);
303
304         switch (tgt_subtype) {
305         case NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT:
306                 err = nfctype2_read_meta(adapter_idx, target_idx, cb);
307                 break;
308
309         /* Specific Mifare read access */
310         case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K:
311         case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K:
312                 err= mifare_read( adapter_idx, target_idx,
313                         cb, tgt_subtype);
314                 break;
315
316         default:
317                 DBG("Unknown TAG Type 2 subtype (%d)", tgt_subtype);
318                 err = -1;
319                 break;
320         }
321
322         return err;
323 }
324
325 static int data_write_resp(uint8_t *resp, int length, void *data)
326 {
327         int err;
328         struct t2_cookie *cookie = data;
329         struct type2_cmd cmd;
330
331         DBG("");
332
333         if (length < 0 || resp[0] != 0) {
334                 err = -EIO;
335                 goto out;
336         }
337
338         if (cookie->ndef->offset > cookie->ndef->length) {
339                 DBG("Done writing");
340
341                 if (cookie->cb)
342                         cookie->cb(cookie->adapter_idx, cookie->target_idx, 0);
343
344                 t2_cookie_release(cookie);
345
346                 return 0;
347         }
348
349         cmd.cmd = CMD_WRITE;
350         cmd.block = cookie->current_block;
351         cookie->current_block++;
352
353         if ((cookie->ndef->offset + BLOCK_SIZE) <
354                         cookie->ndef->length) {
355                 memcpy(cmd.data, cookie->ndef->data +
356                                         cookie->ndef->offset, BLOCK_SIZE);
357                 cookie->ndef->offset += BLOCK_SIZE;
358         } else {
359                 memcpy(cmd.data, cookie->ndef->data + cookie->ndef->offset,
360                                 cookie->ndef->length - cookie->ndef->offset);
361                 cookie->ndef->offset = cookie->ndef->length + 1;
362         }
363
364         err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
365                                         sizeof(cmd), data_write_resp, cookie);
366
367
368         if (err < 0)
369                 goto out;
370
371         return 0;
372
373 out:
374         if (err < 0 && cookie->cb)
375                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
376
377         t2_cookie_release(cookie);
378
379         return err;
380 }
381
382 static int data_write(uint32_t adapter_idx, uint32_t target_idx,
383                                 struct near_ndef_message *ndef,
384                                 near_tag_io_cb cb)
385 {
386         struct type2_cmd cmd;
387         struct t2_cookie *cookie;
388         int err;
389
390         DBG("");
391
392         cookie = g_try_malloc0(sizeof(struct t2_cookie));
393         if (cookie == NULL)
394                 return -ENOMEM;
395
396         cookie->adapter_idx = adapter_idx;
397         cookie->target_idx = target_idx;
398         cookie->current_block = DATA_BLOCK_START;
399         cookie->ndef = ndef;
400         cookie->cb = cb;
401
402         cmd.cmd = CMD_WRITE;
403         cmd.block = cookie->current_block;
404         memcpy(cmd.data, cookie->ndef->data, BLOCK_SIZE);
405         cookie->ndef->offset += BLOCK_SIZE;
406         cookie->current_block++;
407
408         err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
409                                         sizeof(cmd), data_write_resp, cookie);
410
411         if (err < 0)
412                 goto out;
413
414         return 0;
415
416 out:
417         t2_cookie_release(cookie);
418
419         return err;
420 }
421
422 static int nfctype2_write(uint32_t adapter_idx, uint32_t target_idx,
423                                 struct near_ndef_message *ndef,
424                                 near_tag_io_cb cb)
425 {
426         struct near_tag *tag;
427         enum near_tag_sub_type tgt_subtype;
428
429         DBG("");
430
431         if (ndef == NULL || cb == NULL)
432                 return -EINVAL;
433
434         tag = near_tag_get_tag(adapter_idx, target_idx);
435         if (tag == NULL)
436                 return -EINVAL;
437
438         tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx);
439
440         if (tgt_subtype != NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT) {
441                 DBG("Unknown Tag Type 2 subtype (%d)", tgt_subtype);
442                 return -1;
443         }
444
445         /* This check is valid for only static tags.
446          * Max data length on Type 2 Tag including TLV's is NDEF_MAX_SIZE */
447         if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) {
448                 if ((ndef->length + 3) > NDEF_MAX_SIZE) {
449                         near_error("not enough space on tag");
450                         return -ENOSPC;
451                 }
452         }
453
454         return data_write(adapter_idx, target_idx, ndef, cb);
455 }
456
457 static int check_presence(uint8_t *resp, int length, void *data)
458 {
459         struct t2_cookie *cookie = data;
460         int err = 0;
461
462         DBG("%d", length);
463
464         if (length < 0)
465                 err = -EIO;
466
467         if (cookie->cb)
468                 cookie->cb(cookie->adapter_idx,
469                                 cookie->target_idx, err);
470
471         t2_cookie_release(cookie);
472
473         return err;
474 }
475
476 static int nfctype2_check_presence(uint32_t adapter_idx, uint32_t target_idx,
477                                                         near_tag_io_cb cb)
478 {
479         struct type2_cmd cmd;
480         struct t2_cookie *cookie;
481         int err;
482
483         DBG("");
484
485         cmd.cmd = CMD_READ;
486         cmd.block = META_BLOCK_START;
487
488         cookie = g_try_malloc0(sizeof(struct t2_cookie));
489         if (cookie == NULL)
490                 return -ENOMEM;
491
492         cookie->adapter_idx = adapter_idx;
493         cookie->target_idx = target_idx;
494         cookie->cb = cb;
495
496         err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, CMD_READ_SIZE,
497                                                         check_presence, cookie);
498         if (err < 0)
499                 goto out;
500
501         return 0;
502
503 out:
504         t2_cookie_release(cookie);
505
506         return err;
507 }
508
509 static int format_resp(uint8_t *resp, int length, void *data)
510 {
511         int err = 0;
512         struct t2_cookie *cookie = data;
513         struct near_tag *tag;
514
515         DBG("");
516
517         if (length < 0 || resp[0] != 0) {
518                 err = -EIO;
519                 goto out;
520         }
521
522         tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
523         if (tag == NULL) {
524                 err = -EINVAL;
525                 goto out;
526         }
527
528         DBG("Done formatting");
529         near_tag_set_blank(tag, FALSE);
530
531 out:
532         if (cookie->cb)
533                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
534
535         t2_cookie_release(cookie);
536
537         return err;
538 }
539
540 static int nfctype2_format(uint32_t adapter_idx, uint32_t target_idx,
541                                 near_tag_io_cb cb)
542 {
543         struct type2_cmd cmd;
544         struct t2_cookie *cookie;
545         struct near_ndef_message *cc_ndef;
546         struct type2_cc *t2_cc;
547         struct near_tag *tag;
548         enum near_tag_sub_type tgt_subtype;
549         int err;
550
551         DBG("");
552
553         tag = near_tag_get_tag(adapter_idx, target_idx);
554         if (tag == NULL)
555                 return -EINVAL;
556
557
558         tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx);
559
560         if (tgt_subtype != NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT) {
561                 DBG("Unknown Tag Type 2 subtype (%d)", tgt_subtype);
562                 return -1;
563         }
564
565         t2_cc = g_try_malloc0(sizeof(struct type2_cc));
566         cc_ndef = g_try_malloc0(sizeof(struct near_ndef_message));
567         cookie = g_try_malloc0(sizeof(struct t2_cookie));
568
569         if (t2_cc == NULL || cc_ndef == NULL || cookie == NULL) {
570                 err = -ENOMEM;
571                 goto out;
572         }
573
574         t2_cc->magic = TYPE2_MAGIC;
575         t2_cc->version = TYPE2_TAG_VER_1_0;
576         t2_cc->mem_size = TYPE2_DATA_SIZE_48;
577         t2_cc->read_write = TYPE2_READWRITE_ACCESS;
578
579         cookie->adapter_idx = adapter_idx;
580         cookie->target_idx = target_idx;
581         cookie->current_block = CC_BLOCK_START;
582         cookie->ndef = cc_ndef;
583         cookie->ndef->data = (uint8_t *)t2_cc;
584         cookie->cb = cb;
585
586         cmd.cmd = CMD_WRITE;
587         cmd.block = CC_BLOCK_START;
588         memcpy(cmd.data, (uint8_t *)t2_cc, BLOCK_SIZE);
589
590         err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
591                                         sizeof(cmd), format_resp, cookie);
592
593 out:
594         if (err < 0) {
595                 g_free(t2_cc);
596                 g_free(cc_ndef);
597                 g_free(cookie);
598         }
599
600         return err;
601 }
602
603 static struct near_tag_driver type2_driver = {
604         .type           = NFC_PROTO_MIFARE,
605         .priority       = NEAR_TAG_PRIORITY_DEFAULT,
606         .read           = nfctype2_read,
607         .write          = nfctype2_write,
608         .check_presence = nfctype2_check_presence,
609         .format         = nfctype2_format,
610 };
611
612 static int nfctype2_init(void)
613 {
614         DBG("");
615
616         return near_tag_driver_register(&type2_driver);
617 }
618
619 static void nfctype2_exit(void)
620 {
621         DBG("");
622
623         near_tag_driver_unregister(&type2_driver);
624 }
625
626 NEAR_PLUGIN_DEFINE(nfctype2, "NFC Forum Type 2 tags support", VERSION,
627                         NEAR_PLUGIN_PRIORITY_HIGH, nfctype2_init, nfctype2_exit)