• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *******************************************************************************/
35 const 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 *******************************************************************************/
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   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 *******************************************************************************/
nfa_dm_ndef_dereg_all(void)106 void 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 *******************************************************************************/
nfa_dm_ndef_reg_hdlr(tNFA_DM_MSG * p_data)128 bool 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 *******************************************************************************/
nfa_dm_ndef_dereg_hdlr(tNFA_DM_MSG * p_data)203 bool 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 *******************************************************************************/
nfa_dm_ndef_find_next_handler(tNFA_DM_API_REG_NDEF_HDLR * p_init_handler,uint8_t tnf,uint8_t * p_type_name,uint8_t type_name_len,uint8_t * p_payload,uint32_t payload_len)230 tNFA_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 *******************************************************************************/
nfa_dm_ndef_clear_notified_flag(void)334 void 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 *******************************************************************************/
nfa_dm_ndef_handle_message(tNFA_STATUS status,uint8_t * p_msg_buf,uint32_t len)354 void 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