adapter: Bypass the target layer
[platform/upstream/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/target.h>
39 #include <near/tag.h>
40 #include <near/ndef.h>
41 #include <near/tlv.h>
42
43 extern int mifare_read_tag(uint32_t adapter_idx, uint32_t target_idx,
44                 near_tag_io_cb cb, enum near_tag_sub_type tgt_subtype);
45
46 #define CMD_READ         0x30
47 #define CMD_WRITE        0xA2
48
49 #define READ_SIZE  16
50 #define BLOCK_SIZE 4
51
52 #define META_BLOCK_START 0
53 #define DATA_BLOCK_START 4
54 #define TYPE2_MAGIC 0xe1
55
56 #define TAG_DATA_CC(data) ((data) + 12)
57 #define TAG_DATA_LENGTH(cc) ((cc)[2] * 8)
58 #define TAG_DATA_NFC(cc) ((cc)[0] & TYPE2_MAGIC)
59
60 #define TYPE2_NOWRITE_ACCESS    0x0F
61 #define TAG_T2_WRITE_FLAG(cc) ((cc)[3] & TYPE2_NOWRITE_ACCESS)
62
63 #define NDEF_MAX_SIZE   0x30
64
65 struct type2_cmd {
66         uint8_t cmd;
67         uint8_t block;
68         uint8_t data[BLOCK_SIZE];
69 } __attribute__((packed));
70
71 struct type2_tag {
72         uint32_t adapter_idx;
73         uint16_t current_block;
74
75         near_tag_io_cb cb;
76         struct near_tag *tag;
77 };
78
79 struct t2_cookie {
80         uint32_t adapter_idx;
81         uint32_t target_idx;
82         uint8_t current_block;
83         struct near_ndef_message *ndef;
84         near_tag_io_cb cb;
85 };
86
87 static void t2_cookie_release(struct t2_cookie *cookie)
88 {
89         if (cookie == NULL)
90                 return;
91
92         if (cookie->ndef)
93                 g_free(cookie->ndef->data);
94
95         g_free(cookie->ndef);
96         g_free(cookie);
97         cookie = NULL;
98 }
99
100 static int data_recv(uint8_t *resp, int length, void *data)
101 {
102         struct type2_tag *tag = data;
103         struct type2_cmd cmd;
104         uint8_t *nfc_data;
105         uint16_t current_length, length_read, data_length;
106         uint32_t adapter_idx;
107         int read_blocks;
108
109         DBG("%d", length);
110
111         if (length < 0) {
112                 g_free(tag);
113
114                 return  length;
115         }
116
117         nfc_data = near_tag_get_data(tag->tag, (size_t *)&data_length);
118         adapter_idx = near_tag_get_adapter_idx(tag->tag);
119
120         length_read = length - NFC_HEADER_SIZE;
121         current_length = tag->current_block * BLOCK_SIZE;
122         if (current_length + length - NFC_HEADER_SIZE > data_length)
123                 length_read = data_length - current_length;
124
125         memcpy(nfc_data + current_length, resp + NFC_HEADER_SIZE, length_read);
126
127         if (current_length + length_read == data_length) {
128                 /* TODO parse tag->data for NDEFS, and notify target.c */
129                 tag->current_block = 0;
130
131                 DBG("Done reading");
132
133                 near_tlv_parse(tag->tag, tag->cb);
134
135                 g_free(tag);
136
137                 return 0;
138         }
139
140         read_blocks = length / BLOCK_SIZE;
141         tag->current_block += read_blocks;
142
143         cmd.cmd = CMD_READ;
144         cmd.block = DATA_BLOCK_START + tag->current_block;
145
146         DBG("adapter %d", adapter_idx);
147
148         return near_adapter_send(adapter_idx,
149                                 (uint8_t *)&cmd, sizeof(cmd),
150                                         data_recv, tag);
151 }
152
153 static int data_read(struct type2_tag *tag)
154 {
155         struct type2_cmd cmd;
156         uint32_t adapter_idx;
157
158         DBG("");
159
160         tag->current_block = 0;
161
162         cmd.cmd = CMD_READ;
163         cmd.block = DATA_BLOCK_START;
164
165         adapter_idx = near_tag_get_adapter_idx(tag->tag);
166
167         return near_adapter_send(adapter_idx,
168                                 (uint8_t *)&cmd, sizeof(cmd),
169                                         data_recv, tag);
170 }
171
172 static int meta_recv(uint8_t *resp, int length, void *data)
173 {
174         struct t2_cookie *cookie = data;
175         struct near_tag *tag;
176         struct type2_tag *t2_tag;
177         uint8_t *cc;
178         int err;
179
180         DBG("%d", length);
181
182         if (length < 0) {
183                 err = length;
184                 goto out;
185         }
186
187         if (resp[0] != 0) {
188                 err = -EIO;
189                 goto out;
190         }
191
192         cc = TAG_DATA_CC(resp + NFC_HEADER_SIZE);
193
194         if (TAG_DATA_NFC(cc) == 0) {
195                 err = -EINVAL;
196                 goto out;
197         }
198
199         err = near_tag_add_data(cookie->adapter_idx, cookie->target_idx,
200                                         NULL, TAG_DATA_LENGTH(cc));
201         if (err < 0)
202                 goto out;
203
204         tag = near_tag_get_tag(cookie->adapter_idx, cookie->target_idx);
205         if (tag == NULL) {
206                 err = -ENOMEM;
207                 goto out;
208         }
209
210         t2_tag = g_try_malloc0(sizeof(struct type2_tag));
211         if (t2_tag == NULL) {
212                 err = -ENOMEM;
213                 goto out;
214         }
215
216         t2_tag->adapter_idx = cookie->adapter_idx;
217         t2_tag->cb = cookie->cb;
218         t2_tag->tag = tag;
219
220         /* Set the ReadWrite flag */
221         if (TAG_T2_WRITE_FLAG(cc) == TYPE2_NOWRITE_ACCESS)
222                 near_tag_set_ro(tag, TRUE);
223         else
224                 near_tag_set_ro(tag, FALSE);
225
226         near_tag_set_memory_layout(tag, NEAR_TAG_MEMORY_STATIC);
227
228         err = data_read(t2_tag);
229         if (err < 0)
230                 goto out;
231
232         t2_cookie_release(cookie);
233
234         return 0;
235
236 out:
237         if (err < 0 && cookie->cb)
238                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
239
240         t2_cookie_release(cookie);
241
242         return err;
243 }
244
245 static int nfctype2_read_meta(uint32_t adapter_idx, uint32_t target_idx,
246                                                         near_tag_io_cb cb)
247 {
248         struct type2_cmd cmd;
249         struct t2_cookie *cookie;
250         
251         DBG("");
252
253         cmd.cmd = CMD_READ;
254         cmd.block = META_BLOCK_START;
255
256         cookie = g_try_malloc0(sizeof(struct t2_cookie));
257         cookie->adapter_idx = adapter_idx;
258         cookie->target_idx = target_idx;
259         cookie->cb = cb;
260
261         return near_adapter_send(adapter_idx, (uint8_t *)&cmd, sizeof(cmd),
262                                                         meta_recv, cookie);
263 }
264
265 static int nfctype2_read_tag(uint32_t adapter_idx,
266                                 uint32_t target_idx, near_tag_io_cb cb)
267 {
268         int err;
269         enum near_tag_sub_type tgt_subtype;
270
271         DBG("");
272
273         tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx);
274
275         switch (tgt_subtype) {
276         case NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT:
277                 err = nfctype2_read_meta(adapter_idx, target_idx, cb);
278                 break;
279
280         /* Specific Mifare read access */
281         case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_1K:
282         case NEAR_TAG_NFC_T2_MIFARE_CLASSIC_4K:
283                 err= mifare_read_tag( adapter_idx, target_idx,
284                         cb, tgt_subtype);
285                 break;
286
287         default:
288                 DBG("Unknown TAG Type 2 subtype (%d)", tgt_subtype);
289                 err = -1;
290                 break;
291         }
292
293         return err;
294 }
295
296 static int data_write_resp(uint8_t *resp, int length, void *data)
297 {
298         int err;
299         struct t2_cookie *cookie = data;
300         struct type2_cmd cmd;
301
302         DBG("");
303
304         if (length < 0 || resp[0] != 0) {
305                 err = -EIO;
306                 goto out;
307         }
308
309         if (cookie->ndef->offset > cookie->ndef->length) {
310                 DBG("Done writing");
311
312                 if (cookie->cb)
313                         cookie->cb(cookie->adapter_idx, cookie->target_idx, 0);
314
315                 t2_cookie_release(cookie);
316
317                 return 0;
318         }
319
320         cmd.cmd = CMD_WRITE;
321         cmd.block = cookie->current_block;
322         cookie->current_block++;
323
324         if ((cookie->ndef->offset + BLOCK_SIZE) <
325                         cookie->ndef->length) {
326                 memcpy(cmd.data, cookie->ndef->data +
327                                         cookie->ndef->offset, BLOCK_SIZE);
328                 cookie->ndef->offset += BLOCK_SIZE;
329         } else {
330                 memcpy(cmd.data, cookie->ndef->data + cookie->ndef->offset,
331                                 cookie->ndef->length - cookie->ndef->offset);
332                 cookie->ndef->offset = cookie->ndef->length + 1;
333         }
334
335         err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
336                                         sizeof(cmd), data_write_resp, cookie);
337
338
339         if (err < 0)
340                 goto out;
341
342         return 0;
343
344 out:
345         if (err < 0 && cookie->cb)
346                 cookie->cb(cookie->adapter_idx, cookie->target_idx, err);
347
348         t2_cookie_release(cookie);
349
350         return err;
351 }
352
353 static int data_write(uint32_t adapter_idx, uint32_t target_idx,
354                                 struct near_ndef_message *ndef,
355                                 near_tag_io_cb cb)
356 {
357         struct type2_cmd cmd;
358         struct t2_cookie *cookie;
359         int err;
360
361         DBG("");
362
363         cookie = g_try_malloc0(sizeof(struct t2_cookie));
364         cookie->adapter_idx = adapter_idx;
365         cookie->target_idx = target_idx;
366         cookie->current_block = DATA_BLOCK_START;
367         cookie->ndef = ndef;
368         cookie->cb = cb;
369
370         cmd.cmd = CMD_WRITE;
371         cmd.block = cookie->current_block;
372         memcpy(cmd.data, cookie->ndef->data, BLOCK_SIZE);
373         cookie->ndef->offset += BLOCK_SIZE;
374         cookie->current_block++;
375
376         err = near_adapter_send(cookie->adapter_idx, (uint8_t *)&cmd,
377                                         sizeof(cmd), data_write_resp, cookie);
378
379         if (err < 0)
380                 goto out;
381
382         return 0;
383
384 out:
385         t2_cookie_release(cookie);
386
387         return err;
388 }
389
390 static int nfctype2_write_tag(uint32_t adapter_idx, uint32_t target_idx,
391                                 struct near_ndef_message *ndef,
392                                 near_tag_io_cb cb)
393 {
394         struct near_tag *tag;
395         enum near_tag_sub_type tgt_subtype;
396
397         DBG("");
398
399         if (ndef == NULL || cb == NULL)
400                 return -EINVAL;
401
402         tag = near_tag_get_tag(adapter_idx, target_idx);
403         if (tag == NULL)
404                 return -EINVAL;
405
406         if (near_tag_get_ro(tag) == TRUE) {
407                 DBG("tag is read-only");
408                 return -EPERM;
409         }
410
411         tgt_subtype = near_tag_get_subtype(adapter_idx, target_idx);
412
413         if (tgt_subtype != NEAR_TAG_NFC_T2_MIFARE_ULTRALIGHT) {
414                 DBG("Unknown Tag Type 2 subtype (%d)", tgt_subtype);
415                 return -1;
416         }
417
418         /* This check is valid for only static tags.
419          * Max data length on Type 2 Tag including TLV's is NDEF_MAX_SIZE */
420         if (near_tag_get_memory_layout(tag) == NEAR_TAG_MEMORY_STATIC) {
421                 if ((ndef->length + 3) > NDEF_MAX_SIZE) {
422                         near_error("not enough space on tag");
423                         return -ENOSPC;
424                 }
425         }
426
427         return data_write(adapter_idx, target_idx, ndef, cb);
428 }
429
430 static int check_presence(uint8_t *resp, int length, void *data)
431 {
432         struct t2_cookie *cookie = data;
433         int err = 0;
434
435         DBG("%d", length);
436
437         if (length < 0)
438                 err = -EIO;
439
440         if (cookie->cb)
441                 cookie->cb(cookie->adapter_idx,
442                                 cookie->target_idx, err);
443
444         t2_cookie_release(cookie);
445
446         return err;
447 }
448
449 static int nfctype2_check_presence(uint32_t adapter_idx, uint32_t target_idx,
450                                                         near_tag_io_cb cb)
451 {
452         struct type2_cmd cmd;
453         struct t2_cookie *cookie;
454         int err;
455
456         DBG("");
457
458         cmd.cmd = CMD_READ;
459         cmd.block = META_BLOCK_START;
460
461         cookie = g_try_malloc0(sizeof(struct t2_cookie));
462         if (cookie == NULL)
463                 return -ENOMEM;
464
465         cookie->adapter_idx = adapter_idx;
466         cookie->target_idx = target_idx;
467         cookie->cb = cb;
468
469         err = near_adapter_send(adapter_idx, (uint8_t *)&cmd, sizeof(cmd),
470                                                         check_presence, cookie);
471         if (err < 0)
472                 goto out;
473
474         return 0;
475
476 out:
477         t2_cookie_release(cookie);
478
479         return err;
480 }
481
482 static struct near_tag_driver type2_driver = {
483         .type           = NFC_PROTO_MIFARE,
484         .priority       = NEAR_TAG_PRIORITY_DEFAULT,
485         .read_tag       = nfctype2_read_tag,
486         .add_ndef       = nfctype2_write_tag,
487         .check_presence = nfctype2_check_presence,
488 };
489
490 static int nfctype2_init(void)
491 {
492         DBG("");
493
494         return near_tag_driver_register(&type2_driver);
495 }
496
497 static void nfctype2_exit(void)
498 {
499         DBG("");
500
501         near_tag_driver_unregister(&type2_driver);
502 }
503
504 NEAR_PLUGIN_DEFINE(nfctype2, "NFC Forum Type 2 tags support", VERSION,
505                         NEAR_PLUGIN_PRIORITY_HIGH, nfctype2_init, nfctype2_exit)
506