nfa_dm_ndef.c revision e9df6ba5a8fcccf306a80b1670b423be8fe7746a
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