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