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