3 * neard - Near Field Communication manager
5 * Copyright (C) 2011 Intel Corporation. All rights reserved.
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.
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.
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
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,
47 #define RECORD_ACTION_DO 0x00
48 #define RECORD_ACTION_SAVE 0x01
49 #define RECORD_ACTION_EDIT 0x02
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)
58 #define NDEF_MSG_MIN_LENGTH 0x03
59 #define NDEF_PAYLOAD_LENGTH_OFFSET 0x02
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)
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
78 #define AC_CPS_MASK 0x03
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
98 #define RECORD_TYPE_WKT "urn:nfc:wkt:"
99 #define RECORD_TYPE_EXTERNAL "urn:nfc:ext:"
101 struct near_ndef_record_header {
110 uint32_t payload_len;
113 enum record_type rec_type;
118 struct near_ndef_text_payload {
124 struct near_ndef_uri_payload {
127 uint32_t field_length;
131 struct near_ndef_sp_payload {
132 struct near_ndef_uri_payload *uri;
134 uint8_t number_of_title_records;
135 struct near_ndef_text_payload **title_records;
137 uint32_t size; /* from Size record*/
138 char *type; /* from Type record*/
140 /* TODO add icon and other records fields*/
143 struct near_ndef_mime_payload {
147 enum handover_carrier carrier_type;
148 uint16_t properties; /* e.g.: NO_PAIRING_KEY */
152 /* Handover record definitions */
154 /* alternative record (AC) */
155 #define AC_RECORD_PAYLOAD_LEN 4
157 struct near_ndef_ac_payload {
158 enum carrier_power_state cps; /* carrier power state */
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 */
164 /* !: if adata_refcount == 0, then there's no data reference */
165 uint16_t **adata; /* auxiliary data reference */
169 * carrier data (see cdr in near_ndef_ac_payload )
170 * These settings can be retrieved from mime, carrier records, etc...
172 struct near_ndef_carrier_data {
173 uint8_t cdr; /* carrier data reference */
178 /* Default Handover version */
179 #define HANDOVER_VERSION 0x12
180 #define HANDOVER_MAJOR(version) (((version) >> 4) & 0xf)
181 #define HANDOVER_MINOR(version) ((version) & 0xf)
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 */
189 uint8_t number_of_ac_payloads; /* At least 1 ac is needed */
190 struct near_ndef_ac_payload **ac_payloads;
192 /* Optional records */
193 uint16_t *err_record; /* not NULL if present */
195 uint8_t number_of_cfg_payloads; /* extra NDEF records */
196 struct near_ndef_mime_payload **cfg_payloads;
199 struct near_ndef_record {
202 struct near_ndef_record_header *header;
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 */
217 static DBusConnection *connection = NULL;
219 static inline void fillb8(uint8_t *ptr, uint32_t len)
221 (*(uint8_t *)(ptr)) = ((uint8_t)(len));
224 static inline void fillb16(uint8_t *ptr, uint32_t len)
226 fillb8((ptr), (uint16_t)(len) >> 8);
227 fillb8((uint8_t *)(ptr) + 1, len);
230 static inline void fillb32(uint8_t *ptr, uint32_t len)
232 fillb16((ptr), (uint32_t)(len) >> 16);
233 fillb16((uint8_t *)(ptr) + 2, (uint32_t)(len));
236 char *__near_ndef_record_get_path(struct near_ndef_record *record)
241 char *__near_ndef_record_get_type(struct near_ndef_record *record)
246 uint8_t *__near_ndef_record_get_data(struct near_ndef_record *record,
249 *len = record->data_len;
254 void __near_ndef_append_records(DBusMessageIter *iter, GList *records)
260 for (list = records; list; list = list->next) {
261 struct near_ndef_record *record = list->data;
265 data = __near_ndef_record_get_data(record, &data_len);
269 dbus_message_iter_append_fixed_array(iter, DBUS_TYPE_BYTE,
274 static void append_text_payload(struct near_ndef_text_payload *text,
275 DBusMessageIter *dict)
279 if (text == NULL || dict == NULL)
282 if (text->encoding != NULL)
283 near_dbus_dict_append_basic(dict, "Encoding",
287 if (text->language_code != NULL)
288 near_dbus_dict_append_basic(dict, "Language",
290 &(text->language_code));
292 if (text->data != NULL)
293 near_dbus_dict_append_basic(dict, "Representation",
298 static const char *uri_prefixes[NFC_MAX_URI_ID + 1] = {
306 "ftp://anonymous:anonymous@",
337 const char *__near_ndef_get_uri_prefix(uint8_t id)
339 if (id > NFC_MAX_URI_ID)
342 return uri_prefixes[id];
345 static void append_uri_payload(struct near_ndef_uri_payload *uri,
346 DBusMessageIter *dict)
349 const char *prefix = NULL;
353 if (uri == NULL || dict == NULL)
356 if (uri->identifier > NFC_MAX_URI_ID) {
357 near_error("Invalid URI identifier 0x%x", uri->identifier);
361 prefix = uri_prefixes[uri->identifier];
363 DBG("URI prefix %s", prefix);
365 value = g_strdup_printf("%s%.*s", prefix, uri->field_length,
368 near_dbus_dict_append_basic(dict, "URI", DBUS_TYPE_STRING, &value);
373 static void append_sp_payload(struct near_ndef_sp_payload *sp,
374 DBusMessageIter *dict)
380 if (sp == NULL || dict == NULL)
383 if (sp->action != NULL)
384 near_dbus_dict_append_basic(dict, "Action", DBUS_TYPE_STRING,
388 append_uri_payload(sp->uri, dict);
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);
396 if (sp->type != NULL)
397 near_dbus_dict_append_basic(dict, "MIMEType", DBUS_TYPE_STRING,
401 near_dbus_dict_append_basic(dict, "Size", DBUS_TYPE_UINT32,
405 static void append_mime_payload(struct near_ndef_mime_payload *mime,
406 DBusMessageIter *dict)
410 if (mime == NULL || dict == NULL)
413 if (mime->type != NULL)
414 near_dbus_dict_append_basic(dict, "MIME",
419 static void append_record(struct near_ndef_record *record,
420 DBusMessageIter *dict)
426 if (record == NULL || dict == NULL)
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:
440 case RECORD_TYPE_WKT_TEXT:
442 near_dbus_dict_append_basic(dict, "Type",
443 DBUS_TYPE_STRING, &type);
444 append_text_payload(record->text, dict);
447 case RECORD_TYPE_WKT_URI:
449 near_dbus_dict_append_basic(dict, "Type",
450 DBUS_TYPE_STRING, &type);
451 append_uri_payload(record->uri, dict);
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);
461 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
462 type = "HandoverRequest";
463 near_dbus_dict_append_basic(dict, "Type",
464 DBUS_TYPE_STRING, &type);
467 case RECORD_TYPE_WKT_HANDOVER_SELECT:
468 type = "HandoverSelect";
469 near_dbus_dict_append_basic(dict, "Type",
470 DBUS_TYPE_STRING, &type);
473 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
474 type = "HandoverCarrier";
475 near_dbus_dict_append_basic(dict, "Type",
476 DBUS_TYPE_STRING, &type);
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);
488 static DBusMessage *get_properties(DBusConnection *conn,
489 DBusMessage *msg, void *data)
491 struct near_ndef_record *record = data;
493 DBusMessageIter array, dict;
495 DBG("conn %p", conn);
497 if (conn == NULL || msg == NULL ||
501 reply = dbus_message_new_method_return(msg);
505 dbus_message_iter_init_append(reply, &array);
507 near_dbus_dict_open(&array, &dict);
509 append_record(record, &dict);
511 near_dbus_dict_close(&array, &dict);
516 static const GDBusMethodTable record_methods[] = {
517 { GDBUS_METHOD("GetProperties",
518 NULL, GDBUS_ARGS({"properties", "a{sv}"}),
523 static void free_text_payload(struct near_ndef_text_payload *text)
528 g_free(text->encoding);
529 g_free(text->language_code);
534 static void free_uri_payload(struct near_ndef_uri_payload *uri)
543 static void free_sp_payload(struct near_ndef_sp_payload *sp)
550 free_uri_payload(sp->uri);
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]);
557 g_free(sp->title_records);
563 static void free_mime_payload(struct near_ndef_mime_payload *mime)
572 static void free_ac_payload(struct near_ndef_ac_payload *ac)
581 static void free_ho_payload(struct near_ndef_ho_payload *ho)
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]);
593 g_free(ho->ac_payloads);
597 static void free_ndef_record(struct near_ndef_record *record)
602 g_free(record->path);
604 if (record->header != NULL) {
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:
618 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
619 case RECORD_TYPE_WKT_HANDOVER_SELECT:
620 free_ho_payload(record->ho);
623 case RECORD_TYPE_WKT_TEXT:
624 free_text_payload(record->text);
627 case RECORD_TYPE_WKT_URI:
628 free_uri_payload(record->uri);
631 case RECORD_TYPE_WKT_SMART_POSTER:
632 free_sp_payload(record->sp);
635 case RECORD_TYPE_MIME_TYPE:
636 free_mime_payload(record->mime);
639 g_free(record->header->il_field);
640 g_free(record->header->type_name);
643 g_free(record->header);
644 g_free(record->type);
645 g_free(record->data);
649 static void free_ndef_message(struct near_ndef_message *msg)
658 void __near_ndef_record_free(struct near_ndef_record *record)
660 g_dbus_unregister_interface(connection, record->path,
661 NFC_RECORD_INTERFACE);
663 free_ndef_record(record);
666 static char *action_to_string(uint8_t action)
669 case RECORD_ACTION_DO:
671 case RECORD_ACTION_SAVE:
673 case RECORD_ACTION_EDIT:
676 near_error("Unknown action 0x%x", action);
681 static enum record_type get_external_record_type(uint8_t *type,
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;
690 return RECORD_TYPE_UNKNOWN;
693 static enum record_type get_record_type(enum record_tnf tnf,
694 uint8_t *type, size_t type_length)
699 case RECORD_TNF_EMPTY:
701 case RECORD_TNF_UNKNOWN:
702 case RECORD_TNF_UNCHANGED:
705 case RECORD_TNF_WELLKNOWN:
706 if (type_length == 1) {
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;
716 return RECORD_TYPE_UNKNOWN;
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;
732 return RECORD_TYPE_UNKNOWN;
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;
740 return RECORD_TYPE_UNKNOWN;
744 case RECORD_TNF_MIME:
745 return RECORD_TYPE_MIME_TYPE;
747 case RECORD_TNF_EXTERNAL:
748 return get_external_record_type(type, type_length);
752 return RECORD_TYPE_UNKNOWN;
755 static int build_record_type_string(struct near_ndef_record *rec)
761 if (rec == NULL || rec->header == NULL)
764 tnf = rec->header->tnf;
766 if (rec->header->rec_type == RECORD_TYPE_WKT_SMART_POSTER) {
767 rec->type = g_strdup_printf(RECORD_TYPE_WKT "U");
772 case RECORD_TNF_EMPTY:
773 case RECORD_TNF_UNKNOWN:
774 case RECORD_TNF_UNCHANGED:
778 case RECORD_TNF_MIME:
779 rec->type = g_strndup(rec->header->type_name,
780 rec->header->type_len);
783 case RECORD_TNF_WELLKNOWN:
784 rec->type = g_strdup_printf(RECORD_TYPE_WKT "%s",
785 rec->header->type_name);
788 case RECORD_TNF_EXTERNAL:
789 rec->type = g_strdup_printf(RECORD_TYPE_EXTERNAL "%s",
790 rec->header->type_name);
797 static uint8_t validate_record_begin_and_end_bits(uint8_t *msg_mb,
798 uint8_t *msg_me, uint8_t rec_mb,
803 if (msg_mb == NULL || msg_me == NULL)
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]
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
842 static struct near_ndef_record_header *parse_record_header(uint8_t *rec,
843 uint32_t offset, uint32_t length)
845 struct near_ndef_record_header *rec_header = NULL;
846 uint8_t *type = NULL;
847 uint32_t header_len = 0;
849 DBG("length %d", length);
851 if (rec == NULL || offset >= length)
854 /* This check is for empty record. */
855 if ((length - offset) < NDEF_MSG_MIN_LENGTH)
858 rec_header = g_try_malloc0(sizeof(struct near_ndef_record_header));
859 if (rec_header == NULL)
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]);
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);
873 rec_header->type_len = rec[offset++];
874 header_len = 2; /* type length + header bits */
876 if (rec_header->sr == 1) {
877 rec_header->payload_len = rec[offset++];
880 rec_header->payload_len = near_get_be32(rec + offset);
884 if ((offset + rec_header->payload_len) > length)
888 DBG("payload length %d", rec_header->payload_len);
890 if (rec_header->il == 1) {
891 rec_header->il_length = rec[offset++];
894 if ((offset + rec_header->payload_len) > length)
898 if (rec_header->type_len > 0) {
899 if ((offset + rec_header->type_len) > length)
902 type = g_try_malloc0(rec_header->type_len);
906 memcpy(type, rec + offset, rec_header->type_len);
907 offset += rec_header->type_len;
908 header_len += rec_header->type_len;
910 if ((offset + rec_header->payload_len) > length)
914 if (rec_header->il_length > 0) {
915 if ((offset + rec_header->il_length) > length)
918 rec_header->il_field = g_try_malloc0(rec_header->il_length);
919 if (rec_header->il_field == NULL)
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;
927 if ((offset + rec_header->payload_len) > length)
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);
942 near_error("parsing record header failed");
945 g_free(rec_header->il_field);
946 g_free(rec_header->type_name);
952 static struct near_ndef_text_payload *
953 parse_text_payload(uint8_t *payload, uint32_t length)
955 struct near_ndef_text_payload *text_payload = NULL;
956 uint8_t status, lang_length;
965 text_payload = g_try_malloc0(sizeof(struct near_ndef_text_payload));
966 if (text_payload == NULL)
969 /* 0x80 is used to get 7th bit value (0th bit is LSB) */
970 status = ((payload[offset] & 0x80) >> 7);
972 text_payload->encoding = (status == 0) ?
973 g_strdup("UTF-8") : g_strdup("UTF-16");
975 /* 0x3F is used to get 5th-0th bits value (0th bit is LSB) */
976 lang_length = (payload[offset] & 0x3F);
979 if (lang_length > 0) {
980 if ((offset + lang_length) >= length)
983 text_payload->language_code = g_strndup(
984 (char *)(payload + offset),
987 text_payload->language_code = NULL;
990 offset += lang_length;
992 if ((length - lang_length - 1) > 0) {
993 text_payload->data = g_strndup((char *)(payload + offset),
994 length - lang_length - 1);
996 text_payload->data = NULL;
999 if (offset >= length)
1002 DBG("Encoding '%s'", text_payload->encoding);
1003 DBG("Language Code '%s'", text_payload->language_code);
1004 DBG("Data '%s'", text_payload->data);
1006 return text_payload;
1009 near_error("text payload parsing failed");
1010 free_text_payload(text_payload);
1015 static struct near_ndef_uri_payload *
1016 parse_uri_payload(uint8_t *payload, uint32_t length)
1018 struct near_ndef_uri_payload *uri_payload = NULL;
1019 uint32_t index, offset;
1023 if (payload == NULL)
1027 uri_payload = g_try_malloc0(sizeof(struct near_ndef_uri_payload));
1028 if (uri_payload == NULL)
1031 uri_payload->identifier = payload[offset];
1034 uri_payload->field_length = length - 1;
1036 if (uri_payload->field_length > 0) {
1037 uri_payload->field = g_try_malloc0(uri_payload->field_length);
1038 if (uri_payload->field == NULL)
1041 memcpy(uri_payload->field, payload + offset,
1042 uri_payload->field_length);
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)
1055 DBG("Identifier '0X%X'", uri_payload->identifier);
1056 DBG("Field '%.*s'", uri_payload->field_length, uri_payload->field);
1061 near_error("uri payload parsing failed");
1062 free_uri_payload(uri_payload);
1068 * Validate titles records language code in Smartposter.
1069 * There must not be two or more records with the same language identifier.
1071 static int8_t validate_language_code_in_sp_record(GSList *titles)
1073 uint8_t i, j, length;
1074 struct near_ndef_text_payload *title1, *title2;
1081 length = g_slist_length(titles);
1083 for (i = 0; i < length; i++) {
1084 title1 = g_slist_nth_data(titles, i);
1086 for (j = i + 1; j < length; j++) {
1087 title2 = g_slist_nth_data(titles, j);
1089 if ((title1->language_code == NULL) &&
1090 (title2->language_code == NULL))
1093 if (g_strcmp0(title1->language_code,
1094 title2->language_code) == 0)
1102 static struct near_ndef_sp_payload *
1103 parse_sp_payload(uint8_t *payload, uint32_t length)
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;
1109 GSList *titles = NULL, *temp;
1113 if (payload == NULL)
1117 sp_payload = g_try_malloc0(sizeof(struct near_ndef_sp_payload));
1118 if (sp_payload == NULL)
1121 while (offset < length) {
1123 DBG("Record header : 0x%x", payload[offset]);
1125 rec_header = parse_record_header(payload, offset, length);
1126 if (rec_header == NULL)
1129 if (validate_record_begin_and_end_bits(&mb, &me,
1130 rec_header->mb, rec_header->me) != 0) {
1131 DBG("validate mb me failed");
1135 offset = rec_header->offset;
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:
1150 case RECORD_TYPE_WKT_URI:
1151 /* URI record should be only one. */
1152 if (sp_payload->uri != NULL)
1155 sp_payload->uri = parse_uri_payload(payload + offset,
1156 rec_header->payload_len);
1157 if (sp_payload->uri == NULL)
1162 case RECORD_TYPE_WKT_TEXT:
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.
1169 struct near_ndef_text_payload *title;
1170 title = parse_text_payload(payload + offset,
1171 rec_header->payload_len);
1175 titles = g_slist_append(titles, title);
1179 case RECORD_TYPE_WKT_SIZE:
1181 * If payload length is not exactly 4 bytes
1182 * then record is wrong.
1184 if (rec_header->payload_len != 4)
1187 sp_payload->size = near_get_be32(payload + offset);
1190 case RECORD_TYPE_WKT_TYPE:
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)
1198 sp_payload->type = g_strndup(
1199 (char *) payload + offset,
1200 rec_header->payload_len);
1205 case RECORD_TYPE_WKT_ACTION:
1207 * If the action record exists, payload should be
1208 * single byte, otherwise consider it as error.
1210 if (rec_header->payload_len != 1)
1213 sp_payload->action =
1214 g_strdup(action_to_string(payload[offset]));
1219 offset += rec_header->payload_len;
1220 g_free(rec_header->il_field);
1221 g_free(rec_header->type_name);
1227 * Code to fill smart poster record structure from
1233 if (validate_language_code_in_sp_record(titles) != 0) {
1234 DBG("language code validation failed");
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)
1246 for (i = 0; i < sp_payload->number_of_title_records; i++) {
1247 sp_payload->title_records[i] = temp->data;
1251 g_slist_free(titles);
1257 near_error("smart poster payload parsing failed");
1259 if (rec_header != NULL) {
1260 g_free(rec_header->type_name);
1261 g_free(rec_header->il_field);
1265 free_sp_payload(sp_payload);
1266 g_slist_free(titles);
1271 static void correct_eir_len(struct carrier_data *data)
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.
1278 if (data->data[0] == 0) {
1279 DBG("EIR length in BE");
1280 data->data[0] = data->data[1];
1285 * Some Nokia BH-505 report total OOB block length without length field
1288 if (data->data[0] == data->size - 2) {
1289 DBG("EIR length without length field size");
1294 static int process_mime_type(struct near_ndef_mime_payload *mime,
1295 struct carrier_data *c_data)
1301 if (mime == NULL || c_data == NULL)
1304 switch (mime->handover.carrier_type) {
1305 case NEAR_CARRIER_BLUETOOTH:
1306 err = __near_agent_handover_push_data(HO_AGENT_BT, c_data);
1308 err = __near_bluetooth_parse_oob_record(c_data,
1309 &mime->handover.properties, TRUE);
1312 case NEAR_CARRIER_WIFI:
1313 err = __near_agent_handover_push_data(HO_AGENT_WIFI, c_data);
1316 case NEAR_CARRIER_EMPTY:
1317 case NEAR_CARRIER_UNKNOWN:
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)
1329 struct near_ndef_mime_payload *mime;
1330 struct carrier_data *c_temp;
1334 if (c_data == NULL || ndef_data == NULL ||
1335 ((offset + payload_length) > ndef_length))
1338 mime = g_try_malloc0(sizeof(struct near_ndef_mime_payload));
1342 c_temp = g_try_malloc0(sizeof(struct carrier_data));
1343 if (c_temp == NULL) {
1348 mime->type = g_strdup(record->header->type_name);
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);
1379 /* Set the MB bit in message header */
1380 static uint8_t near_ndef_set_mb(uint8_t *hdr, near_bool_t first_rec)
1382 /* Reset bits 0x40 */
1383 *hdr &= (0xFF & (~RECORD_MB));
1386 if (first_rec == TRUE)
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)
1395 /* Reset bits 0x80 */
1396 *hdr &= (0xFF & (~RECORD_ME));
1399 if (last_rec == TRUE)
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)
1409 near_ndef_set_mb(hdr, first_rec);
1410 return near_ndef_set_me(hdr, last_rec);
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,
1417 uint8_t payload_id_len,
1418 enum record_tnf tnf,
1419 near_bool_t first_rec,
1420 near_bool_t last_rec)
1422 struct near_ndef_message *msg;
1423 uint8_t hdr = 0, type_len, sr_bit, il_bit, id_len;
1425 msg = g_try_malloc0(sizeof(struct near_ndef_message));
1431 msg->length++; /* record header*/
1432 msg->length++; /* type name length byte*/
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)
1439 il_bit = (payload_id != NULL) ? TRUE : FALSE;
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;
1447 msg->data = g_try_malloc0(msg->length);
1448 if (msg->data == NULL)
1451 /* Set MB ME bits */
1452 hdr = near_ndef_set_mb_me(&hdr, first_rec, last_rec);
1457 hdr = RECORD_TNF_WKT_SET(hdr);
1462 case RECORD_TNF_EMPTY:
1463 hdr = RECORD_TNF_EMPTY_SET(hdr);
1466 case RECORD_TNF_URI:
1467 hdr = RECORD_TNF_URI_SET(hdr);
1470 case RECORD_TNF_EXTERNAL:
1471 hdr = RECORD_TNF_EXTERNAL_SET(hdr);
1473 case RECORD_TNF_UNKNOWN:
1474 hdr = RECORD_TNF_UKNOWN_SET(hdr);
1477 case RECORD_TNF_UNCHANGED:
1478 hdr = RECORD_TNF_UNCHANGED_SET(hdr);
1481 case RECORD_TNF_WELLKNOWN:
1482 hdr = RECORD_TNF_WKT_SET(hdr);
1485 case RECORD_TNF_MIME:
1486 hdr = RECORD_TNF_MIME_SET(hdr);
1490 msg->data[msg->offset++] = hdr;
1491 msg->data[msg->offset++] = type_len;
1493 if (sr_bit == TRUE) {
1494 msg->data[msg->offset++] = payload_len;
1496 fillb32((msg->data + msg->offset), payload_len);
1501 msg->data[msg->offset++] = payload_id_len;
1503 if (type_name != NULL) {
1504 memcpy(msg->data + msg->offset, type_name, type_len);
1505 msg->offset += type_len;
1508 if (il_bit == TRUE) {
1509 memcpy(msg->data + msg->offset, payload_id, payload_id_len);
1510 msg->offset += payload_id_len;
1516 near_error("ndef message struct allocation failed");
1517 free_ndef_message(msg);
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
1528 static struct near_ndef_message *ndef_message_alloc(char *type_name,
1529 uint32_t payload_len)
1531 return ndef_message_alloc_complete(type_name, payload_len,
1533 RECORD_TNF_WELLKNOWN,
1537 static enum carrier_power_state get_cps(uint8_t data)
1539 /* enum carrier_power_state values match binary format */
1540 return data & AC_CPS_MASK;
1543 static struct near_ndef_ac_payload *parse_ac_payload(uint8_t *payload,
1546 struct near_ndef_ac_payload *ac_payload = NULL;
1551 if (payload == NULL)
1555 ac_payload = g_try_malloc0(sizeof(struct near_ndef_ac_payload));
1556 if (ac_payload == NULL)
1560 ac_payload->cps = get_cps(payload[offset]);
1563 /* Carrier data reference length */
1564 ac_payload->cdr_len = payload[offset];
1567 /* Carrier data reference */
1568 ac_payload->cdr = payload[offset];
1569 offset = offset + ac_payload->cdr_len;
1571 /* Auxiliary data reference count */
1572 ac_payload->adata_refcount = payload[offset];
1575 if (ac_payload->adata_refcount == 0)
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)
1584 memcpy(ac_payload->adata, payload + offset,
1585 ac_payload->adata_refcount * sizeof(uint16_t));
1591 near_error("ac payload parsing failed");
1592 free_ac_payload(ac_payload);
1597 /* carrier power state & carrier reference */
1598 static struct near_ndef_message *near_ndef_prepare_ac_message(uint8_t cps,
1601 struct near_ndef_message *ac_msg;
1603 /* alloc "ac" message minus adata*/
1604 ac_msg = ndef_message_alloc_complete("ac", AC_RECORD_PAYLOAD_LEN,
1606 RECORD_TNF_WELLKNOWN,
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 */
1617 /* Check if we want an empty record */
1624 /* Collision Record message */
1625 static struct near_ndef_message *near_ndef_prepare_cr_message(uint16_t cr_id)
1627 struct near_ndef_message *cr_msg;
1629 cr_msg = ndef_message_alloc_complete("cr", sizeof(uint16_t),
1631 RECORD_TNF_WELLKNOWN,
1636 /* Prepare ac message */
1637 near_put_be16(cr_id, cr_msg->data + cr_msg->offset);
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)
1646 struct near_ndef_message *msg = NULL;
1648 DBG(" %s", mime_type);
1650 if (mime_type == NULL || data == NULL || data_len <= 0)
1653 msg = ndef_message_alloc_complete(mime_type, data_len, &cdr, cdr_len,
1654 RECORD_TNF_MIME, TRUE, TRUE);
1659 memcpy(msg->data + msg->offset, data, data_len);
1665 * Prepare alternative carrier and configuration records
1666 * (e.g. bluetooth or wifi or Hc)
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)
1674 struct carrier_data *local_carrier;
1676 char *mime_type, *carrier_string;
1681 if (ac == NULL || cfg == NULL)
1685 case NEAR_CARRIER_BLUETOOTH:
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)
1694 prop = (mime != NULL) ? mime->handover.properties :
1696 local_carrier = __near_bluetooth_local_get_properties(prop);
1700 case NEAR_CARRIER_WIFI:
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);
1708 case NEAR_CARRIER_EMPTY:
1709 case NEAR_CARRIER_UNKNOWN:
1714 if (local_carrier == NULL) {
1715 DBG("Unable to retrieve local carrier %s data", carrier_string);
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);
1723 g_free(local_carrier);
1725 if (*cfg == NULL || *ac == NULL) {
1726 free_ndef_message(*ac);
1727 free_ndef_message(*cfg);
1735 static void free_ndef_list(gpointer data)
1737 struct near_ndef_message *msg = data;
1739 free_ndef_message(msg);
1742 static struct near_ndef_message *prepare_handover_message_header(char *type,
1743 uint32_t msg_len, uint32_t payload_len)
1745 struct near_ndef_message *ho_msg;
1747 ho_msg = ndef_message_alloc(type, msg_len);
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.
1756 ho_msg->data[NDEF_PAYLOAD_LENGTH_OFFSET] = payload_len;
1757 near_ndef_set_mb_me(ho_msg->data, TRUE, FALSE);
1760 ho_msg->data[ho_msg->offset++] = HANDOVER_VERSION;
1765 static uint32_t ndef_message_list_length(GList *list)
1767 struct near_ndef_message *msg;
1768 uint32_t length = 0;
1775 length += msg->length;
1782 static void copy_ac_records(struct near_ndef_message *ho, GList *acs)
1785 struct near_ndef_message *ac;
1787 if (ho == NULL || temp == NULL)
1792 memcpy(ho->data + ho->offset, ac->data, ac->length);
1794 * AC records are part of handover message payload,
1795 * so modifying offset.
1797 ho->offset += ac->length;
1802 static void copy_cfg_records(struct near_ndef_message *ho, GList *cfgs)
1805 struct near_ndef_message *cfg;
1808 if (ho == NULL || temp == NULL)
1811 offset = ho->offset;
1815 memcpy(ho->data + offset, cfg->data, cfg->length);
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.
1821 offset += cfg->length;
1826 static void set_mb_me_to_false(gpointer data, gpointer user_data)
1828 struct near_ndef_message *msg = data;
1830 near_ndef_set_mb_me(msg->data, FALSE, FALSE);
1833 static struct near_ndef_message *near_ndef_prepare_empty_hs_message(void)
1835 struct near_ndef_message *hs_msg;
1836 struct near_ndef_message *ac_msg;
1842 ac_msg = near_ndef_prepare_ac_message(CPS_UNKNOWN, cdr);
1847 hs_length += ac_msg->length;
1849 hs_msg = prepare_handover_message_header("Hs", hs_length, hs_length);
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;
1857 if (hs_msg->offset > hs_msg->length)
1860 free_ndef_message(ac_msg);
1865 free_ndef_message(ac_msg);
1866 free_ndef_message(hs_msg);
1871 static struct near_ndef_message *near_ndef_prepare_hs_reply(
1872 GSList *remote_mimes,
1873 GSList *remote_cfgs)
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;
1888 * Preparing empty Hs message in case remote devices has zero
1889 * alternative carries or unknown mime types or unknown
1890 * configuration data.
1892 if ((remote_mimes == NULL || remote_cfgs == NULL))
1893 return near_ndef_prepare_empty_hs_message();
1895 mime_iter = remote_mimes;
1896 cfg_iter = remote_cfgs;
1899 remote_mime = mime_iter->data;
1900 remote_cfg = cfg_iter->data;
1901 if (remote_mime == NULL || remote_cfg == NULL)
1904 ret = near_ndef_prepare_ac_and_cfg_records(
1905 remote_mime->handover.carrier_type,
1907 remote_mime, remote_cfg);
1909 ac_msgs = g_list_append(ac_msgs, ac_msg);
1910 cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
1913 mime_iter = mime_iter->next;
1914 cfg_iter = cfg_iter->next;
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();
1922 /* Prepare Hs message */
1924 /* Alternative carriers are part of handover record payload length */
1925 hs_pl_length += ndef_message_list_length(ac_msgs);
1927 hs_length = hs_pl_length;
1928 /* Configuration records are part of handover message length */
1929 hs_length += ndef_message_list_length(cfg_msgs);
1931 hs_msg = prepare_handover_message_header("Hs", hs_length, hs_pl_length);
1935 num_of_carriers = g_list_length(ac_msgs);
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);
1944 temp = g_list_first(ac_msgs);
1945 ac_msg = temp->data;
1946 near_ndef_set_mb_me(ac_msg->data, TRUE, FALSE);
1948 temp = g_list_last(ac_msgs);
1949 ac_msg = temp->data;
1950 near_ndef_set_mb_me(ac_msg->data, FALSE, TRUE);
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);
1959 copy_ac_records(hs_msg, ac_msgs);
1960 if (hs_msg->offset > hs_msg->length)
1964 * copy cfgs, cfg (associated to the ac) records length
1965 * (bt or wifi) is not part of Hs initial size.
1967 copy_cfg_records(hs_msg, cfg_msgs);
1969 DBG("Hs message preparation is done");
1971 g_list_free_full(ac_msgs, free_ndef_list);
1972 g_list_free_full(cfg_msgs, free_ndef_list);
1977 near_error("handover Hs message preparation failed");
1979 g_list_free_full(ac_msgs, free_ndef_list);
1980 g_list_free_full(cfg_msgs, free_ndef_list);
1982 free_ndef_message(hs_msg);
1987 static enum handover_carrier string2carrier(char *carrier)
1989 if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_BLUETOOTH) == 0)
1990 return NEAR_CARRIER_BLUETOOTH;
1992 if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_WIFI) == 0)
1993 return NEAR_CARRIER_WIFI;
1995 return NEAR_CARRIER_UNKNOWN;
1998 static struct near_ndef_message *near_ndef_prepare_hr_message(GSList *carriers)
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;
2006 uint8_t hr_length, hr_pl_length;
2011 /* Hr message should have at least one carrier */
2013 ret = near_ndef_prepare_ac_and_cfg_records(
2014 string2carrier(carriers->data),
2015 &ac_msg, &cfg_msg, NULL, NULL);
2017 ac_msgs = g_list_append(ac_msgs, ac_msg);
2018 cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
2021 carriers = carriers->next;
2024 if (g_list_length(ac_msgs) == 0) {
2025 DBG("no alternative carriers to prepare Hr message");
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);
2035 near_ndef_set_mb_me(cr_msg->data, TRUE, FALSE);
2037 /* Prepare Hr message */
2039 hr_pl_length += cr_msg->length;
2041 /* Alternative carriers are part of handover record payload length */
2042 hr_pl_length += ndef_message_list_length(ac_msgs);
2044 hr_length = hr_pl_length;
2045 /* Configuration records are part of handover message length */
2046 hr_length += ndef_message_list_length(cfg_msgs);
2048 hr_msg = prepare_handover_message_header("Hr", hr_length, hr_pl_length);
2052 g_list_foreach(ac_msgs, set_mb_me_to_false, NULL);
2054 temp = g_list_last(ac_msgs);
2055 ac_msg = temp->data;
2056 near_ndef_set_mb_me(ac_msg->data, FALSE, TRUE);
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);
2064 memcpy(hr_msg->data + hr_msg->offset, cr_msg->data, cr_msg->length);
2065 hr_msg->offset += cr_msg->length;
2067 if (hr_msg->offset > hr_msg->length)
2071 copy_ac_records(hr_msg, ac_msgs);
2072 if (hr_msg->offset > hr_msg->length)
2076 * copy cfgs, cfg (associated to the ac) records length
2077 * (bt or wifi) is not part of Hr initial size.
2079 copy_cfg_records(hr_msg, cfg_msgs);
2081 DBG("Hr message preparation is done");
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);
2090 near_error("handover Hr record preparation failed");
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);
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)
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)
2114 for (i = 0; i < rec_count; i++) {
2115 ho->ac_payloads[i] = temp->data;
2118 ho->number_of_ac_payloads = rec_count;
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)
2128 for (i = 0; i < rec_count; i++) {
2129 ho->cfg_payloads[i] = temp->data;
2133 ho->number_of_cfg_payloads = rec_count;
2134 g_slist_free(mimes);
2138 g_free(ho->ac_payloads);
2139 g_free(ho->cfg_payloads);
2140 ho->ac_payloads = NULL;
2141 ho->cfg_payloads = NULL;
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
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)
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;
2167 int16_t count_ac = 0;
2168 near_bool_t action = FALSE, status;
2172 if (payload == NULL)
2176 /* Create the handover record payload */
2177 ho_payload = g_try_malloc0(sizeof(struct near_ndef_ho_payload));
2178 if (ho_payload == NULL)
2181 /* Version is the first mandatory field of hr payload */
2182 ho_payload->version = payload[offset];
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 */
2190 *reply = near_ndef_prepare_empty_hs_message();
2195 offset = offset + 1;
2197 /* We should work on the whole frame */
2198 ho_length = frame_length;
2200 while (offset < ho_length) {
2201 /* Create local record for mime parsing */
2202 trec = g_try_malloc0(sizeof(struct near_ndef_record));
2206 trec->header = parse_record_header(payload, offset, ho_length);
2208 if (trec->header == NULL)
2211 offset = trec->header->offset;
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:
2227 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2228 DBG("HANDOVER_CARRIER");
2230 * TODO process Hc record too !!!
2231 * Used for Wifi session
2235 case RECORD_TYPE_MIME_TYPE:
2236 DBG("TYPE_MIME_TYPE");
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");
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.
2251 if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT)
2256 /* HO payload for reply creation */
2257 trec->ho = ho_payload;
2259 mime = parse_mime_type(trec, payload, frame_length,
2260 offset, trec->header->payload_len,
2264 if (mime == NULL || c_data == NULL)
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);
2277 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2278 DBG("COLLISION_RESOLUTION");
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");
2287 ho_payload->collision_record =
2288 near_get_be16(payload + offset);
2292 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2293 DBG("ALTERNATIVE_CARRIER");
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");
2302 ac = parse_ac_payload(payload + offset,
2303 trec->header->payload_len);
2307 acs = g_slist_append(acs, ac);
2309 /* TODO check if adata are present */
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;
2325 * In case of multiple carriers, handover with any carrier
2326 * gets done then leave the loop.
2328 if (action == TRUE) {
2330 count_ac = g_slist_length(mimes);
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) {
2340 if (status == FALSE) {
2341 DBG("could not process alternative carriers");
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");
2353 if ((acs == NULL) || (mimes == NULL))
2356 /* Save the records */
2357 if (near_fill_ho_payload(ho_payload, acs, mimes) < 0)
2360 DBG("handover payload parsing complete");
2362 g_slist_free_full(c_datas, g_free);
2367 near_error("handover payload parsing failed");
2370 if (trec->header != NULL) {
2371 g_free(trec->header->type_name);
2372 g_free(trec->header->il_field);
2373 g_free(trec->header);
2378 g_slist_free_full(c_datas, g_free);
2379 free_ho_payload(ho_payload);
2384 int __near_ndef_record_register(struct near_ndef_record *record, char *path)
2386 record->path = path;
2388 g_dbus_register_interface(connection, record->path,
2389 NFC_RECORD_INTERFACE,
2398 * These functions parse a specific type record (id or mime) to find the
2399 * associated string.
2401 near_bool_t near_ndef_record_cmp_id(struct near_ndef_record *rec1,
2402 struct near_ndef_record *rec2)
2406 if ((rec1 == NULL) || (rec2 == NULL))
2409 if ((rec1->header == NULL) || (rec2->header == NULL))
2413 if ((rec1->header->il_field == NULL) ||
2414 (rec2->header->il_field == NULL))
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)
2426 near_bool_t near_ndef_record_cmp_mime(struct near_ndef_record *rec1,
2427 struct near_ndef_record *rec2)
2432 if ((rec1 == NULL) || (rec2 == NULL))
2435 if ((rec1->header == NULL) || (rec2->header == NULL))
2438 if ((rec1->mime == NULL) || (rec2->mime == NULL))
2441 if ((rec1->mime->type == NULL) || (rec2->mime->type == NULL))
2444 if (strlen(rec1->mime->type) != strlen(rec2->mime->type))
2447 if ((g_strcmp0(rec1->mime->type, rec2->mime->type) != 0))
2453 /* helper to get the record data length */
2454 size_t near_ndef_data_length(struct near_ndef_record *rec)
2459 return rec->data_len;
2462 /* helper to get the record data pointer */
2463 uint8_t *near_ndef_data_ptr(struct near_ndef_record *rec)
2471 GList *near_ndef_parse_msg(uint8_t *ndef_data, size_t ndef_length,
2472 struct near_ndef_message **reply)
2475 uint8_t p_mb = 0, p_me = 0, *record_start;
2477 struct near_ndef_record *record = NULL;
2478 struct carrier_data *c_data;
2484 if (ndef_data == NULL ||
2485 ndef_length < NDEF_MSG_MIN_LENGTH)
2488 while (offset < ndef_length) {
2490 DBG("Record Header : 0x%X", ndef_data[offset]);
2492 record = g_try_malloc0(sizeof(struct near_ndef_record));
2496 record->header = parse_record_header(ndef_data, offset,
2498 if (record->header == NULL)
2501 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2503 record->header->me) != 0) {
2504 DBG("validate mb me failed");
2508 record_start = ndef_data + offset;
2509 offset = record->header->offset;
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:
2523 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2524 case RECORD_TYPE_WKT_HANDOVER_SELECT:
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
2531 record->ho = parse_ho_payload(record->header->rec_type,
2533 record->header->payload_len,
2534 ndef_length - offset,
2535 record->header->mb, record->header->me,
2537 if (record->ho == NULL)
2540 /* the complete frame is processed, break the loop */
2541 record->header->payload_len = ndef_length;
2544 case RECORD_TYPE_WKT_TEXT:
2545 record->text = parse_text_payload(ndef_data + offset,
2546 record->header->payload_len);
2548 if (record->text == NULL)
2553 case RECORD_TYPE_WKT_URI:
2554 record->uri = parse_uri_payload(ndef_data + offset,
2555 record->header->payload_len);
2557 if (record->uri == NULL)
2562 case RECORD_TYPE_WKT_SMART_POSTER:
2563 record->sp = parse_sp_payload(
2565 record->header->payload_len);
2567 if (record->sp == NULL)
2572 case RECORD_TYPE_MIME_TYPE:
2573 record->mime = parse_mime_type(record, ndef_data,
2574 ndef_length, offset,
2575 record->header->payload_len,
2577 if (record->mime == NULL)
2580 /* No carrier data, move on */
2584 if (process_mime_type(record->mime, c_data) < 0) {
2595 record->data_len = record->header->header_len +
2596 record->header->payload_len;
2598 record->data = g_try_malloc0(record->data_len);
2599 if (record->data == NULL)
2602 memcpy(record->data, record_start, record->data_len);
2604 records = g_list_append(records, record);
2606 build_record_type_string(record);
2608 offset += record->header->payload_len;
2614 near_error("ndef parsing failed");
2615 free_ndef_record(record);
2620 void near_ndef_records_free(GList *records)
2624 for (list = records; list; list = list->next) {
2625 struct near_ndef_record *record = list->data;
2627 __near_ndef_record_free(record);
2630 g_list_free(records);
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
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
2645 int near_ndef_record_length(uint8_t *ndef_in, size_t ndef_in_length)
2647 int ndef_size; /* default size for NDEF hdr + rec typ len + payl */
2653 if (ndef_in_length < 3)
2659 /* save header byte */
2660 hdr = ndef_in[offset];
2663 /* header->type_len */
2664 ndef_size += ndef_in[offset++];
2666 /* header->payload_len */
2667 if (RECORD_SR_BIT(hdr) == 1) {
2668 ndef_size += ndef_in[offset++];
2670 ndef_size += near_get_be32(ndef_in + offset);
2673 if (offset >= ndef_in_length)
2678 ndef_size += RECORD_IL_BIT(hdr);
2680 /* header->il_length */
2681 if (RECORD_IL_BIT(hdr) == 1)
2682 ndef_size += ndef_in[offset++];
2684 DBG("near_ndef_message_length is %d", ndef_size);
2689 int near_ndef_count_records(uint8_t *ndef_in, size_t ndef_in_length,
2690 uint8_t record_type)
2692 uint8_t p_mb = 0, p_me = 0;
2695 struct near_ndef_record *record = NULL;
2696 int counted_records = 0 ;
2702 if (ndef_in == NULL || ndef_in_length < NDEF_MSG_MIN_LENGTH) {
2707 while (offset < ndef_in_length) {
2708 record = g_try_malloc0(sizeof(struct near_ndef_record));
2709 if (record == NULL) {
2714 /* Create a record */
2715 record->header = parse_record_header(ndef_in, offset,
2717 if (record->header == NULL) {
2722 /* Validate MB ME */
2723 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2725 record->header->me) != 0) {
2726 DBG("validate mb me failed");
2731 /* Is this what we want ? */
2732 if (record->header->rec_type == record_type)
2735 /* Jump to the next record */
2736 offset = record->header->offset + record->header->payload_len;
2738 free_ndef_record(record);
2741 DBG("Type %d Records found: %d", record_type, counted_records);
2743 return counted_records;
2746 near_error("ndef counting failed");
2747 free_ndef_record(record);
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)
2755 struct near_ndef_message *msg;
2756 uint32_t text_len, payload_length;
2757 uint8_t code_len, status = 0;
2761 /* Validate input parameters*/
2762 if (((g_strcmp0(encoding, "UTF-8") != 0) &&
2763 (g_strcmp0(encoding, "UTF-16") != 0)) ||
2764 (language_code == NULL) ||
2769 code_len = strlen(language_code);
2770 text_len = strlen(text);
2771 payload_length = 1 + code_len + text_len;
2773 msg = ndef_message_alloc("T", payload_length);
2777 if (g_strcmp0(encoding, "UTF-16") == 0)
2778 status |= NDEF_TEXT_RECORD_UTF16_STATUS;
2780 status = status | code_len;
2781 msg->data[msg->offset++] = status;
2784 memcpy(msg->data + msg->offset, language_code, code_len);
2786 msg->offset += code_len;
2789 memcpy(msg->data + msg->offset, text, text_len);
2791 msg->offset += text_len;
2793 if (msg->offset > msg->length)
2799 near_error("text record preparation failed");
2800 free_ndef_message(msg);
2805 struct near_ndef_message *near_ndef_prepare_uri_record(uint8_t identifier,
2806 uint32_t field_length, uint8_t *field)
2808 struct near_ndef_message *msg = NULL;
2809 uint32_t payload_length;
2813 /* Validate input parameters*/
2814 if ((field_length == 0 && field != NULL) ||
2815 (field_length != 0 && field == NULL)) {
2819 payload_length = field_length + 1;
2821 msg = ndef_message_alloc("U", payload_length);
2825 msg->data[msg->offset++] = identifier;
2827 if (field_length > 0) {
2828 memcpy(msg->data + msg->offset, field, field_length);
2829 msg->offset += field_length;
2832 if (msg->offset > msg->length)
2838 near_error("uri record preparation failed");
2839 free_ndef_message(msg);
2844 struct near_ndef_message *
2845 near_ndef_prepare_smartposter_record(uint8_t uri_identifier,
2846 uint32_t uri_field_length,
2849 struct near_ndef_message *msg = NULL, *uri = NULL;
2851 /* URI is mandatory in Smartposter */
2852 uri = near_ndef_prepare_uri_record(uri_identifier, uri_field_length,
2857 /* URI record length is equal to payload length of Sp record */
2858 msg = ndef_message_alloc("Sp", uri->length);
2862 memcpy(msg->data + msg->offset, uri->data, uri->length);
2863 msg->offset += uri->length;
2865 if (msg->offset > msg->length)
2868 free_ndef_message(uri);
2873 near_error("smartposter record preparation failed");
2875 free_ndef_message(uri);
2876 free_ndef_message(msg);
2881 static char *get_text_field(DBusMessage *msg, char *text)
2883 DBusMessageIter iter, arr_iter;
2891 dbus_message_iter_init(msg, &iter);
2892 dbus_message_iter_recurse(&iter, &arr_iter);
2894 while (dbus_message_iter_get_arg_type(&arr_iter) !=
2895 DBUS_TYPE_INVALID) {
2897 DBusMessageIter ent_iter;
2898 DBusMessageIter var_iter;
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);
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);
2913 dbus_message_iter_next(&arr_iter);
2919 static inline char *get_uri_field(DBusMessage *msg)
2921 return get_text_field(msg, "URI");
2924 static GSList *get_carrier_field(DBusMessage *msg)
2928 GSList *carriers = NULL;
2929 uint8_t num_of_carriers, i;
2933 carrier = get_text_field(msg, "Carrier");
2934 if (carrier == NULL)
2937 arr = g_strsplit(carrier, ",", NEAR_CARRIER_MAX);
2938 num_of_carriers = g_strv_length(arr);
2940 for (i = 0; i < num_of_carriers; i++)
2941 carriers = g_slist_append(carriers, g_strdup(arr[i]));
2948 static struct near_ndef_message *build_text_record(DBusMessage *msg)
2950 DBusMessageIter iter, arr_iter;
2951 char *cod = NULL, *lang = NULL, *rep = NULL;
2955 dbus_message_iter_init(msg, &iter);
2956 dbus_message_iter_recurse(&iter, &arr_iter);
2958 while (dbus_message_iter_get_arg_type(&arr_iter) !=
2959 DBUS_TYPE_INVALID) {
2961 DBusMessageIter ent_iter;
2962 DBusMessageIter var_iter;
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);
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);
2981 dbus_message_iter_next(&arr_iter);
2984 return near_ndef_prepare_text_record(cod, lang, rep);
2987 static struct near_ndef_message *build_uri_record(DBusMessage *msg)
2990 const char *uri_prefix = NULL;
2991 uint8_t id_len, i, id;
2996 uri = get_uri_field(msg);
3003 for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3004 uri_prefix = __near_ndef_get_uri_prefix(i);
3006 if (uri_prefix != NULL &&
3007 g_str_has_prefix(uri, uri_prefix) == TRUE) {
3009 id_len = strlen(uri_prefix);
3014 DBG("%d %d\n", i, id_len);
3016 uri_len = strlen(uri) - id_len;
3017 return near_ndef_prepare_uri_record(id, uri_len,
3018 (uint8_t *)(uri + id_len));
3021 static struct near_ndef_message *build_sp_record(DBusMessage *msg)
3024 const char *uri_prefix;
3031 * Currently this function supports only mandatory URI record,
3032 * TODO: Other records support.
3034 uri = get_uri_field(msg);
3038 for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3039 uri_prefix = __near_ndef_get_uri_prefix(i);
3041 if (uri_prefix != NULL &&
3042 g_str_has_prefix(uri, uri_prefix) == TRUE)
3046 if (uri_prefix == NULL) {
3050 id_len = strlen(uri_prefix);
3052 uri_len = strlen(uri) - id_len;
3053 return near_ndef_prepare_smartposter_record(i, uri_len,
3054 (uint8_t *)(uri + id_len));
3057 static struct near_ndef_message *build_hr_record(DBusMessage *msg)
3059 struct near_ndef_message *hr;
3064 carriers = get_carrier_field(msg);
3065 hr = near_ndef_prepare_hr_message(carriers);
3066 g_slist_free_full(carriers, g_free);
3071 static int fill_wifi_wsc_data(uint8_t *tlv, uint16_t id,
3072 uint16_t data_len, uint8_t *data)
3076 if (tlv == NULL || data == NULL)
3080 offset += WIFI_WSC_ID_LENGTH;
3082 fillb16(tlv + offset, data_len);
3083 offset += WIFI_WSC_ID_DATA_LENGTH;
3085 memcpy(tlv + offset, data, data_len);
3091 static void get_wsc_data(DBusMessageIter iter, char **ssid, char **pass)
3098 while (dbus_message_iter_get_arg_type(&iter) !=
3099 DBUS_TYPE_INVALID) {
3101 DBusMessageIter ent_iter;
3102 DBusMessageIter var_iter;
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);
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);
3119 dbus_message_iter_next(&iter);
3123 struct near_ndef_message *near_ndef_prepare_wsc_record(char *ssid,
3126 uint16_t ssid_len, pass_len, key_type;
3127 uint8_t temp_key[2];
3129 uint32_t tlv_len, offset;
3130 struct near_ndef_message *mime;
3132 /* At least SSID is required in case of open network */
3136 DBG("SSID %s Passphrase %s", ssid, passphrase);
3138 /* Prepare TLV from ssid and passphrasse */
3139 ssid_len = strlen(ssid);
3141 if (passphrase != NULL) {
3142 pass_len = strlen(passphrase);
3143 key_type = WIFI_WSC_KEY_PSK;
3146 key_type = WIFI_WSC_KEY_OPEN;
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;
3158 tlv = g_try_malloc0(tlv_len);
3164 offset += fill_wifi_wsc_data(tlv, WIFI_WSC_ID_SSID,
3165 ssid_len, (uint8_t *) ssid);
3168 * copy authentication type
3169 * copy key type to temp key array to maintain endianess
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);
3177 /* copy Network Key */
3178 if (passphrase != NULL)
3179 offset += fill_wifi_wsc_data(tlv + offset, WIFI_WSC_ID_KEY,
3181 (uint8_t *) passphrase);
3183 mime = ndef_message_alloc_complete(WIFI_WSC_MIME_STRING, tlv_len, NULL,
3184 0, RECORD_TNF_MIME, TRUE, TRUE);
3190 memcpy(mime->data + mime->offset, tlv, tlv_len);
3196 static struct near_ndef_message *build_mime_record(DBusMessage *msg)
3198 DBusMessageIter iter, arr_iter;
3199 char *key, *mime_str, *ssid, *passphrase;
3203 dbus_message_iter_init(msg, &iter);
3204 dbus_message_iter_recurse(&iter, &arr_iter);
3206 while (dbus_message_iter_get_arg_type(&arr_iter) !=
3207 DBUS_TYPE_INVALID) {
3208 DBusMessageIter ent_iter;
3209 DBusMessageIter var_iter;
3211 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3212 dbus_message_iter_get_basic(&ent_iter, &key);
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);
3219 if (g_strcmp0(mime_str, WIFI_WSC_MIME_STRING) == 0) {
3220 struct near_ndef_message *mime;
3221 struct carrier_data *carrier;
3223 get_wsc_data(arr_iter, &ssid, &passphrase);
3225 return near_ndef_prepare_wsc_record(
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.
3233 carrier = __near_agent_handover_request_data(
3234 HO_AGENT_WIFI, NULL);
3235 if (carrier == NULL)
3238 mime = ndef_message_alloc_complete(
3239 WIFI_WSC_MIME_STRING, carrier->size,
3240 NULL, 0, RECORD_TNF_MIME, TRUE, TRUE);
3246 memcpy(mime->data + mime->offset,
3247 carrier->data, carrier->size);
3256 dbus_message_iter_next(&arr_iter);
3262 struct near_ndef_message *__ndef_build_from_message(DBusMessage *msg)
3264 DBusMessageIter iter;
3265 DBusMessageIter arr_iter;
3266 struct near_ndef_message *ndef;
3270 dbus_message_iter_init(msg, &iter);
3271 dbus_message_iter_recurse(&iter, &arr_iter);
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;
3281 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3282 dbus_message_iter_get_basic(&ent_iter, &key);
3284 if (g_strcmp0(key, "Type") != 0) {
3285 dbus_message_iter_next(&arr_iter);
3289 dbus_message_iter_next(&ent_iter);
3290 dbus_message_iter_recurse(&ent_iter, &var_iter);
3292 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3293 case DBUS_TYPE_STRING:
3294 dbus_message_iter_get_basic(&var_iter, &value);
3296 if (g_strcmp0(value, "Text") == 0) {
3297 ndef = build_text_record(msg);
3299 } else if (g_strcmp0(value, "URI") == 0) {
3300 ndef = build_uri_record(msg);
3302 } else if (g_strcmp0(value, "SmartPoster") == 0) {
3303 ndef = build_sp_record(msg);
3305 } else if (g_strcmp0(value, "Handover") == 0) {
3306 ndef = build_hr_record(msg);
3308 } else if (g_strcmp0(value, "MIME") == 0) {
3309 ndef = build_mime_record(msg);
3312 near_error("%s not supported", value);
3320 dbus_message_iter_next(&arr_iter);
3326 int __near_ndef_init(void)
3330 connection = near_dbus_get_connection();
3335 void __near_ndef_cleanup(void)