1 /****************************************************************************** 2 * 3 * Copyright (C) 2010-2014 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /****************************************************************************** 20 * 21 * Handle ndef messages 22 * 23 ******************************************************************************/ 24 #include <string.h> 25 #include "ndef_utils.h" 26 #include "nfa_api.h" 27 #include "nfa_dm_int.h" 28 #include "nfa_sys.h" 29 #include "nfa_sys_int.h" 30 #include "nfc_api.h" 31 32 /******************************************************************************* 33 * URI Well-known-type prefixes 34 *******************************************************************************/ 35 const uint8_t* nfa_dm_ndef_wkt_uri_str_tbl[] = { 36 NULL, /* 0x00 */ 37 (const uint8_t*)"http://www.", /* 0x01 */ 38 (const uint8_t*)"https://www.", /* 0x02 */ 39 (const uint8_t*)"http://", /* 0x03 */ 40 (const uint8_t*)"https://", /* 0x04 */ 41 (const uint8_t*)"tel:", /* 0x05 */ 42 (const uint8_t*)"mailto:", /* 0x06 */ 43 (const uint8_t*)"ftp://anonymous:anonymous@", /* 0x07 */ 44 (const uint8_t*)"ftp://ftp.", /* 0x08 */ 45 (const uint8_t*)"ftps://", /* 0x09 */ 46 (const uint8_t*)"sftp://", /* 0x0A */ 47 (const uint8_t*)"smb://", /* 0x0B */ 48 (const uint8_t*)"nfs://", /* 0x0C */ 49 (const uint8_t*)"ftp://", /* 0x0D */ 50 (const uint8_t*)"dav://", /* 0x0E */ 51 (const uint8_t*)"news:", /* 0x0F */ 52 (const uint8_t*)"telnet://", /* 0x10 */ 53 (const uint8_t*)"imap:", /* 0x11 */ 54 (const uint8_t*)"rtsp://", /* 0x12 */ 55 (const uint8_t*)"urn:", /* 0x13 */ 56 (const uint8_t*)"pop:", /* 0x14 */ 57 (const uint8_t*)"sip:", /* 0x15 */ 58 (const uint8_t*)"sips:", /* 0x16 */ 59 (const uint8_t*)"tftp:", /* 0x17 */ 60 (const uint8_t*)"btspp://", /* 0x18 */ 61 (const uint8_t*)"btl2cap://", /* 0x19 */ 62 (const uint8_t*)"btgoep://", /* 0x1A */ 63 (const uint8_t*)"tcpobex://", /* 0x1B */ 64 (const uint8_t*)"irdaobex://", /* 0x1C */ 65 (const uint8_t*)"file://", /* 0x1D */ 66 (const uint8_t*)"urn:epc:id:", /* 0x1E */ 67 (const uint8_t*)"urn:epc:tag:", /* 0x1F */ 68 (const uint8_t*)"urn:epc:pat:", /* 0x20 */ 69 (const uint8_t*)"urn:epc:raw:", /* 0x21 */ 70 (const uint8_t*)"urn:epc:", /* 0x22 */ 71 (const uint8_t*)"urn:nfc:" /* 0x23 */ 72 }; 73 #define NFA_DM_NDEF_WKT_URI_STR_TBL_SIZE \ 74 (sizeof(nfa_dm_ndef_wkt_uri_str_tbl) / sizeof(uint8_t*)) 75 76 /******************************************************************************* 77 ** 78 ** Function nfa_dm_ndef_dereg_hdlr_by_handle 79 ** 80 ** Description Deregister NDEF record type handler 81 ** 82 ** Returns TRUE (message buffer to be freed by caller) 83 ** 84 *******************************************************************************/ 85 void nfa_dm_ndef_dereg_hdlr_by_handle(tNFA_HANDLE ndef_type_handle) { 86 tNFA_DM_CB* p_cb = &nfa_dm_cb; 87 uint16_t hdlr_idx; 88 hdlr_idx = (uint16_t)(ndef_type_handle & NFA_HANDLE_MASK); 89 90 if (p_cb->p_ndef_handler[hdlr_idx]) { 91 GKI_freebuf(p_cb->p_ndef_handler[hdlr_idx]); 92 p_cb->p_ndef_handler[hdlr_idx] = NULL; 93 } 94 } 95 96 /******************************************************************************* 97 ** 98 ** Function nfa_dm_ndef_dereg_all 99 ** 100 ** Description Deregister all NDEF record type handlers (called during 101 ** shutdown(. 102 ** 103 ** Returns Nothing 104 ** 105 *******************************************************************************/ 106 void nfa_dm_ndef_dereg_all(void) { 107 tNFA_DM_CB* p_cb = &nfa_dm_cb; 108 uint32_t i; 109 110 for (i = 0; i < NFA_NDEF_MAX_HANDLERS; i++) { 111 /* If this is a free slot, then remember it */ 112 if (p_cb->p_ndef_handler[i] != NULL) { 113 GKI_freebuf(p_cb->p_ndef_handler[i]); 114 p_cb->p_ndef_handler[i] = NULL; 115 } 116 } 117 } 118 119 /******************************************************************************* 120 ** 121 ** Function nfa_dm_ndef_reg_hdlr 122 ** 123 ** Description Register NDEF record type handler 124 ** 125 ** Returns TRUE if message buffer is to be freed by caller 126 ** 127 *******************************************************************************/ 128 bool nfa_dm_ndef_reg_hdlr(tNFA_DM_MSG* p_data) { 129 tNFA_DM_CB* p_cb = &nfa_dm_cb; 130 uint32_t hdlr_idx, i; 131 tNFA_DM_API_REG_NDEF_HDLR* p_reg_info = (tNFA_DM_API_REG_NDEF_HDLR*)p_data; 132 tNFA_NDEF_REGISTER ndef_register; 133 134 /* If registering default handler, check to see if one is already registered 135 */ 136 if (p_reg_info->tnf == NFA_TNF_DEFAULT) { 137 /* check if default handler is already registered */ 138 if (p_cb->p_ndef_handler[NFA_NDEF_DEFAULT_HANDLER_IDX]) { 139 NFA_TRACE_WARNING0("Default NDEF handler being changed."); 140 141 /* Free old registration info */ 142 nfa_dm_ndef_dereg_hdlr_by_handle( 143 (tNFA_HANDLE)NFA_NDEF_DEFAULT_HANDLER_IDX); 144 } 145 NFA_TRACE_DEBUG0("Default NDEF handler successfully registered."); 146 hdlr_idx = NFA_NDEF_DEFAULT_HANDLER_IDX; 147 } 148 /* Get available entry in ndef_handler table, and check if requested type is 149 already registered */ 150 else { 151 hdlr_idx = NFA_HANDLE_INVALID; 152 153 /* Check if this type is already registered */ 154 for (i = (NFA_NDEF_DEFAULT_HANDLER_IDX + 1); i < NFA_NDEF_MAX_HANDLERS; 155 i++) { 156 /* If this is a free slot, then remember it */ 157 if (p_cb->p_ndef_handler[i] == NULL) { 158 hdlr_idx = i; 159 break; 160 } 161 } 162 } 163 164 if (hdlr_idx != NFA_HANDLE_INVALID) { 165 /* Update the table */ 166 p_cb->p_ndef_handler[hdlr_idx] = p_reg_info; 167 168 p_reg_info->ndef_type_handle = 169 (tNFA_HANDLE)(NFA_HANDLE_GROUP_NDEF_HANDLER | hdlr_idx); 170 171 ndef_register.ndef_type_handle = p_reg_info->ndef_type_handle; 172 ndef_register.status = NFA_STATUS_OK; 173 174 NFA_TRACE_DEBUG1("NDEF handler successfully registered. Handle=0x%08x", 175 p_reg_info->ndef_type_handle); 176 (*(p_reg_info->p_ndef_cback))(NFA_NDEF_REGISTER_EVT, 177 (tNFA_NDEF_EVT_DATA*)&ndef_register); 178 179 /* indicate that we will free message buffer when type_handler is 180 * deregistered */ 181 return false; 182 } else { 183 /* Error */ 184 NFA_TRACE_ERROR0("NDEF handler failed to register."); 185 ndef_register.ndef_type_handle = NFA_HANDLE_INVALID; 186 ndef_register.status = NFA_STATUS_FAILED; 187 (*(p_reg_info->p_ndef_cback))(NFA_NDEF_REGISTER_EVT, 188 (tNFA_NDEF_EVT_DATA*)&ndef_register); 189 190 return true; 191 } 192 } 193 194 /******************************************************************************* 195 ** 196 ** Function nfa_dm_ndef_dereg_hdlr 197 ** 198 ** Description Deregister NDEF record type handler 199 ** 200 ** Returns TRUE (message buffer to be freed by caller) 201 ** 202 *******************************************************************************/ 203 bool nfa_dm_ndef_dereg_hdlr(tNFA_DM_MSG* p_data) { 204 tNFA_DM_API_DEREG_NDEF_HDLR* p_dereginfo = 205 (tNFA_DM_API_DEREG_NDEF_HDLR*)p_data; 206 207 /* Make sure this is a NDEF_HDLR handle */ 208 if (((p_dereginfo->ndef_type_handle & NFA_HANDLE_GROUP_MASK) != 209 NFA_HANDLE_GROUP_NDEF_HANDLER) || 210 ((p_dereginfo->ndef_type_handle & NFA_HANDLE_MASK) >= 211 NFA_NDEF_MAX_HANDLERS)) { 212 NFA_TRACE_ERROR1("Invalid handle for NDEF type handler: 0x%08x", 213 p_dereginfo->ndef_type_handle); 214 } else { 215 nfa_dm_ndef_dereg_hdlr_by_handle(p_dereginfo->ndef_type_handle); 216 } 217 218 return true; 219 } 220 221 /******************************************************************************* 222 ** 223 ** Function nfa_dm_ndef_find_next_handler 224 ** 225 ** Description Find next ndef handler for a given record type 226 ** 227 ** Returns void 228 ** 229 *******************************************************************************/ 230 tNFA_DM_API_REG_NDEF_HDLR* nfa_dm_ndef_find_next_handler( 231 tNFA_DM_API_REG_NDEF_HDLR* p_init_handler, uint8_t tnf, 232 uint8_t* p_type_name, uint8_t type_name_len, uint8_t* p_payload, 233 uint32_t payload_len) { 234 tNFA_DM_CB* p_cb = &nfa_dm_cb; 235 uint8_t i; 236 237 /* if init_handler is NULL, then start with the first non-default handler */ 238 if (!p_init_handler) 239 i = NFA_NDEF_DEFAULT_HANDLER_IDX + 1; 240 else { 241 /* Point to handler index after p_init_handler */ 242 i = (p_init_handler->ndef_type_handle & NFA_HANDLE_MASK) + 1; 243 } 244 245 /* Look for next handler */ 246 for (; i < NFA_NDEF_MAX_HANDLERS; i++) { 247 /* Check if TNF matches */ 248 if ((p_cb->p_ndef_handler[i]) && (p_cb->p_ndef_handler[i]->tnf == tnf)) { 249 /* TNF matches. */ 250 /* If handler is for a specific URI type, check if type is WKT URI, */ 251 /* and that the URI prefix abrieviation for this handler matches */ 252 if (p_cb->p_ndef_handler[i]->flags & NFA_NDEF_FLAGS_WKT_URI) { 253 /* This is a handler for a specific URI type */ 254 /* Check if this recurd is WKT URI */ 255 if ((p_payload) && (type_name_len == 1) && (*p_type_name == 'U')) { 256 /* Check if URI prefix abrieviation matches */ 257 if ((payload_len > 1) && 258 (p_payload[0] == p_cb->p_ndef_handler[i]->uri_id)) { 259 /* URI prefix abrieviation matches */ 260 /* If handler does not specify an absolute URI, then match found. */ 261 /* If absolute URI, then compare URI for match (skip over uri_id in 262 * ndef payload) */ 263 if ((p_cb->p_ndef_handler[i]->uri_id != NFA_NDEF_URI_ID_ABSOLUTE) || 264 (memcmp(&p_payload[1], p_cb->p_ndef_handler[i]->name, 265 p_cb->p_ndef_handler[i]->name_len) == 0)) { 266 /* Handler found. */ 267 break; 268 } 269 } 270 /* Check if handler is absolute URI but NDEF is using prefix 271 abrieviation */ 272 else if ((p_cb->p_ndef_handler[i]->uri_id == 273 NFA_NDEF_URI_ID_ABSOLUTE) && 274 (p_payload[0] != NFA_NDEF_URI_ID_ABSOLUTE)) { 275 /* Handler is absolute URI but NDEF is using prefix abrieviation. 276 * Compare URI prefix */ 277 if ((p_payload[0] < NFA_DM_NDEF_WKT_URI_STR_TBL_SIZE) && 278 (memcmp(p_cb->p_ndef_handler[i]->name, 279 (char*)nfa_dm_ndef_wkt_uri_str_tbl[p_payload[0]], 280 p_cb->p_ndef_handler[i]->name_len) == 0)) { 281 /* Handler found. */ 282 break; 283 } 284 } 285 /* Check if handler is using prefix abrieviation, but NDEF is using 286 absolute URI */ 287 else if ((p_cb->p_ndef_handler[i]->uri_id != 288 NFA_NDEF_URI_ID_ABSOLUTE) && 289 (p_payload[0] == NFA_NDEF_URI_ID_ABSOLUTE)) { 290 /* Handler is using prefix abrieviation, but NDEF is using absolute 291 * URI. Compare URI prefix */ 292 if ((p_cb->p_ndef_handler[i]->uri_id < 293 NFA_DM_NDEF_WKT_URI_STR_TBL_SIZE) && 294 (memcmp(&p_payload[1], 295 nfa_dm_ndef_wkt_uri_str_tbl[p_cb->p_ndef_handler[i] 296 ->uri_id], 297 strlen((const char*)nfa_dm_ndef_wkt_uri_str_tbl 298 [p_cb->p_ndef_handler[i]->uri_id])) == 0)) { 299 /* Handler found. */ 300 break; 301 } 302 } 303 } 304 } 305 /* Not looking for specific URI. Check if type_name for this handler 306 matches the NDEF record's type_name */ 307 else if (p_cb->p_ndef_handler[i]->name_len == type_name_len) { 308 if ((type_name_len == 0) || (memcmp(p_cb->p_ndef_handler[i]->name, 309 p_type_name, type_name_len) == 0)) { 310 /* Handler found */ 311 break; 312 } 313 } 314 } 315 } 316 317 if (i < NFA_NDEF_MAX_HANDLERS) 318 return (p_cb->p_ndef_handler[i]); 319 else 320 return (NULL); 321 } 322 323 /******************************************************************************* 324 ** 325 ** Function nfa_dm_ndef_clear_notified_flag 326 ** 327 ** Description Clear 'whole_message_notified' flag for all the handlers 328 ** (flag used to indicate that this handler has already 329 ** handled the entire incoming NDEF message) 330 ** 331 ** Returns void 332 ** 333 *******************************************************************************/ 334 void nfa_dm_ndef_clear_notified_flag(void) { 335 tNFA_DM_CB* p_cb = &nfa_dm_cb; 336 uint8_t i; 337 338 for (i = 0; i < NFA_NDEF_MAX_HANDLERS; i++) { 339 if (p_cb->p_ndef_handler[i]) { 340 p_cb->p_ndef_handler[i]->flags &= ~NFA_NDEF_FLAGS_WHOLE_MESSAGE_NOTIFIED; 341 } 342 } 343 } 344 345 /******************************************************************************* 346 ** 347 ** Function nfa_dm_ndef_handle_message 348 ** 349 ** Description Handle incoming ndef message 350 ** 351 ** Returns void 352 ** 353 *******************************************************************************/ 354 void nfa_dm_ndef_handle_message(tNFA_STATUS status, uint8_t* p_msg_buf, 355 uint32_t len) { 356 tNFA_DM_CB* p_cb = &nfa_dm_cb; 357 tNDEF_STATUS ndef_status; 358 uint8_t *p_rec, *p_ndef_start, *p_type, *p_payload, *p_rec_end; 359 uint32_t payload_len; 360 uint8_t tnf, type_len, rec_hdr_flags, id_len; 361 tNFA_DM_API_REG_NDEF_HDLR* p_handler; 362 tNFA_NDEF_DATA ndef_data; 363 uint8_t rec_count = 0; 364 bool record_handled, entire_message_handled; 365 366 NFA_TRACE_DEBUG3("nfa_dm_ndef_handle_message status=%i, msgbuf=%08x, len=%i", 367 status, p_msg_buf, len); 368 369 if (status != NFA_STATUS_OK) { 370 /* If problem reading NDEF message, then exit (no action required) */ 371 return; 372 } 373 374 /* If in exclusive RF mode is activer, then route NDEF message callback 375 * registered with NFA_StartExclusiveRfControl */ 376 if ((p_cb->flags & NFA_DM_FLAGS_EXCL_RF_ACTIVE) && 377 (p_cb->p_excl_ndef_cback)) { 378 /* No ndef-handler handle, since this callback is not from 379 * RegisterNDefHandler */ 380 ndef_data.ndef_type_handle = 0; 381 ndef_data.p_data = p_msg_buf; 382 ndef_data.len = len; 383 (*p_cb->p_excl_ndef_cback)(NFA_NDEF_DATA_EVT, 384 (tNFA_NDEF_EVT_DATA*)&ndef_data); 385 return; 386 } 387 388 /* Handle zero length - notify default handler */ 389 if (len == 0) { 390 p_handler = p_cb->p_ndef_handler[NFA_NDEF_DEFAULT_HANDLER_IDX]; 391 if (p_handler != NULL) { 392 NFA_TRACE_DEBUG0( 393 "Notifying default handler of zero-length NDEF message..."); 394 ndef_data.ndef_type_handle = p_handler->ndef_type_handle; 395 ndef_data.p_data = NULL; /* Start of record */ 396 ndef_data.len = 0; 397 (*p_handler->p_ndef_cback)(NFA_NDEF_DATA_EVT, 398 (tNFA_NDEF_EVT_DATA*)&ndef_data); 399 } 400 return; 401 } 402 403 /* Validate the NDEF message */ 404 ndef_status = NDEF_MsgValidate(p_msg_buf, len, true); 405 if (ndef_status != NDEF_OK) { 406 NFA_TRACE_ERROR1("Received invalid NDEF message. NDEF status=0x%x", 407 ndef_status); 408 return; 409 } 410 411 /* NDEF message received from backgound polling. Pass the NDEF message to the 412 * NDEF handlers */ 413 414 /* New NDEF message. Clear 'notified' flag for all the handlers */ 415 nfa_dm_ndef_clear_notified_flag(); 416 417 /* Indicate that no handler has handled this entire NDEF message (e.g. 418 * connection-handover handler *) */ 419 entire_message_handled = false; 420 421 /* Get first record in message */ 422 p_rec = p_ndef_start = p_msg_buf; 423 424 /* Check each record in the NDEF message */ 425 while (p_rec != NULL) { 426 /* Get record type */ 427 p_type = NDEF_RecGetType(p_rec, &tnf, &type_len); 428 429 /* Indicate record not handled yet */ 430 record_handled = false; 431 432 /* Get pointer to record payload */ 433 p_payload = NDEF_RecGetPayload(p_rec, &payload_len); 434 435 /* Find first handler for this type */ 436 p_handler = nfa_dm_ndef_find_next_handler(NULL, tnf, p_type, type_len, 437 p_payload, payload_len); 438 if (p_handler == NULL) { 439 /* Not a registered NDEF type. Use default handler */ 440 p_handler = p_cb->p_ndef_handler[NFA_NDEF_DEFAULT_HANDLER_IDX]; 441 if (p_handler != NULL) { 442 NFA_TRACE_DEBUG0("No handler found. Using default handler..."); 443 } 444 } 445 446 while (p_handler) { 447 /* If handler is for whole NDEF message, and it has already been notified, 448 * then skip notification */ 449 if (p_handler->flags & NFA_NDEF_FLAGS_WHOLE_MESSAGE_NOTIFIED) { 450 /* Look for next handler */ 451 p_handler = nfa_dm_ndef_find_next_handler( 452 p_handler, tnf, p_type, type_len, p_payload, payload_len); 453 continue; 454 } 455 456 /* Get pointer to record payload */ 457 NFA_TRACE_DEBUG1("Calling ndef type handler (%x)", 458 p_handler->ndef_type_handle); 459 460 ndef_data.ndef_type_handle = p_handler->ndef_type_handle; 461 ndef_data.p_data = p_rec; /* Start of record */ 462 463 /* Calculate length of NDEF record */ 464 if (p_payload != NULL) 465 ndef_data.len = payload_len + (uint32_t)(p_payload - p_rec); 466 else { 467 /* If no payload, calculate length of ndef record header */ 468 p_rec_end = p_rec; 469 470 /* First byte is the header flags */ 471 rec_hdr_flags = *p_rec_end++; 472 473 /* Next byte is the type field length */ 474 type_len = *p_rec_end++; 475 476 /* Next is the payload length (1 or 4 bytes) */ 477 if (rec_hdr_flags & NDEF_SR_MASK) { 478 p_rec_end++; 479 } else { 480 p_rec_end += 4; 481 } 482 483 /* ID field Length */ 484 if (rec_hdr_flags & NDEF_IL_MASK) 485 id_len = *p_rec_end++; 486 else 487 id_len = 0; 488 p_rec_end += id_len; 489 490 ndef_data.len = (uint32_t)(p_rec_end - p_rec); 491 } 492 493 /* If handler wants entire ndef message, then pass pointer to start of 494 * message and */ 495 /* set 'notified' flag so handler won't get notified on subsequent records 496 * for this */ 497 /* NDEF message. */ 498 if (p_handler->flags & NFA_NDEF_FLAGS_HANDLE_WHOLE_MESSAGE) { 499 ndef_data.p_data = p_ndef_start; /* Start of NDEF message */ 500 ndef_data.len = len; 501 p_handler->flags |= NFA_NDEF_FLAGS_WHOLE_MESSAGE_NOTIFIED; 502 503 /* Indicate that at least one handler has received entire NDEF message 504 */ 505 entire_message_handled = true; 506 } 507 508 /* Notify NDEF type handler */ 509 (*p_handler->p_ndef_cback)(NFA_NDEF_DATA_EVT, 510 (tNFA_NDEF_EVT_DATA*)&ndef_data); 511 512 /* Indicate that at lease one handler has received this record */ 513 record_handled = true; 514 515 /* Look for next handler */ 516 p_handler = nfa_dm_ndef_find_next_handler( 517 p_handler, tnf, p_type, type_len, p_payload, payload_len); 518 } 519 520 /* Check if at least one handler was notified of this record (only happens 521 * if no default handler was register) */ 522 if ((!record_handled) && (!entire_message_handled)) { 523 /* Unregistered NDEF record type; no default handler */ 524 NFA_TRACE_WARNING1("Unhandled NDEF record (#%i)", rec_count); 525 } 526 527 rec_count++; 528 p_rec = NDEF_MsgGetNextRec(p_rec); 529 } 530 } 531