| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "device/bluetooth/bluetooth_device_win.h" |
| |
| #include <string> |
| #include <unordered_map> |
| |
| #include "base/check_op.h" |
| #include "base/functional/bind.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/notimplemented.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "device/bluetooth/bluetooth_adapter_win.h" |
| #include "device/bluetooth/bluetooth_service_record_win.h" |
| #include "device/bluetooth/bluetooth_socket_thread.h" |
| #include "device/bluetooth/bluetooth_socket_win.h" |
| #include "device/bluetooth/bluetooth_task_manager_win.h" |
| #include "device/bluetooth/public/cpp/bluetooth_address.h" |
| #include "device/bluetooth/public/cpp/bluetooth_uuid.h" |
| |
| namespace { |
| |
| const char kApiUnavailable[] = "This API is not implemented on this platform."; |
| |
| } // namespace |
| |
| namespace device { |
| |
| BluetoothDeviceWin::BluetoothDeviceWin( |
| BluetoothAdapterWin* adapter, |
| const BluetoothTaskManagerWin::DeviceState& device_state, |
| scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| scoped_refptr<BluetoothSocketThread> socket_thread) |
| : BluetoothDevice(adapter), |
| ui_task_runner_(std::move(ui_task_runner)), |
| socket_thread_(std::move(socket_thread)) { |
| Update(device_state); |
| } |
| |
| BluetoothDeviceWin::~BluetoothDeviceWin() = default; |
| |
| uint32_t BluetoothDeviceWin::GetBluetoothClass() const { |
| return bluetooth_class_; |
| } |
| |
| std::string BluetoothDeviceWin::GetAddress() const { |
| return address_; |
| } |
| |
| BluetoothDevice::AddressType BluetoothDeviceWin::GetAddressType() const { |
| NOTIMPLEMENTED(); |
| return ADDR_TYPE_UNKNOWN; |
| } |
| |
| BluetoothDevice::VendorIDSource |
| BluetoothDeviceWin::GetVendorIDSource() const { |
| return VENDOR_ID_UNKNOWN; |
| } |
| |
| uint16_t BluetoothDeviceWin::GetVendorID() const { |
| return 0; |
| } |
| |
| uint16_t BluetoothDeviceWin::GetProductID() const { |
| return 0; |
| } |
| |
| uint16_t BluetoothDeviceWin::GetDeviceID() const { |
| return 0; |
| } |
| |
| uint16_t BluetoothDeviceWin::GetAppearance() const { |
| // TODO(crbug.com/41240161): Implementing GetAppearance() |
| // on mac, win, and android platforms for chrome |
| NOTIMPLEMENTED(); |
| return 0; |
| } |
| |
| std::optional<std::string> BluetoothDeviceWin::GetName() const { |
| return name_; |
| } |
| |
| bool BluetoothDeviceWin::IsPaired() const { |
| return paired_; |
| } |
| |
| bool BluetoothDeviceWin::IsConnected() const { |
| return connected_; |
| } |
| |
| bool BluetoothDeviceWin::IsGattConnected() const { |
| return false; |
| } |
| |
| bool BluetoothDeviceWin::IsConnectable() const { |
| return false; |
| } |
| |
| bool BluetoothDeviceWin::IsConnecting() const { |
| return false; |
| } |
| |
| BluetoothDevice::UUIDSet BluetoothDeviceWin::GetUUIDs() const { |
| return uuids_; |
| } |
| |
| std::optional<int8_t> BluetoothDeviceWin::GetInquiryRSSI() const { |
| // In windows, we can only get connected devices and connected |
| // devices don't have an Inquiry RSSI. |
| return std::nullopt; |
| } |
| |
| std::optional<int8_t> BluetoothDeviceWin::GetInquiryTxPower() const { |
| // In windows, we can only get connected devices and connected |
| // devices don't have an Inquiry Tx Power. |
| return std::nullopt; |
| } |
| |
| bool BluetoothDeviceWin::ExpectingPinCode() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| bool BluetoothDeviceWin::ExpectingPasskey() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| bool BluetoothDeviceWin::ExpectingConfirmation() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void BluetoothDeviceWin::GetConnectionInfo(ConnectionInfoCallback callback) { |
| NOTIMPLEMENTED(); |
| std::move(callback).Run(ConnectionInfo()); |
| } |
| |
| void BluetoothDeviceWin::SetConnectionLatency( |
| ConnectionLatency connection_latency, |
| base::OnceClosure callback, |
| ErrorCallback error_callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::Connect(PairingDelegate* pairing_delegate, |
| ConnectCallback callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::SetPinCode(const std::string& pincode) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::SetPasskey(uint32_t passkey) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::ConfirmPairing() { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::RejectPairing() { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::CancelPairing() { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::Disconnect(base::OnceClosure callback, |
| ErrorCallback error_callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::Forget(base::OnceClosure callback, |
| ErrorCallback error_callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothDeviceWin::ConnectToService( |
| const BluetoothUUID& uuid, |
| ConnectToServiceCallback callback, |
| ConnectToServiceErrorCallback error_callback) { |
| scoped_refptr<BluetoothSocketWin> socket( |
| BluetoothSocketWin::CreateBluetoothSocket( |
| ui_task_runner_, socket_thread_)); |
| socket->Connect(this, uuid, base::BindOnce(std::move(callback), socket), |
| std::move(error_callback)); |
| } |
| |
| void BluetoothDeviceWin::ConnectToServiceInsecurely( |
| const BluetoothUUID& uuid, |
| ConnectToServiceCallback callback, |
| ConnectToServiceErrorCallback error_callback) { |
| std::move(error_callback).Run(kApiUnavailable); |
| } |
| |
| const BluetoothServiceRecordWin* BluetoothDeviceWin::GetServiceRecord( |
| const device::BluetoothUUID& uuid) const { |
| for (const auto& record : service_record_list_) |
| if (record->uuid() == uuid) |
| return record.get(); |
| |
| return nullptr; |
| } |
| |
| bool BluetoothDeviceWin::IsEqual( |
| const BluetoothTaskManagerWin::DeviceState& device_state) { |
| if (address_ != device_state.address || name_ != device_state.name || |
| bluetooth_class_ != device_state.bluetooth_class || |
| visible_ != device_state.visible || |
| connected_ != device_state.connected || |
| paired_ != device_state.authenticated) { |
| return false; |
| } |
| |
| // Checks service collection |
| UUIDSet new_services; |
| std::unordered_map<std::string, std::unique_ptr<BluetoothServiceRecordWin>> |
| new_service_records; |
| for (auto iter = device_state.service_record_states.begin(); |
| iter != device_state.service_record_states.end(); ++iter) { |
| auto service_record = std::make_unique<BluetoothServiceRecordWin>( |
| address_, (*iter)->name, (*iter)->sdp_bytes, (*iter)->gatt_uuid); |
| new_services.insert(service_record->uuid()); |
| new_service_records[service_record->uuid().canonical_value()] = |
| std::move(service_record); |
| } |
| |
| // Check that no new services have been added or removed. |
| if (uuids_ != new_services) { |
| return false; |
| } |
| |
| for (const auto& service_record : service_record_list_) { |
| BluetoothServiceRecordWin* new_service_record = |
| new_service_records[service_record->uuid().canonical_value()].get(); |
| if (!service_record->IsEqual(*new_service_record)) |
| return false; |
| } |
| return true; |
| } |
| |
| void BluetoothDeviceWin::Update( |
| const BluetoothTaskManagerWin::DeviceState& device_state) { |
| address_ = device_state.address; |
| // Note: Callers are responsible for providing a canonicalized address. |
| DCHECK_EQ(address_, CanonicalizeBluetoothAddress(address_)); |
| name_ = device_state.name; |
| bluetooth_class_ = device_state.bluetooth_class; |
| visible_ = device_state.visible; |
| connected_ = device_state.connected; |
| paired_ = device_state.authenticated; |
| UpdateServices(device_state); |
| } |
| |
| void BluetoothDeviceWin::CreateGattConnectionImpl( |
| std::optional<BluetoothUUID> service_uuid) { |
| // Windows will create the Gatt connection as needed. See: |
| // https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/gatt-client#connecting-to-the-device |
| } |
| |
| void BluetoothDeviceWin::DisconnectGatt() { |
| // On Windows, the adapter cannot force a disconnection. |
| } |
| |
| void BluetoothDeviceWin::SetVisible(bool visible) { |
| visible_ = visible; |
| } |
| |
| void BluetoothDeviceWin::UpdateServices( |
| const BluetoothTaskManagerWin::DeviceState& device_state) { |
| uuids_.clear(); |
| service_record_list_.clear(); |
| |
| for (const auto& record_state : device_state.service_record_states) { |
| auto service_record = std::make_unique<BluetoothServiceRecordWin>( |
| device_state.address, record_state->name, record_state->sdp_bytes, |
| record_state->gatt_uuid); |
| uuids_.insert(service_record->uuid()); |
| service_record_list_.push_back(std::move(service_record)); |
| } |
| } |
| |
| } // namespace device |