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*******************************************************************************/
35const 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*******************************************************************************/
85void 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*******************************************************************************/
106void 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*******************************************************************************/
128bool 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*******************************************************************************/
203bool 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*******************************************************************************/
230tNFA_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*******************************************************************************/
334void 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*******************************************************************************/
354void 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