nfa_dm_ndef.c revision e9629bad30a9f478b336ab46b8e6e02f7f87af46
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*******************************************************************************/
36const 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*******************************************************************************/
85void 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*******************************************************************************/
108void 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*******************************************************************************/
134BOOLEAN 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*******************************************************************************/
208BOOLEAN 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*******************************************************************************/
236tNFA_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*******************************************************************************/
340void 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*******************************************************************************/
365void 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