/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "bta/include/bta_rfcomm_scn.h" #define LOG_TAG "bta" #include #include #include #include "bta/jv/bta_jv_int.h" // tBTA_JV_CB #include "stack/include/rfcdefs.h" // RFCOMM_MAX_SCN using namespace bluetooth; extern tBTA_JV_CB bta_jv_cb; /******************************************************************************* * * Function BTA_AllocateSCN * * Description Look through the Server Channel Numbers for a free one. * * Returns Allocated SCN or 0 if none. * ******************************************************************************/ uint8_t BTA_AllocateSCN(void) { // SCN can be allocated in the range of [1, RFCOMM_MAX_SCN] // btm_scn uses indexes 0 to RFCOMM_MAX_SCN-1 to track RFC ports for (uint8_t i = bta_jv_cb.scn_search_index; i < RFCOMM_MAX_SCN; ++i) { if (!bta_jv_cb.scn_in_use[i]) { bta_jv_cb.scn_in_use[i] = true; bta_jv_cb.scn_search_index = (i + 1); log::debug("Allocating scn: {}", i + 1); return i + 1; // allocated scn is index + 1 } } // In order to avoid OOB, scn_search_index must be no more than // RFCOMM_MAX_SCN. bta_jv_cb.scn_search_index = std::min(bta_jv_cb.scn_search_index, (uint8_t)(RFCOMM_MAX_SCN)); // If there's no empty SCN from scn_search_index to RFCOMM_MAX_SCN // Start from index 1 because index 0 (scn 1) is reserved for HFP for (uint8_t i = 1; i < bta_jv_cb.scn_search_index; ++i) { if (!bta_jv_cb.scn_in_use[i]) { bta_jv_cb.scn_in_use[i] = true; bta_jv_cb.scn_search_index = (i + 1); log::debug("Allocating scn: {}", i + 1); return i + 1; // allocated scn is index + 1 } } log::warn("Unable to allocate an scn"); return 0; /* No free ports */ } /******************************************************************************* * * Function BTA_TryAllocateSCN * * Description Try to allocate a fixed server channel * * Returns true if SCN was available, false otherwise * ******************************************************************************/ bool BTA_TryAllocateSCN(uint8_t scn) { /* Make sure we don't exceed max scn range. * Stack reserves scn 1 for HFP and HSP */ if ((scn > RFCOMM_MAX_SCN) || (scn == 1) || (scn == 0)) { return false; } /* check if this scn is available */ if (!bta_jv_cb.scn_in_use[scn - 1]) { bta_jv_cb.scn_in_use[scn - 1] = true; log::debug("Allocating scn: {}", scn); return true; } log::debug("Unable to allocate scn {}", scn); return false; /* scn was busy */ } /******************************************************************************* * * Function BTA_FreeSCN * * Description Free the specified SCN. * * Returns true if SCN was freed, false if SCN was invalid * ******************************************************************************/ bool BTA_FreeSCN(uint8_t scn) { /* Since this isn't used by HFP, this function will only free valid SCNs * that aren't reserved for HFP, which is range [2, RFCOMM_MAX_SCN]. */ if (com::android::bluetooth::flags::allow_free_last_scn()) { if (scn <= RFCOMM_MAX_SCN && scn > 1) { bta_jv_cb.scn_in_use[scn - 1] = false; log::debug("Freed SCN: {}", scn); return true; } } else { if (scn < RFCOMM_MAX_SCN && scn > 1) { bta_jv_cb.scn_in_use[scn - 1] = false; log::debug("Freed SCN: {}", scn); return true; } } log::warn("Invalid SCN: {}", scn); return false; /* Illegal SCN passed in */ }