1 /* 2 * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA - 3 * www.ehima.com 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <map> 19 #include <queue> 20 21 #include "acl_api.h" 22 #include "base/bind_helpers.h" 23 #include "bt_types.h" 24 #include "device/include/controller.h" 25 #include "eatt.h" 26 #include "l2c_api.h" 27 #include "osi/include/alarm.h" 28 #include "stack/btm/btm_sec.h" 29 #include "stack/gatt/gatt_int.h" 30 #include "stack/l2cap/l2c_int.h" 31 32 namespace bluetooth { 33 namespace eatt { 34 35 #define BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK 0x01 36 37 class eatt_device { 38 public: 39 RawAddress bda_; 40 uint16_t rx_mtu_; 41 uint16_t rx_mps_; 42 43 tGATT_TCB* eatt_tcb_; 44 45 std::map<uint16_t, std::shared_ptr<EattChannel>> eatt_channels; 46 eatt_device(const RawAddress & bd_addr,uint16_t mtu,uint16_t mps)47 eatt_device(const RawAddress& bd_addr, uint16_t mtu, uint16_t mps) 48 : rx_mtu_(mtu), rx_mps_(mps), eatt_tcb_(nullptr) { 49 bda_ = bd_addr; 50 } 51 }; 52 53 struct eatt_impl { 54 std::vector<eatt_device> devices_; 55 uint16_t psm_; 56 uint16_t default_mtu_; 57 uint16_t max_mps_; 58 tL2CAP_APPL_INFO reg_info_; 59 eatt_impleatt_impl60 eatt_impl() { 61 default_mtu_ = EATT_DEFAULT_MTU; 62 max_mps_ = EATT_MIN_MTU_MPS; 63 psm_ = BT_PSM_EATT; 64 }; 65 66 ~eatt_impl() = default; 67 find_device_by_cideatt_impl68 eatt_device* find_device_by_cid(uint16_t lcid) { 69 /* This works only because Android CIDs are unique across the ACL 70 * connections */ 71 auto iter = find_if(devices_.begin(), devices_.end(), 72 [&lcid](const eatt_device& ed) { 73 auto it = ed.eatt_channels.find(lcid); 74 return it != ed.eatt_channels.end(); 75 }); 76 77 return (iter == devices_.end()) ? nullptr : &(*iter); 78 } 79 find_channel_by_cideatt_impl80 EattChannel* find_channel_by_cid(uint16_t lcid) { 81 eatt_device* eatt_dev = find_device_by_cid(lcid); 82 if (!eatt_dev) return nullptr; 83 84 auto it = eatt_dev->eatt_channels.find(lcid); 85 return (it == eatt_dev->eatt_channels.end()) ? nullptr : it->second.get(); 86 } 87 find_channel_by_cideatt_impl88 EattChannel* find_channel_by_cid(const RawAddress& bdaddr, uint16_t lcid) { 89 eatt_device* eatt_dev = find_device_by_address(bdaddr); 90 if (!eatt_dev) return nullptr; 91 92 auto it = eatt_dev->eatt_channels.find(lcid); 93 return (it == eatt_dev->eatt_channels.end()) ? nullptr : it->second.get(); 94 } 95 remove_channel_by_cideatt_impl96 void remove_channel_by_cid(eatt_device* eatt_dev, uint16_t lcid) { 97 eatt_dev->eatt_channels.erase(lcid); 98 99 if (eatt_dev->eatt_channels.size() == 0) eatt_dev->eatt_tcb_ = NULL; 100 } 101 remove_channel_by_cideatt_impl102 void remove_channel_by_cid(uint16_t lcid) { 103 eatt_device* eatt_dev = find_device_by_cid(lcid); 104 if (!eatt_dev) return; 105 106 remove_channel_by_cid(eatt_dev, lcid); 107 } 108 eatt_l2cap_connect_indeatt_impl109 void eatt_l2cap_connect_ind(const RawAddress& bda, 110 std::vector<uint16_t>& lcids, uint16_t psm, 111 uint16_t peer_mtu, uint8_t identifier) { 112 /* The assumption is that L2CAP layer already check parameters etc. 113 * Get our capabilities and accept all the channels. 114 */ 115 eatt_device* eatt_dev = this->find_device_by_address(bda); 116 if (!eatt_dev) { 117 LOG(ERROR) << __func__ << " unknown device: " << bda; 118 L2CA_ConnectCreditBasedRsp(bda, identifier, lcids, 119 L2CAP_CONN_NO_RESOURCES, NULL); 120 return; 121 } 122 123 uint16_t max_mps = controller_get_interface()->get_acl_data_size_ble(); 124 125 tL2CAP_LE_CFG_INFO local_coc_cfg = { 126 .mtu = eatt_dev->rx_mtu_, 127 .mps = eatt_dev->rx_mps_ < max_mps ? eatt_dev->rx_mps_ : max_mps, 128 .credits = L2CAP_LE_CREDIT_DEFAULT}; 129 130 if (!L2CA_ConnectCreditBasedRsp(bda, identifier, lcids, L2CAP_CONN_OK, 131 &local_coc_cfg)) 132 return; 133 134 if (!eatt_dev->eatt_tcb_) { 135 eatt_dev->eatt_tcb_ = 136 gatt_find_tcb_by_addr(eatt_dev->bda_, BT_TRANSPORT_LE); 137 CHECK(eatt_dev->eatt_tcb_); 138 } 139 140 for (uint16_t cid : lcids) { 141 EattChannel* channel = find_eatt_channel_by_cid(bda, cid); 142 CHECK(!channel); 143 144 auto chan = std::make_shared<EattChannel>(eatt_dev->bda_, cid, peer_mtu, 145 eatt_dev->rx_mtu_); 146 eatt_dev->eatt_channels.insert({cid, chan}); 147 148 chan->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED); 149 eatt_dev->eatt_tcb_->eatt++; 150 151 LOG(INFO) << __func__ << " Channel connected CID " << loghex(cid); 152 } 153 } 154 eatt_l2cap_connect_cfmeatt_impl155 void eatt_l2cap_connect_cfm(const RawAddress& bda, uint16_t lcid, 156 uint16_t peer_mtu, uint16_t result) { 157 LOG(INFO) << __func__ << " bda: " << bda << " cid: " << +lcid 158 << "peer mtu: " << +peer_mtu << " result " << +result; 159 160 eatt_device* eatt_dev = find_device_by_address(bda); 161 if (!eatt_dev) { 162 LOG(ERROR) << __func__ << " unknown device"; 163 return; 164 } 165 166 EattChannel* channel = this->find_channel_by_cid(bda, lcid); 167 if (!channel) { 168 LOG(ERROR) << __func__ << " unknown cid: " << loghex(lcid); 169 return; 170 } 171 172 if (result != L2CAP_CONN_OK) { 173 LOG(ERROR) << __func__ 174 << " Could not connect CoC result: " << loghex(result); 175 remove_channel_by_cid(eatt_dev, lcid); 176 return; 177 } 178 179 channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED); 180 channel->EattChannelSetTxMTU(peer_mtu); 181 182 CHECK(eatt_dev->eatt_tcb_); 183 CHECK(eatt_dev->bda_ == channel->bda_); 184 eatt_dev->eatt_tcb_->eatt++; 185 186 LOG(INFO) << __func__ << " Channel connected CID " << loghex(lcid); 187 } 188 eatt_l2cap_reconfig_completedeatt_impl189 void eatt_l2cap_reconfig_completed(const RawAddress& bda, uint16_t lcid, 190 bool is_local_cfg, 191 tL2CAP_LE_CFG_INFO* p_cfg) { 192 LOG(INFO) << __func__ << "lcid: " << loghex(lcid) 193 << " local cfg?: " << is_local_cfg; 194 195 if (p_cfg->result != L2CAP_CFG_OK) { 196 LOG(INFO) << __func__ << " reconfig failed lcid: " << loghex(lcid) 197 << " result: " << loghex(p_cfg->result); 198 return; 199 } 200 201 EattChannel* channel = find_channel_by_cid(bda, lcid); 202 if (!channel) return; 203 204 /* On this layer we don't care about mps as this is handled in L2CAP layer 205 */ 206 if (is_local_cfg) 207 channel->rx_mtu_ = p_cfg->mtu; 208 else 209 channel->tx_mtu_ = p_cfg->mtu; 210 211 /* Go back to open state */ 212 channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED); 213 } 214 eatt_l2cap_error_cbeatt_impl215 void eatt_l2cap_error_cb(uint16_t lcid, uint16_t reason) { 216 LOG(INFO) << __func__ << " cid: " << loghex(lcid) << " reason " 217 << loghex(reason); 218 219 /*TODO: provide address in the L2CAP callback */ 220 221 EattChannel* channel = find_channel_by_cid(lcid); 222 if (!channel) { 223 LOG(ERROR) << __func__ << "Unknown lcid"; 224 return; 225 } 226 227 eatt_device* eatt_dev = find_device_by_address(channel->bda_); 228 229 switch (channel->state_) { 230 case EattChannelState::EATT_CHANNEL_PENDING: 231 LOG(ERROR) << "Connecting failed"; 232 remove_channel_by_cid(eatt_dev, lcid); 233 break; 234 case EattChannelState::EATT_CHANNEL_RECONFIGURING: 235 /* Just go back to open state */ 236 LOG(ERROR) << "Reconfig failed"; 237 channel->EattChannelSetState(EattChannelState::EATT_CHANNEL_OPENED); 238 break; 239 default: 240 LOG(ERROR) << __func__ << "Invalid state: " 241 << static_cast<uint8_t>(channel->state_); 242 break; 243 } 244 } 245 eatt_l2cap_disconnect_indeatt_impl246 void eatt_l2cap_disconnect_ind(uint16_t lcid, bool please_confirm) { 247 LOG(INFO) << __func__ << " cid: " << loghex(lcid); 248 eatt_device* eatt_dev = find_device_by_cid(lcid); 249 if (!eatt_dev) { 250 LOG(ERROR) << __func__ << " unknown cid: " << loghex(lcid); 251 return; 252 } 253 254 eatt_dev->eatt_tcb_->eatt--; 255 remove_channel_by_cid(eatt_dev, lcid); 256 } 257 eatt_l2cap_data_indeatt_impl258 void eatt_l2cap_data_ind(uint16_t lcid, BT_HDR* data_p) { 259 LOG(INFO) << __func__ << " cid: " << loghex(lcid); 260 eatt_device* eatt_dev = find_device_by_cid(lcid); 261 if (!eatt_dev) { 262 LOG(ERROR) << __func__ << " unknown cid: " << loghex(lcid); 263 return; 264 } 265 266 EattChannel* channel = find_channel_by_cid(eatt_dev->bda_, lcid); 267 if (!channel) { 268 LOG(ERROR) << __func__ << "Received data on closed channel " 269 << loghex(lcid); 270 return; 271 } 272 273 gatt_data_process(*eatt_dev->eatt_tcb_, channel->cid_, data_p); 274 osi_free(data_p); 275 } 276 is_eatt_supported_by_peereatt_impl277 bool is_eatt_supported_by_peer(const RawAddress& bd_addr) { 278 return gatt_profile_get_eatt_support(bd_addr); 279 } 280 find_device_by_addresseatt_impl281 eatt_device* find_device_by_address(const RawAddress& bd_addr) { 282 auto iter = find_if( 283 devices_.begin(), devices_.end(), 284 [&bd_addr](const eatt_device& ed) { return ed.bda_ == bd_addr; }); 285 286 return iter == devices_.end() ? nullptr : &(*iter); 287 } 288 add_eatt_deviceeatt_impl289 eatt_device* add_eatt_device(const RawAddress& bd_addr) { 290 devices_.push_back(eatt_device(bd_addr, default_mtu_, max_mps_)); 291 eatt_device* eatt_dev = &devices_.back(); 292 return eatt_dev; 293 } 294 connect_eatteatt_impl295 void connect_eatt(eatt_device* eatt_dev) { 296 /* Let us use maximum possible mps */ 297 if (eatt_dev->rx_mps_ == EATT_MIN_MTU_MPS) 298 eatt_dev->rx_mps_ = controller_get_interface()->get_acl_data_size_ble(); 299 300 tL2CAP_LE_CFG_INFO local_coc_cfg = { 301 .mtu = eatt_dev->rx_mtu_, 302 .mps = eatt_dev->rx_mps_, 303 .credits = L2CAP_LE_CREDIT_DEFAULT, 304 }; 305 306 /* Warning! CIDs in Android are unique across the ACL connections */ 307 std::vector<uint16_t> connecting_cids = 308 L2CA_ConnectCreditBasedReq(psm_, eatt_dev->bda_, &local_coc_cfg); 309 310 if (connecting_cids.size() == 0) { 311 LOG(ERROR) << "Unable to get cid"; 312 return; 313 } 314 315 LOG(INFO) << __func__ 316 << "Successfully sent CoC request, number of channel: " 317 << +connecting_cids.size(); 318 319 for (uint16_t cid : connecting_cids) { 320 LOG(INFO) << " \t cid: " << loghex(cid); 321 322 auto chan = std::make_shared<EattChannel>(eatt_dev->bda_, cid, 0, 323 eatt_dev->rx_mtu_); 324 eatt_dev->eatt_channels.insert({cid, chan}); 325 } 326 327 if (eatt_dev->eatt_tcb_) { 328 LOG(INFO) << __func__ << " has tcb ? " << eatt_dev->eatt_tcb_; 329 return; 330 } 331 332 eatt_dev->eatt_tcb_ = 333 gatt_find_tcb_by_addr(eatt_dev->bda_, BT_TRANSPORT_LE); 334 CHECK(eatt_dev->eatt_tcb_); 335 } 336 find_eatt_channel_by_cideatt_impl337 EattChannel* find_eatt_channel_by_cid(const RawAddress& bd_addr, 338 uint16_t cid) { 339 eatt_device* eatt_dev = find_device_by_address(bd_addr); 340 341 LOG(INFO) << __func__ << bd_addr << " " << +cid; 342 343 if (!eatt_dev) return nullptr; 344 345 auto iter = find_if( 346 eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(), 347 [&cid](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) { 348 return el.first == cid; 349 }); 350 351 return iter == eatt_dev->eatt_channels.end() ? nullptr : iter->second.get(); 352 } 353 find_eatt_channel_by_transideatt_impl354 EattChannel* find_eatt_channel_by_transid(const RawAddress& bd_addr, 355 uint32_t trans_id) { 356 eatt_device* eatt_dev = find_device_by_address(bd_addr); 357 if (!eatt_dev) return nullptr; 358 359 auto iter = find_if( 360 eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(), 361 [&trans_id]( 362 const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) { 363 return el.second->server_outstanding_cmd_.trans_id == trans_id; 364 }); 365 366 return iter == eatt_dev->eatt_channels.end() ? nullptr : iter->second.get(); 367 } 368 is_indication_pendingeatt_impl369 bool is_indication_pending(const RawAddress& bd_addr, 370 uint16_t indication_handle) { 371 eatt_device* eatt_dev = find_device_by_address(bd_addr); 372 if (!eatt_dev) return false; 373 374 auto iter = find_if( 375 eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(), 376 [&indication_handle]( 377 const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) { 378 return el.second->indicate_handle_ == indication_handle; 379 }); 380 381 return (iter != eatt_dev->eatt_channels.end()); 382 }; 383 get_channel_available_for_indicationeatt_impl384 EattChannel* get_channel_available_for_indication(const RawAddress& bd_addr) { 385 eatt_device* eatt_dev = find_device_by_address(bd_addr); 386 auto iter = find_if( 387 eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(), 388 [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) { 389 return !GATT_HANDLE_IS_VALID(el.second->indicate_handle_); 390 }); 391 392 return (iter == eatt_dev->eatt_channels.end()) ? nullptr 393 : iter->second.get(); 394 }; 395 get_channel_available_for_client_requesteatt_impl396 EattChannel* get_channel_available_for_client_request( 397 const RawAddress& bd_addr) { 398 eatt_device* eatt_dev = find_device_by_address(bd_addr); 399 if (!eatt_dev) return nullptr; 400 401 auto iter = find_if( 402 eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(), 403 [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) { 404 return el.second->cl_cmd_q_.empty(); 405 }); 406 407 return (iter == eatt_dev->eatt_channels.end()) ? nullptr 408 : iter->second.get(); 409 } 410 free_gatt_resourceseatt_impl411 void free_gatt_resources(const RawAddress& bd_addr) { 412 eatt_device* eatt_dev = find_device_by_address(bd_addr); 413 if (!eatt_dev) return; 414 415 auto iter = eatt_dev->eatt_channels.begin(); 416 while (iter != eatt_dev->eatt_channels.end()) { 417 EattChannel* channel = iter->second.get(); 418 419 fixed_queue_free(channel->server_outstanding_cmd_.multi_rsp_q, NULL); 420 channel->server_outstanding_cmd_.multi_rsp_q = NULL; 421 } 422 } 423 is_outstanding_msg_in_send_queueeatt_impl424 bool is_outstanding_msg_in_send_queue(const RawAddress& bd_addr) { 425 eatt_device* eatt_dev = find_device_by_address(bd_addr); 426 if (!eatt_dev) return false; 427 428 auto iter = find_if( 429 eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(), 430 [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) { 431 return !el.second->cl_cmd_q_.empty(); 432 }); 433 return (iter != eatt_dev->eatt_channels.end()); 434 } 435 get_channel_with_queued_dataeatt_impl436 EattChannel* get_channel_with_queued_data(const RawAddress& bd_addr) { 437 eatt_device* eatt_dev = find_device_by_address(bd_addr); 438 if (!eatt_dev) return nullptr; 439 440 auto iter = find_if( 441 eatt_dev->eatt_channels.begin(), eatt_dev->eatt_channels.end(), 442 [](const std::pair<uint16_t, std::shared_ptr<EattChannel>>& el) { 443 return !el.second->cl_cmd_q_.empty(); 444 }); 445 return (iter == eatt_dev->eatt_channels.end()) ? nullptr 446 : iter->second.get(); 447 } 448 eatt_ind_ack_timeouteatt_impl449 static void eatt_ind_ack_timeout(void* data) { 450 EattChannel* channel = (EattChannel*)data; 451 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(channel->bda_, BT_TRANSPORT_LE); 452 453 LOG(WARNING) << __func__ << ": send ack now"; 454 attp_send_cl_confirmation_msg(*p_tcb, channel->cid_); 455 } 456 eatt_ind_confirmation_timeouteatt_impl457 static void eatt_ind_confirmation_timeout(void* data) { 458 EattChannel* channel = (EattChannel*)data; 459 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(channel->bda_, BT_TRANSPORT_LE); 460 461 LOG(WARNING) << __func__ << " disconnecting..."; 462 gatt_disconnect(p_tcb); 463 } 464 start_indication_confirm_timereatt_impl465 void start_indication_confirm_timer(const RawAddress& bd_addr, uint16_t cid) { 466 EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); 467 if (!channel) { 468 LOG(ERROR) << __func__ << "Unknown cid: " << loghex(cid) << " or device " 469 << bd_addr; 470 return; 471 } 472 473 alarm_set_on_mloop(channel->ind_confirmation_timer_, 474 GATT_WAIT_FOR_RSP_TIMEOUT_MS, 475 eatt_ind_confirmation_timeout, channel); 476 } 477 stop_indication_confirm_timereatt_impl478 void stop_indication_confirm_timer(const RawAddress& bd_addr, uint16_t cid) { 479 EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); 480 if (!channel) { 481 LOG(ERROR) << __func__ << "Unknown cid: " << loghex(cid) << " or device " 482 << bd_addr; 483 return; 484 } 485 486 alarm_cancel(channel->ind_confirmation_timer_); 487 } 488 start_app_indication_timereatt_impl489 void start_app_indication_timer(const RawAddress& bd_addr, uint16_t cid) { 490 EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); 491 if (!channel) { 492 LOG(ERROR) << __func__ << "Unknown cid: " << loghex(cid) << " or device " 493 << bd_addr; 494 return; 495 } 496 497 alarm_set_on_mloop(channel->ind_ack_timer_, GATT_WAIT_FOR_RSP_TIMEOUT_MS, 498 eatt_ind_ack_timeout, channel); 499 } 500 stop_app_indication_timereatt_impl501 void stop_app_indication_timer(const RawAddress& bd_addr, uint16_t cid) { 502 EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); 503 if (!channel) { 504 LOG(ERROR) << __func__ << "Unknown cid: " << loghex(cid) << " or device " 505 << bd_addr; 506 return; 507 } 508 509 alarm_cancel(channel->ind_ack_timer_); 510 } 511 reconfigureeatt_impl512 void reconfigure(const RawAddress& bd_addr, uint16_t cid, uint16_t new_mtu) { 513 eatt_device* eatt_dev = find_device_by_address(bd_addr); 514 if (!eatt_dev) { 515 LOG(ERROR) << __func__ << "Unknown device " << bd_addr; 516 return; 517 } 518 519 EattChannel* channel = find_eatt_channel_by_cid(bd_addr, cid); 520 if (!channel) { 521 LOG(ERROR) << __func__ << "Unknown cid: " << loghex(cid) << " or device " 522 << bd_addr; 523 return; 524 } 525 526 if (new_mtu <= channel->rx_mtu_) { 527 LOG(ERROR) << __func__ << "Invalid mtu: " << loghex(new_mtu); 528 return; 529 } 530 531 std::vector<uint16_t> cids = {cid}; 532 533 tL2CAP_LE_CFG_INFO cfg = {.mps = eatt_dev->rx_mps_, .mtu = new_mtu}; 534 535 if (!L2CA_ReconfigCreditBasedConnsReq(eatt_dev->bda_, cids, &cfg)) 536 LOG(ERROR) << __func__ << "Could not start reconfig cid: " << loghex(cid) 537 << " or device " << bd_addr; 538 } 539 reconfigure_alleatt_impl540 void reconfigure_all(const RawAddress& bd_addr, uint16_t new_mtu) { 541 eatt_device* eatt_dev = find_device_by_address(bd_addr); 542 if (!eatt_dev) { 543 LOG(ERROR) << __func__ << "Unknown device " << bd_addr; 544 return; 545 } 546 547 uint8_t num_of_channels = eatt_dev->eatt_channels.size(); 548 if (num_of_channels == 0) { 549 LOG(ERROR) << __func__ << "No channels for device " << bd_addr; 550 return; 551 } 552 553 std::vector<uint16_t> cids; 554 555 auto iter = eatt_dev->eatt_channels.begin(); 556 while (iter != eatt_dev->eatt_channels.end()) { 557 uint16_t cid = iter->first; 558 cids.push_back(cid); 559 iter++; 560 } 561 562 if (new_mtu <= EATT_MIN_MTU_MPS) { 563 LOG(ERROR) << __func__ << "Invalid mtu: " << loghex(new_mtu); 564 return; 565 } 566 567 tL2CAP_LE_CFG_INFO cfg = {.mps = eatt_dev->rx_mps_, .mtu = new_mtu}; 568 569 if (!L2CA_ReconfigCreditBasedConnsReq(eatt_dev->bda_, cids, &cfg)) 570 LOG(ERROR) << __func__ << "Could not start reconfig for device " 571 << bd_addr; 572 } 573 supported_features_cbeatt_impl574 void supported_features_cb(uint8_t role, const RawAddress& bd_addr, 575 uint8_t features) { 576 bool is_eatt_supported = features & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK; 577 578 LOG(INFO) << __func__ << " " << bd_addr 579 << " is_eatt_supported = " << int(is_eatt_supported); 580 if (!is_eatt_supported) return; 581 582 eatt_device* eatt_dev = add_eatt_device(bd_addr); 583 584 if (role != HCI_ROLE_CENTRAL) { 585 /* TODO For now do nothing, we could run a timer here and start EATT if 586 * not started by central */ 587 LOG(INFO) 588 << " EATT Should be connected by the central. Let's wait for it."; 589 return; 590 } 591 592 connect_eatt(eatt_dev); 593 } 594 disconnect_channeleatt_impl595 void disconnect_channel(uint16_t cid) { L2CA_DisconnectReq(cid); } 596 disconnecteatt_impl597 void disconnect(const RawAddress& bd_addr) { 598 LOG(INFO) << __func__ << " " << bd_addr; 599 600 eatt_device* eatt_dev = find_device_by_address(bd_addr); 601 if (!eatt_dev) { 602 LOG(WARNING) << __func__ << " no eatt device found"; 603 return; 604 } 605 606 if (!eatt_dev->eatt_tcb_) { 607 LOG_ASSERT(eatt_dev->eatt_channels.size() == 0); 608 LOG(WARNING) << __func__ << " no eatt channels found"; 609 return; 610 } 611 612 auto iter = eatt_dev->eatt_channels.begin(); 613 while (iter != eatt_dev->eatt_channels.end()) { 614 uint16_t cid = iter->first; 615 disconnect_channel(cid); 616 /* When initiating disconnection, stack will not notify us that it is 617 * done. We need to assume success 618 */ 619 iter = eatt_dev->eatt_channels.erase(iter); 620 } 621 eatt_dev->eatt_tcb_->eatt = 0; 622 eatt_dev->eatt_tcb_ = nullptr; 623 } 624 connecteatt_impl625 void connect(const RawAddress& bd_addr) { 626 eatt_device* eatt_dev = find_device_by_address(bd_addr); 627 628 uint8_t role = L2CA_GetBleConnRole(bd_addr); 629 if (role == HCI_ROLE_UNKNOWN) { 630 LOG(ERROR) << __func__ << "Could not get device role" << bd_addr; 631 return; 632 } 633 634 LOG(INFO) << __func__ << " device " << bd_addr << " role" 635 << (role == HCI_ROLE_CENTRAL ? "central" : "peripheral"); 636 637 if (eatt_dev) { 638 /* We are reconnecting device we know that support EATT. 639 * Just connect CoC 640 */ 641 LOG(INFO) << __func__ << " Known device, connect eCoC"; 642 643 if (role != HCI_ROLE_CENTRAL) { 644 LOG(INFO) 645 << " EATT Should be connected by the central. Let's wait for it."; 646 return; 647 } 648 649 connect_eatt(eatt_dev); 650 return; 651 } 652 653 /* For new device, first read GATT server supported features. */ 654 if (gatt_cl_read_sr_supp_feat_req( 655 bd_addr, base::BindOnce(&eatt_impl::supported_features_cb, 656 base::Unretained(this), role)) == false) { 657 LOG(INFO) << __func__ << "Eatt is not supported. Checked for device " 658 << bd_addr; 659 } 660 } 661 add_from_storageeatt_impl662 void add_from_storage(const RawAddress& bd_addr) { 663 eatt_device* eatt_dev = find_device_by_address(bd_addr); 664 665 LOG(INFO) << __func__ << ", restoring: " << bd_addr; 666 667 if (!eatt_dev) add_eatt_device(bd_addr); 668 } 669 }; 670 671 } // namespace eatt 672 } // namespace bluetooth 673