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 the LLCP Link Management
22  *
23  ******************************************************************************/
24 
25 #include <string.h>
26 
27 #include <android-base/stringprintf.h>
28 #include <base/logging.h>
29 #include <log/log.h>
30 #include "bt_types.h"
31 #include "gki.h"
32 #include "llcp_defs.h"
33 #include "llcp_int.h"
34 #include "nfa_dm_int.h"
35 #include "nfc_int.h"
36 
37 using android::base::StringPrintf;
38 
39 const uint16_t llcp_link_rwt
40     [15] = /* RWT = (302us)*2**WT; 302us = 256*16/fc; fc = 13.56MHz */
41     {
42         1,    /* WT=0,     302us */
43         1,    /* WT=1,     604us */
44         2,    /* WT=2,    1208us */
45         3,    /* WT=3,     2.4ms */
46         5,    /* WT=4,     4.8ms */
47         10,   /* WT=5,     9.7ms */
48         20,   /* WT=6,    19.3ms */
49         39,   /* WT=7,    38.7ms */
50         78,   /* WT=8,    77.3ms */
51         155,  /* WT=9,   154.6ms */
52         310,  /* WT=10,  309.2ms */
53         619,  /* WT=11,  618.5ms */
54         1237, /* WT=12, 1237.0ms */
55         2474, /* WT=13, 2474.0ms */
56         4948, /* WT=14, 4948.0ms */
57 };
58 
59 static bool llcp_link_parse_gen_bytes(uint8_t gen_bytes_len,
60                                       uint8_t* p_gen_bytes);
61 static bool llcp_link_version_agreement(void);
62 
63 static void llcp_link_send_SYMM(void);
64 static void llcp_link_update_status(bool is_activated);
65 static void llcp_link_check_congestion(void);
66 static void llcp_link_check_uncongested(void);
67 static void llcp_link_proc_ui_pdu(uint8_t local_sap, uint8_t remote_sap,
68                                   uint16_t ui_pdu_length, uint8_t* p_ui_pdu,
69                                   NFC_HDR* p_msg);
70 static void llcp_link_proc_agf_pdu(NFC_HDR* p_msg);
71 static void llcp_link_proc_rx_pdu(uint8_t dsap, uint8_t ptype, uint8_t ssap,
72                                   NFC_HDR* p_msg);
73 static void llcp_link_proc_rx_data(NFC_HDR* p_msg);
74 
75 static NFC_HDR* llcp_link_get_next_pdu(bool length_only,
76                                        uint16_t* p_next_pdu_length);
77 static NFC_HDR* llcp_link_build_next_pdu(NFC_HDR* p_agf);
78 static void llcp_link_send_to_lower(NFC_HDR* p_msg);
79 
80 #if (LLCP_TEST_INCLUDED == TRUE) /* this is for LLCP testing */
81 extern tLLCP_TEST_PARAMS llcp_test_params;
82 #endif
83 
84 extern bool nfc_debug_enabled;
85 extern unsigned char appl_dta_mode_flag;
86 
87 /* debug functions type */
88 static std::string llcp_pdu_type(uint8_t ptype);
89 
90 /*******************************************************************************
91 **
92 ** Function         llcp_link_start_inactivity_timer
93 **
94 ** Description      This function start LLCP link inactivity timer.
95 **
96 ** Returns          void
97 **
98 *******************************************************************************/
llcp_link_start_inactivity_timer(void)99 static void llcp_link_start_inactivity_timer(void) {
100   if ((llcp_cb.lcb.inact_timer.in_use == false) &&
101       (llcp_cb.lcb.inact_timeout > 0)) {
102     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
103         "Start inactivity_timer: %d ms", llcp_cb.lcb.inact_timeout);
104 
105     nfc_start_quick_timer(&llcp_cb.lcb.inact_timer, NFC_TTYPE_LLCP_LINK_INACT,
106                           ((uint32_t)llcp_cb.lcb.inact_timeout) *
107                               QUICK_TIMER_TICKS_PER_SEC / 1000);
108   }
109 }
110 
111 /*******************************************************************************
112 **
113 ** Function         llcp_link_stop_inactivity_timer
114 **
115 ** Description      This function stop LLCP link inactivity timer.
116 **
117 ** Returns          void
118 **
119 *******************************************************************************/
llcp_link_stop_inactivity_timer(void)120 static void llcp_link_stop_inactivity_timer(void) {
121   if (llcp_cb.lcb.inact_timer.in_use) {
122     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Stop inactivity_timer");
123 
124     nfc_stop_quick_timer(&llcp_cb.lcb.inact_timer);
125   }
126 }
127 
128 /*******************************************************************************
129 **
130 ** Function         llcp_link_start_link_timer
131 **
132 ** Description      This function starts LLCP link timer (LTO or delay response)
133 **
134 ** Returns          void
135 **
136 *******************************************************************************/
llcp_link_start_link_timer(void)137 static void llcp_link_start_link_timer(void) {
138   if (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT) {
139     /* wait for application layer sending data */
140     nfc_start_quick_timer(
141         &llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
142         (((uint32_t)llcp_cb.lcb.symm_delay) * QUICK_TIMER_TICKS_PER_SEC) /
143             1000);
144   } else {
145     /* wait for data to receive from remote */
146     nfc_start_quick_timer(
147         &llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
148         ((uint32_t)llcp_cb.lcb.peer_lto) * QUICK_TIMER_TICKS_PER_SEC / 1000);
149   }
150 }
151 
152 /*******************************************************************************
153 **
154 ** Function         llcp_link_stop_link_timer
155 **
156 ** Description      This function stop LLCP link timer (LTO or delay response).
157 **
158 ** Returns          void
159 **
160 *******************************************************************************/
llcp_link_stop_link_timer(void)161 static void llcp_link_stop_link_timer(void) {
162   nfc_stop_quick_timer(&llcp_cb.lcb.timer);
163 }
164 
165 /*******************************************************************************
166 **
167 ** Function         llcp_link_activate
168 **
169 ** Description      Activate LLCP link
170 **
171 ** Returns          tLLCP_STATUS
172 **
173 *******************************************************************************/
llcp_link_activate(tLLCP_ACTIVATE_CONFIG * p_config)174 tLLCP_STATUS llcp_link_activate(tLLCP_ACTIVATE_CONFIG* p_config) {
175   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
176 
177   /* At this point, MAC link activation procedure has been successfully
178    * completed */
179 
180   /* The Length Reduction values LRi and LRt MUST be 11b. (254bytes) */
181   if (p_config->max_payload_size != LLCP_NCI_MAX_PAYL_SIZE) {
182     LOG(WARNING) << StringPrintf("max payload size (%d) must be %d bytes",
183                                  p_config->max_payload_size,
184                                  LLCP_NCI_MAX_PAYL_SIZE);
185   }
186 
187   /* Processing the parametes that have been received with the MAC link
188    * activation */
189   if (llcp_link_parse_gen_bytes(p_config->gen_bytes_len,
190                                 p_config->p_gen_bytes) == false) {
191     LOG(ERROR) << StringPrintf("Failed to parse general bytes");
192     /* For LLCP DTA test, In case of bad magic bytes normal p2p communication is
193      * expected,but in case of wrong magic bytes in ATR_REQ, LLC layer will be
194      * disconnected but P2P connection is expected to be in connected state
195      * and non LLC PDU is expected.
196      * As per NFC forum expectation below changes is to send PDU after
197      * disconnect of LLCP PDU.
198      * This is fix for TC_MAC_TAR_BI_01 LLCP test case */
199 
200     if (appl_dta_mode_flag == 1 && p_config->is_initiator == FALSE) {
201       NFC_HDR* p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
202 
203       if (p_msg) {
204         /*LLCP test scenario requires non LLC PDU to be sent in case of wrong
205           magic bytes. So sending NFC-DEP pdu with size 1 (0x00)*/
206         p_msg->len = 1;
207         p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
208 
209         NFC_SendData(NFC_RF_CONN_ID, p_msg);
210       }
211     }
212 
213     (*llcp_cb.lcb.p_link_cback)(LLCP_LINK_ACTIVATION_FAILED_EVT,
214                                 LLCP_LINK_BAD_GEN_BYTES);
215 
216     if (p_config->is_initiator == false) {
217       /* repond to any incoming PDU with invalid LLCP PDU */
218       llcp_cb.lcb.link_state = LLCP_LINK_STATE_ACTIVATION_FAILED;
219       NFC_SetStaticRfCback(llcp_link_connection_cback);
220     }
221     return LLCP_STATUS_FAIL;
222   }
223 
224   /*
225   ** For the Target device, the scaled value of RWT MUST be less than or equal
226   ** to the scaled value of the LLC Link Timeout (LTO).
227   */
228   if ((p_config->is_initiator) &&
229       (llcp_link_rwt[p_config->waiting_time] > llcp_cb.lcb.peer_lto)) {
230     LOG(WARNING) << StringPrintf(
231         "WT (%d, %dms) must be less than or equal to "
232         "LTO (%dms)",
233         p_config->waiting_time, llcp_link_rwt[p_config->waiting_time],
234         llcp_cb.lcb.peer_lto);
235   }
236   /* For DTA mode Peer LTO Should not include TX RX Delay, Just llcp deactivate
237    * after Peer LTO time */
238   if (!appl_dta_mode_flag) {
239     /* extend LTO as much as internally required processing time and propagation
240      * delays */
241     llcp_cb.lcb.peer_lto += LLCP_INTERNAL_TX_DELAY + LLCP_INTERNAL_RX_DELAY;
242   }
243   /* LLCP version number agreement */
244   if (llcp_link_version_agreement() == false) {
245     LOG(ERROR) << StringPrintf("Failed to agree version");
246     (*llcp_cb.lcb.p_link_cback)(LLCP_LINK_ACTIVATION_FAILED_EVT,
247                                 LLCP_LINK_VERSION_FAILED);
248 
249     if (p_config->is_initiator == false) {
250       /* repond to any incoming PDU with invalid LLCP PDU */
251       llcp_cb.lcb.link_state = LLCP_LINK_STATE_ACTIVATION_FAILED;
252       NFC_SetStaticRfCback(llcp_link_connection_cback);
253     }
254     return LLCP_STATUS_FAIL;
255   }
256 
257   llcp_cb.lcb.received_first_packet = false;
258   llcp_cb.lcb.is_initiator = p_config->is_initiator;
259 
260   /* reset internal flags */
261   llcp_cb.lcb.flags = 0x00;
262 
263   /* set tx MIU to MIN (MIU of local LLCP, MIU of peer LLCP) */
264 
265   if (llcp_cb.lcb.local_link_miu >= llcp_cb.lcb.peer_miu)
266     llcp_cb.lcb.effective_miu = llcp_cb.lcb.peer_miu;
267   else
268     llcp_cb.lcb.effective_miu = llcp_cb.lcb.local_link_miu;
269 
270   /*
271   ** When entering the normal operation phase, LLCP shall initialize the
272   ** symmetry procedure.
273   */
274   if (llcp_cb.lcb.is_initiator) {
275     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Connected as Initiator");
276 
277     llcp_cb.lcb.inact_timeout = llcp_cb.lcb.inact_timeout_init;
278     llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_LOCAL_XMIT_NEXT;
279 
280     if (llcp_cb.lcb.delay_first_pdu_timeout > 0) {
281       /* give a chance to upper layer to send PDU if need */
282       nfc_start_quick_timer(&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_DELAY_FIRST_PDU,
283                             (((uint32_t)llcp_cb.lcb.delay_first_pdu_timeout) *
284                              QUICK_TIMER_TICKS_PER_SEC) /
285                                 1000);
286     } else {
287       llcp_link_send_SYMM();
288     }
289   } else {
290     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Connected as Target");
291     llcp_cb.lcb.inact_timeout = llcp_cb.lcb.inact_timeout_target;
292     llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_REMOTE_XMIT_NEXT;
293 
294     /* wait for data to receive from remote */
295     llcp_link_start_link_timer();
296   }
297 
298   /*
299   ** Set state to LLCP_LINK_STATE_ACTIVATED and notify activation before set
300   ** data callback because LLCP PDU could be in NCI queue.
301   */
302   llcp_cb.lcb.link_state = LLCP_LINK_STATE_ACTIVATED;
303 
304   /* LLCP Link Activation completed */
305   (*llcp_cb.lcb.p_link_cback)(LLCP_LINK_ACTIVATION_COMPLETE_EVT,
306                               LLCP_LINK_SUCCESS);
307 
308   /* Update link status to service layer */
309   llcp_link_update_status(true);
310 
311   NFC_SetStaticRfCback(llcp_link_connection_cback);
312 
313   return (LLCP_STATUS_SUCCESS);
314 }
315 
316 /*******************************************************************************
317 **
318 ** Function         llcp_deactivate_cleanup
319 **
320 ** Description      Clean up for link deactivation
321 **
322 ** Returns          void
323 **
324 *******************************************************************************/
llcp_deactivate_cleanup(uint8_t reason)325 static void llcp_deactivate_cleanup(uint8_t reason) {
326   /* report SDP failure for any pending request */
327   llcp_sdp_proc_deactivation();
328 
329   /* Update link status to service layer */
330   llcp_link_update_status(false);
331 
332   /* We had sent out DISC */
333   llcp_cb.lcb.link_state = LLCP_LINK_STATE_DEACTIVATED;
334 
335   llcp_link_stop_link_timer();
336 
337   /* stop inactivity timer */
338   llcp_link_stop_inactivity_timer();
339 
340   /* Let upper layer deactivate local link */
341   (*llcp_cb.lcb.p_link_cback)(LLCP_LINK_DEACTIVATED_EVT, reason);
342 }
343 
344 /*******************************************************************************
345 **
346 ** Function         llcp_link_process_link_timeout
347 **
348 ** Description      Process timeout events for LTO, SYMM and deactivating
349 **
350 ** Returns          void
351 **
352 *******************************************************************************/
llcp_link_process_link_timeout(void)353 void llcp_link_process_link_timeout(void) {
354   if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED) {
355     if ((llcp_cb.lcb.symm_delay > 0) &&
356         (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT)) {
357       /* upper layer doesn't have anything to send */
358       DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
359           "LEVT_TIMEOUT in state of "
360           "LLCP_LINK_SYMM_LOCAL_XMIT_NEXT");
361       llcp_link_send_SYMM();
362 
363       /* wait for data to receive from remote */
364       llcp_link_start_link_timer();
365 
366       /* start inactivity timer */
367       if (llcp_cb.num_data_link_connection == 0) {
368         llcp_link_start_inactivity_timer();
369       }
370     } else {
371       LOG(ERROR) << StringPrintf(
372           "LEVT_TIMEOUT in state of "
373           "LLCP_LINK_SYMM_REMOTE_XMIT_NEXT");
374       llcp_link_deactivate(LLCP_LINK_TIMEOUT);
375     }
376   } else if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING) {
377     llcp_deactivate_cleanup(llcp_cb.lcb.link_deact_reason);
378 
379     NFC_SetStaticRfCback(nullptr);
380   }
381 }
382 
383 /*******************************************************************************
384 **
385 ** Function         llcp_link_deactivate
386 **
387 ** Description      Deactivate LLCP link
388 **
389 ** Returns          void
390 **
391 *******************************************************************************/
llcp_link_deactivate(uint8_t reason)392 void llcp_link_deactivate(uint8_t reason) {
393   uint8_t local_sap, idx;
394   tLLCP_DLCB* p_dlcb;
395   tLLCP_APP_CB* p_app_cb;
396 
397   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("reason = 0x%x", reason);
398 
399   /* Release any held buffers in signaling PDU queue */
400   while (llcp_cb.lcb.sig_xmit_q.p_first)
401     GKI_freebuf(GKI_dequeue(&llcp_cb.lcb.sig_xmit_q));
402 
403   /* Release any held buffers in UI PDU queue */
404   for (local_sap = LLCP_SAP_SDP + 1; local_sap < LLCP_NUM_SAPS; local_sap++) {
405     p_app_cb = llcp_util_get_app_cb(local_sap);
406 
407     if ((p_app_cb) && (p_app_cb->p_app_cback)) {
408       while (p_app_cb->ui_xmit_q.p_first)
409         GKI_freebuf(GKI_dequeue(&p_app_cb->ui_xmit_q));
410 
411       p_app_cb->is_ui_tx_congested = false;
412 
413       while (p_app_cb->ui_rx_q.p_first)
414         GKI_freebuf(GKI_dequeue(&p_app_cb->ui_rx_q));
415     }
416   }
417 
418   llcp_cb.total_tx_ui_pdu = 0;
419   llcp_cb.total_rx_ui_pdu = 0;
420 
421   /* Notify all of data link */
422   for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
423     if (llcp_cb.dlcb[idx].state != LLCP_DLC_STATE_IDLE) {
424       p_dlcb = &(llcp_cb.dlcb[idx]);
425 
426       llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_LINK_ERROR, nullptr);
427     }
428   }
429   llcp_cb.total_tx_i_pdu = 0;
430   llcp_cb.total_rx_i_pdu = 0;
431 
432   llcp_cb.overall_tx_congested = false;
433   llcp_cb.overall_rx_congested = false;
434 
435   /* As per the LLCP test specification v1.2.00 for test case TC_LLC_TAR_BV_04
436    * the receiving LLC shall commence sending an LLC PDU to the remote
437    * LLC. So, after IUT receives DISC PDU from LT(remote device), IUT shall
438    * send DISC PDU to LT. appl_dta_mode_flag condition is added to fulfil
439    * above requirement. Only in CR8, the IUT shall acknoweledge with SYMM for
440    * DISC PDU. For other CRx, send DISC PDU.
441    */
442   if ((reason == LLCP_LINK_FRAME_ERROR) ||
443       (reason == LLCP_LINK_LOCAL_INITIATED) ||
444       (appl_dta_mode_flag && reason == LLCP_LINK_REMOTE_INITIATED &&
445        llcp_cb.lcb.is_initiator == false &&
446        (nfa_dm_cb.eDtaMode & 0xF0) != NFA_DTA_CR8)) {
447     /* get rid of the data pending in NFC tx queue, so DISC PDU can be sent ASAP
448      */
449     NFC_FlushData(NFC_RF_CONN_ID);
450 
451     llcp_util_send_disc(LLCP_SAP_LM, LLCP_SAP_LM);
452 
453     /* Wait until DISC is sent to peer */
454     DLOG_IF(INFO, nfc_debug_enabled)
455         << StringPrintf("Wait until DISC is sent to peer");
456 
457     llcp_cb.lcb.link_state = LLCP_LINK_STATE_DEACTIVATING;
458 
459     if (llcp_cb.lcb.sig_xmit_q.count == 0) {
460       /* if DISC is sent to NFCC, wait for short period for NFCC to send it to
461        * peer */
462       nfc_start_quick_timer(&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
463                             ((uint32_t)50) * QUICK_TIMER_TICKS_PER_SEC / 1000);
464     }
465 
466     llcp_cb.lcb.link_deact_reason = reason;
467     return;
468   } else if ((reason == LLCP_LINK_REMOTE_INITIATED) &&
469              (!llcp_cb.lcb.is_initiator)) {
470     /* if received DISC to deactivate LLCP link as target role, send SYMM PDU */
471     llcp_link_send_SYMM();
472   } else /*  for link timeout and interface error */
473   {
474     /* if got RF link loss receiving no LLC PDU from peer */
475     if ((reason == LLCP_LINK_RF_LINK_LOSS_ERR) &&
476         (!(llcp_cb.lcb.flags & LLCP_LINK_FLAGS_RX_ANY_LLC_PDU))) {
477       reason = LLCP_LINK_RF_LINK_LOSS_NO_RX_LLC;
478     }
479 
480     NFC_FlushData(NFC_RF_CONN_ID);
481   }
482 
483   llcp_deactivate_cleanup(reason);
484 }
485 
486 /*******************************************************************************
487 **
488 ** Function         llcp_link_parse_gen_bytes
489 **
490 ** Description      Check LLCP magic number and get parameters in general bytes
491 **
492 ** Returns          TRUE if success
493 **
494 *******************************************************************************/
llcp_link_parse_gen_bytes(uint8_t gen_bytes_len,uint8_t * p_gen_bytes)495 static bool llcp_link_parse_gen_bytes(uint8_t gen_bytes_len,
496                                       uint8_t* p_gen_bytes) {
497   uint8_t* p = p_gen_bytes + LLCP_MAGIC_NUMBER_LEN;
498   uint8_t length = gen_bytes_len - LLCP_MAGIC_NUMBER_LEN;
499 
500   if ((gen_bytes_len >= LLCP_MAGIC_NUMBER_LEN) &&
501       (*(p_gen_bytes) == LLCP_MAGIC_NUMBER_BYTE0) &&
502       (*(p_gen_bytes + 1) == LLCP_MAGIC_NUMBER_BYTE1) &&
503       (*(p_gen_bytes + 2) == LLCP_MAGIC_NUMBER_BYTE2)) {
504     /* in case peer didn't include these */
505     llcp_cb.lcb.peer_miu = LLCP_DEFAULT_MIU;
506     llcp_cb.lcb.peer_lto = LLCP_DEFAULT_LTO_IN_MS;
507 
508     return (llcp_util_parse_link_params(length, p));
509   } else /* if this is not LLCP */
510   {
511     return false;
512   }
513 
514   return true;
515 }
516 
517 /*******************************************************************************
518 **
519 ** Function         llcp_link_version_agreement
520 **
521 ** Description      LLCP version number agreement
522 **
523 ** Returns          TRUE if success
524 **
525 *******************************************************************************/
llcp_link_version_agreement(void)526 static bool llcp_link_version_agreement(void) {
527   uint8_t peer_major_version, peer_minor_version;
528 
529   peer_major_version = LLCP_GET_MAJOR_VERSION(llcp_cb.lcb.peer_version);
530   peer_minor_version = LLCP_GET_MINOR_VERSION(llcp_cb.lcb.peer_version);
531 
532   if (peer_major_version < LLCP_MIN_MAJOR_VERSION) {
533     LOG(ERROR) << StringPrintf(
534         "unsupported peer version number. Peer "
535         "Major Version:%d",
536         peer_major_version);
537     return false;
538   } else {
539     if (peer_major_version == LLCP_VERSION_MAJOR) {
540       llcp_cb.lcb.agreed_major_version = LLCP_VERSION_MAJOR;
541       if (peer_minor_version >= LLCP_VERSION_MINOR) {
542         llcp_cb.lcb.agreed_minor_version = LLCP_VERSION_MINOR;
543       } else {
544         llcp_cb.lcb.agreed_minor_version = peer_minor_version;
545       }
546     } else if (peer_major_version < LLCP_VERSION_MAJOR) {
547       /* so far we can support backward compatibility */
548       llcp_cb.lcb.agreed_major_version = peer_major_version;
549       llcp_cb.lcb.agreed_minor_version = peer_minor_version;
550     } else {
551       /* let peer (higher major version) decide it */
552       llcp_cb.lcb.agreed_major_version = LLCP_VERSION_MAJOR;
553       llcp_cb.lcb.agreed_minor_version = LLCP_VERSION_MINOR;
554     }
555 
556     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
557         "local version:%d.%d, remote version:%d.%d, agreed version:%d.%d",
558         LLCP_VERSION_MAJOR, LLCP_VERSION_MINOR, peer_major_version,
559         peer_minor_version, llcp_cb.lcb.agreed_major_version,
560         llcp_cb.lcb.agreed_minor_version);
561 
562     return true;
563   }
564 }
565 
566 /*******************************************************************************
567 **
568 ** Function         llcp_link_update_status
569 **
570 ** Description      Notify all of service layer client link status change
571 **
572 ** Returns          void
573 **
574 *******************************************************************************/
llcp_link_update_status(bool is_activated)575 static void llcp_link_update_status(bool is_activated) {
576   tLLCP_SAP_CBACK_DATA data;
577   tLLCP_APP_CB* p_app_cb;
578   uint8_t sap;
579 
580   data.link_status.event = LLCP_SAP_EVT_LINK_STATUS;
581   data.link_status.is_activated = is_activated;
582   data.link_status.is_initiator = llcp_cb.lcb.is_initiator;
583 
584   /* notify all SAP so they can create connection while link is activated */
585   for (sap = LLCP_SAP_SDP + 1; sap < LLCP_NUM_SAPS; sap++) {
586     p_app_cb = llcp_util_get_app_cb(sap);
587 
588     if ((p_app_cb) && (p_app_cb->p_app_cback)) {
589       data.link_status.local_sap = sap;
590       p_app_cb->p_app_cback(&data);
591     }
592   }
593 }
594 
595 /*******************************************************************************
596 **
597 ** Function         llcp_link_check_congestion
598 **
599 ** Description      Check overall congestion status
600 **                  Notify to all of upper layer if congested
601 **
602 ** Returns          void
603 **
604 *******************************************************************************/
llcp_link_check_congestion(void)605 static void llcp_link_check_congestion(void) {
606   tLLCP_SAP_CBACK_DATA data;
607   tLLCP_APP_CB* p_app_cb;
608   uint8_t sap, idx;
609 
610   if (llcp_cb.overall_tx_congested) {
611     /* already congested so no need to check again */
612     return;
613   }
614 
615   if (llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu >=
616       llcp_cb.max_num_tx_buff) {
617     /* overall buffer usage is high */
618     llcp_cb.overall_tx_congested = true;
619 
620     LOG(WARNING) << StringPrintf(
621         "overall tx congestion start: total_tx_ui_pdu=%d, total_tx_i_pdu=%d",
622         llcp_cb.total_tx_ui_pdu, llcp_cb.total_tx_i_pdu);
623 
624     data.congest.event = LLCP_SAP_EVT_CONGEST;
625     data.congest.is_congested = true;
626 
627     /* notify logical data link congestion status */
628     data.congest.remote_sap = LLCP_INVALID_SAP;
629     data.congest.link_type = LLCP_LINK_TYPE_LOGICAL_DATA_LINK;
630 
631     for (sap = LLCP_SAP_SDP + 1; sap < LLCP_NUM_SAPS; sap++) {
632       p_app_cb = llcp_util_get_app_cb(sap);
633 
634       if ((p_app_cb) && (p_app_cb->p_app_cback) &&
635           (p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK)) {
636         /* if already congested then no need to notify again */
637         if (!p_app_cb->is_ui_tx_congested) {
638           p_app_cb->is_ui_tx_congested = true;
639 
640           LOG(WARNING) << StringPrintf(
641               "Logical link (SAP=0x%X) congestion start: count=%d", sap,
642               p_app_cb->ui_xmit_q.count);
643 
644           data.congest.local_sap = sap;
645           p_app_cb->p_app_cback(&data);
646         }
647       }
648     }
649 
650     /* notify data link connection congestion status */
651     data.congest.link_type = LLCP_LINK_TYPE_DATA_LINK_CONNECTION;
652 
653     for (idx = 0; idx < LLCP_MAX_DATA_LINK; idx++) {
654       if ((llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) &&
655           (llcp_cb.dlcb[idx].remote_busy == false) &&
656           (llcp_cb.dlcb[idx].is_tx_congested == false)) {
657         llcp_cb.dlcb[idx].is_tx_congested = true;
658 
659         LOG(WARNING) << StringPrintf(
660             "Data link (SSAP:DSAP=0x%X:0x%X) congestion start: count=%d",
661             llcp_cb.dlcb[idx].local_sap, llcp_cb.dlcb[idx].remote_sap,
662             llcp_cb.dlcb[idx].i_xmit_q.count);
663 
664         data.congest.local_sap = llcp_cb.dlcb[idx].local_sap;
665         data.congest.remote_sap = llcp_cb.dlcb[idx].remote_sap;
666 
667         (*llcp_cb.dlcb[idx].p_app_cb->p_app_cback)(&data);
668       }
669     }
670   }
671 }
672 
673 /*******************************************************************************
674 **
675 ** Function         llcp_link_check_uncongested
676 **
677 ** Description      Check overall congestion status, logical data link and
678 **                  data link connection congestion status
679 **                  Notify to each upper layer if uncongested
680 **
681 ** Returns          void
682 **
683 *******************************************************************************/
llcp_link_check_uncongested(void)684 static void llcp_link_check_uncongested(void) {
685   tLLCP_SAP_CBACK_DATA data;
686   tLLCP_APP_CB* p_app_cb;
687   uint8_t xx, sap, idx;
688 
689   if (llcp_cb.overall_tx_congested) {
690     if (llcp_cb.total_tx_ui_pdu + llcp_cb.total_tx_i_pdu <=
691         llcp_cb.max_num_tx_buff / 2) {
692       /* overall congestion is cleared */
693       llcp_cb.overall_tx_congested = false;
694 
695       LOG(WARNING) << StringPrintf(
696           "overall tx congestion end: total_tx_ui_pdu=%d, total_tx_i_pdu=%d",
697           llcp_cb.total_tx_ui_pdu, llcp_cb.total_tx_i_pdu);
698     } else {
699       /* wait until more data packets are sent out */
700       return;
701     }
702   }
703 
704   data.congest.event = LLCP_SAP_EVT_CONGEST;
705   data.congest.is_congested = false;
706 
707   /* if total number of UI PDU is below threshold */
708   if (llcp_cb.total_tx_ui_pdu < llcp_cb.max_num_ll_tx_buff) {
709     /* check and notify logical data link congestion status */
710     data.congest.remote_sap = LLCP_INVALID_SAP;
711     data.congest.link_type = LLCP_LINK_TYPE_LOGICAL_DATA_LINK;
712 
713     /*
714     ** start point of uncongested status notification is in round robin
715     ** so each logical data link has equal chance of transmitting.
716     */
717     sap = llcp_cb.ll_tx_uncongest_ntf_start_sap;
718 
719     for (xx = LLCP_SAP_SDP + 1; xx < LLCP_NUM_SAPS; xx++) {
720       /* no logical data link on LM and SDP */
721       if (sap > LLCP_SAP_SDP) {
722         p_app_cb = llcp_util_get_app_cb(sap);
723 
724         if ((p_app_cb) && (p_app_cb->p_app_cback) &&
725             (p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK) &&
726             (p_app_cb->is_ui_tx_congested) &&
727             (p_app_cb->ui_xmit_q.count <= llcp_cb.ll_tx_congest_end)) {
728           /* if it was congested but now tx queue count is below threshold */
729           p_app_cb->is_ui_tx_congested = false;
730 
731           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
732               "Logical link (SAP=0x%X) congestion end: count=%d", sap,
733               p_app_cb->ui_xmit_q.count);
734 
735           data.congest.local_sap = sap;
736           p_app_cb->p_app_cback(&data);
737         }
738       }
739 
740       sap = (sap + 1) % LLCP_NUM_SAPS;
741     }
742 
743     /* move start point for next logical data link */
744     for (xx = 0; xx < LLCP_NUM_SAPS; xx++) {
745       sap = (llcp_cb.ll_tx_uncongest_ntf_start_sap + 1) % LLCP_NUM_SAPS;
746 
747       if (sap > LLCP_SAP_SDP) {
748         p_app_cb = llcp_util_get_app_cb(sap);
749 
750         if ((p_app_cb) && (p_app_cb->p_app_cback) &&
751             (p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK)) {
752           llcp_cb.ll_tx_uncongest_ntf_start_sap = sap;
753           break;
754         }
755       }
756     }
757   }
758 
759   /* notify data link connection congestion status */
760   data.congest.link_type = LLCP_LINK_TYPE_DATA_LINK_CONNECTION;
761 
762   /*
763   ** start point of uncongested status notification is in round robin
764   ** so each data link connection has equal chance of transmitting.
765   */
766   idx = llcp_cb.dl_tx_uncongest_ntf_start_idx;
767 
768   for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++) {
769     /* if it was congested but now tx queue is below threshold (receiving
770      * window) */
771     if ((llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) &&
772         (llcp_cb.dlcb[idx].is_tx_congested) &&
773         (llcp_cb.dlcb[idx].i_xmit_q.count <= llcp_cb.dlcb[idx].remote_rw / 2)) {
774       llcp_cb.dlcb[idx].is_tx_congested = false;
775 
776       if (llcp_cb.dlcb[idx].remote_busy == false) {
777         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
778             "Data link (SSAP:DSAP=0x%X:0x%X) congestion end: count=%d",
779             llcp_cb.dlcb[idx].local_sap, llcp_cb.dlcb[idx].remote_sap,
780             llcp_cb.dlcb[idx].i_xmit_q.count);
781 
782         data.congest.local_sap = llcp_cb.dlcb[idx].local_sap;
783         data.congest.remote_sap = llcp_cb.dlcb[idx].remote_sap;
784 
785         (*llcp_cb.dlcb[idx].p_app_cb->p_app_cback)(&data);
786       }
787     }
788     idx = (idx + 1) % LLCP_MAX_DATA_LINK;
789   }
790 
791   /* move start point for next data link connection */
792   for (xx = 0; xx < LLCP_MAX_DATA_LINK; xx++) {
793     idx = (llcp_cb.dl_tx_uncongest_ntf_start_idx + 1) % LLCP_MAX_DATA_LINK;
794     if (llcp_cb.dlcb[idx].state == LLCP_DLC_STATE_CONNECTED) {
795       llcp_cb.dl_tx_uncongest_ntf_start_idx = idx;
796       break;
797     }
798   }
799 }
800 
801 /*******************************************************************************
802 **
803 ** Function         llcp_link_send_SYMM
804 **
805 ** Description      Send SYMM PDU
806 **
807 ** Returns          void
808 **
809 *******************************************************************************/
llcp_link_send_SYMM(void)810 static void llcp_link_send_SYMM(void) {
811   NFC_HDR* p_msg;
812   uint8_t* p;
813 
814   p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
815 
816   if (p_msg) {
817     p_msg->len = LLCP_PDU_SYMM_SIZE;
818     p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
819 
820     p = (uint8_t*)(p_msg + 1) + p_msg->offset;
821     UINT16_TO_BE_STREAM(
822         p, LLCP_GET_PDU_HEADER(LLCP_SAP_LM, LLCP_PDU_SYMM_TYPE, LLCP_SAP_LM));
823 
824     llcp_link_send_to_lower(p_msg);
825   }
826 }
827 
828 /*******************************************************************************
829 **
830 ** Function         llcp_link_send_invalid_pdu
831 **
832 ** Description      Send invalid LLC PDU in LLCP_LINK_STATE_ACTIVATION_FAILED
833 **
834 ** Returns          void
835 **
836 *******************************************************************************/
llcp_link_send_invalid_pdu(void)837 static void llcp_link_send_invalid_pdu(void) {
838   NFC_HDR* p_msg;
839   uint8_t* p;
840 
841   p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
842 
843   if (p_msg) {
844     /* send one byte of 0x00 as invalid LLC PDU */
845     p_msg->len = 1;
846     p_msg->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
847 
848     p = (uint8_t*)(p_msg + 1) + p_msg->offset;
849     *p = 0x00;
850 
851     NFC_SendData(NFC_RF_CONN_ID, p_msg);
852   }
853 }
854 
855 /*******************************************************************************
856 **
857 ** Function         llcp_link_check_send_data
858 **
859 ** Description      Send PDU to peer
860 **
861 ** Returns          void
862 **
863 *******************************************************************************/
llcp_link_check_send_data(void)864 void llcp_link_check_send_data(void) {
865   NFC_HDR* p_pdu;
866 
867   /* don't re-enter while processing to prevent out of sequence */
868   if (llcp_cb.lcb.is_sending_data)
869     return;
870   else
871     llcp_cb.lcb.is_sending_data = true;
872 
873   /*
874   ** check overall congestion due to high usage of buffer pool
875   ** if congested then notify all of upper layers not to send any more data
876   */
877   llcp_link_check_congestion();
878 
879   if (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT ||
880       (appl_dta_mode_flag &&
881        llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING)) {
882     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
883         "in state of "
884         "LLCP_LINK_SYMM_LOCAL_XMIT_NEXT");
885 
886     p_pdu = llcp_link_build_next_pdu(nullptr);
887 
888     /*
889     ** For data link connection,
890     ** V(RA) was updated and N(R) was set to V(RA), if I PDU was added in
891     ** this transmission. If there was no I PDU to carry V(RA) and V(RA) is
892     ** not V(R) and it's not congested, then RR PDU will be sent.
893     ** If there was no I PDU to carry V(RA) and V(RA) is not V(R) and it's
894     ** congested, then RNR PDU will be sent.
895     ** If local busy state has been changed then RR or RNR PDU may be sent.
896     */
897     llcp_dlc_check_to_send_rr_rnr();
898 
899     /* add RR/RNR PDU to be sent if any */
900     p_pdu = llcp_link_build_next_pdu(p_pdu);
901 
902     if (p_pdu != nullptr) {
903       llcp_link_send_to_lower(p_pdu);
904 
905       /* stop inactivity timer */
906       llcp_link_stop_inactivity_timer();
907 
908       /* check congestion status after sending out some data */
909       llcp_link_check_uncongested();
910     } else {
911       /* There is no data to send, so send SYMM */
912       if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATED) {
913         if (llcp_cb.lcb.symm_delay > 0) {
914           /* wait for application layer sending data */
915           llcp_link_start_link_timer();
916           llcp_cb.lcb.is_sending_data = false;
917           return;
918         } else {
919           llcp_link_send_SYMM();
920 
921           /* start inactivity timer */
922           if (llcp_cb.num_data_link_connection == 0) {
923             llcp_link_start_inactivity_timer();
924           }
925         }
926       } else {
927         llcp_cb.lcb.is_sending_data = false;
928         return;
929       }
930     }
931 
932     if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING) {
933       /* wait for short period for NFCC to send DISC */
934       nfc_start_quick_timer(&llcp_cb.lcb.timer, NFC_TTYPE_LLCP_LINK_MANAGER,
935                             ((uint32_t)50) * QUICK_TIMER_TICKS_PER_SEC / 1000);
936     } else {
937       /* wait for data to receive from remote */
938       llcp_link_start_link_timer();
939     }
940   }
941 
942   llcp_cb.lcb.is_sending_data = false;
943 }
944 
945 /*******************************************************************************
946 **
947 ** Function         llcp_link_proc_ui_pdu
948 **
949 ** Description      Process UI PDU from peer device
950 **
951 ** Returns          None
952 **
953 *******************************************************************************/
llcp_link_proc_ui_pdu(uint8_t local_sap,uint8_t remote_sap,uint16_t ui_pdu_length,uint8_t * p_ui_pdu,NFC_HDR * p_msg)954 static void llcp_link_proc_ui_pdu(uint8_t local_sap, uint8_t remote_sap,
955                                   uint16_t ui_pdu_length, uint8_t* p_ui_pdu,
956                                   NFC_HDR* p_msg) {
957   bool appended;
958   NFC_HDR* p_last_buf;
959   uint16_t available_bytes;
960   uint8_t* p_dst;
961   tLLCP_APP_CB* p_app_cb;
962   tLLCP_SAP_CBACK_DATA data;
963   tLLCP_DLCB* p_dlcb;
964 
965   p_app_cb = llcp_util_get_app_cb(local_sap);
966   /*if UI PDU sent to SAP with data link connection*/
967   p_dlcb = llcp_dlc_find_dlcb_by_sap(local_sap, remote_sap);
968   if (p_dlcb) {
969     llcp_util_send_frmr(p_dlcb, LLCP_FRMR_W_ERROR_FLAG, LLCP_PDU_UI_TYPE, 0);
970     llcp_dlsm_execute(p_dlcb, LLCP_DLC_EVENT_FRAME_ERROR, nullptr);
971     if (p_msg) {
972       GKI_freebuf(p_msg);
973     }
974     return;
975   }
976 
977   /* if application is registered and expecting UI PDU on logical data link */
978   if ((p_app_cb) && (p_app_cb->p_app_cback) &&
979       (p_app_cb->link_type & LLCP_LINK_TYPE_LOGICAL_DATA_LINK)) {
980     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
981         "Local SAP:0x%x, Remote SAP:0x%x", local_sap, remote_sap);
982 
983     /* if this is not from AGF PDU */
984     if (p_msg) {
985       ui_pdu_length = p_msg->len; /* including LLCP header */
986       p_ui_pdu = (uint8_t*)(p_msg + 1) + p_msg->offset;
987     }
988 
989     appended = false;
990 
991     /* get last buffer in rx queue */
992     p_last_buf = (NFC_HDR*)GKI_getlast(&p_app_cb->ui_rx_q);
993 
994     if (p_last_buf) {
995       /* get max length to append at the end of buffer */
996       available_bytes = GKI_get_buf_size(p_last_buf) - NFC_HDR_SIZE -
997                         p_last_buf->offset - p_last_buf->len;
998 
999       /* if new UI PDU with length can be attached at the end of buffer */
1000       if (available_bytes >= LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length) {
1001         p_dst =
1002             (uint8_t*)(p_last_buf + 1) + p_last_buf->offset + p_last_buf->len;
1003 
1004         /* add length of UI PDU */
1005         UINT16_TO_BE_STREAM(p_dst, ui_pdu_length);
1006 
1007         /* copy UI PDU with LLCP header */
1008         memcpy(p_dst, p_ui_pdu, ui_pdu_length);
1009 
1010         p_last_buf->len += LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
1011 
1012         if (p_msg) GKI_freebuf(p_msg);
1013 
1014         appended = true;
1015       }
1016     }
1017 
1018     /* if it is not available to append */
1019     if (!appended) {
1020       /* if it's not from AGF PDU */
1021       if (p_msg) {
1022         /* add length of PDU in front of UI PDU (reuse room for NCI header) */
1023         p_ui_pdu -= LLCP_PDU_AGF_LEN_SIZE;
1024         UINT16_TO_BE_STREAM(p_ui_pdu, ui_pdu_length);
1025 
1026         p_msg->offset -= LLCP_PDU_AGF_LEN_SIZE;
1027         p_msg->len += LLCP_PDU_AGF_LEN_SIZE;
1028         p_msg->layer_specific = 0;
1029       } else {
1030         p_msg = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
1031 
1032         if (p_msg) {
1033           p_dst = (uint8_t*)(p_msg + 1);
1034 
1035           /* add length of PDU in front of UI PDU */
1036           UINT16_TO_BE_STREAM(p_dst, ui_pdu_length);
1037 
1038           memcpy(p_dst, p_ui_pdu, ui_pdu_length);
1039 
1040           p_msg->offset = 0;
1041           p_msg->len = LLCP_PDU_AGF_LEN_SIZE + ui_pdu_length;
1042           p_msg->layer_specific = 0;
1043         } else {
1044           LOG(ERROR) << StringPrintf("out of buffer");
1045         }
1046       }
1047 
1048       /* insert UI PDU in rx queue */
1049       if (p_msg) {
1050         GKI_enqueue(&p_app_cb->ui_rx_q, p_msg);
1051         llcp_cb.total_rx_ui_pdu++;
1052       }
1053     }
1054 
1055     if (p_app_cb->ui_rx_q.count > llcp_cb.ll_rx_congest_start) {
1056       LOG(WARNING) << StringPrintf(
1057           "SAP:0x%x, rx link is congested (%d), "
1058           "discard oldest UI PDU",
1059           local_sap, p_app_cb->ui_rx_q.count);
1060 
1061       GKI_freebuf(GKI_dequeue(&p_app_cb->ui_rx_q));
1062       llcp_cb.total_rx_ui_pdu--;
1063     }
1064 
1065     if ((p_app_cb->ui_rx_q.count == 1) && (appended == false)) {
1066       data.data_ind.event = LLCP_SAP_EVT_DATA_IND;
1067       data.data_ind.local_sap = local_sap;
1068       data.data_ind.remote_sap = remote_sap;
1069       data.data_ind.link_type = LLCP_LINK_TYPE_LOGICAL_DATA_LINK;
1070       (*p_app_cb->p_app_cback)(&data);
1071     }
1072   } else {
1073     LOG(ERROR) << StringPrintf("Unregistered SAP:0x%x", local_sap);
1074 
1075     if (p_msg) {
1076       GKI_freebuf(p_msg);
1077     }
1078   }
1079 }
1080 
1081 /*******************************************************************************
1082 **
1083 ** Function         llcp_link_proc_agf_pdu
1084 **
1085 ** Description      Process AGF PDU from peer device
1086 **
1087 ** Returns          void
1088 **
1089 *******************************************************************************/
llcp_link_proc_agf_pdu(NFC_HDR * p_agf)1090 static void llcp_link_proc_agf_pdu(NFC_HDR* p_agf) {
1091   uint16_t agf_length;
1092   uint8_t *p, *p_info, *p_pdu_length;
1093   uint16_t pdu_hdr, pdu_length, pdu_num;
1094   uint8_t dsap, ptype, ssap;
1095 
1096   p_agf->len -= LLCP_PDU_HEADER_SIZE;
1097   p_agf->offset += LLCP_PDU_HEADER_SIZE;
1098 
1099   /*
1100   ** check integrity of AGF PDU and get number of PDUs in AGF PDU
1101   */
1102   agf_length = p_agf->len;
1103   p = (uint8_t*)(p_agf + 1) + p_agf->offset;
1104   pdu_num = 0;
1105 
1106   while (agf_length > 0) {
1107     if (agf_length > LLCP_PDU_AGF_LEN_SIZE) {
1108       BE_STREAM_TO_UINT16(pdu_length, p);
1109       if (pdu_length < LLCP_PDU_HEADER_SIZE) {
1110         LOG(ERROR) << StringPrintf("Received invalid encapsulated PDU");
1111         break;
1112       }
1113       agf_length -= LLCP_PDU_AGF_LEN_SIZE;
1114     } else {
1115       break;
1116     }
1117 
1118     if (pdu_length <= agf_length) {
1119       p += pdu_length;
1120       agf_length -= pdu_length;
1121       pdu_num++;
1122     } else {
1123       break;
1124     }
1125   }
1126 
1127   if (agf_length != 0 || pdu_num < 2) {
1128     android_errorWriteLog(0x534e4554, "116791157");
1129     LOG(ERROR) << StringPrintf("Received invalid AGF PDU");
1130     GKI_freebuf(p_agf);
1131     return;
1132   }
1133 
1134   /*
1135   ** Process PDUs in AGF
1136   */
1137   agf_length = p_agf->len;
1138   p = (uint8_t*)(p_agf + 1) + p_agf->offset;
1139 
1140   while (agf_length >= (LLCP_PDU_HEADER_SIZE + LLCP_PDU_AGF_LEN_SIZE)) {
1141     /* get length of PDU */
1142     p_pdu_length = p;
1143     BE_STREAM_TO_UINT16(pdu_length, p);
1144     agf_length -= LLCP_PDU_AGF_LEN_SIZE;
1145 
1146     /* get DSAP/PTYPE/SSAP */
1147     p_info = p;
1148     BE_STREAM_TO_UINT16(pdu_hdr, p_info);
1149 
1150     dsap = LLCP_GET_DSAP(pdu_hdr);
1151     ptype = (uint8_t)(LLCP_GET_PTYPE(pdu_hdr));
1152     ssap = LLCP_GET_SSAP(pdu_hdr);
1153 
1154     DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1155         "Rx DSAP:0x%x, PTYPE:%s (0x%x), SSAP:0x%x "
1156         "in AGF",
1157         dsap, llcp_pdu_type(ptype).c_str(), ptype, ssap);
1158 
1159     if ((ptype == LLCP_PDU_DISC_TYPE) && (dsap == LLCP_SAP_LM) &&
1160         (ssap == LLCP_SAP_LM)) {
1161       GKI_freebuf(p_agf);
1162       llcp_link_deactivate(LLCP_LINK_REMOTE_INITIATED);
1163       return;
1164     } else if (ptype == LLCP_PDU_AGF_TYPE) {
1165       LOG(ERROR) << StringPrintf("AGF PDU shall not be in AGF");
1166     } else if (ptype == LLCP_PDU_SYMM_TYPE) {
1167       LOG(ERROR) << StringPrintf("SYMM PDU exchange shall not be in AGF");
1168     } else if (ptype == LLCP_PDU_PAX_TYPE) {
1169       LOG(ERROR) << StringPrintf("PAX PDU exchange shall not be used");
1170     } else if (ptype == LLCP_PDU_SNL_TYPE) {
1171       llcp_sdp_proc_snl((uint16_t)(pdu_length - LLCP_PDU_HEADER_SIZE), p_info);
1172     } else if ((ptype == LLCP_PDU_UI_TYPE) &&
1173                (pdu_length > LLCP_PDU_HEADER_SIZE)) {
1174       llcp_link_proc_ui_pdu(dsap, ssap, pdu_length, p, nullptr);
1175     } else if (ptype == LLCP_PDU_I_TYPE) {
1176       llcp_dlc_proc_i_pdu(dsap, ssap, pdu_length, p, nullptr);
1177     } else /* let data link connection handle PDU */
1178     {
1179       llcp_dlc_proc_rx_pdu(dsap, ptype, ssap,
1180                            (uint16_t)(pdu_length - LLCP_PDU_HEADER_SIZE),
1181                            p_info);
1182     }
1183 
1184     p += pdu_length;
1185     agf_length -= pdu_length;
1186   }
1187 
1188   GKI_freebuf(p_agf);
1189 }
1190 
1191 /*******************************************************************************
1192 **
1193 ** Function         llcp_link_proc_rx_pdu
1194 **
1195 ** Description      Process received PDU from peer device
1196 **
1197 ** Returns          void
1198 **
1199 *******************************************************************************/
llcp_link_proc_rx_pdu(uint8_t dsap,uint8_t ptype,uint8_t ssap,NFC_HDR * p_msg)1200 static void llcp_link_proc_rx_pdu(uint8_t dsap, uint8_t ptype, uint8_t ssap,
1201                                   NFC_HDR* p_msg) {
1202   bool free_buffer = true;
1203   uint8_t* p_data;
1204 
1205   switch (ptype) {
1206     case LLCP_PDU_PAX_TYPE:
1207       LOG(ERROR) << StringPrintf("; PAX PDU exchange shall not be used");
1208       break;
1209 
1210     case LLCP_PDU_DISC_TYPE:
1211       if ((dsap == LLCP_SAP_LM) && (ssap == LLCP_SAP_LM)) {
1212         llcp_link_deactivate(LLCP_LINK_REMOTE_INITIATED);
1213       } else {
1214         p_data = (uint8_t*)(p_msg + 1) + p_msg->offset + LLCP_PDU_HEADER_SIZE;
1215         llcp_dlc_proc_rx_pdu(dsap, ptype, ssap,
1216                              (uint16_t)(p_msg->len - LLCP_PDU_HEADER_SIZE),
1217                              p_data);
1218       }
1219       break;
1220 
1221     case LLCP_PDU_SNL_TYPE:
1222       p_data = (uint8_t*)(p_msg + 1) + p_msg->offset + LLCP_PDU_HEADER_SIZE;
1223       llcp_sdp_proc_snl((uint16_t)(p_msg->len - LLCP_PDU_HEADER_SIZE), p_data);
1224       break;
1225 
1226     case LLCP_PDU_AGF_TYPE:
1227       llcp_link_proc_agf_pdu(p_msg);
1228       free_buffer = false;
1229       break;
1230 
1231     case LLCP_PDU_UI_TYPE:
1232       llcp_link_proc_ui_pdu(dsap, ssap, 0, nullptr, p_msg);
1233       free_buffer = false;
1234       break;
1235 
1236     case LLCP_PDU_I_TYPE:
1237       llcp_dlc_proc_i_pdu(dsap, ssap, 0, nullptr, p_msg);
1238       free_buffer = false;
1239       break;
1240 
1241     default:
1242       p_data = (uint8_t*)(p_msg + 1) + p_msg->offset + LLCP_PDU_HEADER_SIZE;
1243       llcp_dlc_proc_rx_pdu(dsap, ptype, ssap,
1244                            (uint16_t)(p_msg->len - LLCP_PDU_HEADER_SIZE),
1245                            p_data);
1246       break;
1247   }
1248 
1249   if (free_buffer) GKI_freebuf(p_msg);
1250 }
1251 
1252 /*******************************************************************************
1253 **
1254 ** Function         llcp_link_proc_rx_data
1255 **
1256 ** Description      Process received data from NFCC and maintain symmetry state
1257 **
1258 ** Returns          void
1259 **
1260 *******************************************************************************/
llcp_link_proc_rx_data(NFC_HDR * p_msg)1261 static void llcp_link_proc_rx_data(NFC_HDR* p_msg) {
1262   uint8_t* p;
1263   uint16_t pdu_hdr, info_length = 0;
1264   uint8_t dsap, ptype, ssap;
1265   bool free_buffer = true;
1266   bool frame_error = false;
1267 
1268   if (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_REMOTE_XMIT_NEXT) {
1269     llcp_link_stop_link_timer();
1270 
1271     if (llcp_cb.lcb.received_first_packet == false) {
1272       llcp_cb.lcb.received_first_packet = true;
1273       (*llcp_cb.lcb.p_link_cback)(LLCP_LINK_FIRST_PACKET_RECEIVED_EVT,
1274                                   LLCP_LINK_SUCCESS);
1275     }
1276     if ((llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING) &&
1277         (llcp_cb.lcb.sig_xmit_q.count == 0)) {
1278       /* this indicates that DISC PDU had been sent out to peer */
1279       /* initiator may wait for SYMM PDU */
1280       if (appl_dta_mode_flag == 0x01)
1281         llcp_util_send_disc(LLCP_SAP_LM, LLCP_SAP_LM);
1282       else
1283         llcp_link_process_link_timeout();
1284     } else {
1285       if (p_msg->len < LLCP_PDU_HEADER_SIZE) {
1286         LOG(ERROR) << StringPrintf("Received too small PDU: got %d bytes",
1287                                    p_msg->len);
1288         frame_error = true;
1289       } else {
1290         p = (uint8_t*)(p_msg + 1) + p_msg->offset;
1291         BE_STREAM_TO_UINT16(pdu_hdr, p);
1292 
1293         dsap = LLCP_GET_DSAP(pdu_hdr);
1294         ptype = (uint8_t)(LLCP_GET_PTYPE(pdu_hdr));
1295         ssap = LLCP_GET_SSAP(pdu_hdr);
1296 
1297         /* get length of information per PDU type */
1298         if ((ptype == LLCP_PDU_I_TYPE) || (ptype == LLCP_PDU_RR_TYPE) ||
1299             (ptype == LLCP_PDU_RNR_TYPE)) {
1300           if (p_msg->len >= LLCP_PDU_HEADER_SIZE + LLCP_SEQUENCE_SIZE) {
1301             info_length =
1302                 p_msg->len - LLCP_PDU_HEADER_SIZE - LLCP_SEQUENCE_SIZE;
1303           } else {
1304             LOG(ERROR) << StringPrintf(
1305                 "Received I/RR/RNR PDU without sequence");
1306             frame_error = true;
1307           }
1308         } else {
1309           info_length = p_msg->len - LLCP_PDU_HEADER_SIZE;
1310         }
1311 
1312         /* check if length of information is bigger than link MIU */
1313         if ((!frame_error) && (info_length > llcp_cb.lcb.local_link_miu)) {
1314           LOG(ERROR) << StringPrintf(
1315               "Received exceeding MIU (%d): got %d bytes SDU",
1316               llcp_cb.lcb.local_link_miu, info_length);
1317 
1318           frame_error = true;
1319         } else {
1320           DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
1321               "DSAP:0x%x, PTYPE:%s (0x%x), "
1322               "SSAP:0x%x",
1323               dsap, llcp_pdu_type(ptype).c_str(), ptype, ssap);
1324 
1325           if (ptype == LLCP_PDU_SYMM_TYPE) {
1326             if (info_length > 0) {
1327               LOG(ERROR) << StringPrintf(
1328                   "Received extra data (%d bytes) in SYMM PDU", info_length);
1329               frame_error = true;
1330             }
1331           } else {
1332             /* received other than SYMM */
1333             llcp_link_stop_inactivity_timer();
1334 
1335             llcp_link_proc_rx_pdu(dsap, ptype, ssap, p_msg);
1336             free_buffer = false;
1337           }
1338         }
1339       }
1340 
1341       llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_LOCAL_XMIT_NEXT;
1342 
1343       /* check if any pending packet */
1344       llcp_link_check_send_data();
1345     }
1346   } else {
1347     LOG(ERROR) << StringPrintf("Received PDU in state of SYMM_MUST_XMIT_NEXT");
1348   }
1349 
1350   if (free_buffer) GKI_freebuf(p_msg);
1351 }
1352 
1353 /*******************************************************************************
1354 **
1355 ** Function         llcp_link_get_next_pdu
1356 **
1357 ** Description      Get next PDU from link manager or data links w/wo dequeue
1358 **
1359 ** Returns          pointer of a PDU to send if length_only is FALSE
1360 **                  NULL otherwise
1361 **
1362 *******************************************************************************/
llcp_link_get_next_pdu(bool length_only,uint16_t * p_next_pdu_length)1363 static NFC_HDR* llcp_link_get_next_pdu(bool length_only,
1364                                        uint16_t* p_next_pdu_length) {
1365   NFC_HDR* p_msg;
1366   int count, xx;
1367   tLLCP_APP_CB* p_app_cb;
1368 
1369   /* processing signalling PDU first */
1370   if (llcp_cb.lcb.sig_xmit_q.p_first) {
1371     if (length_only) {
1372       p_msg = (NFC_HDR*)llcp_cb.lcb.sig_xmit_q.p_first;
1373       *p_next_pdu_length = p_msg->len;
1374       return nullptr;
1375     } else
1376       p_msg = (NFC_HDR*)GKI_dequeue(&llcp_cb.lcb.sig_xmit_q);
1377 
1378     return p_msg;
1379   } else {
1380     /* transmitting logical data link and data link connection equaly */
1381     for (xx = 0; xx < 2; xx++) {
1382       if (!llcp_cb.lcb.ll_served) {
1383         /* Get one from logical link connection */
1384         for (count = 0; count < LLCP_NUM_SAPS; count++) {
1385           /* round robin schedule without priority  */
1386           p_app_cb = llcp_util_get_app_cb(llcp_cb.lcb.ll_idx);
1387 
1388           if ((p_app_cb) && (p_app_cb->p_app_cback) &&
1389               (p_app_cb->ui_xmit_q.count)) {
1390             if (length_only) {
1391               /* don't alternate next data link to return the same length of PDU
1392                */
1393               p_msg = (NFC_HDR*)p_app_cb->ui_xmit_q.p_first;
1394               *p_next_pdu_length = p_msg->len;
1395               return nullptr;
1396             } else {
1397               /* check data link connection first in next time */
1398               llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1399 
1400               p_msg = (NFC_HDR*)GKI_dequeue(&p_app_cb->ui_xmit_q);
1401               llcp_cb.total_tx_ui_pdu--;
1402 
1403               /* this logical link has been served, so start from next logical
1404                * link next time */
1405               llcp_cb.lcb.ll_idx = (llcp_cb.lcb.ll_idx + 1) % LLCP_NUM_SAPS;
1406 
1407               return p_msg;
1408             }
1409           } else {
1410             /* check next logical link connection */
1411             llcp_cb.lcb.ll_idx = (llcp_cb.lcb.ll_idx + 1) % LLCP_NUM_SAPS;
1412           }
1413         }
1414 
1415         /* no data, so check data link connection if not checked yet */
1416         llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1417       } else {
1418         /* Get one from data link connection */
1419         for (count = 0; count < LLCP_MAX_DATA_LINK; count++) {
1420           /* round robin schedule without priority  */
1421           if (llcp_cb.dlcb[llcp_cb.lcb.dl_idx].state != LLCP_DLC_STATE_IDLE) {
1422             if (length_only) {
1423               *p_next_pdu_length = llcp_dlc_get_next_pdu_length(
1424                   &llcp_cb.dlcb[llcp_cb.lcb.dl_idx]);
1425 
1426               if (*p_next_pdu_length > 0) {
1427                 /* don't change data link connection to return the same length
1428                  * of PDU */
1429                 return nullptr;
1430               } else {
1431                 /* no data, so check next data link connection */
1432                 llcp_cb.lcb.dl_idx =
1433                     (llcp_cb.lcb.dl_idx + 1) % LLCP_MAX_DATA_LINK;
1434               }
1435             } else {
1436               p_msg = llcp_dlc_get_next_pdu(&llcp_cb.dlcb[llcp_cb.lcb.dl_idx]);
1437 
1438               /* this data link has been served, so start from next data link
1439                * next time */
1440               llcp_cb.lcb.dl_idx =
1441                   (llcp_cb.lcb.dl_idx + 1) % LLCP_MAX_DATA_LINK;
1442 
1443               if (p_msg) {
1444                 /* serve logical data link next time */
1445                 llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1446                 return p_msg;
1447               }
1448             }
1449           } else {
1450             /* check next data link connection */
1451             llcp_cb.lcb.dl_idx = (llcp_cb.lcb.dl_idx + 1) % LLCP_MAX_DATA_LINK;
1452           }
1453         }
1454 
1455         /* if all of data link connection doesn't have data to send */
1456         if (count >= LLCP_MAX_DATA_LINK) {
1457           llcp_cb.lcb.ll_served = !llcp_cb.lcb.ll_served;
1458         }
1459       }
1460     }
1461   }
1462 
1463   /* nothing to send */
1464   *p_next_pdu_length = 0;
1465   return nullptr;
1466 }
1467 
1468 /*******************************************************************************
1469 **
1470 ** Function         llcp_link_build_next_pdu
1471 **
1472 ** Description      Build a PDU from Link Manager and Data Link
1473 **                  Perform aggregation procedure if necessary
1474 **
1475 ** Returns          NFC_HDR* if sent any PDU
1476 **
1477 *******************************************************************************/
llcp_link_build_next_pdu(NFC_HDR * p_pdu)1478 static NFC_HDR* llcp_link_build_next_pdu(NFC_HDR* p_pdu) {
1479   NFC_HDR *p_agf = nullptr, *p_msg = nullptr, *p_next_pdu;
1480   uint8_t *p, ptype;
1481   uint16_t next_pdu_length, pdu_hdr;
1482 
1483   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
1484 
1485   /* add any pending SNL PDU into sig_xmit_q for transmitting */
1486   llcp_sdp_check_send_snl();
1487 
1488   if (p_pdu) {
1489     /* get PDU type */
1490     p = (uint8_t*)(p_pdu + 1) + p_pdu->offset;
1491     BE_STREAM_TO_UINT16(pdu_hdr, p);
1492 
1493     ptype = (uint8_t)(LLCP_GET_PTYPE(pdu_hdr));
1494 
1495     if (ptype == LLCP_PDU_AGF_TYPE) {
1496       /* add more PDU into this AGF PDU */
1497       p_agf = p_pdu;
1498     } else {
1499       p_msg = p_pdu;
1500     }
1501   } else {
1502     /* Get a PDU from link manager or data links */
1503     p_msg = llcp_link_get_next_pdu(false, &next_pdu_length);
1504 
1505     if (!p_msg) {
1506       return nullptr;
1507     }
1508   }
1509 
1510   /* Get length of next PDU from link manager or data links without dequeue */
1511   llcp_link_get_next_pdu(true, &next_pdu_length);
1512   while (next_pdu_length > 0) {
1513     /* if it's first visit */
1514     if (!p_agf) {
1515       /* if next PDU fits into MIU, allocate AGF PDU and copy the first PDU */
1516       if (2 + p_msg->len + 2 + next_pdu_length <= llcp_cb.lcb.effective_miu) {
1517         p_agf = (NFC_HDR*)GKI_getpoolbuf(LLCP_POOL_ID);
1518         if (p_agf) {
1519           p_agf->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
1520 
1521           p = (uint8_t*)(p_agf + 1) + p_agf->offset;
1522 
1523           UINT16_TO_BE_STREAM(
1524               p,
1525               LLCP_GET_PDU_HEADER(LLCP_SAP_LM, LLCP_PDU_AGF_TYPE, LLCP_SAP_LM));
1526           UINT16_TO_BE_STREAM(p, p_msg->len);
1527           memcpy(p, (uint8_t*)(p_msg + 1) + p_msg->offset, p_msg->len);
1528 
1529           p_agf->len = LLCP_PDU_HEADER_SIZE + 2 + p_msg->len;
1530 
1531           GKI_freebuf(p_msg);
1532           p_msg = p_agf;
1533         } else {
1534           LOG(ERROR) << StringPrintf("Out of buffer");
1535           return p_msg;
1536         }
1537       } else {
1538         break;
1539       }
1540     }
1541 
1542     /* if next PDU fits into MIU, copy the next PDU into AGF */
1543     if (p_agf->len - LLCP_PDU_HEADER_SIZE + 2 + next_pdu_length <=
1544         llcp_cb.lcb.effective_miu) {
1545       /* Get a next PDU from link manager or data links */
1546       p_next_pdu = llcp_link_get_next_pdu(false, &next_pdu_length);
1547 
1548       p = (uint8_t*)(p_agf + 1) + p_agf->offset + p_agf->len;
1549 
1550       UINT16_TO_BE_STREAM(p, p_next_pdu->len);
1551       memcpy(p, (uint8_t*)(p_next_pdu + 1) + p_next_pdu->offset,
1552              p_next_pdu->len);
1553 
1554       p_agf->len += 2 + p_next_pdu->len;
1555 
1556       GKI_freebuf(p_next_pdu);
1557 
1558       /* Get next PDU length from link manager or data links without dequeue */
1559       llcp_link_get_next_pdu(true, &next_pdu_length);
1560     } else {
1561       break;
1562     }
1563   }
1564 
1565   if (p_agf)
1566     return p_agf;
1567   else
1568     return p_msg;
1569 }
1570 
1571 /*******************************************************************************
1572 **
1573 ** Function         llcp_link_send_to_lower
1574 **
1575 ** Description      Send PDU to lower layer
1576 **
1577 ** Returns          void
1578 **
1579 *******************************************************************************/
llcp_link_send_to_lower(NFC_HDR * p_pdu)1580 static void llcp_link_send_to_lower(NFC_HDR* p_pdu) {
1581   llcp_cb.lcb.symm_state = LLCP_LINK_SYMM_REMOTE_XMIT_NEXT;
1582   NFC_SendData(NFC_RF_CONN_ID, p_pdu);
1583 }
1584 
1585 /*******************************************************************************
1586 **
1587 ** Function         llcp_link_connection_cback
1588 **
1589 ** Description      processing incoming data
1590 **
1591 ** Returns          void
1592 **
1593 *******************************************************************************/
llcp_link_connection_cback(uint8_t conn_id,tNFC_CONN_EVT event,tNFC_CONN * p_data)1594 void llcp_link_connection_cback(__attribute__((unused)) uint8_t conn_id,
1595                                 tNFC_CONN_EVT event, tNFC_CONN* p_data) {
1596   if (event == NFC_DATA_CEVT) {
1597     if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATED) {
1598       /* respoding SYMM while LLCP is deactivated but RF link is not deactivated
1599        * yet */
1600       llcp_link_send_SYMM();
1601       GKI_freebuf((NFC_HDR*)p_data->data.p_data);
1602     } else if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATION_FAILED) {
1603       /* respoding with invalid LLC PDU until initiator deactivates RF link
1604       *after LLCP activation was failed,
1605       ** so that initiator knows LLCP link activation was failed.
1606       */
1607       llcp_link_send_invalid_pdu();
1608       GKI_freebuf((NFC_HDR*)p_data->data.p_data);
1609     } else {
1610       llcp_cb.lcb.flags |= LLCP_LINK_FLAGS_RX_ANY_LLC_PDU;
1611       llcp_link_proc_rx_data((NFC_HDR*)p_data->data.p_data);
1612     }
1613   } else if (event == NFC_ERROR_CEVT) {
1614     /* RF interface specific status code */
1615     llcp_link_deactivate(*(uint8_t*)p_data);
1616   } else if (event == NFC_DEACTIVATE_CEVT) {
1617     if ((llcp_cb.lcb.link_state == LLCP_LINK_STATE_DEACTIVATING) &&
1618         (!llcp_cb.lcb.is_initiator)) {
1619       /* peer initiates NFC link deactivation before timeout */
1620       llcp_link_stop_link_timer();
1621       llcp_link_process_link_timeout();
1622     } else if (llcp_cb.lcb.link_state == LLCP_LINK_STATE_ACTIVATION_FAILED) {
1623       /* do not notify to upper layer because activation failure was already
1624        * notified */
1625       NFC_FlushData(NFC_RF_CONN_ID);
1626       llcp_cb.lcb.link_state = LLCP_LINK_STATE_DEACTIVATED;
1627     } else if (llcp_cb.lcb.link_state != LLCP_LINK_STATE_DEACTIVATED) {
1628       llcp_link_deactivate(LLCP_LINK_RF_LINK_LOSS_ERR);
1629     }
1630 
1631     NFC_SetStaticRfCback(nullptr);
1632   } else if (event == NFC_DATA_START_CEVT) {
1633     if (llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_REMOTE_XMIT_NEXT) {
1634       /* LLCP shall stop LTO timer when receiving the first bit of LLC PDU */
1635       llcp_link_stop_link_timer();
1636     }
1637   }
1638 
1639   /* LLCP ignores the following events
1640 
1641       NFC_CONN_CREATE_CEVT
1642       NFC_CONN_CLOSE_CEVT
1643   */
1644 }
1645 
1646 /*******************************************************************************
1647 **
1648 ** Function         llcp_pdu_type
1649 **
1650 ** Description
1651 **
1652 ** Returns          string of PDU type
1653 **
1654 *******************************************************************************/
llcp_pdu_type(uint8_t ptype)1655 static std::string llcp_pdu_type(uint8_t ptype) {
1656   switch (ptype) {
1657     case LLCP_PDU_SYMM_TYPE:
1658       return "SYMM";
1659     case LLCP_PDU_PAX_TYPE:
1660       return "PAX";
1661     case LLCP_PDU_AGF_TYPE:
1662       return "AGF";
1663     case LLCP_PDU_UI_TYPE:
1664       return "UI";
1665     case LLCP_PDU_CONNECT_TYPE:
1666       return "CONNECT";
1667     case LLCP_PDU_DISC_TYPE:
1668       return "DISC";
1669     case LLCP_PDU_CC_TYPE:
1670       return "CC";
1671     case LLCP_PDU_DM_TYPE:
1672       return "DM";
1673     case LLCP_PDU_FRMR_TYPE:
1674       return "FRMR";
1675     case LLCP_PDU_SNL_TYPE:
1676       return "SNL";
1677     case LLCP_PDU_I_TYPE:
1678       return "I";
1679     case LLCP_PDU_RR_TYPE:
1680       return "RR";
1681     case LLCP_PDU_RNR_TYPE:
1682       return "RNR";
1683     default:
1684       return "RESERVED";
1685   }
1686 }
1687