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