adapter: Bypass the target layer
[platform/upstream/neard.git] / plugins / nfctype1.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_READ_ALL            0x00    /* Read seg 0 (incl: HR) */
44 #define CMD_READ_SEGS           0x10    /* Read 16 blocks (128 bytes) */
45
46 #define CMD_WRITE_E             0x53    /* Write with erase */
47 #define CMD_WRITE_NE            0x1A    /* Write no erase */
48
49 #define OFFSET_STATUS_CMD       0x00
50 #define OFFSET_HEADER_ROM       0x01
51
52 #define HR0_TYPE1_STATIC        0x11
53 #define HR0_TYPE2_HIGH          0x10
54 #define HR0_TYPE2_LOW           0x0F
55
56 #define BLOCK_SIZE              8
57 #define LEN_STATUS_BYTE         0x01    /* Status byte */
58 #define LEN_SPEC_BYTES          (LEN_STATUS_BYTE + 0x02)        /* HRx */
59 #define LEN_UID_BYTES           (LEN_STATUS_BYTE + 0x07)        /* UID bytes */
60 #define LEN_CC_BYTES            0x04    /* Capab. container */
61 #define LEN_DYN_BYTES           0x0A    /* Bytes CtrlIT and TLV - Dyn. only */
62
63 #define TYPE1_MAGIC 0xe1
64
65 #define TAG_T1_DATA_CC(data) ((data) + LEN_SPEC_BYTES + LEN_UID_BYTES)
66 #define TAG_T1_DATA_LENGTH(cc) ((cc[2] + 1) * 8 - LEN_CC_BYTES)
67
68 #define TAG_T1_DATA_NFC(cc) ((cc)[0] & TYPE1_MAGIC)
69
70 #define TYPE1_NOWRITE_ACCESS    0x0F
71 #define TAG_T1_WRITE_FLAG(cc) ((cc)[3] & TYPE1_NOWRITE_ACCESS)
72 #define TAG_T1_SEGMENT_SIZE     128
73
74 #define TYPE1_STATIC_MAX_DATA_SIZE      0x60
75
76 struct type1_cmd {
77         uint8_t cmd;
78         uint8_t addr;
79         uint8_t data[1];
80 } __attribute__((packed));
81
82 struct type1_tag {
83         uint32_t adapter_idx;
84         uint16_t current_block;
85         uint16_t current_seg;
86         uint16_t last_seg;
87         uint16_t data_read;
88
89         near_tag_io_cb cb;
90         struct near_tag *tag;
91 };
92
93 struct t1_cookie {
94         uint32_t adapter_idx;
95         uint32_t target_idx;
96         uint32_t current_block; /* Static tag */
97         uint32_t current_byte;  /* Static tag */
98         struct near_ndef_message *ndef;
99         near_tag_io_cb cb;
100 };
101
102 static void t1_cookie_release(struct t1_cookie *cookie)
103 {
104         if (cookie == NULL)
105                 return;
106
107         if (cookie->ndef)
108                 g_free(cookie->ndef->data);
109
110         g_free(cookie->ndef);
111         g_free(cookie);
112         cookie = NULL;
113 }
114
115 /* Read segments (128 bytes)and store them to the tag data block */
116 static int segment_read_recv(uint8_t *resp, int length, void *data)
117 {
118         struct type1_tag *t1_tag = data;
119         struct type1_cmd t1_cmd;
120         uint8_t *tagdata;
121         size_t data_length;
122
123         int err;
124
125         DBG("%d", length);
126
127         if (length < 0) {
128                 err = length;
129                 goto out_err;
130         }
131
132         length = length - LEN_STATUS_BYTE;  /* ignore first byte */
133
134         /* Add data to tag mem*/
135         tagdata = near_tag_get_data(t1_tag->tag, &data_length);
136         memcpy(tagdata + t1_tag->data_read, resp+1, length);
137
138         /* Next segment */
139         t1_tag->data_read =  t1_tag->data_read + length;
140         t1_tag->current_seg = t1_tag->current_seg + 1;
141
142         if (t1_tag->current_seg <= t1_tag->last_seg) {
143                 /* RSEG cmd */
144                 t1_cmd.cmd = CMD_READ_SEGS;
145                 t1_cmd.addr = (t1_tag->current_seg << 4) & 0xFF;
146
147                 err = near_adapter_send(t1_tag->adapter_idx,
148                                 (uint8_t *)&t1_cmd, sizeof(t1_cmd),
149                                 segment_read_recv, t1_tag);
150                 if (err < 0)
151                         goto out_err;
152         } else { /* This is the end */
153                 DBG("READ complete");
154
155                 err = near_tlv_parse(t1_tag->tag, t1_tag->cb);
156
157                 /* free memory */
158                 g_free(t1_tag);
159         }
160
161 out_err:
162         return err;
163 }
164
165 /* The dynamic read function:
166  * Bytes [0..3] : CC
167  * [4..8]: TLV Lock ControlIT (0x01, 0x03, v1, V2, V3)
168  * [9..13]: TLV Reserved Memory Control (0x02, 0x03, V1, V2, V3)
169  * [14..]: TLV NDEF (0x03, L0, L1, L2, V1,V2 ...)
170  */
171 static int read_dynamic_tag(uint8_t *cc, int length, void *data)
172 {
173         struct type1_tag *t1_tag = data;
174         struct type1_cmd t1_cmd;
175
176         uint8_t *tagdata;
177         uint8_t *pndef;
178         size_t data_length;
179
180         DBG("Dynamic Mode");
181
182         tagdata = near_tag_get_data(t1_tag->tag, &data_length);
183
184         /* Skip un-needed bytes */
185         pndef = cc + 4;         /* right after CC bytes */
186         pndef = pndef + 5;      /* skip TLV Lock bits bytes */
187         pndef = pndef + 5;      /* skip TLV ControlIT bytes */
188
189         /* Save first NFC bytes to tag memory
190          * 10 blocks[0x3..0xC] of 8 bytes + 2 bytes from block 2
191          * */
192         memcpy(tagdata, pndef, 10 * BLOCK_SIZE + 2);
193
194         /* Read the next one, up to the end of the data area */
195         t1_tag->current_seg = 1;
196         t1_tag->last_seg = ((cc[2] * BLOCK_SIZE) / TAG_T1_SEGMENT_SIZE);
197         t1_tag->data_read = 10 * BLOCK_SIZE + 2;
198
199         /* T1 read segment */
200         t1_cmd.cmd = CMD_READ_SEGS;
201         /* 5.3.3 ADDS operand is [b8..b5] */
202         t1_cmd.addr = (t1_tag->current_seg << 4) & 0xFF;
203
204         return near_adapter_send(t1_tag->adapter_idx,
205                         (uint8_t *)&t1_cmd, sizeof(t1_cmd),
206                         segment_read_recv, t1_tag);
207 }
208
209 static int meta_recv(uint8_t *resp, int length, void *data)
210 {
211         struct t1_cookie *cookie = data;
212         struct near_tag *tag;
213         struct type1_tag *t1_tag = NULL;
214
215         uint8_t *cc;
216         int err = -EOPNOTSUPP;
217
218         DBG("%d", length);
219
220         if (length < 0) {
221                 err = length;
222                 goto out_err;
223         }
224
225         /* First byte is cmd status */
226         if (resp[OFFSET_STATUS_CMD] != 0) {
227                 DBG("Command failed: 0x%x",resp[OFFSET_STATUS_CMD]);
228                 err = -EIO;
229                 goto out_err;
230         }
231
232         /* Check Magic NFC tag */
233         cc = TAG_T1_DATA_CC(resp);
234         if (TAG_T1_DATA_NFC(cc) == 0) {
235                 DBG("Not a valid NFC magic tag: 0x%x",cc[0]);
236                 err = -EINVAL;
237                 goto out_err;
238         }
239
240         /* Add data to the tag */
241         err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx,
242                                         NULL, TAG_T1_DATA_LENGTH(cc));
243         if (err < 0)
244                 goto out_err;
245
246         tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
247         if (tag == NULL) {
248                 err = -ENOMEM;
249                 goto out_err;
250         }
251
252         t1_tag = g_try_malloc0(sizeof(struct type1_tag));
253         if (t1_tag == NULL) {
254                 err = -ENOMEM;
255                 goto out_err;
256         }
257
258         DBG("2");
259
260         t1_tag->adapter_idx = cookie->adapter_idx;
261         t1_tag->cb = cookie->cb;
262         t1_tag->tag = tag;
263
264         /*s Set the ReadWrite flag */
265         if (TAG_T1_WRITE_FLAG(cc) == TYPE1_NOWRITE_ACCESS)
266                 near_tag_set_ro(tag, TRUE);
267         else
268                 near_tag_set_ro(tag, FALSE);
269
270         /* Check Static or Dynamic memory model */
271         if (resp[OFFSET_HEADER_ROM] == HR0_TYPE1_STATIC) {
272                 uint8_t *tagdata;
273                 size_t data_length;
274
275                 DBG("READ Static complete");
276
277                 tagdata = near_tag_get_data(t1_tag->tag, &data_length);
278                 memcpy(tagdata, cc + LEN_CC_BYTES, TAG_T1_DATA_LENGTH(cc));
279
280                 near_tag_set_memory_layout(tag, NEAR_TAG_MEMORY_STATIC);
281
282                 err = near_tlv_parse(t1_tag->tag, t1_tag->cb);
283                 if (err < 0)
284                         goto out_err;
285
286                 g_free(t1_tag);
287
288                 return 0;
289         } else if ((resp[OFFSET_HEADER_ROM] & 0xF0) == HR0_TYPE2_HIGH) {
290                 near_tag_set_memory_layout(tag, NEAR_TAG_MEMORY_DYNAMIC);
291                 err = read_dynamic_tag(cc, length, t1_tag);
292         } else {
293                 err = -EOPNOTSUPP ;
294         }
295
296 out_err:
297         DBG("err %d", err);
298
299         if (err < 0 && cookie->cb)
300                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
301
302         t1_cookie_release(cookie);
303
304
305
306         return err;
307 }
308
309 /* First step: READALL to read a maximum of 124 bytes
310  * This cmd is common to static and dynamic targets
311  * This should allow to get the HR0 byte
312  */
313 static int nfctype1_read_tag(uint32_t adapter_idx,
314                                 uint32_t target_idx, near_tag_io_cb cb)
315 {
316         struct type1_cmd t1_cmd;
317         struct t1_cookie *cookie;
318
319         DBG("");
320
321         t1_cmd.cmd = CMD_READ_ALL;     /* Read ALL cmd give 124 bytes */
322         t1_cmd.addr = 0;               /* NA */
323
324         cookie = g_try_malloc0(sizeof(struct t1_cookie));
325         cookie->adapter_idx = adapter_idx;
326         cookie->target_idx = target_idx;
327         cookie->cb = cb;
328
329         return near_adapter_send(adapter_idx, (uint8_t *)&t1_cmd, sizeof(t1_cmd),
330                                                         meta_recv, cookie);
331
332 }
333
334 static int write_nmn_e1_resp(uint8_t *resp, int length, void *data)
335 {
336         int err = 0;
337         struct t1_cookie *cookie = data;
338
339         DBG("");
340
341         if (length < 0)
342                 err = length;
343
344         if (resp[OFFSET_STATUS_CMD] != 0)
345                 err = -EIO;
346
347         DBG("Done writing");
348
349         cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
350
351         t1_cookie_release(cookie);
352
353         return err;
354 }
355
356 static int write_nmn_e1(struct t1_cookie *cookie)
357 {
358         struct type1_cmd cmd;
359
360         DBG("");
361
362         cmd.cmd = CMD_WRITE_E;
363         cmd.addr = 0x08;
364         cmd.data[0] = TYPE1_MAGIC;
365
366         return near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
367                                         sizeof(cmd), write_nmn_e1_resp, cookie);
368 }
369
370 static int data_write(uint8_t *resp, int length, void *data)
371 {
372         struct t1_cookie *cookie = data;
373         uint8_t addr = 0;
374         struct type1_cmd cmd;
375         int err;
376
377         DBG("");
378
379         if (length < 0) {
380                 err = length;
381                 goto out;
382         }
383
384         if (resp[OFFSET_STATUS_CMD] != 0) {
385                 err = -EIO;
386                 goto out;
387         }
388
389         if (cookie->ndef->offset > cookie->ndef->length)
390                 return write_nmn_e1(cookie);
391
392         if (cookie->current_byte >= BLOCK_SIZE) {
393                 cookie->current_byte = 0;
394                 cookie->current_block++;
395         }
396
397         cmd.cmd = CMD_WRITE_E;
398         addr = cookie->current_block << 3;
399         cmd.addr = addr | (cookie->current_byte & 0x7);
400         cmd.data[0] = cookie->ndef->data[cookie->ndef->offset];
401         cookie->ndef->offset++;
402         cookie->current_byte++;
403
404         err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
405                                         sizeof(cmd), data_write, cookie);
406         if (err < 0)
407                 goto out;
408
409         return 0;
410
411 out:
412         if (err < 0 && cookie->cb)
413                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
414
415         t1_cookie_release(cookie);
416
417         return err;
418 }
419
420 static int write_nmn_0(uint32_t adapter_idx, uint32_t target_idx,
421                         struct near_ndef_message *ndef, near_tag_io_cb cb)
422 {
423         int err;
424         struct type1_cmd cmd;
425         struct t1_cookie *cookie;
426
427         DBG("");
428
429         cmd.cmd  = CMD_WRITE_E;
430         cmd.addr = 0x08;
431         cmd.data[0] = 0x00;
432
433         cookie = g_try_malloc0(sizeof(struct t1_cookie));
434         if (cookie == NULL) {
435                 err = -ENOMEM;
436                 return err;
437         }
438
439         cookie->adapter_idx = adapter_idx;
440         cookie->target_idx = target_idx;
441         cookie->current_block = 1;
442         cookie->current_byte = LEN_CC_BYTES;
443         cookie->ndef = ndef;
444         cookie->cb = cb;
445
446         err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
447                                         sizeof(cmd), data_write, cookie);
448         if (err < 0)
449                 goto out;
450
451         return 0;
452
453 out:
454         t1_cookie_release(cookie);
455
456         return err;
457 }
458
459 /*
460  * The writing of a new NDEF message SHALL occur as follows:
461  * Write NMN = 00h to indicate that no valid NDEF message is present
462  * during writing to allow error detection in the event that the tag
463  * is removed from the field prior to completion of operation.
464  * Write VNo and RWA if required
465  * Write NDEF Message TLV
466  * Write NDEF Message data
467  * Write NMN = E1h as the last byte to be written
468  */
469 static int nfctype1_write_tag(uint32_t adapter_idx, uint32_t target_idx,
470                                 struct near_ndef_message *ndef,
471                                 near_tag_io_cb cb)
472 {
473         struct near_tag *tag;
474
475         DBG("");
476
477         if (ndef == NULL || cb == NULL)
478                 return -EINVAL;
479
480         tag = near_tag_get_tag(adapter_idx, target_idx);
481         if (tag == NULL)
482                 return -EINVAL;
483
484         if (near_tag_get_ro(tag) == TRUE) {
485                 DBG("tag is read-only");
486                 return -EPERM;
487         }
488
489         /* This check is valid for only static tags.
490          * Max data length on Type 2 Tag including TLV's
491          * is TYPE1_STATIC_MAX_DATA_SIZE */
492         if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) {
493                 if ((ndef->length + 3) > TYPE1_STATIC_MAX_DATA_SIZE) {
494                         near_error("not enough space on data");
495                         return -ENOMEM;
496                 }
497         }
498
499         return write_nmn_0(adapter_idx, target_idx, ndef, cb);
500 }
501
502 static int check_presence(uint8_t *resp, int length, void *data)
503 {
504         struct t1_cookie *cookie = data;
505         int err = 0;
506
507         DBG("%d", length);
508
509         if (length < 0)
510                 err = -EIO;
511
512         if (cookie->cb)
513                 cookie->cb(cookie->adapter_idx,
514                                 cookie->target_idx, err);
515
516         t1_cookie_release(cookie);
517
518         return err;
519 }
520
521 static int nfctype1_check_presence(uint32_t adapter_idx,
522                                 uint32_t target_idx, near_tag_io_cb cb)
523 {
524         struct type1_cmd t1_cmd;
525         struct t1_cookie *cookie;
526         int err;
527
528         DBG("");
529
530         t1_cmd.cmd = CMD_READ_ALL;     /* Read ALL cmd give 124 bytes */
531         t1_cmd.addr = 0;               /* NA */
532
533         cookie = g_try_malloc0(sizeof(struct t1_cookie));
534         if (cookie == NULL)
535                 return -ENOMEM;
536
537         cookie->adapter_idx = adapter_idx;
538         cookie->target_idx = target_idx;
539         cookie->cb = cb;
540
541         err = near_adapter_send(adapter_idx, (uint8_t *)&t1_cmd, sizeof(t1_cmd),
542                                                         check_presence, cookie);
543         if (err < 0)
544                 goto out;
545
546         return 0;
547
548 out:
549         t1_cookie_release(cookie);
550
551         return err;
552 }
553
554 static struct near_tag_driver type1_driver = {
555         .type           = NFC_PROTO_JEWEL,
556         .priority       = NEAR_TAG_PRIORITY_DEFAULT,
557         .read_tag       = nfctype1_read_tag,
558         .add_ndef       = nfctype1_write_tag,
559         .check_presence = nfctype1_check_presence,
560 };
561
562 static int nfctype1_init(void)
563 {
564         DBG("");
565
566         return near_tag_driver_register(&type1_driver);
567 }
568
569 static void nfctype1_exit(void)
570 {
571         DBG("");
572
573         near_tag_driver_unregister(&type1_driver);
574 }
575
576 NEAR_PLUGIN_DEFINE(nfctype1, "NFC Forum Type 1 tags support", VERSION,
577                         NEAR_PLUGIN_PRIORITY_HIGH, nfctype1_init, nfctype1_exit)