diff options
Diffstat (limited to 'bta/vc/device.cc')
-rw-r--r-- | bta/vc/device.cc | 245 |
1 files changed, 0 insertions, 245 deletions
diff --git a/bta/vc/device.cc b/bta/vc/device.cc deleted file mode 100644 index 9e059e781..000000000 --- a/bta/vc/device.cc +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2020 HIMSA II K/S - www.himsa.com. - * Represented by EHIMA - www.ehima.com - * - * 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 <map> -#include <vector> - -#include "bta_gatt_api.h" -#include "bta_gatt_queue.h" -#include "devices.h" -#include "gatt_api.h" -#include "stack/btm/btm_sec.h" - -using namespace bluetooth::vc::internal; - -void VolumeControlDevice::Disconnect(tGATT_IF gatt_if) { - LOG(INFO) << __func__ << ": " << this->ToString(); - - if (IsConnected()) { - if (volume_state_handle != 0) - BTA_GATTC_DeregisterForNotifications(gatt_if, address, - volume_state_handle); - - if (volume_flags_handle != 0) - BTA_GATTC_DeregisterForNotifications(gatt_if, address, - volume_flags_handle); - - BtaGattQueue::Clean(connection_id); - BTA_GATTC_Close(connection_id); - connection_id = GATT_INVALID_CONN_ID; - } else { - BTA_GATTC_CancelOpen(gatt_if, address, false); - } - - device_ready = false; - handles_pending.clear(); -} - -/* - * Find the handle for the client characteristics configuration of a given - * characteristics - */ -uint16_t VolumeControlDevice::find_ccc_handle(uint16_t chrc_handle) { - const gatt::Characteristic* p_char = - BTA_GATTC_GetCharacteristic(connection_id, chrc_handle); - if (!p_char) { - LOG(WARNING) << __func__ << ": no such handle=" << loghex(chrc_handle); - return 0; - } - - for (const gatt::Descriptor& desc : p_char->descriptors) { - if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)) - return desc.handle; - } - - return 0; -} - -bool VolumeControlDevice::set_volume_control_service_handles( - const gatt::Service& service) { - uint16_t state_handle = 0, state_ccc_handle = 0, control_point_handle = 0, - flags_handle = 0, flags_ccc_handle = 0; - - for (const gatt::Characteristic& chrc : service.characteristics) { - if (chrc.uuid == kVolumeControlStateUuid) { - state_handle = chrc.value_handle; - state_ccc_handle = find_ccc_handle(chrc.value_handle); - } else if (chrc.uuid == kVolumeControlPointUuid) { - control_point_handle = chrc.value_handle; - } else if (chrc.uuid == kVolumeFlagsUuid) { - flags_handle = chrc.value_handle; - flags_ccc_handle = find_ccc_handle(chrc.value_handle); - } else { - LOG(WARNING) << __func__ << ": unknown characteristic=" << chrc.uuid; - } - } - - // Validate service handles - if (GATT_HANDLE_IS_VALID(state_handle) && - GATT_HANDLE_IS_VALID(state_ccc_handle) && - GATT_HANDLE_IS_VALID(control_point_handle) && - GATT_HANDLE_IS_VALID(flags_handle) - /* volume_flags_ccc_handle is optional */) { - volume_state_handle = state_handle; - volume_state_ccc_handle = state_ccc_handle; - volume_control_point_handle = control_point_handle; - volume_flags_handle = flags_handle; - volume_flags_ccc_handle = flags_ccc_handle; - return true; - } - - return false; -} - -bool VolumeControlDevice::UpdateHandles(void) { - ResetHandles(); - - bool vcs_found = false; - const std::list<gatt::Service>* services = - BTA_GATTC_GetServices(connection_id); - if (services == nullptr) { - LOG(ERROR) << "No services found"; - return false; - } - - for (auto const& service : *services) { - if (service.uuid == kVolumeControlUuid) { - LOG(INFO) << "Found VCS, handle=" << loghex(service.handle); - vcs_found = set_volume_control_service_handles(service); - if (!vcs_found) break; - } - } - - return vcs_found; -} - -void VolumeControlDevice::ResetHandles(void) { - device_ready = false; - - // the handles are not valid, so discard pending GATT operations - BtaGattQueue::Clean(connection_id); - - volume_state_handle = 0; - volume_state_ccc_handle = 0; - volume_control_point_handle = 0; - volume_flags_handle = 0; - volume_flags_ccc_handle = 0; -} - -void VolumeControlDevice::ControlPointOperation(uint8_t opcode, - const std::vector<uint8_t>* arg, - GATT_WRITE_OP_CB cb, - void* cb_data) { - std::vector<uint8_t> set_value({opcode, change_counter}); - if (arg != nullptr) - set_value.insert(set_value.end(), (*arg).begin(), (*arg).end()); - - BtaGattQueue::WriteCharacteristic(connection_id, volume_control_point_handle, - set_value, GATT_WRITE, cb, cb_data); -} - -bool VolumeControlDevice::subscribe_for_notifications(tGATT_IF gatt_if, - uint16_t handle, - uint16_t ccc_handle, - GATT_WRITE_OP_CB cb) { - tGATT_STATUS status = - BTA_GATTC_RegisterForNotifications(gatt_if, address, handle); - if (status != GATT_SUCCESS) { - LOG(ERROR) << __func__ << ": failed, status=" << loghex(+status); - return false; - } - - std::vector<uint8_t> value(2); - uint8_t* ptr = value.data(); - UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); - BtaGattQueue::WriteDescriptor(connection_id, ccc_handle, std::move(value), - GATT_WRITE, cb, nullptr); - - return true; -} - -/** - * Enqueue GATT requests that are required by the Volume Control to be - * functional. This includes State characteristics read and subscription. - * Those characteristics contain the change counter needed to send any request - * via Control Point. Once completed successfully, the device can be stored - * and reported as connected. In each case we subscribe first to be sure we do - * not miss any value change. - */ -bool VolumeControlDevice::EnqueueInitialRequests( - tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, - GATT_WRITE_OP_CB cccd_write_cb) { - handles_pending.clear(); - handles_pending.insert(volume_state_handle); - handles_pending.insert(volume_state_ccc_handle); - if (!subscribe_for_notifications(gatt_if, volume_state_handle, - volume_state_ccc_handle, cccd_write_cb)) { - return false; - } - - BtaGattQueue::ReadCharacteristic(connection_id, volume_state_handle, - chrc_read_cb, nullptr); - - return true; -} - -/** - * Enqueue the remaining requests. Those are not so crucial and can be done - * once Volume Control instance indicates it's readiness to profile. - * This includes characteristics read and subscription. - * In each case we subscribe first to be sure we do not miss any value change. - */ -void VolumeControlDevice::EnqueueRemainingRequests( - tGATT_IF gatt_if, GATT_READ_OP_CB chrc_read_cb, - GATT_WRITE_OP_CB cccd_write_cb) { - std::map<uint16_t, uint16_t> handle_pairs{ - {volume_flags_handle, volume_flags_ccc_handle}, - }; - - for (auto const& handles : handle_pairs) { - if (GATT_HANDLE_IS_VALID(handles.second)) { - subscribe_for_notifications(gatt_if, handles.first, handles.second, - cccd_write_cb); - } - - BtaGattQueue::ReadCharacteristic(connection_id, handles.first, chrc_read_cb, - nullptr); - } -} - -bool VolumeControlDevice::VerifyReady(uint16_t handle) { - handles_pending.erase(handle); - device_ready = handles_pending.size() == 0; - return device_ready; -} - -bool VolumeControlDevice::IsEncryptionEnabled() { - uint8_t sec_flag = 0; - bool device_found = - BTM_GetSecurityFlagsByTransport(address, &sec_flag, BT_TRANSPORT_LE); - LOG(INFO) << __func__ << ": found=" << static_cast<int>(device_found) - << " sec_flag=" << loghex(sec_flag); - return device_found && (sec_flag & BTM_SEC_FLAG_ENCRYPTED); -} - -bool VolumeControlDevice::EnableEncryption(tBTM_SEC_CALLBACK* callback) { - int result = BTM_SetEncryption(address, BT_TRANSPORT_LE, callback, nullptr, - BTM_BLE_SEC_ENCRYPT); - LOG(INFO) << __func__ << ": result=" << +result; - // TODO: should we care about the result?? - return true; -} |