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