| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "device/bluetooth/bluetooth_adapter_profile_bluez.h" |
| |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "base/strings/string_util.h" |
| #include "dbus/bus.h" |
| #include "dbus/object_path.h" |
| #include "device/bluetooth/bluetooth_adapter_bluez.h" |
| #include "device/bluetooth/bluetooth_uuid.h" |
| #include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" |
| #include "device/bluetooth/dbus/bluez_dbus_manager.h" |
| |
| namespace bluez { |
| |
| // static |
| void BluetoothAdapterProfileBlueZ::Register( |
| const device::BluetoothUUID& uuid, |
| const bluez::BluetoothProfileManagerClient::Options& options, |
| const ProfileRegisteredCallback& success_callback, |
| const bluez::BluetoothProfileManagerClient::ErrorCallback& error_callback) { |
| scoped_ptr<BluetoothAdapterProfileBlueZ> profile( |
| new BluetoothAdapterProfileBlueZ(uuid)); |
| |
| VLOG(1) << "Registering profile: " << profile->object_path().value(); |
| const dbus::ObjectPath& object_path = profile->object_path(); |
| bluez::BluezDBusManager::Get() |
| ->GetBluetoothProfileManagerClient() |
| ->RegisterProfile(object_path, uuid.canonical_value(), options, |
| base::Bind(success_callback, base::Passed(&profile)), |
| error_callback); |
| } |
| |
| BluetoothAdapterProfileBlueZ::BluetoothAdapterProfileBlueZ( |
| const device::BluetoothUUID& uuid) |
| : uuid_(uuid), weak_ptr_factory_(this) { |
| std::string uuid_path; |
| base::ReplaceChars(uuid.canonical_value(), ":-", "_", &uuid_path); |
| object_path_ = |
| dbus::ObjectPath("/org/chromium/bluetooth_profile/" + uuid_path); |
| |
| dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus(); |
| profile_.reset(bluez::BluetoothProfileServiceProvider::Create( |
| system_bus, object_path_, this)); |
| DCHECK(profile_.get()); |
| } |
| |
| BluetoothAdapterProfileBlueZ::~BluetoothAdapterProfileBlueZ() {} |
| |
| bool BluetoothAdapterProfileBlueZ::SetDelegate( |
| const dbus::ObjectPath& device_path, |
| bluez::BluetoothProfileServiceProvider::Delegate* delegate) { |
| DCHECK(delegate); |
| VLOG(1) << "SetDelegate: " << object_path_.value() << " dev " |
| << device_path.value(); |
| |
| if (delegates_.find(device_path.value()) != delegates_.end()) { |
| return false; |
| } |
| |
| delegates_[device_path.value()] = delegate; |
| return true; |
| } |
| |
| void BluetoothAdapterProfileBlueZ::RemoveDelegate( |
| const dbus::ObjectPath& device_path, |
| const base::Closure& unregistered_callback) { |
| VLOG(1) << object_path_.value() << " dev " << device_path.value() |
| << ": RemoveDelegate"; |
| |
| if (delegates_.find(device_path.value()) == delegates_.end()) |
| return; |
| |
| delegates_.erase(device_path.value()); |
| |
| if (delegates_.size() != 0) |
| return; |
| |
| VLOG(1) << device_path.value() << " No delegates left, unregistering."; |
| |
| // No users left, release the profile. |
| bluez::BluezDBusManager::Get() |
| ->GetBluetoothProfileManagerClient() |
| ->UnregisterProfile( |
| object_path_, unregistered_callback, |
| base::Bind(&BluetoothAdapterProfileBlueZ::OnUnregisterProfileError, |
| weak_ptr_factory_.GetWeakPtr(), unregistered_callback)); |
| } |
| |
| void BluetoothAdapterProfileBlueZ::OnUnregisterProfileError( |
| const base::Closure& unregistered_callback, |
| const std::string& error_name, |
| const std::string& error_message) { |
| LOG(WARNING) << this->object_path().value() |
| << ": Failed to unregister profile: " << error_name << ": " |
| << error_message; |
| |
| unregistered_callback.Run(); |
| } |
| |
| // bluez::BluetoothProfileServiceProvider::Delegate: |
| void BluetoothAdapterProfileBlueZ::Released() { |
| VLOG(1) << object_path_.value() << ": Release"; |
| } |
| |
| void BluetoothAdapterProfileBlueZ::NewConnection( |
| const dbus::ObjectPath& device_path, |
| scoped_ptr<dbus::FileDescriptor> fd, |
| const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, |
| const ConfirmationCallback& callback) { |
| dbus::ObjectPath delegate_path = device_path; |
| |
| if (delegates_.find(device_path.value()) == delegates_.end()) |
| delegate_path = dbus::ObjectPath(""); |
| |
| if (delegates_.find(delegate_path.value()) == delegates_.end()) { |
| VLOG(1) << object_path_.value() << ": New connection for device " |
| << device_path.value() << " which has no delegates!"; |
| callback.Run(REJECTED); |
| return; |
| } |
| |
| delegates_[delegate_path.value()]->NewConnection(device_path, std::move(fd), |
| options, callback); |
| } |
| |
| void BluetoothAdapterProfileBlueZ::RequestDisconnection( |
| const dbus::ObjectPath& device_path, |
| const ConfirmationCallback& callback) { |
| dbus::ObjectPath delegate_path = device_path; |
| |
| if (delegates_.find(device_path.value()) == delegates_.end()) |
| delegate_path = dbus::ObjectPath(""); |
| |
| if (delegates_.find(delegate_path.value()) == delegates_.end()) { |
| VLOG(1) << object_path_.value() << ": RequestDisconnection for device " |
| << device_path.value() << " which has no delegates!"; |
| return; |
| } |
| |
| delegates_[delegate_path.value()]->RequestDisconnection(device_path, |
| callback); |
| } |
| |
| void BluetoothAdapterProfileBlueZ::Cancel() { |
| // Cancel() should only go to a delegate accepting connections. |
| if (delegates_.find("") == delegates_.end()) { |
| VLOG(1) << object_path_.value() << ": Cancel with no delegate!"; |
| return; |
| } |
| |
| delegates_[""]->Cancel(); |
| } |
| |
| } // namespace bluez |