1 /******************************************************************************
2  *
3  *  Copyright (C) 2011-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  *  NFA interface for card emulation
22  *
23  ******************************************************************************/
24 #include <string.h>
25 
26 #include <android-base/stringprintf.h>
27 #include <base/logging.h>
28 
29 #include "nfa_api.h"
30 #include "nfa_ce_int.h"
31 
32 using android::base::StringPrintf;
33 
34 extern bool nfc_debug_enabled;
35 
36 /*******************************************************************************
37 **
38 ** Function         nfa_ce_api_deregister_listen
39 **
40 ** Description      Internal function called by listening for Felica system
41 **                  code, ISO-DEP AID, or UICC technology
42 **
43 ** Returns:
44 **                  NFA_STATUS_OK,            if command accepted
45 **                  NFA_STATUS_BAD_HANDLE     invalid handle
46 **                  NFA_STATUS_FAILED:        otherwise
47 **
48 *******************************************************************************/
nfa_ce_api_deregister_listen(tNFA_HANDLE handle,uint32_t listen_info)49 tNFA_STATUS nfa_ce_api_deregister_listen(tNFA_HANDLE handle,
50                                          uint32_t listen_info) {
51   tNFA_CE_MSG* p_ce_msg;
52 
53   /* Validate handle */
54   if ((listen_info != NFA_CE_LISTEN_INFO_UICC) &&
55       ((handle & NFA_HANDLE_GROUP_MASK) != NFA_HANDLE_GROUP_CE)) {
56     LOG(ERROR) << StringPrintf("nfa_ce_api_reregister_listen: Invalid handle");
57     return (NFA_STATUS_BAD_HANDLE);
58   }
59 
60   p_ce_msg = (tNFA_CE_MSG*)GKI_getbuf((uint16_t)(sizeof(tNFA_CE_MSG)));
61   if (p_ce_msg != nullptr) {
62     p_ce_msg->hdr.event = NFA_CE_API_DEREG_LISTEN_EVT;
63     p_ce_msg->dereg_listen.handle = handle;
64     p_ce_msg->dereg_listen.listen_info = listen_info;
65 
66     nfa_sys_sendmsg(p_ce_msg);
67 
68     return (NFA_STATUS_OK);
69   } else {
70     LOG(ERROR) << StringPrintf("nfa_ce_api_reregister_listen: Out of buffers");
71     return (NFA_STATUS_FAILED);
72   }
73 }
74 
75 /*****************************************************************************
76 **  APIs
77 *****************************************************************************/
78 
79 /*******************************************************************************
80 **
81 ** Function         NFA_CeConfigureLocalTag
82 **
83 ** Description      Configure local NDEF tag.
84 **
85 **                  Tag events will be notifed using the tNFA_CONN_CBACK
86 **                  (registered during NFA_Enable)
87 **
88 **                  The NFA_CE_LOCAL_TAG_CONFIGURED_EVT reports the status of
89 **                  the operation.
90 **
91 **                  Activation and deactivation are reported using the
92 **                  NFA_ACTIVATED_EVT and NFA_DEACTIVATED_EVT events
93 **
94 **                  If a write-request is received to update the tag memory,
95 **                  an NFA_CE_NDEF_WRITE_CPLT_EVT will notify the application,
96 **                  along with a buffer containing the updated contents.
97 **
98 **                  To disable the local NDEF tag, set protocol_mask=0
99 **
100 **                  The NDEF data provided by p_ndef_data must be persistent
101 **                  as long as the local NDEF tag is enabled.
102 **
103 **
104 ** Note:            If RF discovery is started,
105 **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
106 **                  happen before calling this function. Also, Input parameters
107 **                  p_uid and uid_len are reserved for future use.
108 **
109 ** Returns:
110 **                  NFA_STATUS_OK,            if command accepted
111 **                  NFA_STATUS_INVALID_PARAM,
112 **                      if protocol_maks is not 0 and p_ndef_data is NULL
113 **                  (or)uid_len is not 0
114 **                  (or)if protocol mask is set for Type 1 or Type 2
115 **
116 **                  NFA_STATUS_FAILED:        otherwise
117 **
118 *******************************************************************************/
NFA_CeConfigureLocalTag(tNFA_PROTOCOL_MASK protocol_mask,uint8_t * p_ndef_data,uint16_t ndef_cur_size,uint16_t ndef_max_size,bool read_only,uint8_t uid_len,uint8_t * p_uid)119 tNFA_STATUS NFA_CeConfigureLocalTag(tNFA_PROTOCOL_MASK protocol_mask,
120                                     uint8_t* p_ndef_data,
121                                     uint16_t ndef_cur_size,
122                                     uint16_t ndef_max_size, bool read_only,
123                                     uint8_t uid_len, uint8_t* p_uid)
124 
125 {
126   tNFA_CE_MSG* p_msg;
127 
128   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
129 
130   if (protocol_mask) {
131     /* If any protocols are specified, then NDEF buffer pointer must be non-NULL
132      */
133     if (p_ndef_data == nullptr) {
134       LOG(ERROR) << StringPrintf(
135           "NFA_CeConfigureLocalTag: NULL ndef data pointer");
136       return (NFA_STATUS_INVALID_PARAM);
137     }
138 
139     if ((protocol_mask & NFA_PROTOCOL_MASK_T1T) ||
140         (protocol_mask & NFA_PROTOCOL_MASK_T2T)) {
141       LOG(ERROR) << StringPrintf(
142           "NFA_CeConfigureLocalTag: Cannot emulate Type 1 / Type 2 tag");
143       return (NFA_STATUS_INVALID_PARAM);
144     }
145 
146     if (uid_len) {
147       LOG(ERROR) << StringPrintf(
148           "NFA_CeConfigureLocalTag: Cannot Set UID for Protocol_mask: 0x%x",
149           protocol_mask);
150       return (NFA_STATUS_INVALID_PARAM);
151     }
152   }
153   p_msg = (tNFA_CE_MSG*)GKI_getbuf((uint16_t)sizeof(tNFA_CE_MSG));
154   if (p_msg != nullptr) {
155     p_msg->local_tag.hdr.event = NFA_CE_API_CFG_LOCAL_TAG_EVT;
156 
157     /* Copy ndef info */
158     p_msg->local_tag.protocol_mask = protocol_mask;
159     p_msg->local_tag.p_ndef_data = p_ndef_data;
160     p_msg->local_tag.ndef_cur_size = ndef_cur_size;
161     p_msg->local_tag.ndef_max_size = ndef_max_size;
162     p_msg->local_tag.read_only = read_only;
163     p_msg->local_tag.uid_len = uid_len;
164 
165     if (uid_len) memcpy(p_msg->local_tag.uid, p_uid, uid_len);
166 
167     nfa_sys_sendmsg(p_msg);
168 
169     return (NFA_STATUS_OK);
170   }
171 
172   return (NFA_STATUS_FAILED);
173 }
174 
175 /*******************************************************************************
176 **
177 ** Function         NFA_CeConfigureUiccListenTech
178 **
179 ** Description      Configure listening for the UICC, using the specified
180 **                  technologies.
181 **
182 **                  Events will be notifed using the tNFA_CONN_CBACK
183 **                  (registered during NFA_Enable)
184 **
185 **                  The NFA_CE_UICC_LISTEN_CONFIGURED_EVT reports the status of
186 **                  the operation.
187 **
188 **                  Activation and deactivation are reported using the
189 **                  NFA_ACTIVATED_EVT and NFA_DEACTIVATED_EVT events
190 **
191 ** Note:            If RF discovery is started,
192 **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
193 **                  happen before calling this function
194 **
195 ** Returns:
196 **                  NFA_STATUS_OK, if command accepted
197 **                  NFA_STATUS_FAILED: otherwise
198 **
199 *******************************************************************************/
NFA_CeConfigureUiccListenTech(tNFA_HANDLE ee_handle,tNFA_TECHNOLOGY_MASK tech_mask)200 tNFA_STATUS NFA_CeConfigureUiccListenTech(tNFA_HANDLE ee_handle,
201                                           tNFA_TECHNOLOGY_MASK tech_mask) {
202 #if (NFC_NFCEE_INCLUDED == TRUE)
203   tNFA_CE_MSG* p_msg;
204 
205   DLOG_IF(INFO, nfc_debug_enabled)
206       << StringPrintf("ee_handle = 0x%x", ee_handle);
207 
208   /* If tech_mask is zero, then app is disabling listening for specified uicc */
209   if (tech_mask == 0) {
210     return (nfa_ce_api_deregister_listen(ee_handle, NFA_CE_LISTEN_INFO_UICC));
211   }
212 
213   /* Otherwise then app is configuring uicc listen for the specificed
214    * technologies */
215   p_msg = (tNFA_CE_MSG*)GKI_getbuf((uint16_t)sizeof(tNFA_CE_MSG));
216   if (p_msg != nullptr) {
217     p_msg->reg_listen.hdr.event = NFA_CE_API_REG_LISTEN_EVT;
218     p_msg->reg_listen.listen_type = NFA_CE_REG_TYPE_UICC;
219 
220     p_msg->reg_listen.ee_handle = ee_handle;
221     p_msg->reg_listen.tech_mask = tech_mask;
222 
223     nfa_sys_sendmsg(p_msg);
224 
225     return (NFA_STATUS_OK);
226   }
227 #else
228   LOG(ERROR) << StringPrintf(
229       "NFCEE related functions are not "
230       "enabled!");
231 #endif
232   return (NFA_STATUS_FAILED);
233 }
234 
235 /*******************************************************************************
236 **
237 ** Function         NFA_CeRegisterFelicaSystemCodeOnDH
238 **
239 ** Description      Register listening callback for Felica system code
240 **
241 **                  The NFA_CE_REGISTERED_EVT reports the status of the
242 **                  operation.
243 **
244 ** Note:            If RF discovery is started,
245 **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
246 **                  happen before calling this function
247 **
248 ** Returns:
249 **                  NFA_STATUS_OK, if command accepted
250 **                  NFA_STATUS_FAILED: otherwise
251 **
252 *******************************************************************************/
NFA_CeRegisterFelicaSystemCodeOnDH(uint16_t system_code,uint8_t nfcid2[NCI_RF_F_UID_LEN],uint8_t t3tPmm[NCI_T3T_PMM_LEN],tNFA_CONN_CBACK * p_conn_cback)253 tNFA_STATUS NFA_CeRegisterFelicaSystemCodeOnDH(uint16_t system_code,
254                                                uint8_t nfcid2[NCI_RF_F_UID_LEN],
255                                                uint8_t t3tPmm[NCI_T3T_PMM_LEN],
256                                                tNFA_CONN_CBACK* p_conn_cback) {
257   tNFA_CE_MSG* p_msg;
258 
259   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
260 
261   /* Validate parameters */
262   if (p_conn_cback == nullptr) return (NFA_STATUS_INVALID_PARAM);
263 
264   p_msg = (tNFA_CE_MSG*)GKI_getbuf((uint16_t)sizeof(tNFA_CE_MSG));
265   if (p_msg != nullptr) {
266     p_msg->reg_listen.hdr.event = NFA_CE_API_REG_LISTEN_EVT;
267     p_msg->reg_listen.p_conn_cback = p_conn_cback;
268     p_msg->reg_listen.listen_type = NFA_CE_REG_TYPE_FELICA;
269 
270     /* Listen info */
271     memcpy(p_msg->reg_listen.nfcid2, nfcid2, NCI_RF_F_UID_LEN);
272     memcpy(p_msg->reg_listen.t3tPmm, t3tPmm, NCI_T3T_PMM_LEN);
273     p_msg->reg_listen.system_code = system_code;
274 
275     nfa_sys_sendmsg(p_msg);
276 
277     return (NFA_STATUS_OK);
278   }
279 
280   return (NFA_STATUS_FAILED);
281 }
282 
283 /*******************************************************************************
284 **
285 ** Function         NFA_CeDeregisterFelicaSystemCodeOnDH
286 **
287 ** Description      Deregister listening callback for Felica
288 **                  (previously registered using
289 **                  NFA_CeRegisterFelicaSystemCodeOnDH)
290 **
291 **                  The NFA_CE_DEREGISTERED_EVT reports the status of the
292 **                  operation.
293 **
294 ** Note:            If RF discovery is started,
295 **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
296 **                  happen before calling this function
297 **
298 ** Returns          NFA_STATUS_OK if successfully initiated
299 **                  NFA_STATUS_BAD_HANDLE if invalid handle
300 **                  NFA_STATUS_FAILED otherwise
301 **
302 *******************************************************************************/
NFA_CeDeregisterFelicaSystemCodeOnDH(tNFA_HANDLE handle)303 tNFA_STATUS NFA_CeDeregisterFelicaSystemCodeOnDH(tNFA_HANDLE handle) {
304   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("handle:0x%X", handle);
305   return (nfa_ce_api_deregister_listen(handle, NFA_CE_LISTEN_INFO_FELICA));
306 }
307 
308 /*******************************************************************************
309 **
310 ** Function         NFA_CeRegisterAidOnDH
311 **
312 ** Description      Register listening callback for the specified ISODEP AID
313 **
314 **                  The NFA_CE_REGISTERED_EVT reports the status of the
315 **                  operation.
316 **
317 **                  If no AID is specified (aid_len=0), then p_conn_cback will
318 **                  will get notifications for any AIDs routed to the DH. This
319 **                  over-rides callbacks registered for specific AIDs.
320 **
321 ** Note:            If RF discovery is started,
322 **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
323 **                  happen before calling this function
324 **
325 ** Returns:
326 **                  NFA_STATUS_OK, if command accepted
327 **                  NFA_STATUS_FAILED: otherwise
328 **
329 *******************************************************************************/
NFA_CeRegisterAidOnDH(uint8_t aid[NFC_MAX_AID_LEN],uint8_t aid_len,tNFA_CONN_CBACK * p_conn_cback)330 tNFA_STATUS NFA_CeRegisterAidOnDH(uint8_t aid[NFC_MAX_AID_LEN], uint8_t aid_len,
331                                   tNFA_CONN_CBACK* p_conn_cback) {
332   tNFA_CE_MSG* p_msg;
333 
334   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
335 
336   /* Validate parameters */
337   if (p_conn_cback == nullptr) return (NFA_STATUS_INVALID_PARAM);
338 
339   p_msg = (tNFA_CE_MSG*)GKI_getbuf((uint16_t)sizeof(tNFA_CE_MSG));
340   if (p_msg != nullptr) {
341     p_msg->reg_listen.hdr.event = NFA_CE_API_REG_LISTEN_EVT;
342     p_msg->reg_listen.p_conn_cback = p_conn_cback;
343     p_msg->reg_listen.listen_type = NFA_CE_REG_TYPE_ISO_DEP;
344 
345     /* Listen info */
346     memcpy(p_msg->reg_listen.aid, aid, aid_len);
347     p_msg->reg_listen.aid_len = aid_len;
348 
349     nfa_sys_sendmsg(p_msg);
350 
351     return (NFA_STATUS_OK);
352   }
353 
354   return (NFA_STATUS_FAILED);
355 }
356 
357 /*******************************************************************************
358 **
359 ** Function         NFA_CeDeregisterAidOnDH
360 **
361 ** Description      Deregister listening callback for ISODEP AID
362 **                  (previously registered using NFA_CeRegisterAidOnDH)
363 **
364 **                  The NFA_CE_DEREGISTERED_EVT reports the status of the
365 **                  operation.
366 **
367 ** Note:            If RF discovery is started,
368 **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
369 **                  happen before calling this function
370 **
371 ** Returns          NFA_STATUS_OK if successfully initiated
372 **                  NFA_STATUS_BAD_HANDLE if invalid handle
373 **                  NFA_STATUS_FAILED otherwise
374 **
375 *******************************************************************************/
NFA_CeDeregisterAidOnDH(tNFA_HANDLE handle)376 tNFA_STATUS NFA_CeDeregisterAidOnDH(tNFA_HANDLE handle) {
377   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("handle:0x%X", handle);
378   return (nfa_ce_api_deregister_listen(handle, NFA_CE_LISTEN_INFO_T4T_AID));
379 }
380 
381 /*******************************************************************************
382 **
383 ** Function         NFA_CeSetIsoDepListenTech
384 **
385 ** Description      Set the technologies (NFC-A and/or NFC-B) to listen for when
386 **                  NFA_CeConfigureLocalTag or NFA_CeDeregisterAidOnDH are
387 **                  called.
388 **
389 **                  By default (if this API is not called), NFA will listen
390 **                  for both NFC-A and NFC-B for ISODEP.
391 **
392 ** Note:            If listening for ISODEP on UICC, the DH listen callbacks
393 **                  may still get activate notifications for ISODEP if the
394 **                  reader/writer selects an AID that is not routed to the UICC
395 **                  (regardless of whether A or B was disabled using
396 **                  NFA_CeSetIsoDepListenTech)
397 **
398 ** Note:            If RF discovery is started,
399 **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
400 **                  happen before calling this function
401 **
402 ** Returns:
403 **                  NFA_STATUS_OK, if command accepted
404 **                  NFA_STATUS_FAILED: otherwise
405 **
406 *******************************************************************************/
NFA_CeSetIsoDepListenTech(tNFA_TECHNOLOGY_MASK tech_mask)407 tNFA_STATUS NFA_CeSetIsoDepListenTech(tNFA_TECHNOLOGY_MASK tech_mask) {
408   tNFA_CE_MSG* p_msg;
409   tNFA_TECHNOLOGY_MASK use_mask =
410       (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B);
411 
412   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("0x%x", tech_mask);
413   if (((tech_mask & use_mask) == 0) || ((tech_mask & ~use_mask) != 0)) {
414     LOG(ERROR) << StringPrintf(
415         "NFA_CeSetIsoDepListenTech: Invalid technology mask");
416     return (NFA_STATUS_INVALID_PARAM);
417   }
418 
419   p_msg = (tNFA_CE_MSG*)GKI_getbuf((uint16_t)sizeof(tNFA_CE_MSG));
420   if (p_msg != nullptr) {
421     p_msg->hdr.event = NFA_CE_API_CFG_ISODEP_TECH_EVT;
422     p_msg->hdr.layer_specific = tech_mask;
423 
424     nfa_sys_sendmsg(p_msg);
425 
426     return (NFA_STATUS_OK);
427   }
428 
429   return (NFA_STATUS_FAILED);
430 }
431