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_EXT_AAR = 0x0e,
95 RECORD_TYPE_UNKNOWN = 0xfe,
96 RECORD_TYPE_ERROR = 0xff
99 #define RECORD_TYPE_WKT "urn:nfc:wkt:"
100 #define RECORD_TYPE_EXTERNAL "urn:nfc:ext:"
101 #define AAR_STRING "android.com:pkg"
103 struct near_ndef_record_header {
112 uint32_t payload_len;
115 enum record_type rec_type;
120 struct near_ndef_text_payload {
126 struct near_ndef_uri_payload {
129 uint32_t field_length;
133 struct near_ndef_sp_payload {
134 struct near_ndef_uri_payload *uri;
136 uint8_t number_of_title_records;
137 struct near_ndef_text_payload **title_records;
139 uint32_t size; /* from Size record*/
140 char *type; /* from Type record*/
142 /* TODO add icon and other records fields*/
145 struct near_ndef_mime_payload {
149 enum handover_carrier carrier_type;
150 uint16_t properties; /* e.g.: NO_PAIRING_KEY */
154 /* Handover record definitions */
156 /* alternative record (AC) length based on cdr length without adata */
157 #define AC_RECORD_PAYLOAD_LEN(cdr_len) (3 + cdr_len)
159 struct near_ndef_ac_payload {
160 enum carrier_power_state cps; /* carrier power state */
162 uint8_t cdr_len; /* carrier data reference length */
163 uint8_t *cdr; /* carrier data reference */
164 uint8_t adata_refcount; /* auxiliary data reference count */
166 /* !: if adata_refcount == 0, then there's no data reference */
167 uint16_t **adata; /* auxiliary data reference */
170 /* Default Handover version */
171 #define HANDOVER_VERSION 0x12
172 #define HANDOVER_MAJOR(version) (((version) >> 4) & 0xf)
173 #define HANDOVER_MINOR(version) ((version) & 0xf)
176 /* General Handover Request/Select record */
177 struct near_ndef_ho_payload {
178 uint8_t version; /* version id */
179 uint16_t collision_record; /* collision record */
181 uint8_t number_of_ac_payloads; /* At least 1 ac is needed */
182 struct near_ndef_ac_payload **ac_payloads;
184 /* Optional records */
185 uint16_t *err_record; /* not NULL if present */
187 uint8_t number_of_cfg_payloads; /* extra NDEF records */
188 struct near_ndef_mime_payload **cfg_payloads;
191 struct near_ndef_aar_payload {
195 struct near_ndef_record {
198 struct near_ndef_record_header *header;
200 /* specific payloads */
201 struct near_ndef_text_payload *text;
202 struct near_ndef_uri_payload *uri;
203 struct near_ndef_sp_payload *sp;
204 struct near_ndef_mime_payload *mime;
205 struct near_ndef_ho_payload *ho; /* handover payload */
206 struct near_ndef_aar_payload *aar;
214 static DBusConnection *connection = NULL;
216 static inline void fillb8(uint8_t *ptr, uint32_t len)
218 (*(uint8_t *)(ptr)) = ((uint8_t)(len));
221 static inline void fillb16(uint8_t *ptr, uint32_t len)
223 fillb8((ptr), (uint16_t)(len) >> 8);
224 fillb8((uint8_t *)(ptr) + 1, len);
227 static inline void fillb32(uint8_t *ptr, uint32_t len)
229 fillb16((ptr), (uint32_t)(len) >> 16);
230 fillb16((uint8_t *)(ptr) + 2, (uint32_t)(len));
233 char *__near_ndef_record_get_path(struct near_ndef_record *record)
238 char *__near_ndef_record_get_type(struct near_ndef_record *record)
243 uint8_t *__near_ndef_record_get_data(struct near_ndef_record *record,
246 *len = record->data_len;
251 uint8_t *__near_ndef_record_get_payload(struct near_ndef_record *record,
254 *len = record->header->payload_len;
256 return record->data + record->header->header_len;
259 void __near_ndef_append_records(DBusMessageIter *iter, GList *records)
265 for (list = records; list; list = list->next) {
266 struct near_ndef_record *record = list->data;
270 data = __near_ndef_record_get_data(record, &data_len);
274 dbus_message_iter_append_fixed_array(iter, DBUS_TYPE_BYTE,
279 static const char *uri_prefixes[NFC_MAX_URI_ID + 1] = {
287 "ftp://anonymous:anonymous@",
318 const char *__near_ndef_get_uri_prefix(uint8_t id)
320 if (id > NFC_MAX_URI_ID)
323 return uri_prefixes[id];
326 static gboolean property_get_type(const GDBusPropertyTable *property,
327 DBusMessageIter *iter, void *user_data)
329 struct near_ndef_record *record = user_data;
334 switch (record->header->rec_type) {
335 case RECORD_TYPE_WKT_SIZE:
336 case RECORD_TYPE_WKT_TYPE:
337 case RECORD_TYPE_WKT_ACTION:
338 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
339 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
340 case RECORD_TYPE_WKT_ERROR:
341 case RECORD_TYPE_UNKNOWN:
342 case RECORD_TYPE_ERROR:
346 case RECORD_TYPE_WKT_TEXT:
350 case RECORD_TYPE_WKT_URI:
354 case RECORD_TYPE_WKT_SMART_POSTER:
355 type = "SmartPoster";
358 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
359 type = "HandoverRequest";
362 case RECORD_TYPE_WKT_HANDOVER_SELECT:
363 type = "HandoverSelect";
366 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
367 type = "HandoverCarrier";
370 case RECORD_TYPE_MIME_TYPE:
374 case RECORD_TYPE_EXT_AAR:
382 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &type);
387 static gboolean text_exists(const GDBusPropertyTable *property, void *data)
389 struct near_ndef_record *record = data;
396 if (record->sp && record->sp->title_records)
404 static const char *get_text_payload(const GDBusPropertyTable *property,
405 struct near_ndef_text_payload *text)
407 if (!strcmp(property->name, "Encoding"))
408 return text->encoding;
409 else if (!strcmp(property->name, "Language"))
410 return text->language_code;
411 else if (!strcmp(property->name, "Representation"))
417 static gboolean property_get_text(const GDBusPropertyTable *property,
418 DBusMessageIter *iter, void *user_data)
420 struct near_ndef_record *record = user_data;
426 text = get_text_payload(property, record->text);
430 DBG("text %s", text);
432 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &text);
437 if (record->sp && record->sp->title_records) {
440 for (i = 0; i < record->sp->number_of_title_records; i++) {
441 text = get_text_payload(property,
442 record->sp->title_records[i]);
446 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
456 static gboolean uri_exists(const GDBusPropertyTable *property, void *data)
458 struct near_ndef_record *record = data;
465 if (record->sp && record->sp->uri)
473 static gboolean property_get_uri(const GDBusPropertyTable *property,
474 DBusMessageIter *iter, void *user_data)
476 struct near_ndef_record *record = user_data;
477 struct near_ndef_uri_payload *uri;
479 const char *prefix = NULL;
485 else if (record->sp && record->sp->uri)
486 uri = record->sp->uri;
490 if (uri->identifier > NFC_MAX_URI_ID) {
491 near_error("Invalid URI identifier 0x%x", uri->identifier);
495 prefix = uri_prefixes[uri->identifier];
497 DBG("URI prefix %s", prefix);
499 value = g_strdup_printf("%s%.*s", prefix, uri->field_length,
502 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &value);
509 static gboolean sp_action_exists(const GDBusPropertyTable *property,
512 struct near_ndef_record *record = data;
516 if (record->sp && record->sp->action)
519 DBG("No SmartPoster action");
524 static gboolean sp_mime_exists(const GDBusPropertyTable *property, void *data)
526 struct near_ndef_record *record = data;
530 if (record->sp && record->sp->type)
533 DBG("No SmartPoster MIME type");
538 static gboolean sp_size_exists(const GDBusPropertyTable *property, void *data)
540 struct near_ndef_record *record = data;
544 if (record->sp && record->sp->size)
547 DBG("No SmartPoster size");
552 static gboolean property_get_action(const GDBusPropertyTable *property,
553 DBusMessageIter *iter, void *user_data)
555 struct near_ndef_record *record = user_data;
557 DBG("%s", record->sp->action);
559 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->sp->action);
564 static gboolean property_get_mime_type(const GDBusPropertyTable *property,
565 DBusMessageIter *iter, void *user_data)
567 struct near_ndef_record *record = user_data;
569 DBG("%s", record->sp->type);
571 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->sp->type);
576 static gboolean property_get_size(const GDBusPropertyTable *property,
577 DBusMessageIter *iter, void *user_data)
579 struct near_ndef_record *record = user_data;
581 DBG("%d", record->sp->size);
583 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &record->sp->size);
588 static gboolean mime_exists(const GDBusPropertyTable *property, void *data)
590 struct near_ndef_record *record = data;
602 static gboolean property_get_mime(const GDBusPropertyTable *property,
603 DBusMessageIter *iter, void *user_data)
605 struct near_ndef_record *record = user_data;
609 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->mime->type);
614 static gboolean aar_exists(const GDBusPropertyTable *property, void *data)
616 struct near_ndef_record *record = data;
628 static gboolean property_get_aar(const GDBusPropertyTable *property,
629 DBusMessageIter *iter, void *user_data)
631 struct near_ndef_record *record = user_data;
635 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &record->aar->package);
640 static const GDBusPropertyTable record_properties[] = {
642 { "Type", "s", property_get_type },
643 { "Encoding", "s", property_get_text, NULL, text_exists },
644 { "Language", "s", property_get_text, NULL, text_exists },
645 { "Representation", "s", property_get_text, NULL, text_exists},
646 { "URI", "s", property_get_uri, NULL, uri_exists },
647 { "Action", "s", property_get_action, NULL, sp_action_exists },
648 { "MIMEType", "s", property_get_mime_type, NULL, sp_mime_exists },
649 { "Size", "u", property_get_size, NULL, sp_size_exists },
650 { "MIME", "s", property_get_mime, NULL, mime_exists },
651 { "AAR", "s", property_get_aar, NULL, aar_exists },
655 static void free_text_payload(struct near_ndef_text_payload *text)
660 g_free(text->encoding);
661 g_free(text->language_code);
666 static void free_uri_payload(struct near_ndef_uri_payload *uri)
675 static void free_sp_payload(struct near_ndef_sp_payload *sp)
682 free_uri_payload(sp->uri);
684 if (sp->title_records) {
685 for (i = 0; i < sp->number_of_title_records; i++)
686 free_text_payload(sp->title_records[i]);
689 g_free(sp->title_records);
695 static void free_mime_payload(struct near_ndef_mime_payload *mime)
704 static void free_ac_payload(struct near_ndef_ac_payload *ac)
714 static void free_ho_payload(struct near_ndef_ho_payload *ho)
721 if (ho->ac_payloads) {
722 for (i = 0; i < ho->number_of_ac_payloads; i++)
723 free_ac_payload(ho->ac_payloads[i]);
726 g_free(ho->ac_payloads);
730 static void free_aar_payload(struct near_ndef_aar_payload *aar)
735 g_free(aar->package);
739 static void free_ndef_record(struct near_ndef_record *record)
744 g_free(record->path);
746 if (record->header) {
748 switch (record->header->rec_type) {
749 case RECORD_TYPE_WKT_SIZE:
750 case RECORD_TYPE_WKT_TYPE:
751 case RECORD_TYPE_WKT_ACTION:
752 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
753 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
754 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
755 case RECORD_TYPE_WKT_ERROR:
756 case RECORD_TYPE_UNKNOWN:
757 case RECORD_TYPE_ERROR:
760 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
761 case RECORD_TYPE_WKT_HANDOVER_SELECT:
762 free_ho_payload(record->ho);
765 case RECORD_TYPE_WKT_TEXT:
766 free_text_payload(record->text);
769 case RECORD_TYPE_WKT_URI:
770 free_uri_payload(record->uri);
773 case RECORD_TYPE_WKT_SMART_POSTER:
774 free_sp_payload(record->sp);
777 case RECORD_TYPE_MIME_TYPE:
778 free_mime_payload(record->mime);
781 case RECORD_TYPE_EXT_AAR:
782 free_aar_payload(record->aar);
786 g_free(record->header->il_field);
787 g_free(record->header->type_name);
790 g_free(record->header);
791 g_free(record->type);
792 g_free(record->data);
796 static void free_ndef_message(struct near_ndef_message *msg)
805 void __near_ndef_record_free(struct near_ndef_record *record)
807 g_dbus_unregister_interface(connection, record->path,
808 NFC_RECORD_INTERFACE);
810 free_ndef_record(record);
813 static char *action_to_string(uint8_t action)
816 case RECORD_ACTION_DO:
818 case RECORD_ACTION_SAVE:
820 case RECORD_ACTION_EDIT:
823 near_error("Unknown action 0x%x", action);
828 static enum record_type get_external_record_type(uint8_t *type,
833 if (strncmp((char *) type, BT_MIME_STRING_2_0,
834 sizeof(BT_MIME_STRING_2_0) - 1) == 0)
835 return RECORD_TYPE_MIME_TYPE;
836 else if (strncmp((char *) type, AAR_STRING,
837 sizeof(AAR_STRING) - 1) == 0)
838 return RECORD_TYPE_EXT_AAR;
840 return RECORD_TYPE_UNKNOWN;
843 static enum record_type get_record_type(enum record_tnf tnf,
844 uint8_t *type, size_t type_length)
849 case RECORD_TNF_EMPTY:
851 case RECORD_TNF_UNKNOWN:
852 case RECORD_TNF_UNCHANGED:
855 case RECORD_TNF_WELLKNOWN:
856 if (type_length == 1) {
858 return RECORD_TYPE_WKT_TEXT;
859 else if (type[0] == 'U')
860 return RECORD_TYPE_WKT_URI;
861 else if (type[0] == 's')
862 return RECORD_TYPE_WKT_SIZE;
863 else if (type[0] == 't')
864 return RECORD_TYPE_WKT_TYPE;
866 return RECORD_TYPE_UNKNOWN;
868 } else if (type_length == 2) {
869 if (strncmp((char *)type, "Sp", 2) == 0)
870 return RECORD_TYPE_WKT_SMART_POSTER;
871 else if (strncmp((char *) type, "Hr", 2) == 0)
872 return RECORD_TYPE_WKT_HANDOVER_REQUEST;
873 else if (strncmp((char *) type, "Hs", 2) == 0)
874 return RECORD_TYPE_WKT_HANDOVER_SELECT;
875 else if (strncmp((char *) type, "Hc", 2) == 0)
876 return RECORD_TYPE_WKT_HANDOVER_CARRIER;
877 else if (strncmp((char *) type, "ac", 2) == 0)
878 return RECORD_TYPE_WKT_ALTERNATIVE_CARRIER;
879 else if (strncmp((char *) type, "cr", 2) == 0)
880 return RECORD_TYPE_WKT_COLLISION_RESOLUTION;
882 return RECORD_TYPE_UNKNOWN;
884 } else if (type_length == 3) {
885 if (strncmp((char *)type, "act", 3) == 0)
886 return RECORD_TYPE_WKT_ACTION;
887 else if (strncmp((char *)type, "err", 3) == 0)
888 return RECORD_TYPE_WKT_ERROR;
890 return RECORD_TYPE_UNKNOWN;
894 case RECORD_TNF_MIME:
895 return RECORD_TYPE_MIME_TYPE;
897 case RECORD_TNF_EXTERNAL:
898 return get_external_record_type(type, type_length);
902 return RECORD_TYPE_UNKNOWN;
905 static int build_record_type_string(struct near_ndef_record *rec)
911 if (!rec || !rec->header)
914 tnf = rec->header->tnf;
916 if (rec->header->rec_type == RECORD_TYPE_WKT_SMART_POSTER) {
917 rec->type = g_strdup_printf(RECORD_TYPE_WKT "U");
922 case RECORD_TNF_EMPTY:
923 case RECORD_TNF_UNKNOWN:
924 case RECORD_TNF_UNCHANGED:
928 case RECORD_TNF_MIME:
929 rec->type = g_strndup(rec->header->type_name,
930 rec->header->type_len);
933 case RECORD_TNF_WELLKNOWN:
934 rec->type = g_strdup_printf(RECORD_TYPE_WKT "%s",
935 rec->header->type_name);
938 case RECORD_TNF_EXTERNAL:
939 rec->type = g_strdup_printf(RECORD_TYPE_EXTERNAL "%s",
940 rec->header->type_name);
947 static uint8_t validate_record_begin_and_end_bits(uint8_t *msg_mb,
948 uint8_t *msg_me, uint8_t rec_mb,
953 if (!msg_mb || !msg_me)
956 /* Validating record header begin and end bits
957 * eg: Single record: [mb:1,me:1]
958 * Two records: [mb:1,me:0 - mb:0,me:1]
959 * Three or more records [mb:1,me:0 - mb:0,me:0 .. mb:0,me:1]
986 * Parse the ndef record header and cache the begin, end, chunkflag,
987 * short-record and type-name-format bits. ID length and field, record
988 * type, payload length and offset (where payload byte starts in input
989 * parameter). Validate offset for every step forward against total
992 static struct near_ndef_record_header *parse_record_header(uint8_t *rec,
993 uint32_t offset, uint32_t length)
995 struct near_ndef_record_header *rec_header = NULL;
996 uint8_t *type = NULL;
997 uint32_t header_len = 0;
999 DBG("length %d", length);
1001 if (!rec || offset >= length)
1004 /* This check is for empty record. */
1005 if ((length - offset) < NDEF_MSG_MIN_LENGTH)
1008 rec_header = g_try_malloc0(sizeof(struct near_ndef_record_header));
1012 rec_header->mb = RECORD_MB_BIT(rec[offset]);
1013 rec_header->me = RECORD_ME_BIT(rec[offset]);
1014 rec_header->sr = RECORD_SR_BIT(rec[offset]);
1015 rec_header->il = RECORD_IL_BIT(rec[offset]);
1016 rec_header->tnf = RECORD_TNF_BIT(rec[offset]);
1018 DBG("mb %d me %d sr %d il %d tnf %d",
1019 rec_header->mb, rec_header->me, rec_header->sr,
1020 rec_header->il, rec_header->tnf);
1023 rec_header->type_len = rec[offset++];
1024 header_len = 2; /* type length + header bits */
1026 if (rec_header->sr == 1) {
1027 rec_header->payload_len = rec[offset++];
1030 rec_header->payload_len = near_get_be32(rec + offset);
1034 if ((offset + rec_header->payload_len) > length)
1038 DBG("payload length %d", rec_header->payload_len);
1040 if (rec_header->il == 1) {
1041 rec_header->il_length = rec[offset++];
1044 if ((offset + rec_header->payload_len) > length)
1048 if (rec_header->type_len > 0) {
1049 if ((offset + rec_header->type_len) > length)
1052 type = g_try_malloc0(rec_header->type_len);
1056 memcpy(type, rec + offset, rec_header->type_len);
1057 offset += rec_header->type_len;
1058 header_len += rec_header->type_len;
1060 if ((offset + rec_header->payload_len) > length)
1064 if (rec_header->il_length > 0) {
1065 if ((offset + rec_header->il_length) > length)
1068 rec_header->il_field = g_try_malloc0(rec_header->il_length);
1069 if (!rec_header->il_field)
1072 memcpy(rec_header->il_field, rec + offset,
1073 rec_header->il_length);
1074 offset += rec_header->il_length;
1075 header_len += rec_header->il_length;
1077 if ((offset + rec_header->payload_len) > length)
1081 rec_header->rec_type = get_record_type(rec_header->tnf, type,
1082 rec_header->type_len);
1083 rec_header->offset = offset;
1084 rec_header->header_len = header_len;
1085 rec_header->type_name = g_strndup((char *) type, rec_header->type_len);
1092 near_error("parsing record header failed");
1095 g_free(rec_header->il_field);
1096 g_free(rec_header->type_name);
1102 static struct near_ndef_text_payload *
1103 parse_text_payload(uint8_t *payload, uint32_t length)
1105 struct near_ndef_text_payload *text_payload = NULL;
1106 uint8_t status, lang_length;
1115 text_payload = g_try_malloc0(sizeof(struct near_ndef_text_payload));
1119 /* 0x80 is used to get 7th bit value (0th bit is LSB) */
1120 status = ((payload[offset] & 0x80) >> 7);
1122 text_payload->encoding = (status == 0) ?
1123 g_strdup("UTF-8") : g_strdup("UTF-16");
1125 /* 0x3F is used to get 5th-0th bits value (0th bit is LSB) */
1126 lang_length = (payload[offset] & 0x3F);
1129 if (lang_length > 0) {
1130 if ((offset + lang_length) >= length)
1133 text_payload->language_code = g_strndup(
1134 (char *)(payload + offset),
1137 text_payload->language_code = NULL;
1140 offset += lang_length;
1142 if ((length - lang_length - 1) > 0) {
1143 text_payload->data = g_strndup((char *)(payload + offset),
1144 length - lang_length - 1);
1146 text_payload->data = NULL;
1149 if (offset >= length)
1152 DBG("Encoding '%s'", text_payload->encoding);
1153 DBG("Language Code '%s'", text_payload->language_code);
1154 DBG("Data '%s'", text_payload->data);
1156 return text_payload;
1159 near_error("text payload parsing failed");
1160 free_text_payload(text_payload);
1165 static struct near_ndef_uri_payload *
1166 parse_uri_payload(uint8_t *payload, uint32_t length)
1168 struct near_ndef_uri_payload *uri_payload = NULL;
1169 uint32_t index, offset;
1177 uri_payload = g_try_malloc0(sizeof(struct near_ndef_uri_payload));
1181 uri_payload->identifier = payload[offset];
1184 uri_payload->field_length = length - 1;
1186 if (uri_payload->field_length > 0) {
1187 uri_payload->field = g_try_malloc0(uri_payload->field_length);
1188 if (!uri_payload->field)
1191 memcpy(uri_payload->field, payload + offset,
1192 uri_payload->field_length);
1194 for (index = 0; index < uri_payload->field_length; index++) {
1195 /* URI Record Type Definition 1.0 [3.2.3]
1196 * Any character value within the URI between
1197 * (and including) 0 and 31 SHALL be recorded as
1198 * an error, and the URI record to be discarded */
1199 if (uri_payload->field[index] <= 31)
1205 DBG("Identifier '0X%X'", uri_payload->identifier);
1206 DBG("Field '%.*s'", uri_payload->field_length, uri_payload->field);
1211 near_error("uri payload parsing failed");
1212 free_uri_payload(uri_payload);
1218 * Validate titles records language code in Smartposter.
1219 * There must not be two or more records with the same language identifier.
1221 static int8_t validate_language_code_in_sp_record(GSList *titles)
1223 uint8_t i, j, length;
1224 struct near_ndef_text_payload *title1, *title2;
1231 length = g_slist_length(titles);
1233 for (i = 0; i < length; i++) {
1234 title1 = g_slist_nth_data(titles, i);
1236 for (j = i + 1; j < length; j++) {
1237 title2 = g_slist_nth_data(titles, j);
1239 if ((!title1->language_code) &&
1240 (!title2->language_code))
1243 if (g_strcmp0(title1->language_code,
1244 title2->language_code) == 0)
1252 static struct near_ndef_sp_payload *
1253 parse_sp_payload(uint8_t *payload, uint32_t length)
1255 struct near_ndef_sp_payload *sp_payload = NULL;
1256 struct near_ndef_record_header *rec_header = NULL;
1257 uint8_t mb = 0, me = 0, i;
1259 GSList *titles = NULL, *temp;
1267 sp_payload = g_try_malloc0(sizeof(struct near_ndef_sp_payload));
1271 while (offset < length) {
1273 DBG("Record header : 0x%x", payload[offset]);
1275 rec_header = parse_record_header(payload, offset, length);
1279 if (validate_record_begin_and_end_bits(&mb, &me,
1280 rec_header->mb, rec_header->me) != 0) {
1281 DBG("validate mb me failed");
1285 offset = rec_header->offset;
1287 switch (rec_header->rec_type) {
1288 case RECORD_TYPE_WKT_SMART_POSTER:
1289 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
1290 case RECORD_TYPE_WKT_HANDOVER_SELECT:
1291 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
1292 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
1293 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
1294 case RECORD_TYPE_MIME_TYPE:
1295 case RECORD_TYPE_WKT_ERROR:
1296 case RECORD_TYPE_EXT_AAR:
1297 case RECORD_TYPE_UNKNOWN:
1298 case RECORD_TYPE_ERROR:
1301 case RECORD_TYPE_WKT_URI:
1302 /* URI record should be only one. */
1303 if (sp_payload->uri)
1306 sp_payload->uri = parse_uri_payload(payload + offset,
1307 rec_header->payload_len);
1308 if (!sp_payload->uri)
1313 case RECORD_TYPE_WKT_TEXT:
1315 * Title records can zero or more. First fill the
1316 * records in list and validate language identifier
1317 * and then cache them into sp record structure.
1320 struct near_ndef_text_payload *title;
1321 title = parse_text_payload(payload + offset,
1322 rec_header->payload_len);
1326 titles = g_slist_append(titles, title);
1330 case RECORD_TYPE_WKT_SIZE:
1332 * If payload length is not exactly 4 bytes
1333 * then record is wrong.
1335 if (rec_header->payload_len != 4)
1338 sp_payload->size = near_get_be32(payload + offset);
1341 case RECORD_TYPE_WKT_TYPE:
1343 if (rec_header->payload_len > 0) {
1344 sp_payload->type = g_try_malloc0(
1345 rec_header->payload_len);
1346 if (!sp_payload->type)
1349 sp_payload->type = g_strndup(
1350 (char *) payload + offset,
1351 rec_header->payload_len);
1356 case RECORD_TYPE_WKT_ACTION:
1358 * If the action record exists, payload should be
1359 * single byte, otherwise consider it as error.
1361 if (rec_header->payload_len != 1)
1364 sp_payload->action =
1365 g_strdup(action_to_string(payload[offset]));
1370 offset += rec_header->payload_len;
1371 g_free(rec_header->il_field);
1372 g_free(rec_header->type_name);
1378 * Code to fill smart poster record structure from
1384 if (validate_language_code_in_sp_record(titles) != 0) {
1385 DBG("language code validation failed");
1390 sp_payload->number_of_title_records = g_slist_length(temp);
1391 sp_payload->title_records = g_try_malloc0(
1392 sp_payload->number_of_title_records *
1393 sizeof(struct near_ndef_text_payload *));
1394 if (!sp_payload->title_records)
1397 for (i = 0; i < sp_payload->number_of_title_records; i++) {
1398 sp_payload->title_records[i] = temp->data;
1402 g_slist_free(titles);
1408 near_error("smart poster payload parsing failed");
1411 g_free(rec_header->type_name);
1412 g_free(rec_header->il_field);
1416 free_sp_payload(sp_payload);
1417 g_slist_free(titles);
1422 static void correct_eir_len(struct carrier_data *data)
1425 * Android 4.1 BUG - OOB EIR length should be in LE, but is in BE.
1426 * Fortunately payload length is 1 byte so this can be detected and
1427 * corrected before sending it to handover agent.
1429 if (data->data[0] == 0) {
1430 DBG("EIR length in BE");
1431 data->data[0] = data->data[1];
1436 * Some Nokia BH-505 report total OOB block length without length field
1439 if (data->data[0] == data->size - 2) {
1440 DBG("EIR length without length field size");
1445 static int process_mime_type(struct near_ndef_mime_payload *mime,
1446 struct carrier_data *c_data)
1452 if (!mime || !c_data)
1455 switch (mime->handover.carrier_type) {
1456 case NEAR_CARRIER_BLUETOOTH:
1457 err = __near_agent_handover_push_data(HO_AGENT_BT, c_data);
1459 err = __near_bluetooth_parse_oob_record(c_data,
1460 &mime->handover.properties, true);
1463 case NEAR_CARRIER_WIFI:
1464 err = __near_agent_handover_push_data(HO_AGENT_WIFI, c_data);
1467 case NEAR_CARRIER_EMPTY:
1468 case NEAR_CARRIER_UNKNOWN:
1475 static struct near_ndef_mime_payload *parse_mime_type(
1476 struct near_ndef_record *record, uint8_t *ndef_data,
1477 size_t ndef_length, size_t offset,
1478 uint32_t payload_length, struct carrier_data **c_data)
1480 struct near_ndef_mime_payload *mime;
1481 struct carrier_data *c_temp;
1485 if (!c_data || !ndef_data ||
1486 ((offset + payload_length) > ndef_length))
1489 mime = g_try_malloc0(sizeof(struct near_ndef_mime_payload));
1493 c_temp = g_try_malloc0(sizeof(struct carrier_data));
1499 mime->type = g_strdup(record->header->type_name);
1501 DBG("MIME Type '%s'", mime->type);
1502 if (strcmp(mime->type, BT_MIME_STRING_2_1) == 0) {
1503 mime->handover.carrier_type = NEAR_CARRIER_BLUETOOTH;
1504 c_temp->type = BT_MIME_V2_1;
1505 c_temp->size = record->header->payload_len;
1506 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1507 correct_eir_len(c_temp);
1508 } else if (strcmp(mime->type, BT_MIME_STRING_2_0) == 0) {
1509 mime->handover.carrier_type = NEAR_CARRIER_BLUETOOTH;
1510 c_temp->type = BT_MIME_V2_0;
1511 c_temp->size = record->header->payload_len;
1512 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1513 } else if (strcmp(mime->type, WIFI_WSC_MIME_STRING) == 0) {
1514 mime->handover.carrier_type = NEAR_CARRIER_WIFI;
1515 c_temp->type = WIFI_WSC_MIME;
1516 c_temp->size = record->header->payload_len;
1517 memcpy(c_temp->data, ndef_data + offset, c_temp->size);
1530 /* Set the MB bit in message header */
1531 static uint8_t near_ndef_set_mb(uint8_t *hdr, bool first_rec)
1533 /* Reset bits 0x40 */
1534 *hdr &= (0xFF & (~RECORD_MB));
1543 /* Set the MB/ME bit in message header */
1544 static uint8_t near_ndef_set_me(uint8_t *hdr, bool last_rec)
1546 /* Reset bits 0x80 */
1547 *hdr &= (0xFF & (~RECORD_ME));
1556 /* Set the MB/ME bit in message header */
1557 static uint8_t near_ndef_set_mb_me(uint8_t *hdr, bool first_rec,
1560 near_ndef_set_mb(hdr, first_rec);
1561 return near_ndef_set_me(hdr, last_rec);
1564 /* Caller should put own payload starting from offset value */
1565 static struct near_ndef_message *ndef_message_alloc_complete(char *type_name,
1566 uint32_t payload_len,
1568 uint8_t payload_id_len,
1569 enum record_tnf tnf,
1573 struct near_ndef_message *msg;
1574 uint8_t hdr = 0, type_len, sr_bit, il_bit, id_len;
1576 msg = g_try_malloc0(sizeof(struct near_ndef_message));
1582 msg->length++; /* record header*/
1583 msg->length++; /* type name length byte*/
1585 type_len = (type_name) ? strlen(type_name) : 0;
1586 id_len = (payload_id) ? payload_id_len : 0;
1587 sr_bit = (payload_len <= NDEF_MSG_SHORT_RECORD_MAX_LENGTH)
1590 il_bit = (payload_id) ? TRUE : FALSE;
1592 msg->length += (sr_bit) ? 1 : 4;
1593 msg->length += (il_bit) ? 1 : 0;
1594 msg->length += type_len;
1595 msg->length += payload_len;
1596 msg->length += id_len;
1598 msg->data = g_try_malloc0(msg->length);
1602 /* Set MB ME bits */
1603 hdr = near_ndef_set_mb_me(&hdr, first_rec, last_rec);
1608 hdr = RECORD_TNF_WKT_SET(hdr);
1613 case RECORD_TNF_EMPTY:
1614 hdr = RECORD_TNF_EMPTY_SET(hdr);
1617 case RECORD_TNF_URI:
1618 hdr = RECORD_TNF_URI_SET(hdr);
1621 case RECORD_TNF_EXTERNAL:
1622 hdr = RECORD_TNF_EXTERNAL_SET(hdr);
1624 case RECORD_TNF_UNKNOWN:
1625 hdr = RECORD_TNF_UKNOWN_SET(hdr);
1628 case RECORD_TNF_UNCHANGED:
1629 hdr = RECORD_TNF_UNCHANGED_SET(hdr);
1632 case RECORD_TNF_WELLKNOWN:
1633 hdr = RECORD_TNF_WKT_SET(hdr);
1636 case RECORD_TNF_MIME:
1637 hdr = RECORD_TNF_MIME_SET(hdr);
1641 msg->data[msg->offset++] = hdr;
1642 msg->data[msg->offset++] = type_len;
1645 msg->data[msg->offset++] = payload_len;
1647 fillb32((msg->data + msg->offset), payload_len);
1652 msg->data[msg->offset++] = payload_id_len;
1655 memcpy(msg->data + msg->offset, type_name, type_len);
1656 msg->offset += type_len;
1660 memcpy(msg->data + msg->offset, payload_id, payload_id_len);
1661 msg->offset += payload_id_len;
1667 near_error("ndef message struct allocation failed");
1668 free_ndef_message(msg);
1674 * This is a wrapper to ndef_message_alloc, as, in most cases,
1675 * there's no payload id, and MB=TRUE and ME=TRUE. Default type name format
1676 * is also set to RECORD_TNF_WELLKNOWN
1679 static struct near_ndef_message *ndef_message_alloc(char *type_name,
1680 uint32_t payload_len)
1682 return ndef_message_alloc_complete(type_name, payload_len,
1684 RECORD_TNF_WELLKNOWN,
1688 static enum carrier_power_state get_cps(uint8_t data)
1690 /* enum carrier_power_state values match binary format */
1691 return data & AC_CPS_MASK;
1694 static struct near_ndef_ac_payload *parse_ac_payload(uint8_t *payload,
1697 struct near_ndef_ac_payload *ac_payload = NULL;
1706 ac_payload = g_try_malloc0(sizeof(struct near_ndef_ac_payload));
1711 ac_payload->cps = get_cps(payload[offset]);
1714 /* Carrier data reference length */
1715 ac_payload->cdr_len = payload[offset];
1718 if (ac_payload->cdr_len == 0)
1721 /* Carrier data reference */
1722 ac_payload->cdr = g_try_malloc0(ac_payload->cdr_len + 1);
1723 if (!ac_payload->cdr)
1726 memcpy(ac_payload->cdr, payload + offset, ac_payload->cdr_len);
1727 offset = offset + ac_payload->cdr_len;
1729 /* Auxiliary data reference count */
1730 ac_payload->adata_refcount = payload[offset];
1733 if (ac_payload->adata_refcount == 0)
1736 /* save the auxiliary data reference */
1737 ac_payload->adata = g_try_malloc0(
1738 ac_payload->adata_refcount * sizeof(uint16_t));
1739 if (!ac_payload->adata)
1742 memcpy(ac_payload->adata, payload + offset,
1743 ac_payload->adata_refcount * sizeof(uint16_t));
1749 near_error("ac payload parsing failed");
1750 free_ac_payload(ac_payload);
1755 /* carrier power state & carrier reference */
1756 static struct near_ndef_message *near_ndef_prepare_ac_message(uint8_t cps,
1760 struct near_ndef_message *ac_msg;
1762 /* alloc "ac" message minus adata*/
1763 ac_msg = ndef_message_alloc_complete("ac",
1764 AC_RECORD_PAYLOAD_LEN(cdr_len),
1766 RECORD_TNF_WELLKNOWN,
1771 /* Prepare ac message */
1772 ac_msg->data[ac_msg->offset++] = cps;
1774 ac_msg->data[ac_msg->offset++] = cdr_len;
1775 memcpy(ac_msg->data + ac_msg->offset, cdr, cdr_len); /* cdr */
1776 ac_msg->offset += cdr_len;
1778 ac_msg->data[ac_msg->offset] = 0; /* adata ref count */
1780 /* Check if we want an empty record */
1787 /* Collision Record message */
1788 static struct near_ndef_message *near_ndef_prepare_cr_message(uint16_t cr_id)
1790 struct near_ndef_message *cr_msg;
1792 cr_msg = ndef_message_alloc_complete("cr", sizeof(uint16_t),
1794 RECORD_TNF_WELLKNOWN,
1799 /* Prepare ac message */
1800 near_put_be16(cr_id, cr_msg->data + cr_msg->offset);
1805 static struct near_ndef_message *near_ndef_prepare_cfg_message(char *mime_type,
1806 uint8_t *data, int data_len,
1807 char *cdr, uint8_t cdr_len)
1809 struct near_ndef_message *msg = NULL;
1811 DBG(" %s", mime_type);
1816 msg = ndef_message_alloc_complete(mime_type, data_len, cdr, cdr_len,
1817 RECORD_TNF_MIME, true, true);
1823 memcpy(msg->data + msg->offset, data, data_len);
1829 * Prepare alternative carrier and configuration records
1830 * (e.g. bluetooth or wifi or Hc)
1832 static int near_ndef_prepare_ac_and_cfg_records(enum record_type type,
1833 enum handover_carrier carrier,
1834 struct near_ndef_message **ac,
1835 struct near_ndef_message **cfg,
1836 struct near_ndef_mime_payload *mime,
1837 struct carrier_data *remote_carrier)
1839 struct carrier_data *local_carrier;
1841 char *mime_type, *carrier_string;
1850 case NEAR_CARRIER_BLUETOOTH:
1852 carrier_string = "Bluetooth";
1853 mime_type = BT_MIME_STRING_2_1;
1854 local_carrier = __near_agent_handover_request_data(
1855 HO_AGENT_BT, remote_carrier);
1859 prop = (mime) ? mime->handover.properties :
1861 local_carrier = __near_bluetooth_local_get_properties(prop);
1865 case NEAR_CARRIER_WIFI:
1867 carrier_string = "WiFi-WSC";
1868 mime_type = WIFI_WSC_MIME_STRING;
1869 local_carrier = __near_agent_handover_request_data(
1870 HO_AGENT_WIFI, remote_carrier);
1873 case NEAR_CARRIER_EMPTY:
1874 case NEAR_CARRIER_UNKNOWN:
1880 * WiFi has to be handled a bit differently when we're trying
1881 * to send the first Hr or Hs (i.e. remote_carrier == NULL).
1882 * There are 2 invalid combinations:
1883 * a) AP mode and sending an Hr, as we won't be able to
1884 * initiate the association.
1885 * b) STA mode and sending an Hs, as the AP won't be able
1886 * initiate the association.
1888 * a) is detected when local_carrier != NULL and record_type is
1890 * b) is detected when local_carrier == NULL and record_type is
1892 * In those 2 cases we return an error.
1894 if (carrier == NEAR_CARRIER_WIFI && !remote_carrier) {
1895 if (local_carrier &&
1896 type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
1897 g_free(local_carrier);
1901 if (!local_carrier &&
1902 type == RECORD_TYPE_WKT_HANDOVER_SELECT)
1905 if (!local_carrier &&
1906 type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
1907 *cfg = near_ndef_prepare_cfg_message(mime_type,
1910 *ac = near_ndef_prepare_ac_message(CPS_UNKNOWN, &cdr,
1917 if (!local_carrier) {
1918 DBG("Unable to retrieve local carrier %s data", carrier_string);
1922 *cfg = near_ndef_prepare_cfg_message(mime_type, local_carrier->data,
1923 local_carrier->size,
1925 *ac = near_ndef_prepare_ac_message(local_carrier->state,
1928 g_free(local_carrier);
1930 if (!*cfg || !*ac) {
1931 free_ndef_message(*ac);
1932 free_ndef_message(*cfg);
1940 static void free_ndef_list(gpointer data)
1942 struct near_ndef_message *msg = data;
1944 free_ndef_message(msg);
1947 static struct near_ndef_message *prepare_handover_message_header(char *type,
1948 uint32_t msg_len, uint32_t payload_len)
1950 struct near_ndef_message *ho_msg;
1952 ho_msg = ndef_message_alloc(type, msg_len);
1957 * The handover payload length is not the *real* length.
1958 * The PL refers to the NDEF record, not the extra ones.
1959 * So, we have to fix the payload length in the header.
1961 ho_msg->data[NDEF_PAYLOAD_LENGTH_OFFSET] = payload_len;
1962 near_ndef_set_mb_me(ho_msg->data, true, false);
1965 ho_msg->data[ho_msg->offset++] = HANDOVER_VERSION;
1970 static uint32_t ndef_message_list_length(GList *list)
1972 struct near_ndef_message *msg;
1973 uint32_t length = 0;
1980 length += msg->length;
1987 static void copy_ac_records(struct near_ndef_message *ho, GList *acs)
1990 struct near_ndef_message *ac;
1997 memcpy(ho->data + ho->offset, ac->data, ac->length);
1999 * AC records are part of handover message payload,
2000 * so modifying offset.
2002 ho->offset += ac->length;
2007 static void copy_cfg_records(struct near_ndef_message *ho, GList *cfgs)
2010 struct near_ndef_message *cfg;
2016 offset = ho->offset;
2020 memcpy(ho->data + offset, cfg->data, cfg->length);
2022 * Configuration records (e.g. bt or wifi) records are not part
2023 * of handover payload, they are consecutive ndef msgs. So
2024 * here we are not modifying ho->offset.
2026 offset += cfg->length;
2031 static void set_mb_me_to_false(gpointer data, gpointer user_data)
2033 struct near_ndef_message *msg = data;
2035 near_ndef_set_mb_me(msg->data, false, false);
2038 static struct near_ndef_message *near_ndef_prepare_empty_hs_message(void)
2040 struct near_ndef_message *hs_msg;
2041 struct near_ndef_message *ac_msg;
2047 ac_msg = near_ndef_prepare_ac_message(CPS_UNKNOWN, &cdr, sizeof(cdr));
2052 hs_length += ac_msg->length;
2054 hs_msg = prepare_handover_message_header("Hs", hs_length, hs_length);
2058 near_ndef_set_mb_me(hs_msg->data, true, true);
2059 memcpy(hs_msg->data + hs_msg->offset, ac_msg->data, ac_msg->length);
2060 hs_msg->offset += ac_msg->length;
2062 if (hs_msg->offset > hs_msg->length)
2065 free_ndef_message(ac_msg);
2070 free_ndef_message(ac_msg);
2071 free_ndef_message(hs_msg);
2076 static struct near_ndef_message *near_ndef_prepare_hs_reply(
2077 GSList *remote_mimes,
2078 GSList *remote_cfgs)
2080 struct near_ndef_message *hs_msg = NULL;
2081 struct near_ndef_message *ac_msg;
2082 struct near_ndef_message *cfg_msg;
2083 struct near_ndef_mime_payload *remote_mime;
2084 struct carrier_data *remote_cfg;
2085 GList *ac_msgs = NULL, *cfg_msgs = NULL, *temp;
2086 GSList *mime_iter, *cfg_iter;
2087 uint8_t hs_length, hs_pl_length, num_of_carriers;
2093 * Preparing empty Hs message in case remote devices has zero
2094 * alternative carries or unknown mime types or unknown
2095 * configuration data.
2097 if ((!remote_mimes || !remote_cfgs))
2098 return near_ndef_prepare_empty_hs_message();
2100 mime_iter = remote_mimes;
2101 cfg_iter = remote_cfgs;
2104 remote_mime = mime_iter->data;
2105 remote_cfg = cfg_iter->data;
2106 if (!remote_mime || !remote_cfg)
2109 ret = near_ndef_prepare_ac_and_cfg_records(
2110 RECORD_TYPE_WKT_HANDOVER_SELECT,
2111 remote_mime->handover.carrier_type,
2113 remote_mime, remote_cfg);
2115 ac_msgs = g_list_append(ac_msgs, ac_msg);
2116 cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
2119 mime_iter = mime_iter->next;
2120 cfg_iter = cfg_iter->next;
2123 if (g_list_length(ac_msgs) == 0) {
2124 DBG("no alternative carriers, so preparing empty Hs message");
2125 return near_ndef_prepare_empty_hs_message();
2128 /* Prepare Hs message */
2130 /* Alternative carriers are part of handover record payload length */
2131 hs_pl_length += ndef_message_list_length(ac_msgs);
2133 hs_length = hs_pl_length;
2134 /* Configuration records are part of handover message length */
2135 hs_length += ndef_message_list_length(cfg_msgs);
2137 hs_msg = prepare_handover_message_header("Hs", hs_length, hs_pl_length);
2141 num_of_carriers = g_list_length(ac_msgs);
2143 if (num_of_carriers == 1) {
2144 /* only one message */
2145 ac_msg = ac_msgs->data;
2146 near_ndef_set_mb_me(ac_msg->data, true, true);
2147 } else if (num_of_carriers > 1) {
2148 g_list_foreach(ac_msgs, set_mb_me_to_false, NULL);
2150 temp = g_list_first(ac_msgs);
2151 ac_msg = temp->data;
2152 near_ndef_set_mb_me(ac_msg->data, true, false);
2154 temp = g_list_last(ac_msgs);
2155 ac_msg = temp->data;
2156 near_ndef_set_mb_me(ac_msg->data, false, true);
2159 g_list_foreach(cfg_msgs, set_mb_me_to_false, NULL);
2160 temp = g_list_last(cfg_msgs);
2161 cfg_msg = temp->data;
2162 near_ndef_set_mb_me(cfg_msg->data, false, true);
2165 copy_ac_records(hs_msg, ac_msgs);
2166 if (hs_msg->offset > hs_msg->length)
2170 * copy cfgs, cfg (associated to the ac) records length
2171 * (bt or wifi) is not part of Hs initial size.
2173 copy_cfg_records(hs_msg, cfg_msgs);
2175 DBG("Hs message preparation is done");
2177 g_list_free_full(ac_msgs, free_ndef_list);
2178 g_list_free_full(cfg_msgs, free_ndef_list);
2183 near_error("handover Hs message preparation failed");
2185 g_list_free_full(ac_msgs, free_ndef_list);
2186 g_list_free_full(cfg_msgs, free_ndef_list);
2188 free_ndef_message(hs_msg);
2193 static enum handover_carrier string2carrier(char *carrier)
2195 if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_BLUETOOTH) == 0)
2196 return NEAR_CARRIER_BLUETOOTH;
2198 if (strcasecmp(carrier, NEAR_HANDOVER_AGENT_WIFI) == 0)
2199 return NEAR_CARRIER_WIFI;
2201 return NEAR_CARRIER_UNKNOWN;
2204 static struct near_ndef_message *
2205 near_ndef_prepare_ho_message(enum record_type type, GSList *carriers)
2207 struct near_ndef_message *ho_msg = NULL;
2208 struct near_ndef_message *cr_msg = NULL;
2209 struct near_ndef_message *ac_msg;
2210 struct near_ndef_message *cfg_msg;
2211 GList *ac_msgs = NULL, *cfg_msgs = NULL, *temp;
2213 uint8_t ho_length, ho_pl_length;
2220 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2224 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2232 /* Hr message should have at least one carrier */
2234 ret = near_ndef_prepare_ac_and_cfg_records(
2236 string2carrier(carriers->data),
2237 &ac_msg, &cfg_msg, NULL, NULL);
2239 ac_msgs = g_list_append(ac_msgs, ac_msg);
2240 cfg_msgs = g_list_append(cfg_msgs, cfg_msg);
2243 carriers = carriers->next;
2246 if (g_list_length(ac_msgs) == 0) {
2247 DBG("no alternative carriers to prepare Hr message");
2251 /* Prepare Hr message */
2254 /* Prepare collision resolution record MB=1 ME=0, only for Hr */
2255 if (type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
2256 collision = GUINT16_TO_BE(g_random_int_range(0, G_MAXUINT16 + 1));
2257 cr_msg = near_ndef_prepare_cr_message(collision);
2261 near_ndef_set_mb_me(cr_msg->data, true, false);
2263 ho_pl_length += cr_msg->length;
2266 /* Alternative carriers are part of handover record payload length */
2267 ho_pl_length += ndef_message_list_length(ac_msgs);
2269 ho_length = ho_pl_length;
2270 /* Configuration records are part of handover message length */
2271 ho_length += ndef_message_list_length(cfg_msgs);
2273 ho_msg = prepare_handover_message_header(str_type,
2274 ho_length, ho_pl_length);
2278 g_list_foreach(ac_msgs, set_mb_me_to_false, NULL);
2280 temp = g_list_last(ac_msgs);
2281 ac_msg = temp->data;
2282 near_ndef_set_mb_me(ac_msg->data, false, true);
2285 * Hs record payloads do not have collision recore, the first record
2286 * will be the first ac record.
2288 if (type == RECORD_TYPE_WKT_HANDOVER_SELECT) {
2289 temp = g_list_first(ac_msgs);
2290 ac_msg = temp->data;
2291 near_ndef_set_mb_me(ac_msg->data, true, false);
2294 g_list_foreach(cfg_msgs, set_mb_me_to_false, NULL);
2295 temp = g_list_last(cfg_msgs);
2296 cfg_msg = temp->data;
2297 near_ndef_set_mb_me(cfg_msg->data, false, true);
2299 if (type == RECORD_TYPE_WKT_HANDOVER_REQUEST) {
2301 memcpy(ho_msg->data + ho_msg->offset,
2302 cr_msg->data, cr_msg->length);
2303 ho_msg->offset += cr_msg->length;
2305 if (ho_msg->offset > ho_msg->length)
2310 copy_ac_records(ho_msg, ac_msgs);
2311 if (ho_msg->offset > ho_msg->length)
2315 * copy cfgs, cfg (associated to the ac) records length
2316 * (bt or wifi) is not part of Hr initial size.
2318 copy_cfg_records(ho_msg, cfg_msgs);
2320 DBG("Handover message preparation is done");
2322 free_ndef_message(cr_msg);
2323 g_list_free_full(ac_msgs, free_ndef_list);
2324 g_list_free_full(cfg_msgs, free_ndef_list);
2329 near_error("handover record preparation failed");
2331 g_list_free_full(ac_msgs, free_ndef_list);
2332 g_list_free_full(cfg_msgs, free_ndef_list);
2333 free_ndef_message(cr_msg);
2334 free_ndef_message(ho_msg);
2339 /* Code to fill hr record structure from acs and mimes lists */
2340 static int near_fill_ho_payload(struct near_ndef_ho_payload *ho,
2341 GSList *acs, GSList *mimes)
2347 rec_count = g_slist_length(acs);
2348 ho->ac_payloads = g_try_malloc0(rec_count *
2349 sizeof(struct near_ndef_ac_payload *));
2350 if (!ho->ac_payloads)
2353 for (i = 0; i < rec_count; i++) {
2354 ho->ac_payloads[i] = temp->data;
2357 ho->number_of_ac_payloads = rec_count;
2360 /* Same process for cfg mimes */
2361 rec_count = g_slist_length(mimes);
2362 ho->cfg_payloads = g_try_malloc0(rec_count *
2363 sizeof(struct near_ndef_mime_payload *));
2364 if (!ho->cfg_payloads)
2367 for (i = 0; i < rec_count; i++) {
2368 ho->cfg_payloads[i] = temp->data;
2372 ho->number_of_cfg_payloads = rec_count;
2373 g_slist_free(mimes);
2377 g_free(ho->ac_payloads);
2378 g_free(ho->cfg_payloads);
2379 ho->ac_payloads = NULL;
2380 ho->cfg_payloads = NULL;
2385 * This function will parse an handover record payload, retrieving sub records
2386 * like (ac, cr, er) but it will also get the associated ndefs
2387 * (eg: handover carrier record, mime type for BT)
2388 * In a handover frame, only the following types are expected:
2389 * RECORD_TYPE_WKT_HANDOVER_CARRIER:
2390 * RECORD_TYPE_WKT_COLLISION_RESOLUTION
2391 * RECORD_TYPE_MIME_TYPE
2392 * RECORD_TYPE_WKT_ALTERNATIVE_CARRIER
2394 static struct near_ndef_ho_payload *parse_ho_payload(enum record_type rec_type,
2395 uint8_t *payload, uint32_t ho_length, size_t frame_length,
2396 uint8_t ho_mb, uint8_t ho_me, struct near_ndef_message **reply)
2398 struct near_ndef_ho_payload *ho_payload = NULL;
2399 struct near_ndef_ac_payload *ac = NULL;
2400 struct near_ndef_mime_payload *mime = NULL;
2401 struct carrier_data *c_data;
2402 struct near_ndef_record *trec = NULL;
2403 GSList *acs = NULL, *mimes = NULL, *c_datas = NULL;
2404 uint8_t mb = 0, me = 0, i;
2406 int16_t count_ac = 0;
2407 bool action = false, status;
2415 /* Create the handover record payload */
2416 ho_payload = g_try_malloc0(sizeof(struct near_ndef_ho_payload));
2420 /* Version is the first mandatory field of hr payload */
2421 ho_payload->version = payload[offset];
2423 /* If major is different, reply with an empty Hs */
2424 if (HANDOVER_MAJOR(ho_payload->version) !=
2425 HANDOVER_MAJOR(HANDOVER_VERSION)) {
2426 near_error("Unsupported version (%d)", ho_payload->version);
2427 /* Skip parsing and return an empty record */
2429 *reply = near_ndef_prepare_empty_hs_message();
2434 offset = offset + 1;
2436 /* We should work on the whole frame */
2437 ho_length = frame_length;
2439 while (offset < ho_length) {
2440 /* Create local record for mime parsing */
2441 trec = g_try_malloc0(sizeof(struct near_ndef_record));
2445 trec->header = parse_record_header(payload, offset, ho_length);
2450 offset = trec->header->offset;
2452 switch (trec->header->rec_type) {
2453 case RECORD_TYPE_WKT_SMART_POSTER:
2454 case RECORD_TYPE_WKT_SIZE:
2455 case RECORD_TYPE_WKT_TEXT:
2456 case RECORD_TYPE_WKT_TYPE:
2457 case RECORD_TYPE_WKT_ACTION:
2458 case RECORD_TYPE_WKT_URI:
2459 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2460 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2461 case RECORD_TYPE_WKT_ERROR:
2462 case RECORD_TYPE_EXT_AAR:
2463 case RECORD_TYPE_UNKNOWN:
2464 case RECORD_TYPE_ERROR:
2467 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2468 DBG("HANDOVER_CARRIER");
2470 * TODO process Hc record too !!!
2471 * Used for Wifi session
2475 case RECORD_TYPE_MIME_TYPE:
2476 DBG("TYPE_MIME_TYPE");
2478 /* check mb/me bits */
2479 if (validate_record_begin_and_end_bits(&ho_mb, &ho_me,
2480 trec->header->mb, trec->header->me) != 0) {
2481 DBG("validate mb me failed");
2486 * In Handover, the mime type gives bluetooth handover
2487 * or WiFi configuration data.
2488 * If we initiated the session, the received Hs frame
2489 * is the signal to launch the pairing.
2491 if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT)
2496 /* HO payload for reply creation */
2497 trec->ho = ho_payload;
2499 mime = parse_mime_type(trec, payload, frame_length,
2500 offset, trec->header->payload_len,
2504 if (!mime || !c_data)
2507 /* add the mime to the list */
2508 mimes = g_slist_append(mimes, mime);
2509 /* add the carrier data to the list */
2510 c_datas = g_slist_append(c_datas, c_data);
2517 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2518 DBG("COLLISION_RESOLUTION");
2520 /* check nested mb/me bits */
2521 if (validate_record_begin_and_end_bits(&mb, &me,
2522 trec->header->mb, trec->header->me) != 0) {
2523 DBG("validate mb me failed");
2527 ho_payload->collision_record =
2528 near_get_be16(payload + offset);
2532 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2533 DBG("ALTERNATIVE_CARRIER");
2535 /* check nested mb/me bits */
2536 if (validate_record_begin_and_end_bits(&mb, &me,
2537 trec->header->mb, trec->header->me) != 0) {
2538 DBG("validate mb me failed");
2542 ac = parse_ac_payload(payload + offset,
2543 trec->header->payload_len);
2547 acs = g_slist_append(acs, ac);
2549 /* TODO check if adata are present */
2554 offset += trec->header->payload_len;
2555 g_free(trec->header->il_field);
2556 g_free(trec->header->type_name);
2557 g_free(trec->header);
2558 trec->header = NULL;
2565 * In case of multiple carriers, handover with any carrier
2566 * gets done then leave the loop.
2570 count_ac = g_slist_length(mimes);
2572 for (i = 0; i < count_ac; i++) {
2573 if (process_mime_type(g_slist_nth_data(mimes, i),
2574 g_slist_nth_data(c_datas, i)) == 0) {
2581 DBG("could not process alternative carriers");
2585 /* This is a Hs with no cfg and no Ac: No reply and fail */
2586 if (rec_type == RECORD_TYPE_WKT_HANDOVER_SELECT &&
2587 g_slist_length(acs) == 0) {
2592 /* Prepare Hs, it depends upon Hr message carrier types */
2593 *reply = near_ndef_prepare_hs_reply(mimes, c_datas);
2595 DBG("error in preparing in HS record");
2600 if ((!acs) || (!mimes))
2603 /* Save the records */
2604 if (near_fill_ho_payload(ho_payload, acs, mimes) < 0)
2607 DBG("handover payload parsing complete");
2609 g_slist_free_full(c_datas, g_free);
2614 near_error("handover payload parsing failed");
2618 g_free(trec->header->type_name);
2619 g_free(trec->header->il_field);
2620 g_free(trec->header);
2625 g_slist_free_full(c_datas, g_free);
2626 free_ho_payload(ho_payload);
2631 static struct near_ndef_aar_payload *
2632 parse_aar_payload(uint8_t *payload, uint32_t length)
2634 struct near_ndef_aar_payload *aar_payload = NULL;
2641 aar_payload = g_try_malloc0(sizeof(struct near_ndef_uri_payload));
2645 aar_payload->package = g_strndup((char *)payload, length);
2646 if (!aar_payload->package) {
2647 near_error("AAR payload parsing failed");
2648 free_aar_payload(aar_payload);
2652 DBG("AAR package %s", aar_payload->package);
2657 int __near_ndef_record_register(struct near_ndef_record *record, char *path)
2659 record->path = path;
2661 g_dbus_register_interface(connection, record->path,
2662 NFC_RECORD_INTERFACE,
2663 NULL, NULL, record_properties,
2670 * These functions parse a specific type record (id or mime) to find the
2671 * associated string.
2673 bool near_ndef_record_cmp_id(struct near_ndef_record *rec1,
2674 struct near_ndef_record *rec2)
2678 if ((!rec1) || (!rec2))
2681 if ((!rec1->header) || (!rec2->header))
2685 if ((!rec1->header->il_field) ||
2686 (!rec2->header->il_field))
2689 if (memcmp(rec1->header->il_field, rec2->header->il_field,
2690 (rec1->header->il_length) > (rec2->header->il_length)
2691 ? (rec1->header->il_length) :
2692 (rec2->header->il_length)) != 0)
2698 bool near_ndef_record_cmp_mime(struct near_ndef_record *rec1,
2699 struct near_ndef_record *rec2)
2704 if ((!rec1) || (!rec2))
2707 if ((!rec1->header) || (!rec2->header))
2710 if ((!rec1->mime) || (!rec2->mime))
2713 if ((!rec1->mime->type) || (!rec2->mime->type))
2716 if (strlen(rec1->mime->type) != strlen(rec2->mime->type))
2719 if ((g_strcmp0(rec1->mime->type, rec2->mime->type) != 0))
2725 /* helper to get the record data length */
2726 size_t near_ndef_data_length(struct near_ndef_record *rec)
2731 return rec->data_len;
2734 /* helper to get the record data pointer */
2735 uint8_t *near_ndef_data_ptr(struct near_ndef_record *rec)
2743 GList *near_ndef_parse_msg(uint8_t *ndef_data, size_t ndef_length,
2744 struct near_ndef_message **reply)
2747 uint8_t p_mb = 0, p_me = 0, *record_start;
2749 struct near_ndef_record *record = NULL;
2750 struct carrier_data *c_data;
2757 ndef_length < NDEF_MSG_MIN_LENGTH)
2760 while (offset < ndef_length) {
2762 DBG("Record Header : 0x%X", ndef_data[offset]);
2764 record = g_try_malloc0(sizeof(struct near_ndef_record));
2768 record->header = parse_record_header(ndef_data, offset,
2770 if (!record->header)
2773 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
2775 record->header->me) != 0) {
2776 DBG("validate mb me failed");
2780 record_start = ndef_data + offset;
2781 offset = record->header->offset;
2783 switch (record->header->rec_type) {
2784 case RECORD_TYPE_WKT_SIZE:
2785 case RECORD_TYPE_WKT_TYPE:
2786 case RECORD_TYPE_WKT_ACTION:
2787 case RECORD_TYPE_WKT_HANDOVER_CARRIER:
2788 case RECORD_TYPE_WKT_ALTERNATIVE_CARRIER:
2789 case RECORD_TYPE_WKT_COLLISION_RESOLUTION:
2790 case RECORD_TYPE_WKT_ERROR:
2791 case RECORD_TYPE_UNKNOWN:
2792 case RECORD_TYPE_ERROR:
2795 case RECORD_TYPE_WKT_HANDOVER_REQUEST:
2796 case RECORD_TYPE_WKT_HANDOVER_SELECT:
2798 * Handover frame are a little bit special as the NDEF
2799 * length (specified in the header) is not the real
2800 * frame size. The complete frame includes extra NDEF
2801 * following the initial handover NDEF
2803 record->ho = parse_ho_payload(record->header->rec_type,
2805 record->header->payload_len,
2806 ndef_length - offset,
2807 record->header->mb, record->header->me,
2812 /* the complete frame is processed, break the loop */
2813 record->header->payload_len = ndef_length;
2816 case RECORD_TYPE_WKT_TEXT:
2817 record->text = parse_text_payload(ndef_data + offset,
2818 record->header->payload_len);
2825 case RECORD_TYPE_WKT_URI:
2826 record->uri = parse_uri_payload(ndef_data + offset,
2827 record->header->payload_len);
2834 case RECORD_TYPE_WKT_SMART_POSTER:
2835 record->sp = parse_sp_payload(
2837 record->header->payload_len);
2844 case RECORD_TYPE_MIME_TYPE:
2845 record->mime = parse_mime_type(record, ndef_data,
2846 ndef_length, offset,
2847 record->header->payload_len,
2852 /* No carrier data, move on */
2856 if (process_mime_type(record->mime, c_data) < 0) {
2866 case RECORD_TYPE_EXT_AAR:
2867 record->aar = parse_aar_payload(ndef_data + offset,
2868 record->header->payload_len);
2876 record->data_len = record->header->header_len +
2877 record->header->payload_len;
2879 record->data = g_try_malloc0(record->data_len);
2883 memcpy(record->data, record_start, record->data_len);
2885 records = g_list_append(records, record);
2887 build_record_type_string(record);
2889 offset += record->header->payload_len;
2895 near_error("ndef parsing failed");
2896 free_ndef_record(record);
2901 void near_ndef_records_free(GList *records)
2905 for (list = records; list; list = list->next) {
2906 struct near_ndef_record *record = list->data;
2908 __near_ndef_record_free(record);
2911 g_list_free(records);
2915 * Compute ndef records length, even though the submitted frame is incomplete.
2916 * This code is used in the handover read function, as we have to "guess" the
2919 * Message size for SR=1 is:
2920 * 1 : ndef rec header (offset 0)
2921 * x : record type length (offset 1)
2922 * y : payload length (offset 2) 1 byte ONLY if SR=1
2923 * if SR=0: (4bytes) 32 bits
2924 * z : payload id length (offset 3) ONLY if il_length=1
2926 int near_ndef_record_length(uint8_t *ndef_in, size_t ndef_in_length)
2928 int ndef_size; /* default size for NDEF hdr + rec typ len + payl */
2934 if (ndef_in_length < 3)
2940 /* save header byte */
2941 hdr = ndef_in[offset];
2944 /* header->type_len */
2945 ndef_size += ndef_in[offset++];
2947 /* header->payload_len */
2948 if (RECORD_SR_BIT(hdr) == 1) {
2949 ndef_size += ndef_in[offset++];
2951 ndef_size += near_get_be32(ndef_in + offset);
2954 if (offset >= ndef_in_length)
2959 ndef_size += RECORD_IL_BIT(hdr);
2961 /* header->il_length */
2962 if (RECORD_IL_BIT(hdr) == 1)
2963 ndef_size += ndef_in[offset++];
2965 DBG("near_ndef_message_length is %d", ndef_size);
2970 int near_ndef_count_records(uint8_t *ndef_in, size_t ndef_in_length,
2971 uint8_t record_type)
2973 uint8_t p_mb = 0, p_me = 0;
2976 struct near_ndef_record *record = NULL;
2977 int counted_records = 0 ;
2983 if (!ndef_in || ndef_in_length < NDEF_MSG_MIN_LENGTH) {
2988 while (offset < ndef_in_length) {
2989 record = g_try_malloc0(sizeof(struct near_ndef_record));
2995 /* Create a record */
2996 record->header = parse_record_header(ndef_in, offset,
2998 if (!record->header) {
3003 /* Validate MB ME */
3004 if (validate_record_begin_and_end_bits(&p_mb, &p_me,
3006 record->header->me) != 0) {
3007 DBG("validate mb me failed");
3012 /* Is this what we want ? */
3013 if (record->header->rec_type == record_type)
3016 /* Jump to the next record */
3017 offset = record->header->offset + record->header->payload_len;
3019 free_ndef_record(record);
3022 DBG("Type %d Records found: %d", record_type, counted_records);
3024 return counted_records;
3027 near_error("ndef counting failed");
3028 free_ndef_record(record);
3032 /* Possible encoding "UTF-8" or "UTF-16" */
3033 struct near_ndef_message *near_ndef_prepare_text_record(char *encoding,
3034 char *language_code, char *text)
3036 struct near_ndef_message *msg;
3037 uint32_t text_len, payload_length;
3038 uint8_t code_len, status = 0;
3042 /* Validate input parameters*/
3043 if (((g_strcmp0(encoding, "UTF-8") != 0) &&
3044 (g_strcmp0(encoding, "UTF-16") != 0)) ||
3050 code_len = strlen(language_code);
3051 text_len = strlen(text);
3052 payload_length = 1 + code_len + text_len;
3054 msg = ndef_message_alloc("T", payload_length);
3058 if (g_strcmp0(encoding, "UTF-16") == 0)
3059 status |= NDEF_TEXT_RECORD_UTF16_STATUS;
3061 status = status | code_len;
3062 msg->data[msg->offset++] = status;
3065 memcpy(msg->data + msg->offset, language_code, code_len);
3067 msg->offset += code_len;
3070 memcpy(msg->data + msg->offset, text, text_len);
3072 msg->offset += text_len;
3074 if (msg->offset > msg->length)
3080 near_error("text record preparation failed");
3081 free_ndef_message(msg);
3086 struct near_ndef_message *near_ndef_prepare_uri_record(uint8_t identifier,
3087 uint32_t field_length, uint8_t *field)
3089 struct near_ndef_message *msg = NULL;
3090 uint32_t payload_length;
3094 /* Validate input parameters*/
3095 if ((field_length == 0 && field) ||
3096 (field_length != 0 && !field)) {
3100 payload_length = field_length + 1;
3102 msg = ndef_message_alloc("U", payload_length);
3106 msg->data[msg->offset++] = identifier;
3108 if (field_length > 0) {
3109 memcpy(msg->data + msg->offset, field, field_length);
3110 msg->offset += field_length;
3113 if (msg->offset > msg->length)
3119 near_error("uri record preparation failed");
3120 free_ndef_message(msg);
3125 struct near_ndef_message *
3126 near_ndef_prepare_smartposter_record(uint8_t uri_identifier,
3127 uint32_t uri_field_length,
3130 struct near_ndef_message *msg = NULL, *uri = NULL;
3132 /* URI is mandatory in Smartposter */
3133 uri = near_ndef_prepare_uri_record(uri_identifier, uri_field_length,
3138 /* URI record length is equal to payload length of Sp record */
3139 msg = ndef_message_alloc("Sp", uri->length);
3143 memcpy(msg->data + msg->offset, uri->data, uri->length);
3144 msg->offset += uri->length;
3146 if (msg->offset > msg->length)
3149 free_ndef_message(uri);
3154 near_error("smartposter record preparation failed");
3156 free_ndef_message(uri);
3157 free_ndef_message(msg);
3162 static char *get_text_field(DBusMessage *msg, char *text)
3164 DBusMessageIter iter, arr_iter;
3172 dbus_message_iter_init(msg, &iter);
3173 dbus_message_iter_recurse(&iter, &arr_iter);
3175 while (dbus_message_iter_get_arg_type(&arr_iter) !=
3176 DBUS_TYPE_INVALID) {
3178 DBusMessageIter ent_iter;
3179 DBusMessageIter var_iter;
3181 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3182 dbus_message_iter_get_basic(&ent_iter, &key);
3183 dbus_message_iter_next(&ent_iter);
3184 dbus_message_iter_recurse(&ent_iter, &var_iter);
3186 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3187 case DBUS_TYPE_STRING:
3188 if (g_strcmp0(key, text) == 0)
3189 dbus_message_iter_get_basic(&var_iter, &uri);
3194 dbus_message_iter_next(&arr_iter);
3200 static inline char *get_uri_field(DBusMessage *msg)
3202 return get_text_field(msg, "URI");
3205 static GSList *get_carrier_field(DBusMessage *msg)
3209 GSList *carriers = NULL;
3210 uint8_t num_of_carriers, i;
3214 carrier = get_text_field(msg, "Carrier");
3218 arr = g_strsplit(carrier, ",", NEAR_CARRIER_MAX);
3219 num_of_carriers = g_strv_length(arr);
3221 for (i = 0; i < num_of_carriers; i++)
3222 carriers = g_slist_append(carriers, g_strdup(arr[i]));
3229 static struct near_ndef_message *build_text_record(DBusMessage *msg)
3231 DBusMessageIter iter, arr_iter;
3232 char *cod = NULL, *lang = NULL, *rep = NULL;
3236 dbus_message_iter_init(msg, &iter);
3237 dbus_message_iter_recurse(&iter, &arr_iter);
3239 while (dbus_message_iter_get_arg_type(&arr_iter) !=
3240 DBUS_TYPE_INVALID) {
3242 DBusMessageIter ent_iter;
3243 DBusMessageIter var_iter;
3245 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3246 dbus_message_iter_get_basic(&ent_iter, &key);
3247 dbus_message_iter_next(&ent_iter);
3248 dbus_message_iter_recurse(&ent_iter, &var_iter);
3250 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3251 case DBUS_TYPE_STRING:
3252 if (g_strcmp0(key, "Encoding") == 0)
3253 dbus_message_iter_get_basic(&var_iter, &cod);
3254 else if (g_strcmp0(key, "Language") == 0)
3255 dbus_message_iter_get_basic(&var_iter, &lang);
3256 else if (g_strcmp0(key, "Representation") == 0)
3257 dbus_message_iter_get_basic(&var_iter, &rep);
3262 dbus_message_iter_next(&arr_iter);
3265 return near_ndef_prepare_text_record(cod, lang, rep);
3268 static struct near_ndef_message *build_uri_record(DBusMessage *msg)
3271 const char *uri_prefix = NULL;
3272 uint8_t id_len, i, id;
3277 uri = get_uri_field(msg);
3284 for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3285 uri_prefix = __near_ndef_get_uri_prefix(i);
3288 g_str_has_prefix(uri, uri_prefix)) {
3290 id_len = strlen(uri_prefix);
3295 DBG("%d %d\n", i, id_len);
3297 uri_len = strlen(uri) - id_len;
3298 return near_ndef_prepare_uri_record(id, uri_len,
3299 (uint8_t *)(uri + id_len));
3302 static struct near_ndef_message *build_sp_record(DBusMessage *msg)
3305 const char *uri_prefix;
3312 * Currently this function supports only mandatory URI record,
3313 * TODO: Other records support.
3315 uri = get_uri_field(msg);
3319 for (i = 1; i <= NFC_MAX_URI_ID; i++) {
3320 uri_prefix = __near_ndef_get_uri_prefix(i);
3323 g_str_has_prefix(uri, uri_prefix))
3331 id_len = strlen(uri_prefix);
3333 uri_len = strlen(uri) - id_len;
3334 return near_ndef_prepare_smartposter_record(i, uri_len,
3335 (uint8_t *)(uri + id_len));
3338 static struct near_ndef_message *build_ho_record(enum record_type type,
3341 struct near_ndef_message *ho;
3346 carriers = get_carrier_field(msg);
3347 ho = near_ndef_prepare_ho_message(type, carriers);
3348 g_slist_free_full(carriers, g_free);
3353 static int fill_wifi_wsc_data(uint8_t *tlv, uint16_t id,
3354 uint16_t data_len, uint8_t *data)
3362 offset += WIFI_WSC_ID_LENGTH;
3364 fillb16(tlv + offset, data_len);
3365 offset += WIFI_WSC_ID_DATA_LENGTH;
3367 memcpy(tlv + offset, data, data_len);
3373 static void get_wsc_data(DBusMessageIter iter, char **ssid, char **pass)
3380 while (dbus_message_iter_get_arg_type(&iter) !=
3381 DBUS_TYPE_INVALID) {
3383 DBusMessageIter ent_iter;
3384 DBusMessageIter var_iter;
3386 dbus_message_iter_recurse(&iter, &ent_iter);
3387 dbus_message_iter_get_basic(&ent_iter, &key);
3388 dbus_message_iter_next(&ent_iter);
3389 dbus_message_iter_recurse(&ent_iter, &var_iter);
3391 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3392 case DBUS_TYPE_STRING:
3393 if (g_strcmp0(key, "SSID") == 0)
3394 dbus_message_iter_get_basic(&var_iter, ssid);
3395 else if (g_strcmp0(key, "Passphrase") == 0)
3396 dbus_message_iter_get_basic(&var_iter, pass);
3401 dbus_message_iter_next(&iter);
3405 struct near_ndef_message *near_ndef_prepare_wsc_record(char *ssid,
3408 uint16_t ssid_len, pass_len, key_type;
3409 uint8_t temp_key[2];
3411 uint32_t tlv_len, offset;
3412 struct near_ndef_message *mime;
3414 /* At least SSID is required in case of open network */
3418 DBG("SSID %s Passphrase %s", ssid, passphrase);
3420 /* Prepare TLV from ssid and passphrasse */
3421 ssid_len = strlen(ssid);
3424 pass_len = strlen(passphrase);
3425 key_type = WIFI_WSC_KEY_PSK;
3428 key_type = WIFI_WSC_KEY_OPEN;
3431 /* add ssid length */
3432 tlv_len = WIFI_WSC_ID_LENGTH + WIFI_WSC_ID_DATA_LENGTH + ssid_len;
3433 /* add authentication type length */
3434 tlv_len += WIFI_WSC_ID_LENGTH + WIFI_WSC_ID_DATA_LENGTH + 2;
3435 /* add network key length */
3437 tlv_len += WIFI_WSC_ID_LENGTH +
3438 WIFI_WSC_ID_DATA_LENGTH + pass_len;
3440 tlv = g_try_malloc0(tlv_len);
3446 offset += fill_wifi_wsc_data(tlv, WIFI_WSC_ID_SSID,
3447 ssid_len, (uint8_t *) ssid);
3450 * copy authentication type
3451 * copy key type to temp key array to maintain endianess
3454 fillb16(temp_key, key_type);
3455 offset += fill_wifi_wsc_data(tlv + offset, WIFI_WSC_ID_AUTH_TYPE,
3456 WIFI_WSC_ID_DATA_LENGTH,
3457 (uint8_t *) temp_key);
3459 /* copy Network Key */
3461 offset += fill_wifi_wsc_data(tlv + offset, WIFI_WSC_ID_KEY,
3463 (uint8_t *) passphrase);
3465 mime = ndef_message_alloc_complete(WIFI_WSC_MIME_STRING, tlv_len, NULL,
3466 0, RECORD_TNF_MIME, true,
3473 memcpy(mime->data + mime->offset, tlv, tlv_len);
3479 static char *get_mime_payload_data(DBusMessageIter iter,
3480 char **payload, int *payload_len)
3484 if (!payload || !payload_len) {
3485 near_error("Payload %p payload_len %p", payload, payload_len);
3489 while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
3491 DBusMessageIter ent_iter;
3492 DBusMessageIter var_iter;
3493 DBusMessageIter arr_iter;
3495 dbus_message_iter_recurse(&iter, &ent_iter);
3496 dbus_message_iter_get_basic(&ent_iter, &key);
3497 dbus_message_iter_next(&ent_iter);
3498 dbus_message_iter_recurse(&ent_iter, &var_iter);
3500 if (g_strcmp0(key, "Payload") == 0) {
3501 if (dbus_message_iter_get_arg_type(&var_iter) ==
3503 dbus_message_iter_get_element_type(&var_iter) ==
3505 dbus_message_iter_recurse(&var_iter,
3507 dbus_message_iter_get_fixed_array(
3511 near_error("Unexpected payload type");
3515 dbus_message_iter_next(&iter);
3521 static struct near_ndef_message *near_ndef_prepare_mime_payload_record(
3522 char *type, char *payload, int payload_len)
3524 struct near_ndef_message *mime;
3526 DBG("Payload %*s", payload_len, payload);
3527 mime = ndef_message_alloc_complete(type, payload_len, NULL, 0,
3528 RECORD_TNF_MIME, true, true);
3530 near_error("Failed to alloc NDEF message");
3534 memcpy(mime->data + mime->offset, payload, payload_len);
3539 #define DE_AUTHENTICATION_TYPE 0x1003
3540 #define DE_NETWORK_KEY 0x1027
3541 #define DE_SSID 0x1045
3542 static void parse_wsc_oob(guint8 *oob_data, guint32 oob_length,
3543 char **ssid, char **passphrase)
3546 guint16 de_length, de_type;
3549 while (offset < oob_length) {
3550 de_type = near_get_be16(oob_data + offset);
3551 de_length = near_get_be16(oob_data + offset + 2);
3554 case DE_AUTHENTICATION_TYPE:
3555 auth_type = near_get_be16(oob_data + offset + 4);
3556 DBG("WSC Authentication Type: 0x%02x",
3561 *ssid = g_try_malloc0(de_length + 1);
3565 g_snprintf(*ssid, de_length + 1,
3566 "%s", oob_data + offset + 4);
3568 DBG("SSID: %s", *ssid);
3571 case DE_NETWORK_KEY:
3572 *passphrase = g_try_malloc0(de_length + 1);
3576 g_snprintf(*passphrase, de_length + 1,
3577 "%s", oob_data + offset + 4);
3579 DBG("Passphrase: %s", *passphrase);
3583 DBG("Unknown Data Element");
3588 offset += 4 + de_length;
3592 static struct near_ndef_message *build_mime_record(DBusMessage *msg)
3594 DBusMessageIter iter, arr_iter;
3595 char *key, *mime_str, *ssid, *passphrase;
3599 dbus_message_iter_init(msg, &iter);
3600 dbus_message_iter_recurse(&iter, &arr_iter);
3602 while (dbus_message_iter_get_arg_type(&arr_iter) !=
3603 DBUS_TYPE_INVALID) {
3604 DBusMessageIter ent_iter;
3605 DBusMessageIter var_iter;
3607 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3608 dbus_message_iter_get_basic(&ent_iter, &key);
3610 if (g_strcmp0(key, "MIME") == 0) {
3611 dbus_message_iter_next(&ent_iter);
3612 dbus_message_iter_recurse(&ent_iter, &var_iter);
3613 dbus_message_iter_get_basic(&var_iter, &mime_str);
3615 if (g_strcmp0(mime_str, WIFI_WSC_MIME_STRING) == 0) {
3616 struct near_ndef_message *mime;
3617 struct carrier_data *carrier;
3619 get_wsc_data(arr_iter, &ssid, &passphrase);
3621 return near_ndef_prepare_wsc_record(
3625 * If we did not get an SSID and optionally
3626 * a passphrase from the DBus message, then
3627 * we try to get one from the WiFi-WSC agent.
3629 carrier = __near_agent_handover_request_data(
3630 HO_AGENT_WIFI, NULL);
3634 mime = ndef_message_alloc_complete(
3635 WIFI_WSC_MIME_STRING, carrier->size,
3636 NULL, 0, RECORD_TNF_MIME, true, true);
3642 memcpy(mime->data + mime->offset,
3643 carrier->data, carrier->size);
3648 } else if (g_strcmp0(mime_str, "x/nfctl") == 0) {
3649 struct carrier_data *carrier;
3650 char *ssid = NULL, *passphrase = NULL;
3653 carrier = __near_agent_handover_request_data(
3654 HO_AGENT_WIFI, NULL);
3658 parse_wsc_oob(carrier->data, carrier->size,
3659 &ssid, &passphrase);
3660 if (!ssid || !passphrase)
3663 g_snprintf(payload, 128,
3664 "enZ:wifi association;C:I4:%s:2:%s",
3669 DBG("payload %s", payload);
3671 return near_ndef_prepare_mime_payload_record(
3672 mime_str, payload, strlen(payload));
3675 * Expect data is set in the Payload field of
3678 DBusMessageIter payload_iter;
3682 DBG("mime string %s", mime_str);
3683 dbus_message_iter_recurse(&iter, &payload_iter);
3684 if (!get_mime_payload_data(payload_iter,
3685 &payload, &payload_len))
3688 return near_ndef_prepare_mime_payload_record(
3689 mime_str, payload, payload_len);
3693 dbus_message_iter_next(&arr_iter);
3699 static struct near_ndef_message * build_raw_ndef(DBusMessage *msg)
3701 DBusMessageIter iter, arr_iter;
3702 struct near_ndef_message *ndef;
3708 dbus_message_iter_init(msg, &iter);
3709 dbus_message_iter_recurse(&iter, &arr_iter);
3711 while (dbus_message_iter_get_arg_type(&arr_iter) !=
3712 DBUS_TYPE_INVALID) {
3714 DBusMessageIter ent_iter;
3715 DBusMessageIter var_iter;
3717 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3718 dbus_message_iter_get_basic(&ent_iter, &key);
3719 dbus_message_iter_next(&ent_iter);
3720 dbus_message_iter_recurse(&ent_iter, &var_iter);
3722 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3723 case DBUS_TYPE_ARRAY:
3724 if (g_strcmp0(key, "NDEF") == 0) {
3725 DBusMessageIter array;
3729 dbus_message_iter_recurse(&var_iter, &array);
3730 dbus_message_iter_get_fixed_array(&array,
3734 ndef = g_try_malloc0(data_size);
3738 ndef->data = g_try_malloc0(data_size);
3739 if (ndef->data == NULL) {
3744 ndef->length = data_size;
3745 memcpy(ndef->data, data, data_size);
3751 dbus_message_iter_next(&arr_iter);
3757 struct near_ndef_message *__ndef_build_from_message(DBusMessage *msg)
3759 DBusMessageIter iter;
3760 DBusMessageIter arr_iter;
3761 struct near_ndef_message *ndef;
3765 dbus_message_iter_init(msg, &iter);
3766 dbus_message_iter_recurse(&iter, &arr_iter);
3770 while (dbus_message_iter_get_arg_type(&arr_iter) !=
3771 DBUS_TYPE_INVALID) {
3772 const char *key, *value;
3773 DBusMessageIter ent_iter;
3774 DBusMessageIter var_iter;
3776 dbus_message_iter_recurse(&arr_iter, &ent_iter);
3777 dbus_message_iter_get_basic(&ent_iter, &key);
3779 if (g_strcmp0(key, "Type") != 0) {
3780 dbus_message_iter_next(&arr_iter);
3784 dbus_message_iter_next(&ent_iter);
3785 dbus_message_iter_recurse(&ent_iter, &var_iter);
3787 switch (dbus_message_iter_get_arg_type(&var_iter)) {
3788 case DBUS_TYPE_STRING:
3789 dbus_message_iter_get_basic(&var_iter, &value);
3791 if (g_strcmp0(value, "Text") == 0) {
3792 ndef = build_text_record(msg);
3794 } else if (g_strcmp0(value, "URI") == 0) {
3795 ndef = build_uri_record(msg);
3797 } else if (g_strcmp0(value, "SmartPoster") == 0) {
3798 ndef = build_sp_record(msg);
3800 } else if (g_strcmp0(value, "Handover") == 0) {
3801 ndef = build_ho_record(
3802 RECORD_TYPE_WKT_HANDOVER_REQUEST, msg);
3804 } else if (g_strcmp0(value, "StaticHandover") == 0) {
3805 ndef = build_ho_record(
3806 RECORD_TYPE_WKT_HANDOVER_SELECT, msg);
3808 } else if (g_strcmp0(value, "MIME") == 0) {
3809 ndef = build_mime_record(msg);
3811 } else if (g_strcmp0(value, "Raw") == 0) {
3812 ndef = build_raw_ndef(msg);
3815 near_error("%s not supported", value);
3823 dbus_message_iter_next(&arr_iter);
3829 int __near_ndef_init(void)
3833 connection = near_dbus_get_connection();
3838 void __near_ndef_cleanup(void)