ndef: Rename near_ndef_prepare_hs_message
[platform/upstream/neard.git] / src / ndef.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 <stdio.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30
31 #include <glib.h>
32
33 #include <gdbus.h>
34
35 #include "near.h"
36
37 enum record_tnf {
38         RECORD_TNF_EMPTY     = 0x00,
39         RECORD_TNF_WELLKNOWN = 0x01,
40         RECORD_TNF_MIME      = 0x02,
41         RECORD_TNF_URI       = 0x03,
42         RECORD_TNF_EXTERNAL  = 0x04,
43         RECORD_TNF_UNKNOWN   = 0x05,
44         RECORD_TNF_UNCHANGED = 0x06,
45 };
46
47 #define RECORD_ACTION_DO   0x00
48 #define RECORD_ACTION_SAVE 0x01
49 #define RECORD_ACTION_EDIT 0x02
50
51 #define RECORD_MB_BIT(val)  ((val & 0x80) >> 7)
52 #define RECORD_ME_BIT(val)  ((val & 0x40) >> 6)
53 #define RECORD_CF_BIT(val)  ((val & 0x20) >> 5)
54 #define RECORD_SR_BIT(val)  ((val & 0x10) >> 4)
55 #define RECORD_IL_BIT(val)  ((val & 0x8)  >> 3)
56 #define RECORD_TNF_BIT(val) (val & 0x7)
57
58 #define NDEF_MSG_MIN_LENGTH 0x03
59 #define NDEF_PAYLOAD_LENGTH_OFFSET 0x02
60
61 #define RECORD_MB    0x80
62 #define RECORD_ME    0x40
63 #define RECORD_CF    0x20
64 #define RECORD_SR    0x10
65 #define RECORD_IL    0x08
66 #define RECORD_TNF_EMPTY_SET(val)     ((val & ~0x7) | RECORD_TNF_EMPTY)
67 #define RECORD_TNF_WKT_SET(val)       ((val & ~0x7) | RECORD_TNF_WELLKNOWN)
68 #define RECORD_TNF_MIME_SET(val)      ((val & ~0x7) | RECORD_TNF_MIME)
69 #define RECORD_TNF_URI_SET(val)       ((val & ~0x7) | RECORD_TNF_URI)
70 #define RECORD_TNF_EXTERNAL_SET(val)  ((val & ~0x7) | RECORD_TNF_EXTERNAL)
71 #define RECORD_TNF_UKNOWN_SET(val)    ((val & ~0x7) | RECORD_TNF_UNKNOWN)
72 #define RECORD_TNF_UNCHANGED_SET(val) ((val & ~0x7) | RECORD_TNF_UNCHANGED)
73
74 #define NDEF_MSG_SHORT_RECORD_MAX_LENGTH 0xFF
75 #define NDEF_TEXT_RECORD_TYPE_NAME_HEX_VALUE 0x54
76 #define NDEF_TEXT_RECORD_UTF16_STATUS 0x80
77
78 #define AC_CPS_MASK 0x03
79
80 enum record_type {
81         RECORD_TYPE_WKT_SMART_POSTER          =   0x01,
82         RECORD_TYPE_WKT_URI                   =   0x02,
83         RECORD_TYPE_WKT_TEXT                  =   0x03,
84         RECORD_TYPE_WKT_SIZE                  =   0x04,
85         RECORD_TYPE_WKT_TYPE                  =   0x05,
86         RECORD_TYPE_WKT_ACTION                =   0x06,
87         RECORD_TYPE_WKT_HANDOVER_REQUEST      =   0x07,
88         RECORD_TYPE_WKT_HANDOVER_SELECT       =   0x08,
89         RECORD_TYPE_WKT_HANDOVER_CARRIER      =   0x09,
90         RECORD_TYPE_WKT_ALTERNATIVE_CARRIER   =   0x0a,
91         RECORD_TYPE_WKT_COLLISION_RESOLUTION  =   0x0b,
92         RECORD_TYPE_WKT_ERROR                 =   0x0c,
93         RECORD_TYPE_MIME_TYPE                 =   0x0d,
94         RECORD_TYPE_UNKNOWN                   =   0xfe,
95         RECORD_TYPE_ERROR                     =   0xff
96 };
97
98 #define RECORD_TYPE_WKT "urn:nfc:wkt:"
99 #define RECORD_TYPE_EXTERNAL "urn:nfc:ext:"
100
101 struct near_ndef_record_header {
102         uint8_t mb;
103         uint8_t me;
104         uint8_t cf;
105         uint8_t sr;
106         uint8_t il;
107         uint8_t tnf;
108         uint8_t il_length;
109         uint8_t *il_field;
110         uint32_t payload_len;
111         uint32_t offset;
112         uint8_t type_len;
113         enum record_type rec_type;
114         char *type_name;
115         uint32_t header_len;
116 };
117
118 struct near_ndef_text_payload {
119         char *encoding;
120         char *language_code;
121         char *data;
122 };
123
124 struct near_ndef_uri_payload {
125         uint8_t identifier;
126
127         uint32_t  field_length;
128         uint8_t  *field;
129 };
130
131 struct near_ndef_sp_payload {
132         struct near_ndef_uri_payload *uri;
133
134         uint8_t number_of_title_records;
135         struct near_ndef_text_payload **title_records;
136
137         uint32_t size; /* from Size record*/
138         char *type;    /* from Type record*/
139         char *action;
140         /* TODO add icon and other records fields*/
141 };
142
143 struct near_ndef_mime_payload {
144         char *type;
145
146         struct {
147                 enum handover_carrier carrier_type;
148                 uint16_t properties;    /* e.g.: NO_PAIRING_KEY */
149         } handover;
150 };
151
152 /* Handover record definitions */
153
154 /* alternative record (AC) */
155 #define AC_RECORD_PAYLOAD_LEN   4
156
157 struct near_ndef_ac_payload {
158         enum carrier_power_state cps;   /* carrier power state */
159
160         uint8_t cdr_len;        /* carrier data reference length: 0x01 */
161         uint8_t cdr;            /* carrier data reference */
162         uint8_t adata_refcount; /* auxiliary data reference count */
163
164         /* !: if adata_refcount == 0, then there's no data reference */
165         uint16_t **adata;       /* auxiliary data reference */
166 };
167
168 /*
169  * carrier data (see cdr in near_ndef_ac_payload )
170  * These settings can be retrieved from mime, carrier records, etc...
171  */
172 struct near_ndef_carrier_data {
173         uint8_t cdr;            /* carrier data reference */
174         uint8_t *data;
175         size_t data_len;
176 };
177
178 /* Default Handover version */
179 #define HANDOVER_VERSION        0x12
180 #define HANDOVER_MAJOR(version) (((version) >> 4) & 0xf)
181 #define HANDOVER_MINOR(version) ((version) & 0xf)
182
183
184 /* General Handover Request/Select record */
185 struct near_ndef_ho_payload {
186         uint8_t version;                /* version id */
187         uint16_t collision_record;      /* collision record */
188
189         uint8_t number_of_ac_payloads;  /* At least 1 ac is needed */
190         struct near_ndef_ac_payload **ac_payloads;
191
192         /* Optional records */
193         uint16_t *err_record;   /* not NULL if present */
194
195         uint8_t number_of_cfg_payloads; /* extra NDEF records */
196         struct near_ndef_mime_payload **cfg_payloads;
197 };
198
199 struct near_ndef_record {
200         char *path;
201
202         struct near_ndef_record_header *header;
203
204         /* specific payloads */
205         struct near_ndef_text_payload *text;
206         struct near_ndef_uri_payload  *uri;
207         struct near_ndef_sp_payload   *sp;
208         struct near_ndef_mime_payload *mime;
209         struct near_ndef_ho_payload   *ho;      /* handover payload */
210
211         char *type;
212
213         uint8_t *data;
214         size_t data_len;
215 };
216
217 static DBusConnection *connection = NULL;
218
219 static inline void fillb8(uint8_t *ptr, uint32_t len)
220 {
221         (*(uint8_t *)(ptr)) = ((uint8_t)(len));
222 }
223
224 static inline void fillb16(uint8_t *ptr, uint32_t len)
225 {
226         fillb8((ptr), (uint16_t)(len) >> 8);
227         fillb8((uint8_t *)(ptr) + 1, len);
228 }
229
230 static inline void fillb32(uint8_t *ptr, uint32_t len)
231 {
232         fillb16((ptr), (uint32_t)(len) >> 16);
233         fillb16((uint8_t *)(ptr) + 2, (uint32_t)(len));
234 }
235
236 char *__near_ndef_record_get_path(struct near_ndef_record *record)
237 {
238         return record->path;
239 }
240
241 char *__near_ndef_record_get_type(struct near_ndef_record *record)
242 {
243         return record->type;
244 }
245
246 uint8_t *__near_ndef_record_get_data(struct near_ndef_record *record,
247                                                                 size_t *len)
248 {
249         *len = record->data_len;
250
251         return record->data;
252 }
253
254 void __near_ndef_append_records(DBusMessageIter *iter, GList *records)
255 {
256         GList *list;
257
258         DBG("");
259
260         for (list = records; list; list = list->next) {
261                 struct near_ndef_record *record = list->data;
262                 uint8_t *data;
263                 size_t data_len;
264
265                 data = __near_ndef_record_get_data(record, &data_len);
266                 if (data == NULL)
267                         continue;
268
269                 dbus_message_iter_append_fixed_array(iter, DBUS_TYPE_BYTE,
270                                                         &data, data_len);
271         }
272 }
273
274 static void append_text_payload(struct near_ndef_text_payload *text,
275                                         DBusMessageIter *dict)
276 {
277         DBG("");
278
279         if (text == NULL || dict == NULL)
280                 return;
281
282         if (text->encoding != NULL)
283                 near_dbus_dict_append_basic(dict, "Encoding",
284                                                 DBUS_TYPE_STRING,
285                                                 &(text->encoding));
286
287         if (text->language_code != NULL)
288                 near_dbus_dict_append_basic(dict, "Language",
289                                                 DBUS_TYPE_STRING,
290                                                 &(text->language_code));
291
292         if (text->data != NULL)
293                 near_dbus_dict_append_basic(dict, "Representation",
294                                                 DBUS_TYPE_STRING,
295                                                 &(text->data));
296 }
297
298 static const char *uri_prefixes[NFC_MAX_URI_ID + 1] = {
299         "",
300         "http://www.",
301         "https://www.",
302         "http://",
303         "https://",
304         "tel:",
305         "mailto:",
306         "ftp://anonymous:anonymous@",
307         "ftp://ftp.",
308         "ftps://",
309         "sftp://",
310         "smb://",
311         "nfs://",
312         "ftp://",
313         "dav://",
314         "news:",
315         "telnet://",
316         "imap:",
317         "rstp://",
318         "urn:",
319         "pop:",
320         "sip:",
321         "sips:",
322         "tftp:",
323         "btspp://",
324         "btl2cap://",
325         "btgoep://",
326         "tcpobex://",
327         "irdaobex://",
328         "file://",
329         "urn:epc:id:",
330         "urn:epc:tag:",
331         "urn:epc:pat:",
332         "urn:epc:raw:",
333         "urn:epc:",
334         "urn:nfc:",
335 };
336
337 const char *__near_ndef_get_uri_prefix(uint8_t id)
338 {
339         if (id > NFC_MAX_URI_ID)
340                 return NULL;
341
342         return uri_prefixes[id];
343 }
344
345 static void append_uri_payload(struct near_ndef_uri_payload *uri,
346                                         DBusMessageIter *dict)
347 {
348         char *value;
349         const char *prefix = NULL;
350
351         DBG("");
352
353         if (uri == NULL || dict == NULL)
354                 return;
355
356         if (uri->identifier > NFC_MAX_URI_ID) {
357                 near_error("Invalid URI identifier 0x%x", uri->identifier);
358                 return;
359         }
360
361         prefix = uri_prefixes[uri->identifier];
362
363         DBG("URI prefix %s", prefix);
364
365         value = g_strdup_printf("%s%.*s", prefix, uri->field_length,
366                                                          uri->field);
367
368         near_dbus_dict_append_basic(dict, "URI", DBUS_TYPE_STRING, &value);
369
370         g_free(value);
371 }
372
373 static void append_sp_payload(struct near_ndef_sp_payload *sp,
374                                                 DBusMessageIter *dict)
375 {
376         uint8_t i;
377
378         DBG("");
379
380         if (sp == NULL || dict == NULL)
381                 return;
382
383         if (sp->action != NULL)
384                 near_dbus_dict_append_basic(dict, "Action", DBUS_TYPE_STRING,
385                                                         &(sp->action));
386
387         if (sp->uri != NULL)
388                 append_uri_payload(sp->uri, dict);
389
390         if (sp->title_records != NULL &&
391                         sp->number_of_title_records > 0) {
392                 for (i = 0; i < sp->number_of_title_records; i++)
393                         append_text_payload(sp->title_records[i], dict);
394         }
395
396         if (sp->type != NULL)
397                 near_dbus_dict_append_basic(dict, "MIMEType", DBUS_TYPE_STRING,
398                                                                 &(sp->type));
399
400         if (sp->size > 0)
401                 near_dbus_dict_append_basic(dict, "Size", DBUS_TYPE_UINT32,
402                                                         &(sp->size));
403 }
404
405 static void append_mime_payload(struct near_ndef_mime_payload *mime,
406                                         DBusMessageIter *dict)
407 {
408         DBG("");
409
410         if (mime == NULL || dict == NULL)
411                 return;
412
413         if (mime->type != NULL)
414                 near_dbus_dict_append_basic(dict, "MIME",
415                                                 DBUS_TYPE_STRING,
416                                                 &(mime->type));
417 }
418
419 static void append_record(struct near_ndef_record *record,
420                                         DBusMessageIter *dict)
421 {
422         char *type;
423
424         DBG("");
425
426         if (record == NULL || dict == NULL)
427                 return;
428
429         switch (record->header->rec_type) {
430         case RECORD_TYPE_WKT_SIZE:
431         case RECORD_TYPE_WKT_TYPE:
432         case RECORD_TYPE_WKT_ACTION:
433         case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
434         case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
435         case RECORD_TYPE_WKT_ERROR:
436         case RECORD_TYPE_UNKNOWN:
437         case RECORD_TYPE_ERROR:
438                 break;
439
440         case RECORD_TYPE_WKT_TEXT:
441                 type = "Text";
442                 near_dbus_dict_append_basic(dict, "Type",
443                                         DBUS_TYPE_STRING, &type);
444                 append_text_payload(record->text, dict);
445                 break;
446
447         case RECORD_TYPE_WKT_URI:
448                 type = "URI";
449                 near_dbus_dict_append_basic(dict, "Type",
450                                         DBUS_TYPE_STRING, &type);
451                 append_uri_payload(record->uri, dict);
452                 break;
453
454         case RECORD_TYPE_WKT_SMART_POSTER:
455                 type = "SmartPoster";
456                 near_dbus_dict_append_basic(dict, "Type",
457                                         DBUS_TYPE_STRING, &type);
458                 append_sp_payload(record->sp, dict);
459                 break;
460
461         case RECORD_TYPE_WKT_HANDOVER_REQUEST:
462                 type = "HandoverRequest";
463                 near_dbus_dict_append_basic(dict, "Type",
464                                         DBUS_TYPE_STRING, &type);
465                 break;
466
467         case RECORD_TYPE_WKT_HANDOVER_SELECT:
468                 type = "HandoverSelect";
469                 near_dbus_dict_append_basic(dict, "Type",
470                                         DBUS_TYPE_STRING, &type);
471                 break;
472
473         case RECORD_TYPE_WKT_HANDOVER_CARRIER:
474                 type = "HandoverCarrier";
475                 near_dbus_dict_append_basic(dict, "Type",
476                                         DBUS_TYPE_STRING, &type);
477                 break;
478
479         case RECORD_TYPE_MIME_TYPE:
480                 type = "MIME Type (RFC 2046)";
481                 near_dbus_dict_append_basic(dict, "Type",
482                                         DBUS_TYPE_STRING, &type);
483                 append_mime_payload(record->mime, dict);
484                 break;
485         }
486 }
487
488 static DBusMessage *get_properties(DBusConnection *conn,
489                                         DBusMessage *msg, void *data)
490 {
491         struct near_ndef_record *record = data;
492         DBusMessage *reply;
493         DBusMessageIter array, dict;
494
495         DBG("conn %p", conn);
496
497         if (conn == NULL || msg == NULL ||
498                 data == NULL)
499                 return NULL;
500
501         reply = dbus_message_new_method_return(msg);
502         if (reply == NULL)
503                 return NULL;
504
505         dbus_message_iter_init_append(reply, &array);
506
507         near_dbus_dict_open(&array, &dict);
508
509         append_record(record, &dict);
510
511         near_dbus_dict_close(&array, &dict);
512
513         return reply;
514 }
515
516 static const GDBusMethodTable record_methods[] = {
517         { GDBUS_METHOD("GetProperties",
518                                 NULL, GDBUS_ARGS({"properties", "a{sv}"}),
519                                 get_properties) },
520         { },
521 };
522
523 static void free_text_payload(struct near_ndef_text_payload *text)
524 {
525         if (text == NULL)
526                 return;
527
528         g_free(text->encoding);
529         g_free(text->language_code);
530         g_free(text->data);
531         g_free(text);
532 }
533
534 static void free_uri_payload(struct near_ndef_uri_payload *uri)
535 {
536         if (uri == NULL)
537                 return;
538
539         g_free(uri->field);
540         g_free(uri);
541 }
542
543 static void free_sp_payload(struct near_ndef_sp_payload *sp)
544 {
545         uint8_t i;
546
547         if (sp == NULL)
548                 return;
549
550         free_uri_payload(sp->uri);
551
552         if (sp->title_records != NULL) {
553                 for (i = 0; i < sp->number_of_title_records; i++)
554                         free_text_payload(sp->title_records[i]);
555         }
556
557         g_free(sp->title_records);
558         g_free(sp->type);
559         g_free(sp->action);
560         g_free(sp);
561 }
562
563 static void free_mime_payload(struct near_ndef_mime_payload *mime)
564 {
565         if (mime == NULL)
566                 return;
567
568         g_free(mime->type);
569         g_free(mime);
570 }
571
572 static void free_ac_payload(struct near_ndef_ac_payload *ac)
573 {
574         if (ac == NULL)
575                 return;
576
577         g_free(ac->adata);
578         g_free(ac);
579 }
580
581 static void free_ho_payload(struct near_ndef_ho_payload *ho)
582 {
583         int i;
584
585         if (ho == NULL)
586                 return;
587
588         if (ho->ac_payloads != NULL) {
589                 for (i = 0; i < ho->number_of_ac_payloads; i++)
590                         free_ac_payload(ho->ac_payloads[i]);
591         }
592
593         g_free(ho->ac_payloads);
594         g_free(ho);
595 }
596
597 static void free_ndef_record(struct near_ndef_record *record)
598 {
599         if (record == NULL)
600                 return;
601
602         g_free(record->path);
603
604         if (record->header != NULL) {
605
606                 switch (record->header->rec_type) {
607                 case RECORD_TYPE_WKT_SIZE:
608                 case RECORD_TYPE_WKT_TYPE:
609                 case RECORD_TYPE_WKT_ACTION:
610                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
611                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
612                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
613                 case RECORD_TYPE_WKT_ERROR:
614                 case RECORD_TYPE_UNKNOWN:
615                 case RECORD_TYPE_ERROR:
616                         break;
617
618                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
619                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
620                         free_ho_payload(record->ho);
621                         break;
622
623                 case RECORD_TYPE_WKT_TEXT:
624                         free_text_payload(record->text);
625                         break;
626
627                 case RECORD_TYPE_WKT_URI:
628                         free_uri_payload(record->uri);
629                         break;
630
631                 case RECORD_TYPE_WKT_SMART_POSTER:
632                         free_sp_payload(record->sp);
633                         break;
634
635                 case RECORD_TYPE_MIME_TYPE:
636                         free_mime_payload(record->mime);
637                 }
638
639                 g_free(record->header->il_field);
640                 g_free(record->header->type_name);
641         }
642
643         g_free(record->header);
644         g_free(record->type);
645         g_free(record->data);
646         g_free(record);
647 }
648
649 static void free_ndef_message(struct near_ndef_message *msg)
650 {
651         if (msg == NULL)
652                 return;
653
654         g_free(msg->data);
655         g_free(msg);
656 }
657
658 void __near_ndef_record_free(struct near_ndef_record *record)
659 {
660         g_dbus_unregister_interface(connection, record->path,
661                                                 NFC_RECORD_INTERFACE);
662
663         free_ndef_record(record);
664 }
665
666 static char *action_to_string(uint8_t action)
667 {
668         switch (action) {
669         case RECORD_ACTION_DO:
670                 return "Do";
671         case RECORD_ACTION_SAVE:
672                 return "Save";
673         case RECORD_ACTION_EDIT:
674                 return "Edit";
675         default:
676                 near_error("Unknown action 0x%x", action);
677                 return NULL;
678         }
679 }
680
681 static enum record_type get_external_record_type(uint8_t *type,
682                                                 size_t type_length)
683 {
684         DBG("");
685
686         if (strncmp((char *) type, BT_MIME_STRING_2_0,
687                                         sizeof(BT_MIME_STRING_2_0) - 1) == 0)
688                 return RECORD_TYPE_MIME_TYPE;
689         else
690                 return RECORD_TYPE_UNKNOWN;
691 }
692
693 static enum record_type get_record_type(enum record_tnf tnf,
694                                 uint8_t *type, size_t type_length)
695 {
696         DBG("");
697
698         switch (tnf) {
699         case RECORD_TNF_EMPTY:
700         case RECORD_TNF_URI:
701         case RECORD_TNF_UNKNOWN:
702         case RECORD_TNF_UNCHANGED:
703                 break;
704
705         case RECORD_TNF_WELLKNOWN:
706                 if (type_length == 1) {
707                         if (type[0] == 'T')
708                                 return RECORD_TYPE_WKT_TEXT;
709                         else if (type[0] == 'U')
710                                 return RECORD_TYPE_WKT_URI;
711                         else if (type[0] == 's')
712                                 return RECORD_TYPE_WKT_SIZE;
713                         else if (type[0] == 't')
714                                 return RECORD_TYPE_WKT_TYPE;
715                         else
716                                 return RECORD_TYPE_UNKNOWN;
717
718                 } else if (type_length == 2) {
719                         if (strncmp((char *)type, "Sp", 2) == 0)
720                                 return RECORD_TYPE_WKT_SMART_POSTER;
721                         else if (strncmp((char *) type, "Hr", 2) == 0)
722                                 return RECORD_TYPE_WKT_HANDOVER_REQUEST;
723                         else if (strncmp((char *) type, "Hs", 2) == 0)
724                                 return RECORD_TYPE_WKT_HANDOVER_SELECT;
725                         else if (strncmp((char *) type, "Hc", 2) == 0)
726                                 return RECORD_TYPE_WKT_HANDOVER_CARRIER;
727                         else if (strncmp((char *) type, "ac", 2) == 0)
728                                 return RECORD_TYPE_WKT_ALTERNATIVE_CARRIER;
729                         else if (strncmp((char *) type, "cr", 2) == 0)
730                                 return RECORD_TYPE_WKT_COLLISION_RESOLUTION;
731                         else
732                                 return RECORD_TYPE_UNKNOWN;
733
734                 } else if (type_length == 3) {
735                         if (strncmp((char *)type, "act", 3) == 0)
736                                 return RECORD_TYPE_WKT_ACTION;
737                         else if (strncmp((char *)type, "err", 3) == 0)
738                                 return RECORD_TYPE_WKT_ERROR;
739                         else
740                                 return RECORD_TYPE_UNKNOWN;
741
742                 }
743
744         case RECORD_TNF_MIME:
745                 return RECORD_TYPE_MIME_TYPE;
746
747         case RECORD_TNF_EXTERNAL:
748                 return get_external_record_type(type, type_length);
749
750         }
751
752         return RECORD_TYPE_UNKNOWN;
753 }
754
755 static int build_record_type_string(struct near_ndef_record *rec)
756 {
757         uint8_t tnf;
758
759         DBG("");
760
761         if (rec == NULL || rec->header == NULL)
762                 return -EINVAL;
763
764         tnf = rec->header->tnf;
765
766         if (rec->header->rec_type == RECORD_TYPE_WKT_SMART_POSTER) {
767                 rec->type = g_strdup_printf(RECORD_TYPE_WKT "U");
768                 return 0;
769         }
770
771         switch (tnf) {
772         case RECORD_TNF_EMPTY:
773         case RECORD_TNF_UNKNOWN:
774         case RECORD_TNF_UNCHANGED:
775                 return -EINVAL;
776
777         case RECORD_TNF_URI:
778         case RECORD_TNF_MIME:
779                 rec->type = g_strndup(rec->header->type_name,
780                                       rec->header->type_len);
781                 break;
782
783         case RECORD_TNF_WELLKNOWN:
784                 rec->type = g_strdup_printf(RECORD_TYPE_WKT "%s",
785                                       rec->header->type_name);
786                 break;
787
788         case RECORD_TNF_EXTERNAL:
789                 rec->type = g_strdup_printf(RECORD_TYPE_EXTERNAL "%s",
790                                       rec->header->type_name);
791                 break;
792         }
793
794         return 0;
795 }
796
797 static uint8_t validate_record_begin_and_end_bits(uint8_t *msg_mb,
798                                         uint8_t *msg_me, uint8_t rec_mb,
799                                         uint8_t rec_me)
800 {
801         DBG("");
802
803         if (msg_mb == NULL || msg_me == NULL)
804                 return 0;
805
806         /* Validating record header begin and end bits
807          * eg: Single record: [mb:1,me:1]
808          *     Two records:   [mb:1,me:0 - mb:0,me:1]
809          *     Three or more records [mb:1,me:0 - mb:0,me:0 .. mb:0,me:1]
810          **/
811
812         if (rec_mb == 1) {
813                 if (*msg_mb != 1)
814                         *msg_mb = rec_mb;
815                 else
816                         return -EINVAL;
817
818         }
819
820         if (rec_me == 1) {
821                 if (*msg_me != 1) {
822                         if (*msg_mb == 1)
823                                 *msg_me = rec_me;
824                         else
825                                 return -EINVAL;
826
827                 } else
828                         return -EINVAL;
829
830         }
831
832         return 0;
833 }
834
835 /*
836  * Parse the ndef record header and cache the begin, end, chunkflag,
837  * short-record and type-name-format bits. ID length and field, record
838  * type, payload length and offset (where payload byte starts in input
839  * parameter). Validate offset for every step forward against total
840  * available length.
841  */
842 static struct near_ndef_record_header *parse_record_header(uint8_t *rec,
843                                         uint32_t offset, uint32_t length)
844 {
845         struct near_ndef_record_header *rec_header = NULL;
846         uint8_t *type = NULL;
847         uint32_t header_len = 0;
848
849         DBG("length %d", length);
850
851         if (rec == NULL || offset >= length)
852                 return NULL;
853
854         /* This check is for empty record. */
855         if ((length - offset) < NDEF_MSG_MIN_LENGTH)
856                 return NULL;
857
858         rec_header = g_try_malloc0(sizeof(struct near_ndef_record_header));
859         if (rec_header == NULL)
860                 return NULL;
861
862         rec_header->mb = RECORD_MB_BIT(rec[offset]);
863         rec_header->me = RECORD_ME_BIT(rec[offset]);
864         rec_header->sr = RECORD_SR_BIT(rec[offset]);
865         rec_header->il = RECORD_IL_BIT(rec[offset]);
866         rec_header->tnf = RECORD_TNF_BIT(rec[offset]);
867
868         DBG("mb %d me %d sr %d il %d tnf %d",
869                 rec_header->mb, rec_header->me, rec_header->sr,
870                 rec_header->il, rec_header->tnf);
871
872         offset++;
873         rec_header->type_len = rec[offset++];
874         header_len = 2; /* type length + header bits */
875
876         if (rec_header->sr == 1) {
877                 rec_header->payload_len = rec[offset++];
878                 header_len++;
879         } else {
880                 rec_header->payload_len = near_get_be32(rec + offset);
881                 offset += 4;
882                 header_len += 4;
883
884                 if ((offset + rec_header->payload_len) > length)
885                         goto fail;
886         }
887
888         DBG("payload length %d", rec_header->payload_len);
889
890         if (rec_header->il == 1) {
891                 rec_header->il_length = rec[offset++];
892                 header_len++;
893
894                 if ((offset + rec_header->payload_len) > length)
895                         goto fail;
896         }
897
898         if (rec_header->type_len > 0) {
899                 if ((offset + rec_header->type_len) > length)
900                         goto fail;
901
902                 type = g_try_malloc0(rec_header->type_len);
903                 if (type == NULL)
904                         goto fail;
905
906                 memcpy(type, rec + offset, rec_header->type_len);
907                 offset += rec_header->type_len;
908                 header_len += rec_header->type_len;
909
910                 if ((offset + rec_header->payload_len) > length)
911                         goto fail;
912         }
913
914         if (rec_header->il_length > 0) {
915                 if ((offset + rec_header->il_length) > length)
916                         goto fail;
917
918                 rec_header->il_field = g_try_malloc0(rec_header->il_length);
919                 if (rec_header->il_field == NULL)
920                         goto fail;
921
922                 memcpy(rec_header->il_field, rec + offset,
923                                         rec_header->il_length);
924                 offset += rec_header->il_length;
925                 header_len += rec_header->il_length;
926
927                 if ((offset + rec_header->payload_len) > length)
928                         goto fail;
929         }
930
931         rec_header->rec_type = get_record_type(rec_header->tnf, type,
932                                                         rec_header->type_len);
933         rec_header->offset = offset;
934         rec_header->header_len = header_len;
935         rec_header->type_name = g_strndup((char *) type, rec_header->type_len);
936
937         g_free(type);
938
939         return rec_header;
940
941 fail:
942         near_error("parsing record header failed");
943
944         g_free(type);
945         g_free(rec_header->il_field);
946         g_free(rec_header->type_name);
947         g_free(rec_header);
948
949         return NULL;
950 }
951
952 static struct near_ndef_text_payload *
953 parse_text_payload(uint8_t *payload, uint32_t length)
954 {
955         struct near_ndef_text_payload *text_payload = NULL;
956         uint8_t status, lang_length;
957         uint32_t offset;
958
959         DBG("");
960
961         if (payload == NULL)
962                 return NULL;
963
964         offset = 0;
965         text_payload = g_try_malloc0(sizeof(struct near_ndef_text_payload));
966         if (text_payload == NULL)
967                 return NULL;
968
969         /* 0x80 is used to get 7th bit value (0th bit is LSB) */
970         status = ((payload[offset] & 0x80) >> 7);
971
972         text_payload->encoding = (status == 0) ?
973                                         g_strdup("UTF-8") : g_strdup("UTF-16");
974
975         /* 0x3F is used to get 5th-0th bits value (0th bit is LSB) */
976         lang_length = (payload[offset] & 0x3F);
977         offset++;
978
979         if (lang_length > 0) {
980                 if ((offset + lang_length) >= length)
981                         goto fail;
982
983                 text_payload->language_code = g_strndup(
984                                                 (char *)(payload + offset),
985                                                 lang_length);
986         } else {
987                 text_payload->language_code = NULL;
988         }
989
990         offset += lang_length;
991
992         if ((length - lang_length - 1) > 0) {
993                 text_payload->data = g_strndup((char *)(payload + offset),
994                                         length - lang_length - 1);
995         } else {
996                 text_payload->data = NULL;
997         }
998
999         if (offset >= length)
1000                 goto fail;
1001
1002         DBG("Encoding  '%s'", text_payload->encoding);
1003         DBG("Language Code  '%s'", text_payload->language_code);
1004         DBG("Data  '%s'", text_payload->data);
1005
1006         return text_payload;
1007
1008 fail:
1009         near_error("text payload parsing failed");
1010         free_text_payload(text_payload);
1011
1012         return NULL;
1013 }
1014
1015 static struct near_ndef_uri_payload *
1016 parse_uri_payload(uint8_t *payload, uint32_t length)
1017 {
1018         struct near_ndef_uri_payload *uri_payload = NULL;
1019         uint32_t index, offset;
1020
1021         DBG("");
1022
1023         if (payload == NULL)
1024                 return NULL;
1025
1026         offset = 0;
1027         uri_payload = g_try_malloc0(sizeof(struct near_ndef_uri_payload));
1028         if (uri_payload == NULL)
1029                 return NULL;
1030
1031         uri_payload->identifier = payload[offset];
1032         offset++;
1033
1034         uri_payload->field_length = length - 1;
1035
1036         if (uri_payload->field_length > 0) {
1037                 uri_payload->field = g_try_malloc0(uri_payload->field_length);
1038                 if (uri_payload->field == NULL)
1039                         goto fail;
1040
1041                 memcpy(uri_payload->field, payload + offset,
1042                                 uri_payload->field_length);
1043
1044                 for (index = 0; index < uri_payload->field_length; index++) {
1045                         /* URI Record Type Definition 1.0 [3.2.3]
1046                          * Any character value within the URI between
1047                          * (and including) 0 and 31 SHALL be recorded as
1048                          * an error, and the URI record to be discarded */
1049                         if (uri_payload->field[index] <= 31)
1050                                 goto fail;
1051                 }
1052
1053         }
1054
1055         DBG("Identifier  '0X%X'", uri_payload->identifier);
1056         DBG("Field  '%.*s'", uri_payload->field_length, uri_payload->field);
1057
1058         return uri_payload;
1059
1060 fail:
1061         near_error("uri payload parsing failed");
1062         free_uri_payload(uri_payload);
1063
1064         return NULL;
1065 }
1066
1067 /*
1068  * Validate titles records language code in Smartposter.
1069  * There must not be two or more records with the same language identifier.
1070  */
1071 static int8_t validate_language_code_in_sp_record(GSList *titles)
1072 {
1073         uint8_t i, j, length;
1074         struct near_ndef_text_payload *title1, *title2;
1075
1076         DBG("");
1077
1078         if (titles == NULL)
1079                 return -EINVAL;
1080
1081         length = g_slist_length(titles);
1082
1083         for (i = 0; i < length; i++) {
1084                 title1 = g_slist_nth_data(titles, i);
1085
1086                 for (j = i + 1; j < length; j++) {
1087                         title2 = g_slist_nth_data(titles, j);
1088
1089                         if ((title1->language_code == NULL) &&
1090                                         (title2->language_code == NULL))
1091                                 continue;
1092
1093                         if (g_strcmp0(title1->language_code,
1094                                         title2->language_code) == 0)
1095                                 return -EINVAL;
1096                 }
1097         }
1098
1099         return 0;
1100 }
1101
1102 static struct near_ndef_sp_payload *
1103 parse_sp_payload(uint8_t *payload, uint32_t length)
1104 {
1105         struct near_ndef_sp_payload *sp_payload = NULL;
1106         struct near_ndef_record_header *rec_header = NULL;
1107         uint8_t mb = 0, me = 0, i;
1108         uint32_t offset;
1109         GSList *titles = NULL, *temp;
1110
1111         DBG("");
1112
1113         if (payload == NULL)
1114                 return NULL;
1115
1116         offset = 0;
1117         sp_payload = g_try_malloc0(sizeof(struct near_ndef_sp_payload));
1118         if (sp_payload == NULL)
1119                 return NULL;
1120
1121         while (offset < length) {
1122
1123                 DBG("Record header : 0x%x", payload[offset]);
1124
1125                 rec_header = parse_record_header(payload, offset, length);
1126                 if (rec_header == NULL)
1127                         goto fail;
1128
1129                 if (validate_record_begin_and_end_bits(&mb, &me,
1130                                         rec_header->mb, rec_header->me) != 0) {
1131                         DBG("validate mb me failed");
1132                         goto fail;
1133                 }
1134
1135                 offset = rec_header->offset;
1136
1137                 switch (rec_header->rec_type) {
1138                 case RECORD_TYPE_WKT_SMART_POSTER:
1139                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
1140                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
1141                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
1142                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
1143                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
1144                 case RECORD_TYPE_MIME_TYPE:
1145                 case RECORD_TYPE_WKT_ERROR:
1146                 case RECORD_TYPE_UNKNOWN:
1147                 case RECORD_TYPE_ERROR:
1148                         break;
1149
1150                 case RECORD_TYPE_WKT_URI:
1151                         /* URI record should be only one. */
1152                         if (sp_payload->uri != NULL)
1153                                 goto fail;
1154
1155                         sp_payload->uri = parse_uri_payload(payload + offset,
1156                                                 rec_header->payload_len);
1157                         if (sp_payload->uri == NULL)
1158                                 goto fail;
1159
1160                         break;
1161
1162                 case RECORD_TYPE_WKT_TEXT:
1163                         /*
1164                          * Title records can zero or more. First fill the
1165                          * records in list and validate language identifier
1166                          * and then cache them into sp record structure.
1167                          */
1168                         {
1169                         struct near_ndef_text_payload *title;
1170                         title = parse_text_payload(payload + offset,
1171                                                 rec_header->payload_len);
1172                         if (title == NULL)
1173                                 goto fail;
1174
1175                         titles = g_slist_append(titles, title);
1176                         }
1177                         break;
1178
1179                 case RECORD_TYPE_WKT_SIZE:
1180                         /*
1181                          * If payload length is not exactly 4 bytes
1182                          * then record is wrong.
1183                          */
1184                         if (rec_header->payload_len != 4)
1185                                 goto fail;
1186
1187                         sp_payload->size = near_get_be32(payload + offset);
1188                         break;
1189
1190                 case RECORD_TYPE_WKT_TYPE:
1191
1192                         if (rec_header->payload_len > 0) {
1193                                 sp_payload->type = g_try_malloc0(
1194                                                 rec_header->payload_len);
1195                                 if (sp_payload->type == NULL)
1196                                         goto fail;
1197
1198                                 sp_payload->type = g_strndup(
1199                                                 (char *) payload + offset,
1200                                                 rec_header->payload_len);
1201                         }
1202
1203                         break;
1204
1205                 case RECORD_TYPE_WKT_ACTION:
1206                         /*
1207                          * If the action record exists, payload should be
1208                          * single byte, otherwise consider it as error.
1209                          */
1210                         if (rec_header->payload_len != 1)
1211                                 goto fail;
1212
1213                         sp_payload->action =
1214                                 g_strdup(action_to_string(payload[offset]));
1215
1216                         break;
1217                 }
1218
1219                 offset += rec_header->payload_len;
1220                 g_free(rec_header->il_field);
1221                 g_free(rec_header->type_name);
1222                 g_free(rec_header);
1223                 rec_header = NULL;
1224         }
1225
1226         /*
1227          * Code to fill smart poster record structure from
1228          * 'titles' list.
1229          */
1230         if (titles == NULL)
1231                 return sp_payload;
1232
1233         if (validate_language_code_in_sp_record(titles) != 0) {
1234                 DBG("language code validation failed");
1235                 goto fail;
1236         }
1237
1238         temp = titles;
1239         sp_payload->number_of_title_records = g_slist_length(temp);
1240         sp_payload->title_records = g_try_malloc0(
1241                                 sp_payload->number_of_title_records *
1242                                  sizeof(struct near_ndef_text_payload *));
1243         if (sp_payload->title_records == NULL)
1244                 goto fail;
1245
1246         for (i = 0; i < sp_payload->number_of_title_records; i++) {
1247                 sp_payload->title_records[i] = temp->data;
1248                 temp = temp->next;
1249         }
1250
1251         g_slist_free(titles);
1252         titles = NULL;
1253
1254         return sp_payload;
1255
1256 fail:
1257         near_error("smart poster payload parsing failed");
1258
1259         if (rec_header != NULL) {
1260                 g_free(rec_header->type_name);
1261                 g_free(rec_header->il_field);
1262                 g_free(rec_header);
1263         }
1264
1265         free_sp_payload(sp_payload);
1266         g_slist_free(titles);
1267
1268         return NULL;
1269 }
1270
1271 static void correct_eir_len(struct carrier_data *data)
1272 {
1273         /*
1274          * Android 4.1 BUG - OOB EIR length should be in LE, but is in BE.
1275          * Fortunately payload length is 1 byte so this can be detected and
1276          * corrected before sending it to handover agent.
1277          */
1278         if (data->data[0] == 0) {
1279                 DBG("EIR length in BE");
1280                 data->data[0] = data->data[1];
1281                 data->data[1] = 0;
1282         }
1283
1284         /*
1285          * Some Nokia BH-505 report total OOB block length without length field
1286          * size.
1287          */
1288         if (data->data[0] == data->size - 2) {
1289                 DBG("EIR length without length field size");
1290                 data->data[0] += 2;
1291         }
1292 }
1293
1294 static int process_mime_type(struct near_ndef_mime_payload *mime,
1295                                         struct carrier_data *c_data)
1296 {
1297         int err = -EINVAL;
1298
1299         DBG("");
1300
1301         if (mime == NULL || c_data == NULL)
1302                 return -EINVAL;
1303
1304         switch (mime->handover.carrier_type) {
1305         case NEAR_CARRIER_BLUETOOTH:
1306                 err = __near_agent_handover_push_data(HO_AGENT_BT, c_data);
1307                 if (err == -ESRCH)
1308                         err = __near_bluetooth_parse_oob_record(c_data,
1309                                         &mime->handover.properties, TRUE);
1310                 break;
1311
1312         case NEAR_CARRIER_WIFI:
1313                 err = __near_agent_handover_push_data(HO_AGENT_WIFI, c_data);
1314                 break;
1315
1316         case NEAR_CARRIER_EMPTY:
1317         case NEAR_CARRIER_UNKNOWN:
1318                 break;
1319         }
1320
1321         return err;
1322 }
1323
1324 static struct near_ndef_mime_payload *parse_mime_type(
1325                         struct near_ndef_record *record, uint8_t *ndef_data,
1326                         size_t ndef_length, size_t offset,
1327                         uint32_t payload_length, struct carrier_data **c_data)
1328 {
1329         struct near_ndef_mime_payload *mime;
1330         struct carrier_data *c_temp;
1331
1332         DBG("");
1333
1334         if (c_data == NULL || ndef_data == NULL ||
1335                         ((offset + payload_length) > ndef_length))
1336                 return NULL;
1337
1338         mime = g_try_malloc0(sizeof(struct near_ndef_mime_payload));
1339         if (mime == NULL)
1340                 return NULL;
1341
1342         c_temp = g_try_malloc0(sizeof(struct carrier_data));
1343         if (c_temp == NULL) {
1344                 g_free(mime);
1345                 return NULL;
1346         }
1347
1348         mime->type = g_strdup(record->header->type_name);
1349
1350         DBG("MIME Type '%s'", mime->type);
1351         if (strcmp(mime->type, BT_MIME_STRING_2_1) == 0) {
1352                 mime->handover.carrier_type = NEAR_CARRIER_BLUETOOTH;
1353                 c_temp->type = BT_MIME_V2_1;
1354                 c_temp->size = record->header->payload_len;
1355                 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1356                 correct_eir_len(c_temp);
1357         } else if (strcmp(mime->type, BT_MIME_STRING_2_0) == 0) {
1358                 mime->handover.carrier_type = NEAR_CARRIER_BLUETOOTH;
1359                 c_temp->type = BT_MIME_V2_0;
1360                 c_temp->size = record->header->payload_len;
1361                 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1362         } else if (strcmp(mime->type, WIFI_WSC_MIME_STRING) == 0) {
1363                 mime->handover.carrier_type = NEAR_CARRIER_WIFI;
1364                 c_temp->type = WIFI_WSC_MIME;
1365                 c_temp->size = record->header->payload_len;
1366                 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1367         } else {
1368                 g_free(c_temp);
1369                 c_temp = NULL;
1370                 *c_data = NULL;
1371                 return mime;
1372         }
1373
1374         *c_data = c_temp;
1375
1376         return mime;
1377 }
1378
1379 /* Set the MB bit in message header */
1380 static uint8_t near_ndef_set_mb(uint8_t *hdr, near_bool_t first_rec)
1381 {
1382         /* Reset bits 0x40 */
1383         *hdr &= (0xFF & (~RECORD_MB));
1384
1385         /* Set if needed */
1386         if (first_rec == TRUE)
1387                 *hdr |= RECORD_MB;
1388
1389         return *hdr;
1390 }
1391
1392 /* Set the MB/ME bit in message header */
1393 static uint8_t near_ndef_set_me(uint8_t *hdr, near_bool_t last_rec)
1394 {
1395         /* Reset bits 0x80 */
1396         *hdr &= (0xFF & (~RECORD_ME));
1397
1398         /* Set if needed */
1399         if (last_rec == TRUE)
1400                 *hdr |= RECORD_ME;
1401
1402         return *hdr;
1403 }
1404
1405 /* Set the MB/ME bit in message header */
1406 static uint8_t near_ndef_set_mb_me(uint8_t *hdr, near_bool_t first_rec,
1407                                                 near_bool_t last_rec)
1408 {
1409         near_ndef_set_mb(hdr, first_rec);
1410         return near_ndef_set_me(hdr, last_rec);
1411 }
1412
1413 /* Caller should put own payload starting from offset value */
1414 static struct near_ndef_message *ndef_message_alloc_complete(char *type_name,
1415                 uint32_t payload_len,
1416                 char *payload_id,
1417                 uint8_t payload_id_len,
1418                 enum record_tnf tnf,
1419                 near_bool_t first_rec,
1420                 near_bool_t last_rec)
1421 {
1422         struct near_ndef_message *msg;
1423         uint8_t hdr = 0, type_len, sr_bit, il_bit, id_len;
1424
1425         msg = g_try_malloc0(sizeof(struct near_ndef_message));
1426         if (msg == NULL)
1427                 return NULL;
1428
1429         msg->length = 0;
1430         msg->offset = 0;
1431         msg->length++; /* record header*/
1432         msg->length++; /* type name length byte*/
1433
1434         type_len = (type_name != NULL) ? strlen(type_name) : 0;
1435         id_len = (payload_id != NULL) ? payload_id_len : 0;
1436         sr_bit =  (payload_len <= NDEF_MSG_SHORT_RECORD_MAX_LENGTH)
1437                                         ? TRUE : FALSE;
1438
1439         il_bit = (payload_id != NULL) ? TRUE : FALSE;
1440
1441         msg->length += (sr_bit == TRUE) ? 1 : 4;
1442         msg->length += (il_bit == TRUE) ? 1 : 0;
1443         msg->length += type_len;
1444         msg->length += payload_len;
1445         msg->length += id_len;
1446
1447         msg->data = g_try_malloc0(msg->length);
1448         if (msg->data == NULL)
1449                 goto fail;
1450
1451         /* Set MB ME bits */
1452         hdr = near_ndef_set_mb_me(&hdr, first_rec, last_rec);
1453
1454         if (sr_bit == TRUE)
1455                 hdr |= RECORD_SR;
1456
1457         hdr = RECORD_TNF_WKT_SET(hdr);
1458         if (il_bit == TRUE)
1459                 hdr |= RECORD_IL;
1460
1461         switch (tnf) {
1462         case RECORD_TNF_EMPTY:
1463                 hdr = RECORD_TNF_EMPTY_SET(hdr);
1464                 break;
1465
1466         case RECORD_TNF_URI:
1467                 hdr = RECORD_TNF_URI_SET(hdr);
1468                 break;
1469
1470         case RECORD_TNF_EXTERNAL:
1471                 hdr = RECORD_TNF_EXTERNAL_SET(hdr);
1472                 break;
1473         case RECORD_TNF_UNKNOWN:
1474                 hdr = RECORD_TNF_UKNOWN_SET(hdr);
1475                 break;
1476
1477         case RECORD_TNF_UNCHANGED:
1478                 hdr = RECORD_TNF_UNCHANGED_SET(hdr);
1479                 break;
1480
1481         case RECORD_TNF_WELLKNOWN:
1482                 hdr = RECORD_TNF_WKT_SET(hdr);
1483                 break;
1484
1485         case RECORD_TNF_MIME:
1486                 hdr = RECORD_TNF_MIME_SET(hdr);
1487                 break;
1488         }
1489
1490         msg->data[msg->offset++] = hdr;
1491         msg->data[msg->offset++] = type_len;
1492
1493         if (sr_bit == TRUE) {
1494                 msg->data[msg->offset++] = payload_len;
1495         } else {
1496                 fillb32((msg->data + msg->offset), payload_len);
1497                 msg->offset += 4;
1498         }
1499
1500         if (il_bit == TRUE)
1501                 msg->data[msg->offset++] = payload_id_len;
1502
1503         if (type_name != NULL) {
1504                 memcpy(msg->data + msg->offset, type_name, type_len);
1505                 msg->offset += type_len;
1506         }
1507
1508         if (il_bit == TRUE) {
1509                 memcpy(msg->data + msg->offset, payload_id, payload_id_len);
1510                 msg->offset += payload_id_len;
1511         }
1512
1513         return msg;
1514
1515 fail:
1516         near_error("ndef message struct allocation failed");
1517         free_ndef_message(msg);
1518
1519         return NULL;
1520 }
1521
1522 /*
1523  *  This is a wrapper to ndef_message_alloc, as, in most cases,
1524  *  there's no payload id, and MB=TRUE and ME=TRUE. Default type name format
1525  *  is also set to RECORD_TNF_WELLKNOWN
1526  *
1527  */
1528 static struct near_ndef_message *ndef_message_alloc(char *type_name,
1529                                                         uint32_t payload_len)
1530 {
1531         return ndef_message_alloc_complete(type_name, payload_len,
1532                         NULL, 0,
1533                         RECORD_TNF_WELLKNOWN,
1534                         TRUE, TRUE);
1535 }
1536
1537 static enum carrier_power_state get_cps(uint8_t data)
1538 {
1539         /* enum carrier_power_state values match binary format */
1540         return data & AC_CPS_MASK;
1541 }
1542
1543 static struct near_ndef_ac_payload *parse_ac_payload(uint8_t *payload,
1544                                                 uint32_t length)
1545 {
1546         struct near_ndef_ac_payload *ac_payload = NULL;
1547         uint32_t offset;
1548
1549         DBG("");
1550
1551         if (payload == NULL)
1552                 return NULL;
1553
1554         offset = 0;
1555         ac_payload = g_try_malloc0(sizeof(struct near_ndef_ac_payload));
1556         if (ac_payload == NULL)
1557                 goto fail;
1558
1559         /* Carrier flag */
1560         ac_payload->cps = get_cps(payload[offset]);
1561         offset++;
1562
1563         /* Carrier data reference length */
1564         ac_payload->cdr_len = payload[offset];
1565         offset++;
1566
1567         /* Carrier data reference */
1568         ac_payload->cdr = payload[offset];
1569         offset = offset + ac_payload->cdr_len;
1570
1571         /* Auxiliary data reference count */
1572         ac_payload->adata_refcount = payload[offset];
1573         offset++;
1574
1575         if (ac_payload->adata_refcount == 0)
1576                 return ac_payload;
1577
1578         /* save the auxiliary data reference */
1579         ac_payload->adata = g_try_malloc0(
1580                         ac_payload->adata_refcount * sizeof(uint16_t));
1581         if (ac_payload->adata == NULL)
1582                 goto fail;
1583
1584         memcpy(ac_payload->adata, payload + offset,
1585                         ac_payload->adata_refcount * sizeof(uint16_t));
1586
1587         /* and leave */
1588         return ac_payload;
1589
1590 fail:
1591         near_error("ac payload parsing failed");
1592         free_ac_payload(ac_payload);
1593
1594         return NULL;
1595 }
1596
1597 /* carrier power state & carrier reference */
1598 static struct near_ndef_message *near_ndef_prepare_ac_message(uint8_t cps,
1599                                                                 char cdr)
1600 {
1601         struct near_ndef_message *ac_msg;
1602
1603         /* alloc "ac" message minus adata*/
1604         ac_msg = ndef_message_alloc_complete("ac", AC_RECORD_PAYLOAD_LEN,
1605                                         NULL, 0,
1606                                         RECORD_TNF_WELLKNOWN,
1607                                         TRUE, TRUE);
1608         if (ac_msg == NULL)
1609                 return NULL;
1610
1611         /* Prepare ac message */
1612         ac_msg->data[ac_msg->offset++] = cps;
1613         ac_msg->data[ac_msg->offset++] = 1;     /* cdr_len def size */
1614         ac_msg->data[ac_msg->offset++] = cdr;   /* cdr */
1615         ac_msg->data[ac_msg->offset] = 0;       /* adata ref count */
1616
1617         /* Check if we want an empty record */
1618         if (cdr == 0x00)
1619                 ac_msg->length = 0;
1620
1621         return ac_msg;
1622 }
1623
1624 /* Collision Record message */
1625 static struct near_ndef_message *near_ndef_prepare_cr_message(uint16_t cr_id)
1626 {
1627         struct near_ndef_message *cr_msg;
1628
1629         cr_msg = ndef_message_alloc_complete("cr", sizeof(uint16_t),
1630                                                 NULL, 0,
1631                                                 RECORD_TNF_WELLKNOWN,
1632                                                 TRUE, TRUE);
1633         if (cr_msg == NULL)
1634                 return NULL;
1635
1636         /* Prepare ac message */
1637         near_put_be16(cr_id, cr_msg->data + cr_msg->offset);
1638
1639         return cr_msg;
1640 }
1641
1642 static struct near_ndef_message *near_ndef_prepare_cfg_message(char *mime_type,
1643                                         uint8_t *data, int data_len,
1644                                         char cdr, uint8_t cdr_len)
1645 {
1646         struct near_ndef_message *msg = NULL;
1647
1648         DBG(" %s", mime_type);
1649
1650         if (mime_type == NULL || data == NULL || data_len <= 0)
1651                 return NULL;
1652
1653         msg = ndef_message_alloc_complete(mime_type, data_len, &cdr, cdr_len,
1654                                                 RECORD_TNF_MIME, TRUE, TRUE);
1655         if (msg == NULL)
1656                 return NULL;
1657
1658         /* store data */
1659         memcpy(msg->data + msg->offset, data, data_len);
1660
1661         return msg;
1662 }
1663
1664 /*
1665  * Prepare alternative carrier and configuration records
1666  * (e.g. bluetooth or wifi or Hc)
1667  */
1668 static int near_ndef_prepare_ac_and_cfg_records(enum handover_carrier carrier,
1669                                         struct near_ndef_message **ac,
1670                                         struct near_ndef_message **cfg,
1671                                         struct near_ndef_mime_payload *mime,
1672                                         struct carrier_data *remote_carrier)
1673 {
1674         struct carrier_data *local_carrier;
1675         char cdr;
1676         char *mime_type, *carrier_string;
1677         uint16_t prop;
1678
1679         DBG("");
1680
1681         if (ac == NULL || cfg == NULL)
1682                 return -EINVAL;
1683
1684         switch (carrier) {
1685         case NEAR_CARRIER_BLUETOOTH:
1686                 cdr = '0';
1687                 carrier_string = "Bluetooth";
1688                 mime_type = BT_MIME_STRING_2_1;
1689                 local_carrier = __near_agent_handover_request_data(
1690                                         HO_AGENT_BT, remote_carrier);
1691                 if (local_carrier != NULL)
1692                         break;
1693
1694                 prop = (mime != NULL) ? mime->handover.properties :
1695                                                         OOB_PROPS_EMPTY;
1696                 local_carrier = __near_bluetooth_local_get_properties(prop);
1697
1698                 break;
1699
1700         case NEAR_CARRIER_WIFI:
1701                 cdr = '1';
1702                 carrier_string = "WiFi-WSC";
1703                 mime_type = WIFI_WSC_MIME_STRING;
1704                 local_carrier = __near_agent_handover_request_data(
1705                                                 HO_AGENT_WIFI, remote_carrier);
1706                 break;
1707
1708         case NEAR_CARRIER_EMPTY:
1709         case NEAR_CARRIER_UNKNOWN:
1710         default:
1711                 return -EINVAL;
1712         }
1713
1714         if (local_carrier == NULL) {
1715                 DBG("Unable to retrieve local carrier %s data", carrier_string);
1716                 return -ESRCH;
1717         }
1718
1719         *cfg = near_ndef_prepare_cfg_message(mime_type, local_carrier->data,
1720                                                 local_carrier->size, cdr, 1);
1721         *ac = near_ndef_prepare_ac_message(local_carrier->state, cdr);
1722
1723         g_free(local_carrier);
1724
1725         if (*cfg == NULL || *ac == NULL) {
1726                 free_ndef_message(*ac);
1727                 free_ndef_message(*cfg);
1728
1729                 return -ENOMEM;
1730         }
1731
1732         return 0;
1733 }
1734
1735 static void free_ndef_list(gpointer data)
1736 {
1737         struct near_ndef_message *msg = data;
1738
1739         free_ndef_message(msg);
1740 }
1741
1742 static struct near_ndef_message *prepare_handover_message_header(char *type,
1743                                         uint32_t msg_len, uint32_t payload_len)
1744 {
1745         struct near_ndef_message *ho_msg;
1746
1747         ho_msg = ndef_message_alloc(type, msg_len);
1748         if (ho_msg == NULL)
1749                 return NULL;
1750
1751         /*
1752          * The handover payload length is not the *real* length.
1753          * The PL refers to the NDEF record, not the extra ones.
1754          * So, we have to fix the payload length in the header.
1755          */
1756         ho_msg->data[NDEF_PAYLOAD_LENGTH_OFFSET] = payload_len;
1757         near_ndef_set_mb_me(ho_msg->data, TRUE, FALSE);
1758
1759         /* Add version */
1760         ho_msg->data[ho_msg->offset++] = HANDOVER_VERSION;
1761
1762         return ho_msg;
1763 }
1764
1765 static uint32_t ndef_message_list_length(GList *list)
1766 {
1767         struct near_ndef_message *msg;
1768         uint32_t length = 0;
1769
1770         if (list == NULL)
1771                 return 0;
1772
1773         while (list) {
1774                 msg = list->data;
1775                 length += msg->length;
1776                 list = list->next;
1777         }
1778
1779         return length;
1780 }
1781
1782 static void copy_ac_records(struct near_ndef_message *ho, GList *acs)
1783 {
1784         GList *temp = acs;
1785         struct near_ndef_message *ac;
1786
1787         if (ho == NULL || temp == NULL)
1788                 return;
1789
1790         while (temp) {
1791                 ac = temp->data;
1792                 memcpy(ho->data + ho->offset, ac->data, ac->length);
1793                 /*
1794                  * AC records are part of handover message payload,
1795                  * so modifying offset.
1796                  */
1797                 ho->offset += ac->length;
1798                 temp = temp->next;
1799         }
1800 }
1801
1802 static void copy_cfg_records(struct near_ndef_message *ho, GList *cfgs)
1803 {
1804         GList *temp = cfgs;
1805         struct near_ndef_message *cfg;
1806         uint32_t offset;
1807
1808         if (ho == NULL || temp == NULL)
1809                 return;
1810
1811         offset = ho->offset;
1812
1813         while (temp) {
1814                 cfg = temp->data;
1815                 memcpy(ho->data + offset, cfg->data, cfg->length);
1816                 /*
1817                  * Configuration records (e.g. bt or wifi) records are not part
1818                  * of handover payload, they are consecutive ndef msgs. So
1819                  * here we are not modifying ho->offset.
1820                  */
1821                 offset += cfg->length;
1822                 temp = temp->next;
1823         }
1824 }
1825
1826 static void set_mb_me_to_false(gpointer data, gpointer user_data)
1827 {
1828         struct near_ndef_message *msg = data;
1829
1830         near_ndef_set_mb_me(msg->data, FALSE, FALSE);
1831 }
1832
1833 static struct near_ndef_message *near_ndef_prepare_empty_hs_message(void)
1834 {
1835         struct near_ndef_message *hs_msg;
1836         struct near_ndef_message *ac_msg;
1837         char cdr = 0x00;
1838         uint32_t hs_length;
1839
1840         DBG("");
1841
1842         ac_msg = near_ndef_prepare_ac_message(CPS_UNKNOWN, cdr);
1843         if (ac_msg == NULL)
1844                 return NULL;
1845
1846         hs_length = 1;
1847         hs_length += ac_msg->length;
1848
1849         hs_msg = prepare_handover_message_header("Hs", hs_length, hs_length);
1850         if (hs_msg == NULL)
1851                 goto fail;
1852
1853         near_ndef_set_mb_me(hs_msg->data, TRUE, TRUE);
1854         memcpy(hs_msg->data + hs_msg->offset, ac_msg->data, ac_msg->length);
1855         hs_msg->offset += ac_msg->length;
1856
1857         if (hs_msg->offset > hs_msg->length)
1858                 goto fail;
1859
1860         free_ndef_message(ac_msg);
1861
1862         return hs_msg;
1863
1864 fail:
1865         free_ndef_message(ac_msg);
1866         free_ndef_message(hs_msg);
1867
1868         return NULL;
1869 }
1870
1871 static struct near_ndef_message *near_ndef_prepare_hs_reply(
1872                                         GSList *remote_mimes,
1873                                         GSList *remote_cfgs)
1874 {
1875         struct near_ndef_message *hs_msg = NULL;
1876         struct near_ndef_message *ac_msg;
1877         struct near_ndef_message *cfg_msg;
1878         struct near_ndef_mime_payload *remote_mime;
1879         struct carrier_data *remote_cfg;
1880         GList *ac_msgs = NULL, *cfg_msgs = NULL, *temp;
1881         GSList *mime_iter, *cfg_iter;
1882         uint8_t hs_length, hs_pl_length, num_of_carriers;
1883         int ret = -EINVAL;
1884
1885         DBG("");
1886
1887         /*
1888          * Preparing empty Hs message in case remote devices has zero
1889          * alternative carries or unknown mime types or unknown
1890          * configuration data.
1891          */
1892         if ((remote_mimes == NULL || remote_cfgs == NULL))
1893                 return near_ndef_prepare_empty_hs_message();
1894
1895         mime_iter = remote_mimes;
1896         cfg_iter  = remote_cfgs;
1897
1898         while (mime_iter) {
1899                 remote_mime = mime_iter->data;
1900                 remote_cfg  = cfg_iter->data;
1901                 if (remote_mime == NULL || remote_cfg == NULL)
1902                         goto fail;
1903
1904                 ret = near_ndef_prepare_ac_and_cfg_records(
1905                                         remote_mime->handover.carrier_type,
1906                                         &ac_msg, &cfg_msg,
1907                                         remote_mime, remote_cfg);
1908                 if (ret == 0) {
1909                         ac_msgs  = g_list_append(ac_msgs, ac_msg);
1910                         cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
1911                 }
1912
1913                 mime_iter = mime_iter->next;
1914                 cfg_iter  = cfg_iter->next;
1915         }
1916
1917         if (g_list_length(ac_msgs) == 0) {
1918                 DBG("no alternative carriers, so preparing empty Hs message");
1919                 return near_ndef_prepare_empty_hs_message();
1920         }
1921
1922         /* Prepare Hs message */
1923         hs_pl_length = 1;
1924         /* Alternative carriers are part of handover record payload length */
1925         hs_pl_length += ndef_message_list_length(ac_msgs);
1926
1927         hs_length = hs_pl_length;
1928         /* Configuration records are part of handover message length */
1929         hs_length += ndef_message_list_length(cfg_msgs);
1930
1931         hs_msg = prepare_handover_message_header("Hs", hs_length, hs_pl_length);
1932         if (hs_msg == NULL)
1933                 goto fail;
1934
1935         num_of_carriers = g_list_length(ac_msgs);
1936
1937         if (num_of_carriers == 1) {
1938                 /* only one message */
1939                 ac_msg = ac_msgs->data;
1940                 near_ndef_set_mb_me(ac_msg->data, TRUE, TRUE);
1941         } else if (num_of_carriers > 1) {
1942                 g_list_foreach(ac_msgs, set_mb_me_to_false, NULL);
1943                 /* first message */
1944                 temp = g_list_first(ac_msgs);
1945                 ac_msg = temp->data;
1946                 near_ndef_set_mb_me(ac_msg->data, TRUE, FALSE);
1947                 /* last message */
1948                 temp = g_list_last(ac_msgs);
1949                 ac_msg = temp->data;
1950                 near_ndef_set_mb_me(ac_msg->data, FALSE, TRUE);
1951         }
1952
1953         g_list_foreach(cfg_msgs, set_mb_me_to_false, NULL);
1954         temp = g_list_last(cfg_msgs);
1955         cfg_msg = temp->data;
1956         near_ndef_set_mb_me(cfg_msg->data, FALSE, TRUE);
1957
1958         /* copy acs */
1959         copy_ac_records(hs_msg, ac_msgs);
1960         if (hs_msg->offset > hs_msg->length)
1961                 goto fail;
1962
1963         /*
1964          * copy cfgs, cfg (associated to the ac) records length
1965          * (bt or wifi) is not part of Hs initial size.
1966          */
1967         copy_cfg_records(hs_msg, cfg_msgs);
1968
1969         DBG("Hs message preparation is done");
1970
1971         g_list_free_full(ac_msgs, free_ndef_list);
1972         g_list_free_full(cfg_msgs, free_ndef_list);
1973
1974         return hs_msg;
1975
1976 fail:
1977         near_error("handover Hs message preparation failed");
1978
1979         g_list_free_full(ac_msgs, free_ndef_list);
1980         g_list_free_full(cfg_msgs, free_ndef_list);
1981
1982         free_ndef_message(hs_msg);
1983
1984         return NULL;
1985 }
1986
1987 static enum handover_carrier string2carrier(char *carrier)
1988 {
1989         if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_BLUETOOTH) == 0)
1990                 return NEAR_CARRIER_BLUETOOTH;
1991
1992         if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_WIFI) == 0)
1993                 return NEAR_CARRIER_WIFI;
1994
1995         return NEAR_CARRIER_UNKNOWN;
1996 }
1997
1998 static struct near_ndef_message *near_ndef_prepare_hr_message(GSList *carriers)
1999 {
2000         struct near_ndef_message *hr_msg = NULL;
2001         struct near_ndef_message *cr_msg = NULL;
2002         struct near_ndef_message *ac_msg;
2003         struct near_ndef_message *cfg_msg;
2004         GList *ac_msgs = NULL, *cfg_msgs = NULL, *temp;
2005         uint16_t collision;
2006         uint8_t hr_length, hr_pl_length;
2007         int ret = -EINVAL;
2008
2009         DBG("");
2010
2011         /* Hr message should have at least one carrier */
2012         while (carriers) {
2013                 ret = near_ndef_prepare_ac_and_cfg_records(
2014                                 string2carrier(carriers->data),
2015                                 &ac_msg, &cfg_msg, NULL, NULL);
2016                 if (ret == 0) {
2017                         ac_msgs  = g_list_append(ac_msgs, ac_msg);
2018                         cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
2019                 }
2020
2021                 carriers = carriers->next;
2022         }
2023
2024         if (g_list_length(ac_msgs) == 0) {
2025                 DBG("no alternative carriers to prepare Hr message");
2026                 goto fail;
2027         }
2028
2029         /* Prepare collision resolution record MB=1 ME=0 */
2030         collision = GUINT16_TO_BE(g_random_int_range(0, G_MAXUINT16 + 1));
2031         cr_msg = near_ndef_prepare_cr_message(collision);
2032         if (cr_msg == NULL)
2033                 goto fail;
2034
2035         near_ndef_set_mb_me(cr_msg->data, TRUE, FALSE);
2036
2037         /* Prepare Hr message */
2038         hr_pl_length = 1;
2039         hr_pl_length += cr_msg->length;
2040
2041         /* Alternative carriers are part of handover record payload length */
2042         hr_pl_length += ndef_message_list_length(ac_msgs);
2043
2044         hr_length = hr_pl_length;
2045         /* Configuration records are part of handover message length */
2046         hr_length += ndef_message_list_length(cfg_msgs);
2047
2048         hr_msg = prepare_handover_message_header("Hr", hr_length, hr_pl_length);
2049         if (hr_msg == NULL)
2050                 goto fail;
2051
2052         g_list_foreach(ac_msgs, set_mb_me_to_false, NULL);
2053         /* last message */
2054         temp = g_list_last(ac_msgs);
2055         ac_msg = temp->data;
2056         near_ndef_set_mb_me(ac_msg->data, FALSE, TRUE);
2057
2058         g_list_foreach(cfg_msgs, set_mb_me_to_false, NULL);
2059         temp = g_list_last(cfg_msgs);
2060         cfg_msg = temp->data;
2061         near_ndef_set_mb_me(cfg_msg->data, FALSE, TRUE);
2062
2063         /* copy cr */
2064         memcpy(hr_msg->data + hr_msg->offset, cr_msg->data, cr_msg->length);
2065         hr_msg->offset += cr_msg->length;
2066
2067         if (hr_msg->offset > hr_msg->length)
2068                 goto fail;
2069
2070         /* copy acs */
2071         copy_ac_records(hr_msg, ac_msgs);
2072         if (hr_msg->offset > hr_msg->length)
2073                 goto fail;
2074
2075         /*
2076          * copy cfgs, cfg (associated to the ac) records length
2077          * (bt or wifi) is not part of Hr initial size.
2078          */
2079         copy_cfg_records(hr_msg, cfg_msgs);
2080
2081         DBG("Hr message preparation is done");
2082
2083         free_ndef_message(cr_msg);
2084         g_list_free_full(ac_msgs, free_ndef_list);
2085         g_list_free_full(cfg_msgs, free_ndef_list);
2086
2087         return hr_msg;
2088
2089 fail:
2090         near_error("handover Hr record preparation failed");
2091
2092         g_list_free_full(ac_msgs, free_ndef_list);
2093         g_list_free_full(cfg_msgs, free_ndef_list);
2094         free_ndef_message(cr_msg);
2095         free_ndef_message(hr_msg);
2096
2097         return NULL;
2098 }
2099
2100 /* Code to fill hr record structure from acs and mimes lists */
2101 static int near_fill_ho_payload(struct near_ndef_ho_payload *ho,
2102                                         GSList *acs, GSList *mimes)
2103 {
2104         int rec_count;
2105         int i;
2106         GSList *temp;
2107
2108         rec_count = g_slist_length(acs);
2109         ho->ac_payloads = g_try_malloc0(rec_count *
2110                         sizeof(struct near_ndef_ac_payload *));
2111         if (ho->ac_payloads == NULL)
2112                 goto fail;
2113         temp = acs;
2114         for (i = 0; i < rec_count; i++) {
2115                 ho->ac_payloads[i] = temp->data;
2116                 temp = temp->next;
2117         }
2118         ho->number_of_ac_payloads = rec_count;
2119         g_slist_free(acs);
2120
2121         /* Same process for cfg mimes */
2122         rec_count = g_slist_length(mimes);
2123         ho->cfg_payloads = g_try_malloc0(rec_count *
2124                         sizeof(struct near_ndef_mime_payload *));
2125         if (ho->cfg_payloads == NULL)
2126                 goto fail;
2127         temp = mimes;
2128         for (i = 0; i < rec_count; i++) {
2129                 ho->cfg_payloads[i] = temp->data;
2130                 temp = temp->next;
2131         }
2132
2133         ho->number_of_cfg_payloads = rec_count;
2134         g_slist_free(mimes);
2135
2136         return 0;
2137 fail:
2138         g_free(ho->ac_payloads);
2139         g_free(ho->cfg_payloads);
2140         ho->ac_payloads = NULL;
2141         ho->cfg_payloads = NULL;
2142         return -ENOMEM;
2143 }
2144
2145 /*
2146  * This function will parse an handover record payload, retrieving sub records
2147  * like (ac, cr, er) but it  will also get the associated ndefs
2148  * (eg: handover carrier record, mime type for BT)
2149  * In a handover frame, only the following types are expected:
2150  *     RECORD_TYPE_WKT_HANDOVER_CARRIER:
2151  *     RECORD_TYPE_WKT_COLLISION_RESOLUTION
2152  *     RECORD_TYPE_MIME_TYPE
2153  *     RECORD_TYPE_WKT_ALTERNATIVE_CARRIER
2154  */
2155 static struct near_ndef_ho_payload *parse_ho_payload(enum record_type rec_type,
2156                 uint8_t *payload, uint32_t ho_length, size_t frame_length,
2157                 uint8_t ho_mb, uint8_t ho_me, struct near_ndef_message **reply)
2158 {
2159         struct near_ndef_ho_payload *ho_payload = NULL;
2160         struct near_ndef_ac_payload *ac = NULL;
2161         struct near_ndef_mime_payload *mime = NULL;
2162         struct carrier_data *c_data;
2163         struct near_ndef_record *trec = NULL;
2164         GSList *acs = NULL, *mimes = NULL, *c_datas = NULL;
2165         uint8_t mb = 0, me = 0, i;
2166         uint32_t offset;
2167         int16_t count_ac = 0;
2168         near_bool_t action = FALSE, status;
2169
2170         DBG("");
2171
2172         if (payload == NULL)
2173                 return NULL;
2174         offset = 0;
2175
2176         /* Create the handover record payload */
2177         ho_payload = g_try_malloc0(sizeof(struct near_ndef_ho_payload));
2178         if (ho_payload == NULL)
2179                 return NULL;
2180
2181         /* Version is the first mandatory field of hr payload */
2182         ho_payload->version = payload[offset];
2183
2184         /* If major is different, reply with an empty Hs */
2185         if (HANDOVER_MAJOR(ho_payload->version) !=
2186             HANDOVER_MAJOR(HANDOVER_VERSION)) {
2187                 near_error("Unsupported version (%d)", ho_payload->version);
2188                 /* Skip parsing and return an empty record */
2189                 if (reply != NULL)
2190                         *reply = near_ndef_prepare_empty_hs_message();
2191
2192                 return ho_payload;
2193         }
2194
2195         offset = offset + 1;
2196
2197         /* We should work on the whole frame */
2198         ho_length = frame_length;
2199
2200         while (offset < ho_length) {
2201                 /* Create local record for mime parsing */
2202                 trec = g_try_malloc0(sizeof(struct near_ndef_record));
2203                 if (trec == NULL)
2204                         return NULL;
2205
2206                 trec->header = parse_record_header(payload, offset, ho_length);
2207
2208                 if (trec->header == NULL)
2209                         goto fail;
2210
2211                 offset = trec->header->offset;
2212
2213                 switch (trec->header->rec_type) {
2214                 case RECORD_TYPE_WKT_SMART_POSTER:
2215                 case RECORD_TYPE_WKT_SIZE:
2216                 case RECORD_TYPE_WKT_TEXT:
2217                 case RECORD_TYPE_WKT_TYPE:
2218                 case RECORD_TYPE_WKT_ACTION:
2219                 case RECORD_TYPE_WKT_URI:
2220                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2221                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2222                 case RECORD_TYPE_WKT_ERROR:
2223                 case RECORD_TYPE_UNKNOWN:
2224                 case RECORD_TYPE_ERROR:
2225                         break;
2226
2227                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2228                         DBG("HANDOVER_CARRIER");
2229                         /*
2230                          * TODO process Hc record too !!!
2231                          * Used for Wifi session
2232                          */
2233                         break;
2234
2235                 case RECORD_TYPE_MIME_TYPE:
2236                         DBG("TYPE_MIME_TYPE");
2237
2238                         /* check mb/me bits */
2239                         if (validate_record_begin_and_end_bits(&ho_mb, &ho_me,
2240                                 trec->header->mb, trec->header->me) != 0) {
2241                                 DBG("validate mb me failed");
2242                                 goto fail;
2243                         }
2244
2245                         /*
2246                          * In Handover, the mime type gives bluetooth handover
2247                          * or WiFi configuration data.
2248                          * If we initiated the session, the received Hs frame
2249                          * is the signal to launch the pairing.
2250                          */
2251                         if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT)
2252                                 action = TRUE;
2253                         else
2254                                 action = FALSE;
2255
2256                         /* HO payload for reply creation */
2257                         trec->ho = ho_payload;
2258
2259                         mime = parse_mime_type(trec, payload, frame_length,
2260                                         offset, trec->header->payload_len,
2261                                         &c_data);
2262                         trec->ho = NULL;
2263
2264                         if (mime == NULL || c_data == NULL)
2265                                 goto fail;
2266
2267                         /* add the mime to the list */
2268                         mimes = g_slist_append(mimes, mime);
2269                         /* add the carrier data to the list */
2270                         c_datas = g_slist_append(c_datas, c_data);
2271
2272                         count_ac--;
2273                         if (count_ac == 0)
2274                                 offset = ho_length;
2275                         break;
2276
2277                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2278                         DBG("COLLISION_RESOLUTION");
2279
2280                         /* check nested mb/me bits */
2281                         if (validate_record_begin_and_end_bits(&mb, &me,
2282                                 trec->header->mb, trec->header->me) != 0) {
2283                                 DBG("validate mb me failed");
2284                                 goto fail;
2285                         }
2286
2287                         ho_payload->collision_record =
2288                                         near_get_be16(payload + offset);
2289
2290                         break;
2291
2292                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2293                         DBG("ALTERNATIVE_CARRIER");
2294
2295                         /* check nested mb/me bits */
2296                         if (validate_record_begin_and_end_bits(&mb, &me,
2297                                 trec->header->mb, trec->header->me) != 0) {
2298                                 DBG("validate mb me failed");
2299                                 goto fail;
2300                         }
2301
2302                         ac = parse_ac_payload(payload + offset,
2303                                         trec->header->payload_len);
2304                         if (ac == NULL)
2305                                 goto fail;
2306
2307                         acs = g_slist_append(acs, ac);
2308
2309                         /* TODO check if adata are present */
2310                         count_ac++;
2311                         break;
2312                 }
2313
2314                 offset += trec->header->payload_len;
2315                 g_free(trec->header->il_field);
2316                 g_free(trec->header->type_name);
2317                 g_free(trec->header);
2318                 trec->header = NULL;
2319
2320                 g_free(trec);
2321                 trec = NULL;
2322         }
2323
2324         /*
2325          * In case of multiple carriers, handover with any carrier
2326          * gets done then leave the loop.
2327          */
2328         if (action == TRUE) {
2329                 status = FALSE;
2330                 count_ac = g_slist_length(mimes);
2331
2332                 for (i = 0; i < count_ac; i++) {
2333                         if (process_mime_type(g_slist_nth_data(mimes, i),
2334                                         g_slist_nth_data(c_datas, i)) == 0) {
2335                                 status = TRUE;
2336                                 break;
2337                         }
2338                 }
2339
2340                 if (status == FALSE) {
2341                         DBG("could not process alternative carriers");
2342                         goto fail;
2343                 }
2344         } else if (reply != NULL) {
2345                 /* Prepare Hs, it depends upon Hr message carrier types */
2346                 *reply = near_ndef_prepare_hs_reply(mimes, c_datas);
2347                 if (*reply == NULL) {
2348                         DBG("error in preparing in HS record");
2349                         goto fail;
2350                 }
2351         }
2352
2353         if ((acs == NULL) || (mimes == NULL))
2354                 return ho_payload;
2355
2356         /* Save the records */
2357         if (near_fill_ho_payload(ho_payload, acs, mimes) < 0)
2358                 goto fail;
2359
2360         DBG("handover payload parsing complete");
2361
2362         g_slist_free_full(c_datas, g_free);
2363
2364         return ho_payload;
2365
2366 fail:
2367         near_error("handover payload parsing failed");
2368
2369         if (trec != NULL) {
2370                 if (trec->header != NULL) {
2371                         g_free(trec->header->type_name);
2372                         g_free(trec->header->il_field);
2373                         g_free(trec->header);
2374                 }
2375                 g_free(trec);
2376         }
2377
2378         g_slist_free_full(c_datas, g_free);
2379         free_ho_payload(ho_payload);
2380
2381         return NULL;
2382 }
2383
2384 int __near_ndef_record_register(struct near_ndef_record *record, char *path)
2385 {
2386         record->path = path;
2387
2388         g_dbus_register_interface(connection, record->path,
2389                                                 NFC_RECORD_INTERFACE,
2390                                                 record_methods,
2391                                                 NULL, NULL,
2392                                                 record, NULL);
2393
2394         return 0;
2395 }
2396
2397 /*
2398  * These functions parse a specific type record (id or mime) to find the
2399  * associated string.
2400  */
2401 near_bool_t near_ndef_record_cmp_id(struct near_ndef_record *rec1,
2402                                                 struct near_ndef_record *rec2)
2403 {
2404         DBG("");
2405
2406         if ((rec1 == NULL) || (rec2 == NULL))
2407                 return FALSE;
2408
2409         if ((rec1->header == NULL) || (rec2->header == NULL))
2410                 return FALSE;
2411
2412         /* usual checks */
2413         if ((rec1->header->il_field == NULL) ||
2414                         (rec2->header->il_field == NULL))
2415                 return FALSE;
2416
2417         if (memcmp(rec1->header->il_field, rec2->header->il_field,
2418                 (rec1->header->il_length) > (rec2->header->il_length)
2419                                         ? (rec1->header->il_length) :
2420                                         (rec2->header->il_length)) != 0)
2421                 return FALSE;
2422
2423         return TRUE;
2424 }
2425
2426 near_bool_t near_ndef_record_cmp_mime(struct near_ndef_record *rec1,
2427                                         struct near_ndef_record *rec2)
2428 {
2429
2430         DBG("");
2431
2432         if ((rec1 == NULL) || (rec2 == NULL))
2433                 return FALSE;
2434
2435         if ((rec1->header == NULL) || (rec2->header == NULL))
2436                 return FALSE;
2437         /* usual checks */
2438         if ((rec1->mime == NULL) || (rec2->mime == NULL))
2439                 return FALSE;
2440
2441         if ((rec1->mime->type == NULL) || (rec2->mime->type == NULL))
2442                 return FALSE;
2443
2444         if (strlen(rec1->mime->type) != strlen(rec2->mime->type))
2445                 return FALSE;
2446
2447         if ((g_strcmp0(rec1->mime->type, rec2->mime->type) != 0))
2448                 return FALSE;
2449
2450         return TRUE;
2451 }
2452
2453 /* helper to get the record data length */
2454 size_t near_ndef_data_length(struct near_ndef_record *rec)
2455 {
2456         if (rec == NULL)
2457                 return 0;
2458         else
2459                 return rec->data_len;
2460 }
2461
2462 /* helper to get the record data pointer */
2463 uint8_t *near_ndef_data_ptr(struct near_ndef_record *rec)
2464 {
2465         if (rec == NULL)
2466                 return NULL;
2467         else
2468                 return rec->data;
2469 }
2470
2471 GList *near_ndef_parse_msg(uint8_t *ndef_data, size_t ndef_length,
2472                                 struct near_ndef_message **reply)
2473 {
2474         GList *records;
2475         uint8_t p_mb = 0, p_me = 0, *record_start;
2476         size_t offset = 0;
2477         struct near_ndef_record *record = NULL;
2478         struct carrier_data *c_data;
2479
2480         DBG("");
2481
2482         records = NULL;
2483
2484         if (ndef_data == NULL ||
2485                 ndef_length < NDEF_MSG_MIN_LENGTH)
2486                         goto fail;
2487
2488         while (offset < ndef_length) {
2489
2490                 DBG("Record Header : 0x%X", ndef_data[offset]);
2491
2492                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2493                 if (record == NULL)
2494                         goto fail;
2495
2496                 record->header = parse_record_header(ndef_data, offset,
2497                                                         ndef_length);
2498                 if (record->header == NULL)
2499                         goto fail;
2500
2501                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2502                                         record->header->mb,
2503                                         record->header->me) != 0) {
2504                         DBG("validate mb me failed");
2505                         goto fail;
2506                 }
2507
2508                 record_start = ndef_data + offset;
2509                 offset = record->header->offset;
2510
2511                 switch (record->header->rec_type) {
2512                 case RECORD_TYPE_WKT_SIZE:
2513                 case RECORD_TYPE_WKT_TYPE:
2514                 case RECORD_TYPE_WKT_ACTION:
2515                 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2516                 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2517                 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2518                 case RECORD_TYPE_WKT_ERROR:
2519                 case RECORD_TYPE_UNKNOWN:
2520                 case RECORD_TYPE_ERROR:
2521                         break;
2522
2523                 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2524                 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2525                         /*
2526                          * Handover frame are a little bit special as the NDEF
2527                          * length (specified in the header) is not the real
2528                          * frame size. The complete frame includes extra NDEF
2529                          * following the initial handover NDEF
2530                          */
2531                         record->ho = parse_ho_payload(record->header->rec_type,
2532                                         ndef_data + offset,
2533                                         record->header->payload_len,
2534                                         ndef_length - offset,
2535                                         record->header->mb, record->header->me,
2536                                         reply);
2537                         if (record->ho == NULL)
2538                                 goto fail;
2539
2540                         /* the complete frame is processed, break the loop */
2541                         record->header->payload_len = ndef_length;
2542                         break;
2543
2544                 case RECORD_TYPE_WKT_TEXT:
2545                         record->text = parse_text_payload(ndef_data + offset,
2546                                                 record->header->payload_len);
2547
2548                         if (record->text == NULL)
2549                                 goto fail;
2550
2551                         break;
2552
2553                 case RECORD_TYPE_WKT_URI:
2554                         record->uri = parse_uri_payload(ndef_data + offset,
2555                                                 record->header->payload_len);
2556
2557                         if (record->uri == NULL)
2558                                 goto fail;
2559
2560                         break;
2561
2562                 case RECORD_TYPE_WKT_SMART_POSTER:
2563                         record->sp = parse_sp_payload(
2564                                                 ndef_data + offset,
2565                                                 record->header->payload_len);
2566
2567                         if (record->sp == NULL)
2568                                 goto fail;
2569
2570                         break;
2571
2572                 case RECORD_TYPE_MIME_TYPE:
2573                         record->mime = parse_mime_type(record, ndef_data,
2574                                                 ndef_length, offset,
2575                                                 record->header->payload_len,
2576                                                 &c_data);
2577                         if (record->mime == NULL)
2578                                 goto fail;
2579
2580                         /* No carrier data, move on */
2581                         if (c_data == NULL)
2582                                 break;
2583
2584                         if (process_mime_type(record->mime, c_data) < 0) {
2585                                 g_free(c_data);
2586                                 c_data = NULL;
2587                                 goto fail;
2588                         }
2589
2590                         g_free(c_data);
2591                         c_data = NULL;
2592                         break;
2593                 }
2594
2595                 record->data_len = record->header->header_len +
2596                                         record->header->payload_len;
2597
2598                 record->data = g_try_malloc0(record->data_len);
2599                 if (record->data == NULL)
2600                         goto fail;
2601
2602                 memcpy(record->data, record_start, record->data_len);
2603
2604                 records = g_list_append(records, record);
2605
2606                 build_record_type_string(record);
2607
2608                 offset += record->header->payload_len;
2609         }
2610
2611         return records;
2612
2613 fail:
2614         near_error("ndef parsing failed");
2615         free_ndef_record(record);
2616
2617         return records;
2618 }
2619
2620 void near_ndef_records_free(GList *records)
2621 {
2622         GList *list;
2623
2624         for (list = records; list; list = list->next) {
2625                 struct near_ndef_record *record = list->data;
2626
2627                 __near_ndef_record_free(record);
2628         }
2629
2630         g_list_free(records);
2631 }
2632
2633 /*
2634  * Compute ndef records length, even though the submitted frame is incomplete.
2635  * This code is used in the handover read function, as we have to "guess" the
2636  * final frame size.
2637  *
2638  * Message size for SR=1 is:
2639  *  1 : ndef rec header (offset 0)
2640  *  x : record type length (offset 1)
2641  *  y : payload length (offset 2) 1 byte ONLY if SR=1
2642  *      if SR=0: (4bytes) 32 bits
2643  *  z : payload id length (offset 3) ONLY if il_length=1
2644  * */
2645 int near_ndef_record_length(uint8_t *ndef_in, size_t ndef_in_length)
2646 {
2647         int ndef_size;   /* default size for NDEF hdr + rec typ len + payl */
2648         size_t offset;
2649         uint8_t hdr;
2650
2651         DBG("");
2652
2653         if (ndef_in_length < 3)
2654                 return -EINVAL;
2655
2656         ndef_size = 3;
2657         offset = 0;
2658
2659         /* save header byte */
2660         hdr = ndef_in[offset];
2661         offset++;
2662
2663         /* header->type_len */
2664         ndef_size += ndef_in[offset++];
2665
2666         /* header->payload_len */
2667         if (RECORD_SR_BIT(hdr) == 1) {
2668                 ndef_size += ndef_in[offset++];
2669         } else {
2670                 ndef_size += near_get_be32(ndef_in + offset);
2671                 offset += 4;
2672
2673                 if (offset >= ndef_in_length)
2674                         return -ERANGE;
2675         }
2676
2677         /* header->il */
2678         ndef_size += RECORD_IL_BIT(hdr);
2679
2680         /* header->il_length */
2681         if (RECORD_IL_BIT(hdr) == 1)
2682                 ndef_size += ndef_in[offset++];
2683
2684         DBG("near_ndef_message_length is %d", ndef_size);
2685
2686         return ndef_size;
2687 }
2688
2689 int near_ndef_count_records(uint8_t *ndef_in, size_t ndef_in_length,
2690                         uint8_t record_type)
2691 {
2692         uint8_t p_mb = 0, p_me = 0;
2693         int err;
2694         size_t offset;
2695         struct near_ndef_record *record = NULL;
2696         int counted_records = 0 ;
2697
2698         DBG("");
2699
2700         offset = 0;
2701
2702         if (ndef_in == NULL ||  ndef_in_length < NDEF_MSG_MIN_LENGTH) {
2703                 err = -EINVAL;
2704                 goto fail;
2705         }
2706
2707         while (offset < ndef_in_length) {
2708                 record = g_try_malloc0(sizeof(struct near_ndef_record));
2709                 if (record == NULL) {
2710                         err = -ENOMEM;
2711                         goto fail;
2712                 }
2713
2714                 /* Create a record */
2715                 record->header = parse_record_header(ndef_in, offset,
2716                                                         ndef_in_length);
2717                 if (record->header == NULL) {
2718                         err = -EINVAL;
2719                         goto fail;
2720                 }
2721
2722                 /* Validate MB ME */
2723                 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2724                                         record->header->mb,
2725                                         record->header->me) != 0) {
2726                         DBG("validate mb me failed");
2727                         err = -EINVAL;
2728                         goto fail;
2729                 }
2730
2731                 /* Is this what we want ? */
2732                 if (record->header->rec_type == record_type)
2733                         counted_records++;
2734
2735                 /* Jump to the next record */
2736                 offset = record->header->offset + record->header->payload_len;
2737
2738                 free_ndef_record(record);
2739         }
2740
2741         DBG("Type %d Records found: %d", record_type, counted_records);
2742
2743         return counted_records;
2744
2745 fail:
2746         near_error("ndef counting failed");
2747         free_ndef_record(record);
2748         return err;
2749 }
2750
2751 /* Possible encoding "UTF-8" or "UTF-16" */
2752 struct near_ndef_message *near_ndef_prepare_text_record(char *encoding,
2753                                                 char *language_code, char *text)
2754 {
2755         struct near_ndef_message *msg;
2756         uint32_t text_len, payload_length;
2757         uint8_t  code_len, status = 0;
2758
2759         DBG("");
2760
2761         /* Validate input parameters*/
2762         if (((g_strcmp0(encoding, "UTF-8") != 0) &&
2763                  (g_strcmp0(encoding, "UTF-16") != 0)) ||
2764                  (language_code == NULL) ||
2765                  (text == NULL)) {
2766                 return NULL;
2767         }
2768
2769         code_len = strlen(language_code);
2770         text_len = strlen(text);
2771         payload_length = 1 + code_len + text_len;
2772
2773         msg = ndef_message_alloc("T", payload_length);
2774         if (msg == NULL)
2775                 return NULL;
2776
2777         if (g_strcmp0(encoding, "UTF-16") == 0)
2778                 status |= NDEF_TEXT_RECORD_UTF16_STATUS;
2779
2780         status = status | code_len;
2781         msg->data[msg->offset++] = status;
2782
2783         if (code_len > 0)
2784                 memcpy(msg->data + msg->offset, language_code, code_len);
2785
2786         msg->offset += code_len;
2787
2788         if (text_len > 0)
2789                 memcpy(msg->data + msg->offset, text, text_len);
2790
2791         msg->offset += text_len;
2792
2793         if (msg->offset > msg->length)
2794                 goto fail;
2795
2796         return msg;
2797
2798 fail:
2799         near_error("text record preparation failed");
2800         free_ndef_message(msg);
2801
2802         return NULL;
2803 }
2804
2805 struct near_ndef_message *near_ndef_prepare_uri_record(uint8_t identifier,
2806                                         uint32_t field_length, uint8_t *field)
2807 {
2808         struct near_ndef_message *msg = NULL;
2809         uint32_t payload_length;
2810
2811         DBG("");
2812
2813         /* Validate input parameters*/
2814         if ((field_length == 0 && field != NULL) ||
2815                 (field_length != 0 && field == NULL)) {
2816                 return NULL;
2817         }
2818
2819         payload_length = field_length + 1;
2820
2821         msg = ndef_message_alloc("U", payload_length);
2822         if (msg == NULL)
2823                 return NULL;
2824
2825         msg->data[msg->offset++] = identifier;
2826
2827         if (field_length > 0) {
2828                 memcpy(msg->data + msg->offset, field, field_length);
2829                 msg->offset += field_length;
2830         }
2831
2832         if (msg->offset > msg->length)
2833                 goto fail;
2834
2835         return msg;
2836
2837 fail:
2838         near_error("uri record preparation failed");
2839         free_ndef_message(msg);
2840
2841         return NULL;
2842 }
2843
2844 struct near_ndef_message *
2845 near_ndef_prepare_smartposter_record(uint8_t uri_identifier,
2846                                         uint32_t uri_field_length,
2847                                         uint8_t *uri_field)
2848 {
2849         struct near_ndef_message *msg = NULL, *uri = NULL;
2850
2851         /* URI is mandatory in Smartposter */
2852         uri = near_ndef_prepare_uri_record(uri_identifier, uri_field_length,
2853                                                                 uri_field);
2854         if (uri == NULL)
2855                 goto fail;
2856
2857         /* URI record length is equal to payload length of Sp record */
2858         msg = ndef_message_alloc("Sp", uri->length);
2859         if (msg == NULL)
2860                 goto fail;
2861
2862         memcpy(msg->data + msg->offset, uri->data, uri->length);
2863         msg->offset += uri->length;
2864
2865         if (msg->offset > msg->length)
2866                 goto fail;
2867
2868         free_ndef_message(uri);
2869
2870         return msg;
2871
2872 fail:
2873         near_error("smartposter record preparation failed");
2874
2875         free_ndef_message(uri);
2876         free_ndef_message(msg);
2877
2878         return NULL;
2879 }
2880
2881 static char *get_text_field(DBusMessage *msg, char *text)
2882 {
2883         DBusMessageIter iter, arr_iter;
2884         char *uri = NULL;
2885
2886         DBG("");
2887
2888         if (text == NULL)
2889                 return NULL;
2890
2891         dbus_message_iter_init(msg, &iter);
2892         dbus_message_iter_recurse(&iter, &arr_iter);
2893
2894         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2895                                         DBUS_TYPE_INVALID) {
2896                 const char *key;
2897                 DBusMessageIter ent_iter;
2898                 DBusMessageIter var_iter;
2899
2900                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2901                 dbus_message_iter_get_basic(&ent_iter, &key);
2902                 dbus_message_iter_next(&ent_iter);
2903                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2904
2905                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2906                 case DBUS_TYPE_STRING:
2907                         if (g_strcmp0(key, text) == 0)
2908                                 dbus_message_iter_get_basic(&var_iter, &uri);
2909
2910                         break;
2911                 }
2912
2913                 dbus_message_iter_next(&arr_iter);
2914         }
2915
2916         return uri;
2917 }
2918
2919 static inline char *get_uri_field(DBusMessage *msg)
2920 {
2921         return get_text_field(msg, "URI");
2922 }
2923
2924 static GSList *get_carrier_field(DBusMessage *msg)
2925 {
2926         char *carrier;
2927         char **arr;
2928         GSList *carriers = NULL;
2929         uint8_t num_of_carriers, i;
2930
2931         DBG("");
2932
2933         carrier = get_text_field(msg, "Carrier");
2934         if (carrier == NULL)
2935                 return NULL;
2936
2937         arr = g_strsplit(carrier, ",", NEAR_CARRIER_MAX);
2938         num_of_carriers = g_strv_length(arr);
2939
2940         for (i = 0; i < num_of_carriers; i++)
2941                 carriers = g_slist_append(carriers, g_strdup(arr[i]));
2942
2943         g_strfreev(arr);
2944
2945         return carriers;
2946 }
2947
2948 static struct near_ndef_message *build_text_record(DBusMessage *msg)
2949 {
2950         DBusMessageIter iter, arr_iter;
2951         char *cod = NULL, *lang = NULL, *rep = NULL;
2952
2953         DBG("");
2954
2955         dbus_message_iter_init(msg, &iter);
2956         dbus_message_iter_recurse(&iter, &arr_iter);
2957
2958         while (dbus_message_iter_get_arg_type(&arr_iter) !=
2959                                         DBUS_TYPE_INVALID) {
2960                 const char *key;
2961                 DBusMessageIter ent_iter;
2962                 DBusMessageIter var_iter;
2963
2964                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
2965                 dbus_message_iter_get_basic(&ent_iter, &key);
2966                 dbus_message_iter_next(&ent_iter);
2967                 dbus_message_iter_recurse(&ent_iter, &var_iter);
2968
2969                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
2970                 case DBUS_TYPE_STRING:
2971                         if (g_strcmp0(key, "Encoding") == 0)
2972                                 dbus_message_iter_get_basic(&var_iter, &cod);
2973                         else if (g_strcmp0(key, "Language") == 0)
2974                                 dbus_message_iter_get_basic(&var_iter, &lang);
2975                         else if (g_strcmp0(key, "Representation") == 0)
2976                                 dbus_message_iter_get_basic(&var_iter, &rep);
2977
2978                         break;
2979                 }
2980
2981                 dbus_message_iter_next(&arr_iter);
2982         }
2983
2984         return near_ndef_prepare_text_record(cod, lang, rep);
2985 }
2986
2987 static struct near_ndef_message *build_uri_record(DBusMessage *msg)
2988 {
2989         char *uri = NULL;
2990         const char *uri_prefix = NULL;
2991         uint8_t id_len, i, id;
2992         uint32_t uri_len;
2993
2994         DBG("");
2995
2996         uri = get_uri_field(msg);
2997         if (uri == NULL)
2998                 return NULL;
2999
3000         id = 0;
3001         id_len = 0;
3002
3003         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3004                 uri_prefix = __near_ndef_get_uri_prefix(i);
3005
3006                 if (uri_prefix != NULL &&
3007                     g_str_has_prefix(uri, uri_prefix) == TRUE) {
3008                         id = i;
3009                         id_len = strlen(uri_prefix);
3010                         break;
3011                 }
3012         }
3013
3014         DBG("%d %d\n", i, id_len);
3015
3016         uri_len = strlen(uri) - id_len;
3017         return near_ndef_prepare_uri_record(id, uri_len,
3018                                                 (uint8_t *)(uri + id_len));
3019 }
3020
3021 static struct near_ndef_message *build_sp_record(DBusMessage *msg)
3022 {
3023         char *uri = NULL;
3024         const char *uri_prefix;
3025         uint8_t id_len, i;
3026         uint32_t uri_len;
3027
3028         DBG("");
3029
3030         /*
3031          * Currently this function supports only mandatory URI record,
3032          * TODO: Other records support.
3033          */
3034         uri = get_uri_field(msg);
3035         if (uri == NULL)
3036                 return NULL;
3037
3038         for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3039                 uri_prefix = __near_ndef_get_uri_prefix(i);
3040
3041                 if (uri_prefix != NULL &&
3042                                 g_str_has_prefix(uri, uri_prefix) == TRUE)
3043                         break;
3044         }
3045
3046         if (uri_prefix == NULL) {
3047                 i = 0;
3048                 id_len = 0;
3049         } else
3050                 id_len = strlen(uri_prefix);
3051
3052         uri_len = strlen(uri) - id_len;
3053         return near_ndef_prepare_smartposter_record(i, uri_len,
3054                                                 (uint8_t *)(uri + id_len));
3055 }
3056
3057 static struct near_ndef_message *build_hr_record(DBusMessage *msg)
3058 {
3059         struct near_ndef_message *hr;
3060         GSList *carriers;
3061
3062         DBG("");
3063
3064         carriers = get_carrier_field(msg);
3065         hr = near_ndef_prepare_hr_message(carriers);
3066         g_slist_free_full(carriers, g_free);
3067
3068         return hr;
3069 }
3070
3071 static int fill_wifi_wsc_data(uint8_t *tlv, uint16_t id,
3072                                 uint16_t data_len, uint8_t *data)
3073 {
3074         int offset = 0;
3075
3076         if (tlv == NULL || data == NULL)
3077                 return 0;
3078
3079         fillb16(tlv, id);
3080         offset += WIFI_WSC_ID_LENGTH;
3081
3082         fillb16(tlv + offset, data_len);
3083         offset += WIFI_WSC_ID_DATA_LENGTH;
3084
3085         memcpy(tlv + offset, data, data_len);
3086         offset += data_len;
3087
3088         return offset;
3089 }
3090
3091 static void get_wsc_data(DBusMessageIter iter, char **ssid, char **pass)
3092 {
3093         DBG("");
3094
3095         *ssid = NULL;
3096         *pass = NULL;
3097
3098         while (dbus_message_iter_get_arg_type(&iter) !=
3099                                         DBUS_TYPE_INVALID) {
3100                 const char *key;
3101                 DBusMessageIter ent_iter;
3102                 DBusMessageIter var_iter;
3103
3104                 dbus_message_iter_recurse(&iter, &ent_iter);
3105                 dbus_message_iter_get_basic(&ent_iter, &key);
3106                 dbus_message_iter_next(&ent_iter);
3107                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3108
3109                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3110                 case DBUS_TYPE_STRING:
3111                         if (g_strcmp0(key, "SSID") == 0)
3112                                 dbus_message_iter_get_basic(&var_iter, ssid);
3113                         else if (g_strcmp0(key, "Passphrase") == 0)
3114                                 dbus_message_iter_get_basic(&var_iter, pass);
3115
3116                         break;
3117                 }
3118
3119                 dbus_message_iter_next(&iter);
3120         }
3121 }
3122
3123 struct near_ndef_message *near_ndef_prepare_wsc_record(char *ssid,
3124                                                         char *passphrase)
3125 {
3126         uint16_t ssid_len, pass_len, key_type;
3127         uint8_t temp_key[2];
3128         uint8_t *tlv;
3129         uint32_t tlv_len, offset;
3130         struct near_ndef_message *mime;
3131
3132         /* At least SSID is required in case of open network */
3133         if (ssid == NULL)
3134                 return NULL;
3135
3136         DBG("SSID %s Passphrase %s", ssid, passphrase);
3137
3138         /* Prepare TLV from ssid and passphrasse */
3139         ssid_len = strlen(ssid);
3140
3141         if (passphrase != NULL) {
3142                 pass_len = strlen(passphrase);
3143                 key_type = WIFI_WSC_KEY_PSK;
3144         } else {
3145                 pass_len = 0;
3146                 key_type = WIFI_WSC_KEY_OPEN;
3147         }
3148
3149         /* add ssid length */
3150         tlv_len = WIFI_WSC_ID_LENGTH + WIFI_WSC_ID_DATA_LENGTH + ssid_len;
3151         /* add authentication type length */
3152         tlv_len += WIFI_WSC_ID_LENGTH + WIFI_WSC_ID_DATA_LENGTH + 2;
3153         /* add network key length */
3154         if (passphrase != NULL)
3155                 tlv_len += WIFI_WSC_ID_LENGTH +
3156                                 WIFI_WSC_ID_DATA_LENGTH + pass_len;
3157
3158         tlv = g_try_malloc0(tlv_len);
3159         if (tlv ==  NULL)
3160                 return NULL;
3161
3162         offset = 0;
3163         /* copy SSID */
3164         offset += fill_wifi_wsc_data(tlv, WIFI_WSC_ID_SSID,
3165                                         ssid_len, (uint8_t *) ssid);
3166
3167         /*
3168          * copy authentication type
3169          * copy key type to temp key array to maintain endianess
3170          * and fill wsc data
3171          */
3172         fillb16(temp_key, key_type);
3173         offset += fill_wifi_wsc_data(tlv + offset, WIFI_WSC_ID_AUTH_TYPE,
3174                                                 WIFI_WSC_ID_DATA_LENGTH,
3175                                                 (uint8_t *) temp_key);
3176
3177         /* copy Network Key */
3178         if (passphrase != NULL)
3179                 offset += fill_wifi_wsc_data(tlv + offset, WIFI_WSC_ID_KEY,
3180                                                 pass_len,
3181                                                 (uint8_t *) passphrase);
3182
3183         mime = ndef_message_alloc_complete(WIFI_WSC_MIME_STRING, tlv_len, NULL,
3184                                                 0, RECORD_TNF_MIME, TRUE, TRUE);
3185         if (mime == NULL) {
3186                 g_free(tlv);
3187                 return NULL;
3188         }
3189
3190         memcpy(mime->data + mime->offset, tlv, tlv_len);
3191         g_free(tlv);
3192
3193         return mime;
3194 }
3195
3196 static struct near_ndef_message *build_mime_record(DBusMessage *msg)
3197 {
3198         DBusMessageIter iter, arr_iter;
3199         char *key, *mime_str, *ssid, *passphrase;
3200
3201         DBG("");
3202
3203         dbus_message_iter_init(msg, &iter);
3204         dbus_message_iter_recurse(&iter, &arr_iter);
3205
3206         while (dbus_message_iter_get_arg_type(&arr_iter) !=
3207                                         DBUS_TYPE_INVALID) {
3208                 DBusMessageIter ent_iter;
3209                 DBusMessageIter var_iter;
3210
3211                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3212                 dbus_message_iter_get_basic(&ent_iter, &key);
3213
3214                 if (g_strcmp0(key, "MIME") == 0) {
3215                         dbus_message_iter_next(&ent_iter);
3216                         dbus_message_iter_recurse(&ent_iter, &var_iter);
3217                         dbus_message_iter_get_basic(&var_iter, &mime_str);
3218
3219                         if (g_strcmp0(mime_str, WIFI_WSC_MIME_STRING) == 0) {
3220                                 struct near_ndef_message *mime;
3221                                 struct carrier_data *carrier;
3222
3223                                 get_wsc_data(arr_iter, &ssid, &passphrase);
3224                                 if (ssid != NULL)
3225                                         return near_ndef_prepare_wsc_record(
3226                                                         ssid, passphrase);
3227
3228                                 /*
3229                                  * If we did not get an SSID and optionally
3230                                  * a passphrase from the DBus message, then
3231                                  * we try to get one from the WiFi-WSC agent.
3232                                  */
3233                                 carrier = __near_agent_handover_request_data(
3234                                                         HO_AGENT_WIFI, NULL);
3235                                 if (carrier == NULL)
3236                                         return NULL;
3237
3238                                 mime = ndef_message_alloc_complete(
3239                                         WIFI_WSC_MIME_STRING, carrier->size,
3240                                         NULL, 0, RECORD_TNF_MIME, TRUE, TRUE);
3241                                 if (mime == NULL) {
3242                                         g_free(carrier);
3243                                         return NULL;
3244                                 }
3245
3246                                 memcpy(mime->data + mime->offset,
3247                                         carrier->data, carrier->size);
3248
3249                                 g_free(carrier);
3250
3251                                 return mime;
3252                         }
3253
3254                 }
3255
3256                 dbus_message_iter_next(&arr_iter);
3257         }
3258
3259         return NULL;
3260 }
3261
3262 struct near_ndef_message *__ndef_build_from_message(DBusMessage *msg)
3263 {
3264         DBusMessageIter iter;
3265         DBusMessageIter arr_iter;
3266         struct near_ndef_message *ndef;
3267
3268         DBG("");
3269
3270         dbus_message_iter_init(msg, &iter);
3271         dbus_message_iter_recurse(&iter, &arr_iter);
3272
3273         ndef = NULL;
3274
3275         while (dbus_message_iter_get_arg_type(&arr_iter) !=
3276                                                 DBUS_TYPE_INVALID) {
3277                 const char *key, *value;
3278                 DBusMessageIter ent_iter;
3279                 DBusMessageIter var_iter;
3280
3281                 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3282                 dbus_message_iter_get_basic(&ent_iter, &key);
3283
3284                 if (g_strcmp0(key, "Type") != 0) {
3285                         dbus_message_iter_next(&arr_iter);
3286                         continue;
3287                 }
3288
3289                 dbus_message_iter_next(&ent_iter);
3290                 dbus_message_iter_recurse(&ent_iter, &var_iter);
3291
3292                 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3293                 case DBUS_TYPE_STRING:
3294                         dbus_message_iter_get_basic(&var_iter, &value);
3295
3296                         if (g_strcmp0(value, "Text") == 0) {
3297                                 ndef = build_text_record(msg);
3298                                 break;
3299                         } else if (g_strcmp0(value, "URI") == 0) {
3300                                 ndef = build_uri_record(msg);
3301                                 break;
3302                         } else if (g_strcmp0(value, "SmartPoster") == 0) {
3303                                 ndef = build_sp_record(msg);
3304                                 break;
3305                         } else if (g_strcmp0(value, "Handover") == 0) {
3306                                 ndef = build_hr_record(msg);
3307                                 break;
3308                         } else if (g_strcmp0(value, "MIME") == 0) {
3309                                 ndef = build_mime_record(msg);
3310                                 break;
3311                         } else {
3312                                 near_error("%s not supported", value);
3313                                 ndef = NULL;
3314                                 break;
3315                         }
3316
3317                         break;
3318                 }
3319
3320                 dbus_message_iter_next(&arr_iter);
3321         }
3322
3323         return ndef;
3324 }
3325
3326 int __near_ndef_init(void)
3327 {
3328         DBG("");
3329
3330         connection = near_dbus_get_connection();
3331
3332         return 0;
3333 }
3334
3335 void __near_ndef_cleanup(void)
3336 {
3337 }