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 *  This file contains function of the NFC unit to receive/process NCI
22 *  commands.
23 *
24 ******************************************************************************/
25#include <string.h>
26
27#include <android-base/stringprintf.h>
28#include <base/logging.h>
29
30#include "nfc_target.h"
31
32#include "bt_types.h"
33#include "gki.h"
34#include "nci_defs.h"
35#include "nci_hmsgs.h"
36#include "nfc_api.h"
37#include "nfc_int.h"
38
39using android::base::StringPrintf;
40
41extern bool nfc_debug_enabled;
42
43/*******************************************************************************
44**
45** Function         nci_proc_core_rsp
46**
47** Description      Process NCI responses in the CORE group
48**
49** Returns          TRUE-caller of this function to free the GKI buffer p_msg
50**
51*******************************************************************************/
52bool nci_proc_core_rsp(NFC_HDR* p_msg) {
53  uint8_t* p;
54  uint8_t *pp, len, op_code;
55  bool free = true;
56  uint8_t* p_old = nfc_cb.last_cmd;
57
58  /* find the start of the NCI message and parse the NCI header */
59  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
60  pp = p + 1;
61  NCI_MSG_PRS_HDR1(pp, op_code);
62  DLOG_IF(INFO, nfc_debug_enabled)
63      << StringPrintf("nci_proc_core_rsp opcode:0x%x", op_code);
64  len = *pp++;
65
66  /* process the message based on the opcode and message type */
67  switch (op_code) {
68    case NCI_MSG_CORE_RESET:
69      nfc_ncif_proc_reset_rsp(pp, false);
70      break;
71
72    case NCI_MSG_CORE_INIT:
73      nfc_ncif_proc_init_rsp(p_msg);
74      free = false;
75      break;
76
77    case NCI_MSG_CORE_GET_CONFIG:
78      nfc_ncif_proc_get_config_rsp(p_msg);
79      break;
80
81    case NCI_MSG_CORE_SET_CONFIG:
82      nfc_ncif_set_config_status(pp, len);
83      break;
84
85    case NCI_MSG_CORE_CONN_CREATE:
86      nfc_ncif_proc_conn_create_rsp(p, p_msg->len, *p_old);
87      break;
88
89    case NCI_MSG_CORE_CONN_CLOSE:
90      nfc_ncif_report_conn_close_evt(*p_old, *pp);
91      break;
92    case NCI_MSG_CORE_SET_POWER_SUB_STATE:
93      nfc_ncif_event_status(NFC_SET_POWER_SUB_STATE_REVT, *pp);
94      break;
95    default:
96      LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
97      break;
98  }
99
100  return free;
101}
102
103/*******************************************************************************
104**
105** Function         nci_proc_core_ntf
106**
107** Description      Process NCI notifications in the CORE group
108**
109** Returns          void
110**
111*******************************************************************************/
112void nci_proc_core_ntf(NFC_HDR* p_msg) {
113  uint8_t* p;
114  uint8_t *pp, len, op_code;
115  uint8_t conn_id;
116
117  /* find the start of the NCI message and parse the NCI header */
118  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
119  pp = p + 1;
120  NCI_MSG_PRS_HDR1(pp, op_code);
121  DLOG_IF(INFO, nfc_debug_enabled)
122      << StringPrintf("nci_proc_core_ntf opcode:0x%x", op_code);
123  len = *pp++;
124
125  /* process the message based on the opcode and message type */
126  switch (op_code) {
127    case NCI_MSG_CORE_RESET:
128      nfc_ncif_proc_reset_rsp(pp, true);
129      break;
130
131    case NCI_MSG_CORE_GEN_ERR_STATUS:
132      /* process the error ntf */
133      /* in case of timeout: notify the static connection callback */
134      nfc_ncif_event_status(NFC_GEN_ERROR_REVT, *pp);
135      nfc_ncif_error_status(NFC_RF_CONN_ID, *pp);
136      break;
137
138    case NCI_MSG_CORE_INTF_ERR_STATUS:
139      conn_id = *(pp + 1);
140      nfc_ncif_error_status(conn_id, *pp);
141      break;
142
143    case NCI_MSG_CORE_CONN_CREDITS:
144      nfc_ncif_proc_credits(pp, len);
145      break;
146
147    default:
148      LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
149      break;
150  }
151}
152
153/*******************************************************************************
154**
155** Function         nci_proc_rf_management_rsp
156**
157** Description      Process NCI responses in the RF Management group
158**
159** Returns          void
160**
161*******************************************************************************/
162void nci_proc_rf_management_rsp(NFC_HDR* p_msg) {
163  uint8_t* p;
164  uint8_t *pp, len, op_code;
165  uint8_t* p_old = nfc_cb.last_cmd;
166
167  /* find the start of the NCI message and parse the NCI header */
168  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
169  pp = p + 1;
170  NCI_MSG_PRS_HDR1(pp, op_code);
171  len = *pp++;
172
173  switch (op_code) {
174    case NCI_MSG_RF_DISCOVER:
175      nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_RSP);
176      nfc_ncif_rf_management_status(NFC_START_DEVT, *pp);
177      break;
178
179    case NCI_MSG_RF_DISCOVER_SELECT:
180      nfc_ncif_rf_management_status(NFC_SELECT_DEVT, *pp);
181      break;
182
183    case NCI_MSG_RF_T3T_POLLING:
184      break;
185
186    case NCI_MSG_RF_DISCOVER_MAP:
187      nfc_ncif_rf_management_status(NFC_MAP_DEVT, *pp);
188      break;
189
190    case NCI_MSG_RF_DEACTIVATE:
191      if (nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_RSP) == false) {
192        return;
193      }
194      nfc_ncif_proc_deactivate(*pp, *p_old, false);
195      break;
196
197#if (NFC_NFCEE_INCLUDED == TRUE)
198#if (NFC_RW_ONLY == FALSE)
199
200    case NCI_MSG_RF_SET_ROUTING:
201      nfc_ncif_event_status(NFC_SET_ROUTING_REVT, *pp);
202      break;
203
204    case NCI_MSG_RF_GET_ROUTING:
205      if (*pp != NFC_STATUS_OK)
206        nfc_ncif_event_status(NFC_GET_ROUTING_REVT, *pp);
207      break;
208#endif
209#endif
210
211    case NCI_MSG_RF_PARAMETER_UPDATE:
212      nfc_ncif_event_status(NFC_RF_COMM_PARAMS_UPDATE_REVT, *pp);
213      break;
214
215    case NCI_MSG_RF_ISO_DEP_NAK_PRESENCE:
216      nfc_ncif_proc_isodep_nak_presence_check_status(*pp, false);
217      break;
218    default:
219      LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
220      break;
221  }
222}
223
224/*******************************************************************************
225**
226** Function         nci_proc_rf_management_ntf
227**
228** Description      Process NCI notifications in the RF Management group
229**
230** Returns          void
231**
232*******************************************************************************/
233void nci_proc_rf_management_ntf(NFC_HDR* p_msg) {
234  uint8_t* p;
235  uint8_t *pp, len, op_code;
236
237  /* find the start of the NCI message and parse the NCI header */
238  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
239  pp = p + 1;
240  NCI_MSG_PRS_HDR1(pp, op_code);
241  len = *pp++;
242
243  switch (op_code) {
244    case NCI_MSG_RF_DISCOVER:
245      nfc_ncif_proc_discover_ntf(p, p_msg->len);
246      break;
247
248    case NCI_MSG_RF_DEACTIVATE:
249      if (nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_NTF) == false) {
250        return;
251      }
252      if (NFC_GetNCIVersion() == NCI_VERSION_2_0) {
253        nfc_cb.deact_reason = *(pp + 1);
254      }
255      nfc_ncif_proc_deactivate(NFC_STATUS_OK, *pp, true);
256      break;
257
258    case NCI_MSG_RF_INTF_ACTIVATED:
259      if (nfa_dm_p2p_prio_logic(op_code, pp, NFA_DM_P2P_PRIO_NTF) == false) {
260        return;
261      }
262      nfc_ncif_proc_activate(pp, len);
263      break;
264
265    case NCI_MSG_RF_FIELD:
266      nfc_ncif_proc_rf_field_ntf(*pp);
267      break;
268
269    case NCI_MSG_RF_T3T_POLLING:
270      nfc_ncif_proc_t3t_polling_ntf(pp, len);
271      break;
272
273#if (NFC_NFCEE_INCLUDED == TRUE)
274#if (NFC_RW_ONLY == FALSE)
275
276    case NCI_MSG_RF_GET_ROUTING:
277      nfc_ncif_proc_get_routing(pp, len);
278      break;
279
280    case NCI_MSG_RF_EE_ACTION:
281      nfc_ncif_proc_ee_action(pp, len);
282      break;
283
284    case NCI_MSG_RF_EE_DISCOVERY_REQ:
285      nfc_ncif_proc_ee_discover_req(pp, len);
286      break;
287#endif
288#endif
289    case NCI_MSG_RF_ISO_DEP_NAK_PRESENCE:
290      nfc_ncif_proc_isodep_nak_presence_check_status(*pp, true);
291      break;
292    default:
293      LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
294      break;
295  }
296}
297
298#if (NFC_NFCEE_INCLUDED == TRUE)
299#if (NFC_RW_ONLY == FALSE)
300
301/*******************************************************************************
302**
303** Function         nci_proc_ee_management_rsp
304**
305** Description      Process NCI responses in the NFCEE Management group
306**
307** Returns          void
308**
309*******************************************************************************/
310void nci_proc_ee_management_rsp(NFC_HDR* p_msg) {
311  uint8_t* p;
312  uint8_t *pp, len, op_code;
313  tNFC_RESPONSE_CBACK* p_cback = nfc_cb.p_resp_cback;
314  tNFC_RESPONSE nfc_response;
315  tNFC_RESPONSE_EVT event = NFC_NFCEE_INFO_REVT;
316  uint8_t* p_old = nfc_cb.last_cmd;
317
318  /* find the start of the NCI message and parse the NCI header */
319  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
320  pp = p + 1;
321  NCI_MSG_PRS_HDR1(pp, op_code);
322  DLOG_IF(INFO, nfc_debug_enabled)
323      << StringPrintf("nci_proc_ee_management_rsp opcode:0x%x", op_code);
324  len = *pp++;
325
326  switch (op_code) {
327    case NCI_MSG_NFCEE_DISCOVER:
328      nfc_response.nfcee_discover.status = *pp++;
329      nfc_response.nfcee_discover.num_nfcee = *pp++;
330
331      if (nfc_response.nfcee_discover.status != NFC_STATUS_OK)
332        nfc_response.nfcee_discover.num_nfcee = 0;
333
334      event = NFC_NFCEE_DISCOVER_REVT;
335      break;
336
337    case NCI_MSG_NFCEE_MODE_SET:
338      nfc_response.mode_set.status = *pp;
339      nfc_response.mode_set.nfcee_id = *p_old++;
340      nfc_response.mode_set.mode = *p_old++;
341      if (nfc_cb.nci_version != NCI_VERSION_2_0 || *pp != NCI_STATUS_OK) {
342        nfc_cb.flags &= ~NFC_FL_WAIT_MODE_SET_NTF;
343        event = NFC_NFCEE_MODE_SET_REVT;
344      } else {
345        /* else response reports OK status on notification */
346        return;
347      }
348      break;
349
350    case NCI_MSG_NFCEE_POWER_LINK_CTRL:
351      nfc_response.pl_control.status = *pp;
352      nfc_response.pl_control.nfcee_id = *p_old++;
353      nfc_response.pl_control.pl_control = *p_old++;
354      event = NFC_NFCEE_PL_CONTROL_REVT;
355      break;
356    default:
357      p_cback = NULL;
358      LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
359      break;
360  }
361
362  if (p_cback) (*p_cback)(event, &nfc_response);
363}
364
365/*******************************************************************************
366**
367** Function         nci_proc_ee_management_ntf
368**
369** Description      Process NCI notifications in the NFCEE Management group
370**
371** Returns          void
372**
373*******************************************************************************/
374void nci_proc_ee_management_ntf(NFC_HDR* p_msg) {
375  uint8_t* p;
376  uint8_t *pp, len, op_code;
377  tNFC_RESPONSE_CBACK* p_cback = nfc_cb.p_resp_cback;
378  tNFC_RESPONSE nfc_response;
379  tNFC_RESPONSE_EVT event = NFC_NFCEE_INFO_REVT;
380  uint8_t* p_old = nfc_cb.last_cmd;
381  uint8_t xx;
382  uint8_t yy;
383  tNFC_NFCEE_TLV* p_tlv;
384  /* find the start of the NCI message and parse the NCI header */
385  p = (uint8_t*)(p_msg + 1) + p_msg->offset;
386  pp = p + 1;
387  NCI_MSG_PRS_HDR1(pp, op_code);
388  DLOG_IF(INFO, nfc_debug_enabled)
389      << StringPrintf("nci_proc_ee_management_ntf opcode:0x%x", op_code);
390  len = *pp++;
391
392  if (op_code == NCI_MSG_NFCEE_DISCOVER) {
393    nfc_response.nfcee_info.nfcee_id = *pp++;
394
395    nfc_response.nfcee_info.ee_status = *pp++;
396    yy = *pp;
397    nfc_response.nfcee_info.num_interface = *pp++;
398    p = pp;
399
400    if (nfc_response.nfcee_info.num_interface > NFC_MAX_EE_INTERFACE)
401      nfc_response.nfcee_info.num_interface = NFC_MAX_EE_INTERFACE;
402
403    for (xx = 0; xx < nfc_response.nfcee_info.num_interface; xx++) {
404      nfc_response.nfcee_info.ee_interface[xx] = *pp++;
405    }
406
407    pp = p + yy;
408    nfc_response.nfcee_info.num_tlvs = *pp++;
409    DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
410        "nfcee_id: 0x%x num_interface:0x%x/0x%x, num_tlvs:0x%x",
411        nfc_response.nfcee_info.nfcee_id, nfc_response.nfcee_info.num_interface,
412        yy, nfc_response.nfcee_info.num_tlvs);
413
414    if (nfc_response.nfcee_info.num_tlvs > NFC_MAX_EE_TLVS)
415      nfc_response.nfcee_info.num_tlvs = NFC_MAX_EE_TLVS;
416
417    p_tlv = &nfc_response.nfcee_info.ee_tlv[0];
418
419    for (xx = 0; xx < nfc_response.nfcee_info.num_tlvs; xx++, p_tlv++) {
420      p_tlv->tag = *pp++;
421      p_tlv->len = yy = *pp++;
422      DLOG_IF(INFO, nfc_debug_enabled)
423          << StringPrintf("tag:0x%x, len:0x%x", p_tlv->tag, p_tlv->len);
424      if (p_tlv->len > NFC_MAX_EE_INFO) p_tlv->len = NFC_MAX_EE_INFO;
425      p = pp;
426      STREAM_TO_ARRAY(p_tlv->info, pp, p_tlv->len);
427      pp = p += yy;
428    }
429  } else if (op_code == NCI_MSG_NFCEE_MODE_SET) {
430    nfc_response.mode_set.status = *pp;
431    nfc_response.mode_set.nfcee_id = *p_old++;
432    nfc_response.mode_set.mode = *p_old++;
433    event = NFC_NFCEE_MODE_SET_REVT;
434    nfc_cb.flags &= ~NFC_FL_WAIT_MODE_SET_NTF;
435    nfc_stop_timer(&nfc_cb.nci_mode_set_ntf_timer);
436  } else if (op_code == NCI_MSG_NFCEE_STATUS) {
437    event = NFC_NFCEE_STATUS_REVT;
438    nfc_response.nfcee_status.status = NCI_STATUS_OK;
439    nfc_response.nfcee_status.nfcee_id = *pp++;
440    nfc_response.nfcee_status.nfcee_status = *pp;
441  } else {
442    p_cback = NULL;
443    LOG(ERROR) << StringPrintf("unknown opcode:0x%x", op_code);
444  }
445
446  if (p_cback) (*p_cback)(event, &nfc_response);
447}
448
449#endif
450#endif
451
452/*******************************************************************************
453**
454** Function         nci_proc_prop_rsp
455**
456** Description      Process NCI responses in the Proprietary group
457**
458** Returns          void
459**
460*******************************************************************************/
461void nci_proc_prop_rsp(NFC_HDR* p_msg) {
462  uint8_t* p;
463  uint8_t* p_evt;
464  uint8_t *pp, len, op_code;
465  tNFC_VS_CBACK* p_cback = (tNFC_VS_CBACK*)nfc_cb.p_vsc_cback;
466
467  /* find the start of the NCI message and parse the NCI header */
468  p = p_evt = (uint8_t*)(p_msg + 1) + p_msg->offset;
469  pp = p + 1;
470  NCI_MSG_PRS_HDR1(pp, op_code);
471  len = *pp++;
472
473  /*If there's a pending/stored command, restore the associated address of the
474   * callback function */
475  if (p_cback)
476    (*p_cback)((tNFC_VS_EVT)(NCI_RSP_BIT | op_code), p_msg->len, p_evt);
477}
478
479/*******************************************************************************
480**
481** Function         nci_proc_prop_raw_vs_rsp
482**
483** Description      Process RAW VS responses
484**
485** Returns          void
486**
487*******************************************************************************/
488void nci_proc_prop_raw_vs_rsp(NFC_HDR* p_msg) {
489  uint8_t op_code;
490  tNFC_VS_CBACK* p_cback = (tNFC_VS_CBACK*)nfc_cb.p_vsc_cback;
491
492  /* find the start of the NCI message and parse the NCI header */
493  uint8_t* p_evt = (uint8_t*)(p_msg + 1) + p_msg->offset;
494  uint8_t* p = p_evt + 1;
495  NCI_MSG_PRS_HDR1(p, op_code);
496
497  /* If there's a pending/stored command, restore the associated address of the
498   * callback function */
499  if (p_cback) {
500    (*p_cback)((tNFC_VS_EVT)(NCI_RSP_BIT | op_code), p_msg->len, p_evt);
501    nfc_cb.p_vsc_cback = NULL;
502  }
503  nfc_cb.rawVsCbflag = false;
504  nfc_ncif_update_window();
505}
506
507/*******************************************************************************
508**
509** Function         nci_proc_prop_ntf
510**
511** Description      Process NCI notifications in the Proprietary group
512**
513** Returns          void
514**
515*******************************************************************************/
516void nci_proc_prop_ntf(NFC_HDR* p_msg) {
517  uint8_t* p;
518  uint8_t* p_evt;
519  uint8_t *pp, len, op_code;
520  int i;
521
522  /* find the start of the NCI message and parse the NCI header */
523  p = p_evt = (uint8_t*)(p_msg + 1) + p_msg->offset;
524  pp = p + 1;
525  NCI_MSG_PRS_HDR1(pp, op_code);
526  len = *pp++;
527
528  for (i = 0; i < NFC_NUM_VS_CBACKS; i++) {
529    if (nfc_cb.p_vs_cb[i]) {
530      (*nfc_cb.p_vs_cb[i])((tNFC_VS_EVT)(NCI_NTF_BIT | op_code), p_msg->len,
531                           p_evt);
532    }
533  }
534}
535