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