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