You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
816 lines
28 KiB
816 lines
28 KiB
// |
|
// Copyright (C) 2015 Google, Inc. |
|
// |
|
// 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 "service/hal/bluetooth_gatt_interface.h" |
|
|
|
#include <mutex> |
|
#include <shared_mutex> |
|
|
|
#include <base/logging.h> |
|
#include <base/observer_list.h> |
|
|
|
#include "service/hal/bluetooth_interface.h" |
|
#include "service/logging_helpers.h" |
|
|
|
using std::lock_guard; |
|
using std::unique_lock; |
|
using std::shared_lock; |
|
using std::mutex; |
|
#if defined(OS_GENERIC) && defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 3500) |
|
using shared_mutex_impl = std::shared_mutex; |
|
#else |
|
using shared_mutex_impl = std::shared_timed_mutex; |
|
#endif |
|
|
|
namespace bluetooth { |
|
namespace hal { |
|
|
|
namespace { |
|
|
|
// The global BluetoothGattInterface instance. |
|
BluetoothGattInterface* g_interface = nullptr; |
|
|
|
// Mutex used by callbacks to access |g_interface|. If we initialize or clean it |
|
// use unique_lock. If only accessing |g_interface| use shared lock. |
|
// TODO(jpawlowski): this should be just shared_mutex, as we currently don't use |
|
// timed methods. Change to shared_mutex when we upgrade to C++14 |
|
shared_mutex_impl g_instance_lock; |
|
|
|
// Helper for obtaining the observer lists. This is forward declared here |
|
// and defined below since it depends on BluetoothInterfaceImpl. |
|
base::ObserverList<BluetoothGattInterface::ScannerObserver>* |
|
GetScannerObservers(); |
|
base::ObserverList<BluetoothGattInterface::ClientObserver>* |
|
GetClientObservers(); |
|
base::ObserverList<BluetoothGattInterface::ServerObserver>* |
|
GetServerObservers(); |
|
|
|
#define FOR_EACH_SCANNER_OBSERVER(func) \ |
|
FOR_EACH_OBSERVER(BluetoothGattInterface::ScannerObserver, \ |
|
*GetScannerObservers(), func) |
|
|
|
#define FOR_EACH_CLIENT_OBSERVER(func) \ |
|
FOR_EACH_OBSERVER(BluetoothGattInterface::ClientObserver, \ |
|
*GetClientObservers(), func) |
|
|
|
#define FOR_EACH_SERVER_OBSERVER(func) \ |
|
FOR_EACH_OBSERVER(BluetoothGattInterface::ServerObserver, \ |
|
*GetServerObservers(), func) |
|
|
|
#define VERIFY_INTERFACE_OR_RETURN() \ |
|
do { \ |
|
if (!g_interface) { \ |
|
LOG(WARNING) << "Callback received while |g_interface| is NULL"; \ |
|
return; \ |
|
} \ |
|
} while (0) |
|
|
|
void RegisterClientCallback(int status, int client_if, |
|
const bt_uuid_t& app_uuid) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_CLIENT_OBSERVER( |
|
RegisterClientCallback(g_interface, status, client_if, app_uuid)); |
|
} |
|
|
|
void ScanResultCallback( |
|
uint16_t ble_evt_type, uint8_t addr_type, RawAddress* bda, |
|
uint8_t ble_primary_phy, uint8_t ble_secondary_phy, |
|
uint8_t ble_advertising_sid, int8_t ble_tx_power, int8_t rssi, |
|
uint16_t ble_periodic_adv_int, |
|
std::vector<uint8_t> adv_data) { // NOLINT(pass-by-value) |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
CHECK(bda); |
|
|
|
VLOG(2) << __func__ << " - BD_ADDR: " << BtAddrString(bda) |
|
<< " RSSI: " << rssi; |
|
FOR_EACH_SCANNER_OBSERVER( |
|
ScanResultCallback(g_interface, *bda, rssi, adv_data)); |
|
} |
|
|
|
void ConnectCallback(int conn_id, int status, int client_if, |
|
const RawAddress& bda) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if |
|
<< " - BD_ADDR: " << BtAddrString(&bda) << " - conn_id: " << conn_id; |
|
|
|
FOR_EACH_CLIENT_OBSERVER( |
|
ConnectCallback(g_interface, conn_id, status, client_if, bda)); |
|
} |
|
|
|
void DisconnectCallback(int conn_id, int status, int client_if, |
|
const RawAddress& bda) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status |
|
<< " client_if: " << client_if |
|
<< " - BD_ADDR: " << BtAddrString(&bda); |
|
FOR_EACH_CLIENT_OBSERVER( |
|
DisconnectCallback(g_interface, conn_id, status, client_if, bda)); |
|
} |
|
|
|
void SearchCompleteCallback(int conn_id, int status) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status; |
|
FOR_EACH_CLIENT_OBSERVER( |
|
SearchCompleteCallback(g_interface, conn_id, status)); |
|
} |
|
|
|
void RegisterForNotificationCallback(int conn_id, int registered, int status, |
|
uint16_t handle) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
LOG(INFO) << __func__ << " - conn_id: " << conn_id << " - status: " << status |
|
<< " - registered: " << registered << " - handle: " << handle; |
|
FOR_EACH_CLIENT_OBSERVER(RegisterForNotificationCallback( |
|
g_interface, conn_id, status, registered, handle)); |
|
} |
|
|
|
void NotifyCallback(int conn_id, const btgatt_notify_params_t& p_data) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
VLOG(2) << __func__ << " - conn_id: " << conn_id |
|
<< " - address: " << BtAddrString(&p_data.bda) |
|
<< " - handle: " << p_data.handle << " - len: " << p_data.len |
|
<< " - is_notify: " << p_data.is_notify; |
|
|
|
FOR_EACH_CLIENT_OBSERVER(NotifyCallback(g_interface, conn_id, p_data)); |
|
} |
|
|
|
void WriteCharacteristicCallback(int conn_id, int status, uint16_t handle) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status; |
|
|
|
FOR_EACH_CLIENT_OBSERVER( |
|
WriteCharacteristicCallback(g_interface, conn_id, status, handle)); |
|
} |
|
|
|
void WriteDescriptorCallback(int conn_id, int status, uint16_t handle) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status; |
|
|
|
FOR_EACH_CLIENT_OBSERVER( |
|
WriteDescriptorCallback(g_interface, conn_id, status, handle)); |
|
} |
|
|
|
void MtuChangedCallback(int conn_id, int status, int mtu) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " status: " << status |
|
<< " mtu: " << mtu; |
|
|
|
FOR_EACH_CLIENT_OBSERVER( |
|
MtuChangedCallback(g_interface, conn_id, status, mtu)); |
|
} |
|
|
|
void GetGattDbCallback(int conn_id, const btgatt_db_element_t* db, int size) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " size: " << size; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_CLIENT_OBSERVER(GetGattDbCallback(g_interface, conn_id, db, size)); |
|
} |
|
|
|
void ServicesRemovedCallback(int conn_id, uint16_t start_handle, |
|
uint16_t end_handle) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id |
|
<< " start_handle: " << start_handle << " end_handle: " << end_handle; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_CLIENT_OBSERVER( |
|
ServicesRemovedCallback(g_interface, conn_id, start_handle, end_handle)); |
|
} |
|
|
|
void ServicesAddedCallback(int conn_id, const btgatt_db_element_t& added, |
|
int added_count) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id |
|
<< " added_count: " << added_count; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_CLIENT_OBSERVER( |
|
ServicesAddedCallback(g_interface, conn_id, added, added_count)); |
|
} |
|
|
|
void RegisterServerCallback(int status, int server_if, |
|
const bt_uuid_t& app_uuid) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER( |
|
RegisterServerCallback(g_interface, status, server_if, app_uuid)); |
|
} |
|
|
|
void ConnectionCallback(int conn_id, int server_if, int connected, |
|
const RawAddress& bda) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id |
|
<< " server_if: " << server_if << " connected: " << connected; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER( |
|
ConnectionCallback(g_interface, conn_id, server_if, connected, bda)); |
|
} |
|
|
|
void ServiceAddedCallback( |
|
int status, int server_if, |
|
std::vector<btgatt_db_element_t> service) { // NOLINT(pass-by-value) |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if |
|
<< " count: " << service.size(); |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
CHECK(service.size()); |
|
|
|
FOR_EACH_SERVER_OBSERVER( |
|
ServiceAddedCallback(g_interface, status, server_if, service)); |
|
} |
|
|
|
void ServiceStoppedCallback(int status, int server_if, int srvc_handle) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if |
|
<< " handle: " << srvc_handle; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER( |
|
ServiceStoppedCallback(g_interface, status, server_if, srvc_handle)); |
|
} |
|
|
|
void ServiceDeletedCallback(int status, int server_if, int srvc_handle) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if |
|
<< " handle: " << srvc_handle; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER( |
|
ServiceDeletedCallback(g_interface, status, server_if, srvc_handle)); |
|
} |
|
|
|
void RequestReadCharacteristicCallback(int conn_id, int trans_id, |
|
const RawAddress& bda, int attr_handle, |
|
int offset, bool is_long) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id |
|
<< " attr_handle: " << attr_handle << " offset: " << offset |
|
<< " is_long: " << is_long; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER(RequestReadCharacteristicCallback( |
|
g_interface, conn_id, trans_id, bda, attr_handle, offset, is_long)); |
|
} |
|
|
|
void RequestReadDescriptorCallback(int conn_id, int trans_id, |
|
const RawAddress& bda, int attr_handle, |
|
int offset, bool is_long) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id |
|
<< " attr_handle: " << attr_handle << " offset: " << offset |
|
<< " is_long: " << is_long; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER(RequestReadDescriptorCallback( |
|
g_interface, conn_id, trans_id, bda, attr_handle, offset, is_long)); |
|
} |
|
|
|
void RequestWriteCharacteristicCallback(int conn_id, int trans_id, |
|
const RawAddress& bda, int attr_handle, |
|
int offset, bool need_rsp, bool is_prep, |
|
std::vector<uint8_t> value) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id |
|
<< " attr_handle: " << attr_handle << " offset: " << offset |
|
<< " length: " << value.size() << " need_rsp: " << need_rsp |
|
<< " is_prep: " << is_prep; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER(RequestWriteCharacteristicCallback( |
|
g_interface, conn_id, trans_id, bda, attr_handle, offset, need_rsp, |
|
is_prep, value)); |
|
} |
|
|
|
void RequestWriteDescriptorCallback( |
|
int conn_id, int trans_id, const RawAddress& bda, int attr_handle, |
|
int offset, bool need_rsp, bool is_prep, |
|
std::vector<uint8_t> value) { // NOLINT(pass-by-value) |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id |
|
<< " attr_handle: " << attr_handle << " offset: " << offset |
|
<< " length: " << value.size() << " need_rsp: " << need_rsp |
|
<< " is_prep: " << is_prep; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER(RequestWriteDescriptorCallback( |
|
g_interface, conn_id, trans_id, bda, attr_handle, offset, need_rsp, |
|
is_prep, value)); |
|
} |
|
|
|
void RequestExecWriteCallback(int conn_id, int trans_id, const RawAddress& bda, |
|
int exec_write) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id |
|
<< " exec_write: " << exec_write; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER(RequestExecWriteCallback(g_interface, conn_id, |
|
trans_id, bda, exec_write)); |
|
} |
|
|
|
void ResponseConfirmationCallback(int status, int handle) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - status: " << status << " handle: " << handle; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER( |
|
ResponseConfirmationCallback(g_interface, status, handle)); |
|
} |
|
|
|
void IndicationSentCallback(int conn_id, int status) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " status: " << status; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER( |
|
IndicationSentCallback(g_interface, conn_id, status)); |
|
} |
|
|
|
void MtuChangedCallback(int conn_id, int mtu) { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
VLOG(2) << __func__ << " - conn_id: " << conn_id << " mtu: " << mtu; |
|
VERIFY_INTERFACE_OR_RETURN(); |
|
|
|
FOR_EACH_SERVER_OBSERVER(MtuChangedCallback(g_interface, conn_id, mtu)); |
|
} |
|
|
|
// The HAL Bluetooth GATT client interface callbacks. These signal a mixture of |
|
// GATT client-role and GAP events. |
|
|
|
const btgatt_scanner_callbacks_t gatt_scanner_callbacks = { |
|
ScanResultCallback, |
|
nullptr, // batchscan_reports_cb |
|
nullptr, // batchscan_threshold_cb |
|
nullptr, // track_adv_event_cb |
|
}; |
|
|
|
const btgatt_client_callbacks_t gatt_client_callbacks = { |
|
RegisterClientCallback, |
|
ConnectCallback, |
|
DisconnectCallback, |
|
SearchCompleteCallback, |
|
RegisterForNotificationCallback, |
|
NotifyCallback, |
|
nullptr, // read_characteristic_cb |
|
WriteCharacteristicCallback, |
|
nullptr, // read_descriptor_cb |
|
WriteDescriptorCallback, |
|
nullptr, // execute_write_cb |
|
nullptr, // read_remote_rssi_cb |
|
MtuChangedCallback, |
|
nullptr, // congestion_cb |
|
GetGattDbCallback, |
|
ServicesRemovedCallback, |
|
ServicesAddedCallback, |
|
nullptr, |
|
nullptr, |
|
}; |
|
|
|
const btgatt_server_callbacks_t gatt_server_callbacks = { |
|
RegisterServerCallback, |
|
ConnectionCallback, |
|
ServiceAddedCallback, |
|
ServiceStoppedCallback, |
|
ServiceDeletedCallback, |
|
RequestReadCharacteristicCallback, |
|
RequestReadDescriptorCallback, |
|
RequestWriteCharacteristicCallback, |
|
RequestWriteDescriptorCallback, |
|
RequestExecWriteCallback, |
|
ResponseConfirmationCallback, |
|
IndicationSentCallback, |
|
nullptr, // congestion_cb |
|
MtuChangedCallback, |
|
nullptr, |
|
nullptr, |
|
}; |
|
|
|
const btgatt_callbacks_t gatt_callbacks = { |
|
sizeof(btgatt_callbacks_t), &gatt_client_callbacks, &gatt_server_callbacks, |
|
&gatt_scanner_callbacks, |
|
}; |
|
|
|
} // namespace |
|
|
|
// BluetoothGattInterface implementation for production. |
|
class BluetoothGattInterfaceImpl : public BluetoothGattInterface { |
|
public: |
|
BluetoothGattInterfaceImpl() : hal_iface_(nullptr) {} |
|
|
|
~BluetoothGattInterfaceImpl() override { |
|
if (hal_iface_) hal_iface_->cleanup(); |
|
} |
|
|
|
void AddScannerObserver(ScannerObserver* observer) override { |
|
scanner_observers_.AddObserver(observer); |
|
} |
|
|
|
void RemoveScannerObserver(ScannerObserver* observer) override { |
|
scanner_observers_.RemoveObserver(observer); |
|
} |
|
|
|
void AddClientObserver(ClientObserver* observer) override { |
|
client_observers_.AddObserver(observer); |
|
} |
|
|
|
void RemoveClientObserver(ClientObserver* observer) override { |
|
client_observers_.RemoveObserver(observer); |
|
} |
|
|
|
void AddServerObserver(ServerObserver* observer) override { |
|
server_observers_.AddObserver(observer); |
|
} |
|
|
|
void RemoveServerObserver(ServerObserver* observer) override { |
|
server_observers_.RemoveObserver(observer); |
|
} |
|
|
|
BleAdvertiserInterface* GetAdvertiserHALInterface() const override { |
|
return hal_iface_->advertiser; |
|
} |
|
|
|
BleScannerInterface* GetScannerHALInterface() const override { |
|
return hal_iface_->scanner; |
|
} |
|
|
|
const btgatt_client_interface_t* GetClientHALInterface() const override { |
|
return hal_iface_->client; |
|
} |
|
|
|
const btgatt_server_interface_t* GetServerHALInterface() const override { |
|
return hal_iface_->server; |
|
} |
|
|
|
// Initialize the interface. |
|
bool Initialize() { |
|
const bt_interface_t* bt_iface = |
|
BluetoothInterface::Get()->GetHALInterface(); |
|
CHECK(bt_iface); |
|
|
|
const btgatt_interface_t* gatt_iface = |
|
reinterpret_cast<const btgatt_interface_t*>( |
|
bt_iface->get_profile_interface(BT_PROFILE_GATT_ID)); |
|
if (!gatt_iface) { |
|
LOG(ERROR) << "Failed to obtain HAL GATT interface handle"; |
|
return false; |
|
} |
|
|
|
bt_status_t status = gatt_iface->init(&gatt_callbacks); |
|
if (status != BT_STATUS_SUCCESS) { |
|
LOG(ERROR) << "Failed to initialize HAL GATT interface"; |
|
return false; |
|
} |
|
|
|
hal_iface_ = gatt_iface; |
|
|
|
return true; |
|
} |
|
|
|
base::ObserverList<ScannerObserver>* scanner_observers() { |
|
return &scanner_observers_; |
|
} |
|
|
|
base::ObserverList<ClientObserver>* client_observers() { |
|
return &client_observers_; |
|
} |
|
|
|
base::ObserverList<ServerObserver>* server_observers() { |
|
return &server_observers_; |
|
} |
|
|
|
private: |
|
// List of observers that are interested in notifications from us. |
|
// We're not using a base::ObserverListThreadSafe, which it posts observer |
|
// events automatically on the origin threads, as we want to avoid that |
|
// overhead and simply forward the events to the upper layer. |
|
base::ObserverList<ScannerObserver> scanner_observers_; |
|
base::ObserverList<ClientObserver> client_observers_; |
|
base::ObserverList<ServerObserver> server_observers_; |
|
|
|
// The HAL handle obtained from the shared library. We hold a weak reference |
|
// to this since the actual data resides in the shared Bluetooth library. |
|
const btgatt_interface_t* hal_iface_; |
|
|
|
DISALLOW_COPY_AND_ASSIGN(BluetoothGattInterfaceImpl); |
|
}; |
|
|
|
namespace { |
|
|
|
base::ObserverList<BluetoothGattInterface::ScannerObserver>* |
|
GetScannerObservers() { |
|
CHECK(g_interface); |
|
return static_cast<BluetoothGattInterfaceImpl*>(g_interface) |
|
->scanner_observers(); |
|
} |
|
|
|
base::ObserverList<BluetoothGattInterface::ClientObserver>* |
|
GetClientObservers() { |
|
CHECK(g_interface); |
|
return static_cast<BluetoothGattInterfaceImpl*>(g_interface) |
|
->client_observers(); |
|
} |
|
|
|
base::ObserverList<BluetoothGattInterface::ServerObserver>* |
|
GetServerObservers() { |
|
CHECK(g_interface); |
|
return static_cast<BluetoothGattInterfaceImpl*>(g_interface) |
|
->server_observers(); |
|
} |
|
|
|
} // namespace |
|
|
|
// Default observer implementations. These are provided so that the methods |
|
// themselves are optional. |
|
|
|
void BluetoothGattInterface::ScannerObserver::ScanResultCallback( |
|
BluetoothGattInterface* /* gatt_iface */, const RawAddress& /* bda */, |
|
int /* rssi */, |
|
std::vector<uint8_t> /* adv_data */) { // NOLINT(pass-by-value) |
|
// Do Nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::RegisterClientCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* status */, |
|
int /* client_if */, const bt_uuid_t& /* app_uuid */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::ConnectCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* status */, int /* client_if */, const RawAddress& /* bda */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::DisconnectCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* status */, int /* client_if */, const RawAddress& /* bda */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::SearchCompleteCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* status */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::RegisterForNotificationCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* status */, int /* registered */, uint16_t /* handle */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::NotifyCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
const btgatt_notify_params_t& /* p_data */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::WriteCharacteristicCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* status */, uint16_t /* handle */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::WriteDescriptorCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* status */, uint16_t /* handle */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::MtuChangedCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* statis*/, int /* mtu */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::GetGattDbCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
const btgatt_db_element_t* /* gatt_db */, int /* size */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::ServicesRemovedCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
uint16_t /* start_handle */, uint16_t /* end_handle */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ClientObserver::ServicesAddedCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
const btgatt_db_element_t& /* added */, int /* added_count */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::RegisterServerCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* status */, |
|
int /* server_if */, const bt_uuid_t& /* app_uuid */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::ConnectionCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* server_if */, int /* connected */, const RawAddress& /* bda */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::ServiceAddedCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* status */, |
|
int /* server_if */, |
|
std::vector<btgatt_db_element_t> /* service */) { // NOLINT(pass-by-value) |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::ServiceStoppedCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* status */, |
|
int /* server_if */, int /* srvc_handle */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::ServiceDeletedCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* status */, |
|
int /* server_if */, int /* srvc_handle */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::RequestReadCharacteristicCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* trans_id */, const RawAddress& /* bda */, int /* attr_handle */, |
|
int /* offset */, bool /* is_long */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::RequestReadDescriptorCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* trans_id */, const RawAddress& /* bda */, int /* attr_handle */, |
|
int /* offset */, bool /* is_long */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::RequestWriteCharacteristicCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* trans_id */, const RawAddress& /* bda */, int /* attr_handle */, |
|
int /* offset */, bool /* need_rsp */, bool /* is_prep */, |
|
std::vector<uint8_t> /* value */) { // NOLINT(pass-by-value) |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::RequestWriteDescriptorCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* trans_id */, const RawAddress& /* bda */, int /* attr_handle */, |
|
int /* offset */, bool /* need_rsp */, bool /* is_prep */, |
|
std::vector<uint8_t> /* value */) { // NOLINT(pass-by-value) |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::RequestExecWriteCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* trans_id */, const RawAddress& /* bda */, int /* exec_write */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::ResponseConfirmationCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* status */, |
|
int /* handle */) { |
|
// Do nothing |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::IndicationSentCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* status */) { |
|
// Do nothing. |
|
} |
|
|
|
void BluetoothGattInterface::ServerObserver::MtuChangedCallback( |
|
BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, |
|
int /* mtu */) { |
|
// Do nothing. |
|
} |
|
|
|
// static |
|
bool BluetoothGattInterface::Initialize() { |
|
unique_lock<shared_mutex_impl> lock(g_instance_lock); |
|
CHECK(!g_interface); |
|
|
|
std::unique_ptr<BluetoothGattInterfaceImpl> impl( |
|
new BluetoothGattInterfaceImpl()); |
|
if (!impl->Initialize()) { |
|
LOG(ERROR) << "Failed to initialize BluetoothGattInterface"; |
|
return false; |
|
} |
|
|
|
g_interface = impl.release(); |
|
|
|
return true; |
|
} |
|
|
|
// static |
|
void BluetoothGattInterface::CleanUp() { |
|
unique_lock<shared_mutex_impl> lock(g_instance_lock); |
|
CHECK(g_interface); |
|
|
|
delete g_interface; |
|
g_interface = nullptr; |
|
} |
|
|
|
// static |
|
bool BluetoothGattInterface::IsInitialized() { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
|
|
return g_interface != nullptr; |
|
} |
|
|
|
// static |
|
BluetoothGattInterface* BluetoothGattInterface::Get() { |
|
shared_lock<shared_mutex_impl> lock(g_instance_lock); |
|
CHECK(g_interface); |
|
return g_interface; |
|
} |
|
|
|
// static |
|
void BluetoothGattInterface::InitializeForTesting( |
|
BluetoothGattInterface* test_instance) { |
|
unique_lock<shared_mutex_impl> lock(g_instance_lock); |
|
CHECK(test_instance); |
|
CHECK(!g_interface); |
|
|
|
g_interface = test_instance; |
|
} |
|
|
|
bt_status_t BluetoothGattInterface::StartScan(int client_id) { |
|
lock_guard<mutex> lock(scan_clients_lock_); |
|
|
|
// Scan already initiated for this client. |
|
if (scan_client_set_.find(client_id) != scan_client_set_.end()) { |
|
// Assume starting scan multiple times is not error, but warn user. |
|
LOG(WARNING) << "Scan already initiated for client"; |
|
return BT_STATUS_SUCCESS; |
|
} |
|
|
|
// If this is the first scan client, then make a call into the stack. We |
|
// only do this when the reference count changes to or from 0. |
|
if (scan_client_set_.empty()) { |
|
GetScannerHALInterface()->Scan(true); |
|
} |
|
|
|
scan_client_set_.insert(client_id); |
|
|
|
return BT_STATUS_SUCCESS; |
|
} |
|
|
|
bt_status_t BluetoothGattInterface::StopScan(int client_id) { |
|
lock_guard<mutex> lock(scan_clients_lock_); |
|
|
|
// Scan not initiated for this client. |
|
auto iter = scan_client_set_.find(client_id); |
|
if (iter == scan_client_set_.end()) { |
|
// Assume stopping scan multiple times is not error, but warn user. |
|
LOG(WARNING) << "Scan already stopped or not initiated for client"; |
|
return BT_STATUS_SUCCESS; |
|
} |
|
|
|
if (scan_client_set_.size() == 1) { |
|
GetScannerHALInterface()->Scan(false); |
|
} |
|
|
|
scan_client_set_.erase(iter); |
|
return BT_STATUS_SUCCESS; |
|
} |
|
|
|
} // namespace hal |
|
} // namespace bluetooth
|
|
|