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 *******************************************************************************/
nfa_dm_ndef_dereg_hdlr_by_handle(tNFA_HANDLE ndef_type_handle)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 *******************************************************************************/
nfa_dm_ndef_dereg_all(void)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 *******************************************************************************/
nfa_dm_ndef_reg_hdlr(tNFA_DM_MSG * p_data)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 *******************************************************************************/
nfa_dm_ndef_dereg_hdlr(tNFA_DM_MSG * p_data)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 *******************************************************************************/
nfa_dm_ndef_find_next_handler(tNFA_DM_API_REG_NDEF_HDLR * p_init_handler,uint8_t tnf,uint8_t * p_type_name,uint8_t type_name_len,uint8_t * p_payload,uint32_t payload_len)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 *******************************************************************************/
nfa_dm_ndef_clear_notified_flag(void)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 *******************************************************************************/
nfa_dm_ndef_handle_message(tNFA_STATUS status,uint8_t * p_msg_buf,uint32_t len)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