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 *
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 *******************************************************************************/
36 const 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 *******************************************************************************/
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 {
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 *******************************************************************************/
nfa_dm_ndef_dereg_all(void)108 void 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 *******************************************************************************/
nfa_dm_ndef_reg_hdlr(tNFA_DM_MSG * p_data)134 BOOLEAN 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 *******************************************************************************/
nfa_dm_ndef_dereg_hdlr(tNFA_DM_MSG * p_data)208 BOOLEAN 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 *******************************************************************************/
nfa_dm_ndef_find_next_handler(tNFA_DM_API_REG_NDEF_HDLR * p_init_handler,UINT8 tnf,UINT8 * p_type_name,UINT8 type_name_len,UINT8 * p_payload,UINT32 payload_len)236 tNFA_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 *******************************************************************************/
nfa_dm_ndef_clear_notified_flag(void)340 void 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 *******************************************************************************/
nfa_dm_ndef_handle_message(tNFA_STATUS status,UINT8 * p_msg_buf,UINT32 len)365 void 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