adapter: Bypass the target layer
[platform/upstream/neard.git] / plugins / nfctype3.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/target.h>
39 #include <near/tag.h>
40 #include <near/ndef.h>
41 #include <near/tlv.h>
42
43 #define CMD_POLL                0x00
44 #define RESP_POLL               0x01
45
46 #define CMD_REQUEST_SERVICE     0x02
47 #define RESP_REQUEST_SERVICE    0x03
48
49 #define CMD_REQUEST_RESPONSE    0x04
50 #define RESP_REQUEST_RESPONSE   0x05
51
52 #define CMD_READ_WO_ENCRYPT     0x06
53 #define RESP_READ_WO_ENCRYPT    0x07
54
55 #define CMD_WRITE_WO_ENCRYPT    0x08
56 #define RESP_WRITE_WO_ENCRYPT   0x09
57
58 #define CMD_REQUEST_SYS_CODE    0x0C
59 #define RESP_REQUEST_SYS_CODE   0x0D
60
61 #define CMD_AUTHENTICATION_1    0x10
62 #define RESP_AUTHENTICATION_1   0x11
63
64 #define CMD_AUTHENTICATION_2    0x12
65 #define RESP_AUTHENTICATION_2   0x13
66
67 #define CMD_READ                0x14
68 #define RESP_READ               0x15
69
70 #define CMD_WRITE               0x16
71 #define RESP_WRITE              0x17
72
73 #define NFC_SERVICE_CODE        0x000B
74 #define BLOCK_SIZE              16
75 #define META_BLOCK_START        0
76 #define DATA_BLOCK_START        1
77
78 #define LEN_ID                  0x08
79 #define LEN_CMD                 0x01
80 #define LEN_REPLY_CMD           0x02
81 #define LEN_CMD_LEN             0x01
82
83 /* offsets */
84 #define OFS_NFC_STATUS  0
85 #define OFS_NFC_LEN     1
86 #define OFS_CMD_RESP    2
87 #define OFS_IDM         3
88 #define OFS_CMD_DATA    (LEN_CMD_LEN + LEN_CMD + LEN_ID)
89 #define OFS_READ_FLAG   12
90 #define OFS_READ_DATA   14
91 #define BLOCK_SIZE      16
92 #define CHECKSUM_LEN    2
93
94 #define MAX_DATA_SIZE   254
95
96 struct type3_cmd {
97         uint8_t len;
98         uint8_t cmd;
99         uint8_t data[MAX_DATA_SIZE];
100 } __attribute__((packed));
101
102 struct type3_tag {
103         uint32_t adapter_idx;
104         uint16_t current_block;
105         uint8_t IDm[LEN_ID];
106
107         near_tag_io_cb cb;
108         struct near_tag *tag;
109 };
110
111 struct t3_cookie {
112         uint32_t adapter_idx;
113         uint32_t target_idx;
114         near_tag_io_cb cb;
115         uint8_t IDm[LEN_ID];
116         uint8_t current_block;
117         uint8_t attr[BLOCK_SIZE];
118         struct near_ndef_message *ndef;
119 };
120
121 static void t3_cookie_release(struct t3_cookie *cookie)
122 {
123         if (cookie == NULL)
124                 return;
125
126         if (cookie->ndef != NULL)
127                 g_free(cookie->ndef->data);
128
129         g_free(cookie->ndef);
130         g_free(cookie);
131         cookie = NULL;
132 }
133
134 /* common: Intialize structure to write block */
135 static void prepare_write_block(uint8_t *UID, struct type3_cmd *cmd,
136                                         uint8_t block, uint8_t *data)
137 {
138         cmd->cmd = CMD_WRITE_WO_ENCRYPT;        /* command */
139         memcpy(cmd->data, UID, LEN_ID);         /* IDm */
140
141         cmd->data[LEN_ID] = 1;                  /* number of services */
142         cmd->data[LEN_ID + 1] = 0x09;           /* service 0x0009 */
143         cmd->data[LEN_ID + 2] = 0x00;
144
145         cmd->data[LEN_ID + 3] = 0x01;           /* number of blocks */
146         cmd->data[LEN_ID + 4] = 0x80;           /* 2 byte block number format */
147         cmd->data[LEN_ID + 5] = block;          /* block number */
148         memcpy(cmd->data + LEN_ID + 6, data, BLOCK_SIZE); /* data to write */
149
150         cmd->len = LEN_ID + LEN_CMD + LEN_CMD_LEN + 6 + BLOCK_SIZE;
151
152 }
153
154 /* common: Initialize structure to read block */
155 static void prepare_read_block(uint8_t cur_block,
156                                 uint8_t *UID,
157                                 struct type3_cmd *cmd )
158 {
159         cmd->cmd         = CMD_READ_WO_ENCRYPT;         /* command */
160         memcpy(cmd->data, UID, LEN_ID);                 /* IDm */
161
162         cmd->data[LEN_ID] = 1;                          /* number of service */
163         cmd->data[LEN_ID + 1] = 0x0B;                   /* service x000B */
164         cmd->data[LEN_ID + 2] = 0x00;
165
166         cmd->data[LEN_ID + 3] = 0x01;                   /* number of block */
167         cmd->data[LEN_ID + 4] = 0x80;                   /* 2 bytes block id*/
168         cmd->data[LEN_ID + 5] = cur_block;              /* block number */
169
170         cmd->len = LEN_ID + LEN_CMD + LEN_CMD_LEN + 6;
171 }
172
173 /* common: Simple checks on received frame */
174 static int check_recv_frame(uint8_t *resp, uint8_t reply_code)
175 {
176         int err = 0;
177
178         if (resp[OFS_NFC_STATUS] != 0) {
179                 DBG("NFC Command failed: 0x%x",resp[OFS_NFC_STATUS]);
180                 err = -EIO;
181         }
182
183         if (resp[OFS_CMD_RESP] != reply_code ) {
184                 DBG("Felica cmd failed: 0x%x", resp[OFS_CMD_RESP]);
185                 err = -EIO;
186         }
187
188         return err;
189 }
190
191 static int nfctype3_data_recv(uint8_t *resp, int length, void *data)
192 {
193         struct type3_tag *tag = data;
194         struct type3_cmd cmd;
195         uint8_t *nfc_data;
196         uint16_t current_length, length_read, data_length;
197         uint32_t adapter_idx;
198         uint32_t target_idx;
199         int read_blocks;
200         int err;
201
202         DBG("%d", length);
203
204         adapter_idx = near_tag_get_adapter_idx(tag->tag);
205         target_idx = near_tag_get_target_idx(tag->tag);
206
207         if (length < 0) {
208                 err = -EIO;
209                 goto out;
210         }
211
212         nfc_data = near_tag_get_data(tag->tag, (size_t *)&data_length);
213         length_read = length - OFS_READ_DATA  ;
214         current_length = tag->current_block * BLOCK_SIZE;
215         if (current_length + (length - OFS_READ_DATA) > data_length)
216                 length_read = data_length - current_length;
217
218         memcpy(nfc_data + current_length, resp + OFS_READ_DATA, length_read);
219
220         if (current_length + length_read >= data_length) {
221                 tag->current_block = 0;
222
223                 DBG("Done reading %d bytes at %p", data_length, nfc_data);
224                 near_ndef_parse(tag->tag, nfc_data, data_length);
225
226                 if (tag->cb)
227                         tag->cb(adapter_idx, target_idx, 0);
228
229                 g_free(tag);
230
231                 return 0;
232         }
233
234         /* Read the next block */
235         read_blocks = length / BLOCK_SIZE;
236         tag->current_block += read_blocks;
237
238         prepare_read_block(DATA_BLOCK_START + tag->current_block,
239                                 tag->IDm, &cmd );
240
241         err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, cmd.len,
242                         nfctype3_data_recv, tag);
243         if (err < 0)
244                 goto out;
245
246         return 0;
247
248 out:
249         if (err < 0 && tag->cb)
250                 tag->cb(adapter_idx, target_idx, err);
251
252         g_free(tag);
253
254         return err;
255 }
256
257 static int nfctype3_data_read(struct type3_tag *tag)
258 {
259         struct type3_cmd cmd;
260         uint32_t adapter_idx;
261
262         DBG("");
263
264         tag->current_block = 0;
265
266         prepare_read_block(DATA_BLOCK_START + tag->current_block,
267                                                         tag->IDm, &cmd );
268
269         adapter_idx = near_tag_get_adapter_idx(tag->tag);
270
271         return near_adapter_send(adapter_idx,
272                                         (uint8_t *) &cmd, cmd.len,
273                                         nfctype3_data_recv, tag);
274 }
275
276 /* Read block 0 to retrieve the data length */
277 static int nfctype3_recv_block_0(uint8_t *resp, int length, void *data)
278 {
279         struct t3_cookie *cookie = data;
280         int err = 0;
281         struct near_tag *tag;
282         struct type3_tag *t3_tag = NULL;
283         uint32_t  ndef_data_length;
284
285         DBG("%d", length);
286
287         if (length < 0) {
288                 err = -EIO;
289                 goto out;
290         }
291
292         err = check_recv_frame(resp, RESP_READ_WO_ENCRYPT);
293         if (err < 0)
294                 goto out;
295
296         if (resp[OFS_READ_FLAG] != 0) {
297                 DBG("Status 0x%x", resp[OFS_READ_FLAG]);
298                 err = -EIO;
299                 goto out;
300         }
301
302         /* Block 0:[11 - 13]: length is a 3 bytes value */
303         ndef_data_length =  resp[OFS_READ_DATA + 11] * 0x100;
304         ndef_data_length += resp[OFS_READ_DATA + 12];
305         ndef_data_length *= 0x100;
306         ndef_data_length += resp[OFS_READ_DATA + 13];
307
308         /* Add data to the tag */
309         err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx,
310                                         NULL, ndef_data_length);
311         if (err < 0)
312                 goto out;
313
314         tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
315         if (tag == NULL) {
316                 err = -ENOMEM;
317                 goto out;
318         }
319
320         /* Block 0:[10]: RW Flag. 1 for RW */
321         if (resp[OFS_READ_DATA + 10] == 0)
322                 near_tag_set_ro(tag, TRUE);
323         else
324                 near_tag_set_ro(tag, FALSE);
325
326         t3_tag = g_try_malloc0(sizeof(struct type3_tag));
327         if (t3_tag == NULL) {
328                 err = -ENOMEM;
329                 goto out;
330         }
331
332         memcpy(t3_tag->IDm, cookie->IDm , LEN_ID);
333
334         near_tag_set_idm(tag, cookie->IDm, LEN_ID);
335         near_tag_set_attr_block(tag, resp + OFS_READ_DATA, BLOCK_SIZE);
336
337         t3_tag->adapter_idx = cookie->adapter_idx;
338         t3_tag->cb = cookie->cb;
339         t3_tag->tag = tag;
340
341         err = nfctype3_data_read(t3_tag);
342
343 out:
344         if (err < 0 && cookie->cb) {
345                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
346                 g_free(t3_tag);
347         }
348
349         t3_cookie_release(cookie);
350
351         return err;
352 }
353
354 static int nfctype3_recv_UID(uint8_t *resp, int length, void *data)
355 {
356         struct t3_cookie *rcv_cookie = data;
357         struct t3_cookie *snd_cookie;
358         int err = 0;
359         struct type3_cmd cmd;
360
361         DBG(" length: %d", length);
362
363         if (length < 0) {
364                 err = -EIO;
365                 goto out;
366         }
367
368         err = check_recv_frame(resp, RESP_POLL);
369         if (err < 0)
370                 goto out;
371
372         snd_cookie = g_try_malloc0(sizeof(struct t3_cookie));
373         snd_cookie->adapter_idx = rcv_cookie->adapter_idx;
374         snd_cookie->target_idx = rcv_cookie->target_idx;
375         snd_cookie->cb = rcv_cookie->cb;
376
377         memcpy(snd_cookie->IDm, resp + OFS_IDM, LEN_ID);
378
379         prepare_read_block(META_BLOCK_START, snd_cookie->IDm, &cmd);
380
381         err = near_adapter_send(snd_cookie->adapter_idx,
382                         (uint8_t *)&cmd, cmd.len, nfctype3_recv_block_0, snd_cookie);
383
384 out:
385         if (err < 0 && rcv_cookie->cb)
386                 rcv_cookie->cb(rcv_cookie->adapter_idx,
387                                 rcv_cookie->target_idx, err);
388
389         t3_cookie_release(rcv_cookie);
390
391         return err;
392 }
393
394 static int nfctype3_read_tag(uint32_t adapter_idx,
395                                 uint32_t target_idx, near_tag_io_cb cb)
396 {
397         struct type3_cmd cmd;
398         struct t3_cookie *cookie;
399
400         DBG("");
401
402         /* CMD POLL */
403         cmd.cmd  = CMD_POLL;    /* POLL command */
404         cmd.data[0] = 0x12;     /* System code (NFC SC) */
405         cmd.data[1] = 0xFC;
406         cmd.data[2] = 01;       /* request code */
407         cmd.data[3] = 0x00;     /* time slot */
408
409         /* data len + 2 bytes */
410         cmd.len = LEN_CMD + LEN_CMD_LEN + 4 ;
411
412         cookie = g_try_malloc0(sizeof(struct t3_cookie));
413         cookie->adapter_idx = adapter_idx;
414         cookie->target_idx = target_idx;
415         cookie->cb = cb;
416
417         return near_adapter_send(adapter_idx, (uint8_t *)&cmd,
418                         cmd.len , nfctype3_recv_UID, cookie);
419 }
420
421 static int update_attr_block_cb(uint8_t *resp, int length, void *data)
422 {
423         struct t3_cookie *cookie = data;
424         int err;
425
426         DBG("");
427
428         if (length < 0) {
429                 err = -EIO;
430                 goto out;
431         }
432
433         err = check_recv_frame(resp, RESP_WRITE_WO_ENCRYPT);
434         if (err < 0)
435                 goto out;
436
437         DBG("Done writing");
438
439 out:
440         if (cookie->cb)
441                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
442
443         t3_cookie_release(cookie);
444
445         return err;
446 }
447
448 static int update_attr_block(struct t3_cookie *cookie)
449 {
450         struct type3_cmd cmd;
451         uint16_t checksum;
452         uint8_t i;
453
454         DBG("");
455
456         cookie->attr[9] = 0x00; /* writing data completed */
457         cookie->attr[11] = (uint8_t) (cookie->ndef->length >> 16);
458         cookie->attr[12] = (uint8_t) (cookie->ndef->length >> 8);
459         cookie->attr[13] = (uint8_t) cookie->ndef->length;
460         checksum = 0;
461
462         for (i = 0; i < (BLOCK_SIZE - CHECKSUM_LEN); i++)
463                 checksum += cookie->attr[i];
464
465         cookie->attr[14] = (uint8_t) (checksum >> 8);
466         cookie->attr[15] = (uint8_t) checksum;
467
468         prepare_write_block(cookie->IDm, &cmd, 0, cookie->attr);
469
470         return near_adapter_send(cookie->adapter_idx, (uint8_t *) &cmd, cmd.len,
471                                                 update_attr_block_cb, cookie);
472 }
473
474 static int data_write_resp(uint8_t *resp, int length, void *data)
475 {
476         struct t3_cookie *cookie = data;
477         struct type3_cmd cmd;
478         uint8_t padding[BLOCK_SIZE] = {0};
479         int err;
480
481         DBG("");
482
483         if (length < 0) {
484                 err = -EIO;
485                 goto out;
486         }
487
488         err = check_recv_frame(resp, RESP_WRITE_WO_ENCRYPT);
489         if (err < 0)
490                 goto out;
491
492         if (cookie->ndef->offset >= cookie->ndef->length) {
493                 err = update_attr_block(cookie);
494                 if (err < 0)
495                         goto out;
496
497                 return 0;
498         }
499
500         if ((cookie->ndef->length - cookie->ndef->offset) <
501                         BLOCK_SIZE) {
502                 memcpy(padding, cookie->ndef->data + cookie->ndef->offset,
503                                 cookie->ndef->length - cookie->ndef->offset);
504                 prepare_write_block(cookie->IDm, &cmd,
505                                         cookie->current_block, padding);
506         } else {
507                 prepare_write_block(cookie->IDm, &cmd, cookie->current_block,
508                                 cookie->ndef->data + cookie->ndef->offset);
509         }
510
511         cookie->current_block++;
512         cookie->ndef->offset += BLOCK_SIZE;
513
514         err =  near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd, cmd.len,
515                                                 data_write_resp, cookie);
516         if (err < 0)
517                 goto out;
518
519         return 0;
520
521 out:
522         if (err < 0 && cookie->cb)
523                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
524
525         t3_cookie_release(cookie);
526
527         return err;
528 }
529
530 static int data_write(uint32_t adapter_idx, uint32_t target_idx,
531                                 struct near_ndef_message *ndef,
532                                 struct near_tag *tag,
533                                 near_tag_io_cb cb)
534 {
535         struct t3_cookie *cookie;
536         struct type3_cmd cmd;
537         uint16_t checksum, nmaxb;
538         uint8_t i, len = 0;
539         uint8_t *idm, *attr;
540         int err;
541
542         DBG("");
543
544         cookie = g_try_malloc0(sizeof(struct t3_cookie));
545         if (cookie == NULL) {
546                 err = -ENOMEM;
547                 goto out;
548         }
549
550         cookie->adapter_idx = adapter_idx;
551         cookie->target_idx = target_idx;
552         cookie->ndef = ndef;
553         cookie->cb = cb;
554         cookie->current_block = 0;
555
556         idm = near_tag_get_idm(tag, &len);
557         if (idm == NULL) {
558                 err = -EINVAL;
559                 goto out;
560         }
561
562         memcpy(cookie->IDm, idm, len);
563
564         attr = near_tag_get_attr_block(tag, &len);
565         if (attr == NULL) {
566                 err = -EINVAL;
567                 goto out;
568         }
569
570         memcpy(cookie->attr, attr, len);
571         nmaxb = (((uint16_t)(cookie->attr[3])) << 8) | cookie->attr[4];
572
573         if (cookie->ndef->length > (nmaxb * BLOCK_SIZE)) {
574                 near_error("not enough space on tag");
575                 err = -ENOSPC;
576                 goto out;
577         }
578
579         cookie->attr[9] = 0x0F; /* writing data in progress */
580         checksum = 0;
581
582         for (i = 0; i < 14; i++)
583                 checksum += cookie->attr[i];
584
585         cookie->attr[14] = (uint8_t)(checksum >> 8);
586         cookie->attr[15] = (uint8_t)(checksum);
587
588         prepare_write_block(cookie->IDm, &cmd, cookie->current_block,
589                                                         cookie->attr);
590         cookie->current_block++;
591
592         err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, cmd.len,
593                                                 data_write_resp, cookie);
594         if (err < 0)
595                 goto out;
596
597         return 0;
598
599 out:
600         t3_cookie_release(cookie);
601
602         return err;
603 }
604
605 static int nfctype3_write_tag(uint32_t adapter_idx, uint32_t target_idx,
606                                 struct near_ndef_message *ndef,
607                                 near_tag_io_cb cb)
608 {
609         struct near_tag *tag;
610
611         DBG("");
612
613         if (ndef == NULL || cb == NULL)
614                 return -EINVAL;
615
616         tag = near_tag_get_tag(adapter_idx, target_idx);
617         if (tag == NULL)
618                 return -EINVAL;
619
620         if (near_tag_get_ro(tag) == TRUE) {
621                 DBG("tag is read-only");
622                 return -EPERM;
623         }
624
625         return data_write(adapter_idx, target_idx, ndef, tag, cb);
626 }
627
628 static int nfctype3_check_recv_UID(uint8_t *resp, int length, void *data)
629 {
630         struct t3_cookie *rcv_cookie = data;
631         int err = 0;
632
633         DBG("length %d", length);
634
635         if (length < 0)
636                 err = -EIO;
637
638         if (rcv_cookie->cb)
639                 rcv_cookie->cb(rcv_cookie->adapter_idx,
640                                 rcv_cookie->target_idx, err);
641
642         t3_cookie_release(rcv_cookie);
643
644         return err;
645 }
646
647 static int nfctype3_check_presence(uint32_t adapter_idx,
648                                 uint32_t target_idx, near_tag_io_cb cb)
649 {
650         struct type3_cmd cmd;
651         struct t3_cookie *cookie;
652         int err;
653
654         DBG("");
655
656         /* CMD POLL */
657         cmd.cmd  = CMD_POLL;    /* POLL command */
658         cmd.data[0] = 0x12;     /* System code (NFC SC) */
659         cmd.data[1] = 0xFC;
660         cmd.data[2] = 01;       /* request code */
661         cmd.data[3] = 0x00;     /* time slot */
662
663         /* data len + 2 bytes */
664         cmd.len = LEN_CMD + LEN_CMD_LEN + 4 ;
665
666         cookie = g_try_malloc0(sizeof(struct t3_cookie));
667         if (cookie == NULL)
668                 return -ENOMEM;
669
670         cookie->adapter_idx = adapter_idx;
671         cookie->target_idx = target_idx;
672         cookie->cb = cb;
673
674         err = near_adapter_send(adapter_idx, (uint8_t *)&cmd,
675                         cmd.len , nfctype3_check_recv_UID, cookie);
676         if (err < 0)
677                 goto out;
678
679         return 0;
680
681 out:
682         t3_cookie_release(cookie);
683
684         return err;
685 }
686
687 static struct near_tag_driver type1_driver = {
688         .type           = NFC_PROTO_FELICA,
689         .priority       = NEAR_TAG_PRIORITY_DEFAULT,
690         .read_tag       = nfctype3_read_tag,
691         .add_ndef       = nfctype3_write_tag,
692         .check_presence = nfctype3_check_presence,
693 };
694
695 static int nfctype3_init(void)
696 {
697         DBG("");
698
699         return near_tag_driver_register(&type1_driver);
700 }
701
702 static void nfctype3_exit(void)
703 {
704         DBG("");
705
706         near_tag_driver_unregister(&type1_driver);
707 }
708
709 NEAR_PLUGIN_DEFINE(nfctype3, "NFC Forum Type 3 tags support", VERSION,
710                         NEAR_PLUGIN_PRIORITY_HIGH, nfctype3_init, nfctype3_exit)
711