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