• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *******************************************************************************/
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