diff options
author | keybuk@chromium.org <keybuk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-09 03:49:18 +0000 |
---|---|---|
committer | keybuk@chromium.org <keybuk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-09 03:49:18 +0000 |
commit | e882d2cdf5ed5337d68f2b32ba0f885725ca8b3f (patch) | |
tree | c4ca06e4ad129b16aa1f04753db7ac4e98a55240 /chromeos/dbus/fake_bluetooth_device_client.cc | |
parent | dc5d179b1e34c9147630adc9d20e43e7986f7feb (diff) | |
download | chromium_src-e882d2cdf5ed5337d68f2b32ba0f885725ca8b3f.zip chromium_src-e882d2cdf5ed5337d68f2b32ba0f885725ca8b3f.tar.gz chromium_src-e882d2cdf5ed5337d68f2b32ba0f885725ca8b3f.tar.bz2 |
Bluetooth: Profile support for Chrome OS
Implement support for the BluetoothProfile API for the BlueZ 5.x
stack on Chrome OS, including BluetoothSocket support.
BUG=229636
TEST=device_unittests
Review URL: https://chromiumcodereview.appspot.com/14487002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199095 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/dbus/fake_bluetooth_device_client.cc')
-rw-r--r-- | chromeos/dbus/fake_bluetooth_device_client.cc | 153 |
1 files changed, 151 insertions, 2 deletions
diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/chromeos/dbus/fake_bluetooth_device_client.cc index 4d3e189..b1ed840 100644 --- a/chromeos/dbus/fake_bluetooth_device_client.cc +++ b/chromeos/dbus/fake_bluetooth_device_client.cc @@ -4,6 +4,11 @@ #include "chromeos/dbus/fake_bluetooth_device_client.h" +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> + #include <algorithm> #include <map> #include <string> @@ -12,14 +17,19 @@ #include "base/bind.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "base/stl_util.h" +#include "base/threading/worker_pool.h" #include "base/time.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_bluetooth_adapter_client.h" #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" #include "chromeos/dbus/fake_bluetooth_input_client.h" +#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" +#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" +#include "dbus/file_descriptor.h" #include "dbus/object_path.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -28,6 +38,30 @@ namespace { // Default interval between simulated events. const int kSimulationIntervalMs = 750; + +void SimulatedProfileSocket(int fd) { + // Simulate a server-side socket of a profile; read data from the socket, + // write it back, and then close. + char buf[1024]; + ssize_t len; + ssize_t count; + + len = read(fd, buf, sizeof buf); + if (len < 0) { + close(fd); + return; + } + + count = len; + len = write(fd, buf, count); + if (len < 0) { + close(fd); + return; + } + + close(fd); +} + } namespace chromeos { @@ -267,7 +301,63 @@ void FakeBluetoothDeviceClient::ConnectProfile( const base::Closure& callback, const ErrorCallback& error_callback) { VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; - error_callback.Run(kNoResponseError, ""); + + FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothProfileManagerClient*>( + DBusThreadManager::Get()-> + GetExperimentalBluetoothProfileManagerClient()); + FakeBluetoothProfileServiceProvider* profile_service_provider = + fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); + if (profile_service_provider == NULL) { + error_callback.Run(kNoResponseError, "Missing profile"); + return; + } + + // Make a socket pair of a compatible type with the type used by Bluetooth; + // spin up a thread to simulate the server side and wrap the client side in + // a D-Bus file descriptor object. + int socket_type = SOCK_STREAM; + if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid) + socket_type = SOCK_SEQPACKET; + + int fds[2]; + if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) { + error_callback.Run(kNoResponseError, "socketpair call failed"); + return; + } + + int args; + args = fcntl(fds[1], F_GETFL, NULL); + if (args < 0) { + error_callback.Run(kNoResponseError, "failed to get socket flags"); + return; + } + + args |= O_NONBLOCK; + if (fcntl(fds[1], F_SETFL, args) < 0) { + error_callback.Run(kNoResponseError, "failed to set socket non-blocking"); + return; + } + + base::WorkerPool::GetTaskRunner(false)->PostTask( + FROM_HERE, + base::Bind(&SimulatedProfileSocket, + fds[0])); + + scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1])); + + // Post the new connection to the service provider. + ExperimentalBluetoothProfileServiceProvider::Delegate::Options options; + + profile_service_provider->NewConnection( + object_path, + fd.Pass(), + options, + base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback, + base::Unretained(this), + object_path, + callback, + error_callback)); } void FakeBluetoothDeviceClient::DisconnectProfile( @@ -276,7 +366,25 @@ void FakeBluetoothDeviceClient::DisconnectProfile( const base::Closure& callback, const ErrorCallback& error_callback) { VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; - error_callback.Run(kNoResponseError, ""); + + FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = + static_cast<FakeBluetoothProfileManagerClient*>( + DBusThreadManager::Get()-> + GetExperimentalBluetoothProfileManagerClient()); + FakeBluetoothProfileServiceProvider* profile_service_provider = + fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); + if (profile_service_provider == NULL) { + error_callback.Run(kNoResponseError, "Missing profile"); + return; + } + + profile_service_provider->RequestDisconnection( + object_path, + base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback, + base::Unretained(this), + object_path, + callback, + error_callback)); } void FakeBluetoothDeviceClient::Pair( @@ -920,4 +1028,45 @@ void FakeBluetoothDeviceClient::SimulateKeypress( } } +void FakeBluetoothDeviceClient::ConnectionCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) { + VLOG(1) << "ConnectionCallback: " << object_path.value(); + + if (status == + ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) { + callback.Run(); + } else if (status == + ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) { + // TODO(keybuk): tear down this side of the connection + error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled"); + } else if (status == + ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) { + // TODO(keybuk): tear down this side of the connection + error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected"); + } +} + +void FakeBluetoothDeviceClient::DisconnectionCallback( + const dbus::ObjectPath& object_path, + const base::Closure& callback, + const ErrorCallback& error_callback, + ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) { + VLOG(1) << "DisconnectionCallback: " << object_path.value(); + + if (status == + ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) { + // TODO(keybuk): tear down this side of the connection + callback.Run(); + } else if (status == + ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) { + error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled"); + } else if (status == + ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) { + error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected"); + } +} + } // namespace chromeos |