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