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 *******************************************************************************/
nci_proc_core_rsp(BT_HDR * p_msg)46 BOOLEAN 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 *******************************************************************************/
nci_proc_core_ntf(BT_HDR * p_msg)105 void 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 *******************************************************************************/
nci_proc_rf_management_rsp(BT_HDR * p_msg)157 void 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         nfc_ncif_rf_management_status (NFC_START_DEVT, *pp);
173         break;
174 
175     case NCI_MSG_RF_DISCOVER_SELECT:
176         nfc_ncif_rf_management_status (NFC_SELECT_DEVT, *pp);
177         break;
178 
179     case NCI_MSG_RF_T3T_POLLING:
180         break;
181 
182     case NCI_MSG_RF_DISCOVER_MAP:
183         nfc_ncif_rf_management_status (NFC_MAP_DEVT, *pp);
184         break;
185 
186     case NCI_MSG_RF_DEACTIVATE:
187         nfc_ncif_proc_deactivate (*pp, *p_old, FALSE);
188         break;
189 
190 #if (NFC_NFCEE_INCLUDED == TRUE)
191 #if (NFC_RW_ONLY == FALSE)
192 
193     case NCI_MSG_RF_SET_ROUTING:
194         nfc_ncif_event_status (NFC_SET_ROUTING_REVT, *pp);
195         break;
196 
197     case NCI_MSG_RF_GET_ROUTING:
198         if (*pp != NFC_STATUS_OK)
199             nfc_ncif_event_status (NFC_GET_ROUTING_REVT, *pp);
200         break;
201 #endif
202 #endif
203 
204     case NCI_MSG_RF_PARAMETER_UPDATE:
205         nfc_ncif_event_status (NFC_RF_COMM_PARAMS_UPDATE_REVT, *pp);
206         break;
207 
208     default:
209         NFC_TRACE_ERROR1 ("unknown opcode:0x%x", op_code);
210         break;
211     }
212 }
213 
214 /*******************************************************************************
215 **
216 ** Function         nci_proc_rf_management_ntf
217 **
218 ** Description      Process NCI notifications in the RF Management group
219 **
220 ** Returns          void
221 **
222 *******************************************************************************/
nci_proc_rf_management_ntf(BT_HDR * p_msg)223 void nci_proc_rf_management_ntf (BT_HDR *p_msg)
224 {
225     UINT8   *p;
226     UINT8   *pp, len, op_code;
227 
228     /* find the start of the NCI message and parse the NCI header */
229     p   = (UINT8 *) (p_msg + 1) + p_msg->offset;
230     pp  = p+1;
231     NCI_MSG_PRS_HDR1 (pp, op_code);
232     len = *pp++;
233 
234     switch (op_code)
235     {
236     case NCI_MSG_RF_DISCOVER :
237         nfc_ncif_proc_discover_ntf (p, p_msg->len);
238         break;
239 
240     case NCI_MSG_RF_DEACTIVATE:
241         nfc_ncif_proc_deactivate (NFC_STATUS_OK, *pp, TRUE);
242         break;
243 
244     case NCI_MSG_RF_INTF_ACTIVATED:
245         nfc_ncif_proc_activate (pp, len);
246         break;
247 
248     case NCI_MSG_RF_FIELD:
249         nfc_ncif_proc_rf_field_ntf (*pp);
250         break;
251 
252     case NCI_MSG_RF_T3T_POLLING:
253         nfc_ncif_proc_t3t_polling_ntf (pp, len);
254         break;
255 
256 #if (NFC_NFCEE_INCLUDED == TRUE)
257 #if (NFC_RW_ONLY == FALSE)
258 
259     case NCI_MSG_RF_GET_ROUTING:
260         nfc_ncif_proc_get_routing (pp, len);
261         break;
262 
263     case NCI_MSG_RF_EE_ACTION:
264         nfc_ncif_proc_ee_action (pp, len);
265         break;
266 
267     case NCI_MSG_RF_EE_DISCOVERY_REQ:
268         nfc_ncif_proc_ee_discover_req (pp, len);
269         break;
270 #endif
271 #endif
272 
273     default:
274         NFC_TRACE_ERROR1 ("unknown opcode:0x%x", op_code);
275         break;
276     }
277 }
278 
279 #if (NFC_NFCEE_INCLUDED == TRUE)
280 #if (NFC_RW_ONLY == FALSE)
281 
282 /*******************************************************************************
283 **
284 ** Function         nci_proc_ee_management_rsp
285 **
286 ** Description      Process NCI responses in the NFCEE Management group
287 **
288 ** Returns          void
289 **
290 *******************************************************************************/
nci_proc_ee_management_rsp(BT_HDR * p_msg)291 void nci_proc_ee_management_rsp (BT_HDR *p_msg)
292 {
293     UINT8   *p;
294     UINT8   *pp, len, op_code;
295     tNFC_RESPONSE_CBACK *p_cback = nfc_cb.p_resp_cback;
296     tNFC_NFCEE_DISCOVER_REVT    nfcee_discover;
297     tNFC_NFCEE_INFO_REVT        nfcee_info;
298     tNFC_NFCEE_MODE_SET_REVT    mode_set;
299     tNFC_RESPONSE   *p_evt = (tNFC_RESPONSE *) &nfcee_info;
300     tNFC_RESPONSE_EVT event = NFC_NFCEE_INFO_REVT;
301     UINT8   *p_old = nfc_cb.last_cmd;
302 
303     /* find the start of the NCI message and parse the NCI header */
304     p   = (UINT8 *) (p_msg + 1) + p_msg->offset;
305     pp  = p+1;
306     NCI_MSG_PRS_HDR1 (pp, op_code);
307     NFC_TRACE_DEBUG1 ("nci_proc_ee_management_rsp opcode:0x%x", op_code);
308     len = *pp++;
309 
310     switch (op_code)
311     {
312     case NCI_MSG_NFCEE_DISCOVER:
313         p_evt                       = (tNFC_RESPONSE *) &nfcee_discover;
314         nfcee_discover.status       = *pp++;
315         nfcee_discover.num_nfcee    = *pp++;
316 
317         if (nfcee_discover.status != NFC_STATUS_OK)
318             nfcee_discover.num_nfcee    = 0;
319 
320         event                       = NFC_NFCEE_DISCOVER_REVT;
321         break;
322 
323     case NCI_MSG_NFCEE_MODE_SET:
324         p_evt                   = (tNFC_RESPONSE *) &mode_set;
325         mode_set.status         = *pp;
326         mode_set.nfcee_id       = 0;
327         event                   = NFC_NFCEE_MODE_SET_REVT;
328         mode_set.nfcee_id       = *p_old++;
329         mode_set.mode           = *p_old++;
330         break;
331 
332     default:
333         p_cback = NULL;
334         NFC_TRACE_ERROR1 ("unknown opcode:0x%x", op_code);
335         break;
336     }
337 
338     if (p_cback)
339         (*p_cback) (event, p_evt);
340 }
341 
342 /*******************************************************************************
343 **
344 ** Function         nci_proc_ee_management_ntf
345 **
346 ** Description      Process NCI notifications in the NFCEE Management group
347 **
348 ** Returns          void
349 **
350 *******************************************************************************/
nci_proc_ee_management_ntf(BT_HDR * p_msg)351 void nci_proc_ee_management_ntf (BT_HDR *p_msg)
352 {
353     UINT8                 *p;
354     UINT8                 *pp, len, op_code;
355     tNFC_RESPONSE_CBACK   *p_cback = nfc_cb.p_resp_cback;
356     tNFC_NFCEE_INFO_REVT  nfcee_info;
357     tNFC_RESPONSE         *p_evt   = (tNFC_RESPONSE *) &nfcee_info;
358     tNFC_RESPONSE_EVT     event    = NFC_NFCEE_INFO_REVT;
359     UINT8                 xx;
360     UINT8                 yy;
361     UINT8                 ee_status;
362     tNFC_NFCEE_TLV        *p_tlv;
363 
364     /* find the start of the NCI message and parse the NCI header */
365     p   = (UINT8 *) (p_msg + 1) + p_msg->offset;
366     pp  = p+1;
367     NCI_MSG_PRS_HDR1 (pp, op_code);
368     NFC_TRACE_DEBUG1 ("nci_proc_ee_management_ntf opcode:0x%x", op_code);
369     len = *pp++;
370 
371     if (op_code == NCI_MSG_NFCEE_DISCOVER)
372     {
373         nfcee_info.nfcee_id    = *pp++;
374         ee_status                   = *pp++;
375 
376         nfcee_info.ee_status        = ee_status;
377         yy                          = *pp;
378         nfcee_info.num_interface    = *pp++;
379         p                           = pp;
380 
381         if (nfcee_info.num_interface > NFC_MAX_EE_INTERFACE)
382             nfcee_info.num_interface = NFC_MAX_EE_INTERFACE;
383 
384         for (xx = 0; xx < nfcee_info.num_interface; xx++)
385         {
386             nfcee_info.ee_interface[xx] = *pp++;
387         }
388 
389         pp                              = p + yy;
390         nfcee_info.num_tlvs             = *pp++;
391         NFC_TRACE_DEBUG4 ("nfcee_id: 0x%x num_interface:0x%x/0x%x, num_tlvs:0x%x",
392             nfcee_info.nfcee_id, nfcee_info.num_interface, yy, nfcee_info.num_tlvs);
393 
394         if (nfcee_info.num_tlvs > NFC_MAX_EE_TLVS)
395             nfcee_info.num_tlvs = NFC_MAX_EE_TLVS;
396 
397         p_tlv = &nfcee_info.ee_tlv[0];
398 
399         for (xx = 0; xx < nfcee_info.num_tlvs; xx++, p_tlv++)
400         {
401             p_tlv->tag  = *pp++;
402             p_tlv->len  = yy = *pp++;
403             NFC_TRACE_DEBUG2 ("tag:0x%x, len:0x%x", p_tlv->tag, p_tlv->len);
404             if (p_tlv->len > NFC_MAX_EE_INFO)
405                 p_tlv->len = NFC_MAX_EE_INFO;
406             p   = pp;
407             STREAM_TO_ARRAY (p_tlv->info, pp, p_tlv->len);
408             pp  = p += yy;
409         }
410     }
411     else
412     {
413         p_cback = NULL;
414         NFC_TRACE_ERROR1 ("unknown opcode:0x%x", op_code);
415     }
416 
417     if (p_cback)
418         (*p_cback) (event, p_evt);
419 }
420 
421 #endif
422 #endif
423 
424 /*******************************************************************************
425 **
426 ** Function         nci_proc_prop_rsp
427 **
428 ** Description      Process NCI responses in the Proprietary group
429 **
430 ** Returns          void
431 **
432 *******************************************************************************/
nci_proc_prop_rsp(BT_HDR * p_msg)433 void nci_proc_prop_rsp (BT_HDR *p_msg)
434 {
435     UINT8   *p;
436     UINT8   *p_evt;
437     UINT8   *pp, len, op_code;
438     tNFC_VS_CBACK   *p_cback = (tNFC_VS_CBACK *)nfc_cb.p_vsc_cback;
439 
440     /* find the start of the NCI message and parse the NCI header */
441     p   = p_evt = (UINT8 *) (p_msg + 1) + p_msg->offset;
442     pp  = p+1;
443     NCI_MSG_PRS_HDR1 (pp, op_code);
444     len = *pp++;
445 
446     /*If there's a pending/stored command, restore the associated address of the callback function */
447     if (p_cback)
448         (*p_cback) ((tNFC_VS_EVT) (NCI_RSP_BIT|op_code), p_msg->len, p_evt);
449 }
450 
451 /*******************************************************************************
452 **
453 ** Function         nci_proc_prop_ntf
454 **
455 ** Description      Process NCI notifications in the Proprietary group
456 **
457 ** Returns          void
458 **
459 *******************************************************************************/
nci_proc_prop_ntf(BT_HDR * p_msg)460 void nci_proc_prop_ntf (BT_HDR *p_msg)
461 {
462     UINT8   *p;
463     UINT8   *p_evt;
464     UINT8   *pp, len, op_code;
465     int i;
466 
467     /* find the start of the NCI message and parse the NCI header */
468     p   = p_evt = (UINT8 *) (p_msg + 1) + p_msg->offset;
469     pp  = p+1;
470     NCI_MSG_PRS_HDR1 (pp, op_code);
471     len = *pp++;
472 
473     for (i = 0; i < NFC_NUM_VS_CBACKS; i++)
474     {
475         if (nfc_cb.p_vs_cb[i])
476         {
477             (*nfc_cb.p_vs_cb[i]) ((tNFC_VS_EVT) (NCI_NTF_BIT|op_code), p_msg->len, p_evt);
478         }
479     }
480 }
481 
482 #endif /* NFC_INCLUDED == TRUE*/
483