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