Index: chrome/browser/chromeos/bluetooth/bluetooth_device.cc |
diff --git a/chrome/browser/chromeos/bluetooth/bluetooth_device.cc b/chrome/browser/chromeos/bluetooth/bluetooth_device.cc |
index 22d9d19e4caed1a3de3f9678e941cd3d789e8796..26880fc0aa3574b9a31e2766fce655d48703f096 100644 |
--- a/chrome/browser/chromeos/bluetooth/bluetooth_device.cc |
+++ b/chrome/browser/chromeos/bluetooth/bluetooth_device.cc |
@@ -4,17 +4,26 @@ |
#include "chrome/browser/chromeos/bluetooth/bluetooth_device.h" |
+#include <map> |
#include <string> |
#include <vector> |
+#include <bluetooth/bluetooth.h> |
+#include <bluetooth/rfcomm.h> |
+#include <errno.h> |
+#include <sys/socket.h> |
+#include <sys/types.h> |
+ |
#include "base/bind.h" |
#include "base/logging.h" |
+#include "base/memory/weak_ptr.h" |
#include "base/string16.h" |
#include "base/string_util.h" |
#include "base/utf_string_conversions.h" |
#include "base/values.h" |
#include "chrome/browser/chromeos/bluetooth/bluetooth_adapter.h" |
#include "chrome/browser/chromeos/bluetooth/bluetooth_service_record.h" |
+#include "chrome/browser/chromeos/bluetooth/bluetooth_socket.h" |
#include "chrome/browser/chromeos/dbus/introspect_util.h" |
#include "chromeos/dbus/bluetooth_adapter_client.h" |
#include "chromeos/dbus/bluetooth_agent_service_provider.h" |
@@ -456,6 +465,75 @@ void BluetoothDevice::Forget(ErrorCallback error_callback) { |
error_callback)); |
} |
+scoped_refptr<BluetoothSocket> BluetoothDevice::OpenSocket( |
+ const std::string& service_uuid, uint8_t channel) { |
+ // TODO(bryeung): add support for L2CAP sockets as well. |
keybuk
2012/04/19 01:05:40
This seems to be in the wrong place, I was expecti
bryeung
2012/04/19 19:42:43
I put the code here because I wasn't sure how to d
|
+ |
+ // open a non-blocking socket, so the call to connect below will not block |
+ int socket_fd = socket( |
+ AF_BLUETOOTH, SOCK_STREAM | SOCK_NONBLOCK, BTPROTO_RFCOMM); |
+ struct sockaddr_rc socket_address = { 0 }; |
+ socket_address.rc_family = AF_BLUETOOTH; |
+ socket_address.rc_channel = channel; |
+ bdaddr_t* bluetooth_address = strtoba(address().c_str()); |
+ bacpy(&(socket_address.rc_bdaddr), bluetooth_address); |
+ free(bluetooth_address); |
+ |
+ // If EINPROGRESS, optimisticly assume that it will succeed eventually |
keybuk
2012/04/19 01:05:40
I believe EINPROGRESS is the only likely return va
bryeung
2012/04/19 19:42:43
Done.
|
+ int status = connect(socket_fd, (struct sockaddr *)&socket_address, |
+ sizeof(socket_address)); |
+ if (status == 0 || status == EINPROGRESS) { |
keybuk
2012/04/19 01:05:40
connect doesn't return EINPROGRESS, it sets errno
bryeung
2012/04/19 19:42:43
Oops. Good catch. Thanks.
|
+ BluetoothSocket* socket = new BluetoothSocket( |
+ this, service_uuid, socket_fd); |
+ return scoped_refptr<BluetoothSocket>(socket); |
+ } |
+ |
+ return NULL; |
+} |
+ |
+void BluetoothDevice::ConnectToMatchingService( |
+ const std::string& service_uuid, |
+ base::Callback<void(scoped_refptr<BluetoothSocket>)> callback, |
+ const dbus::ObjectPath& object_path, |
+ const BluetoothDeviceClient::ServiceMap& service_map, |
+ bool success) { |
+ if (success) { |
+ // If multiple service records are found, use the first one that works. |
+ BluetoothServiceRecord service_record; |
+ for (BluetoothDeviceClient::ServiceMap::const_iterator i = |
+ service_map.begin(); i != service_map.end(); ++i) { |
+ if (!service_record.Init(i->second)) |
keybuk
2012/04/19 01:05:40
Didn't we drop this Init stuff for a constructor?
bryeung
2012/04/19 19:42:43
Yep: we hadn't finished iterating on the other CL
|
+ continue; |
+ |
keybuk
2012/04/19 01:05:40
You don't check if this is an rfcomm service?
bryeung
2012/04/19 19:42:43
Done.
|
+ scoped_refptr<BluetoothSocket> socket = OpenSocket( |
+ service_uuid, service_record.rfcomm_channel()); |
keybuk
2012/04/19 01:05:40
Would be cleaner if this was a BluetoothSocket con
bryeung
2012/04/19 19:42:43
Done.
|
+ if (socket.get() != NULL) { |
+ callback.Run(socket); |
+ break; |
+ } |
+ } |
+ } |
+ callback.Run(NULL); |
+} |
+ |
+void BluetoothDevice::ConnectToService(const std::string& service_uuid, |
+ base::Callback<void(scoped_refptr<BluetoothSocket>)> callback) { |
+ // quick sanity check |
+ if (!ProvidesServiceWithUUID(service_uuid)) { |
+ callback.Run(NULL); |
+ return; |
+ } |
+ |
+ DBusThreadManager::Get()->GetBluetoothDeviceClient()-> |
+ DiscoverServices( |
+ object_path_, |
+ service_uuid, |
+ base::Bind(&BluetoothDevice::ConnectToMatchingService, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ service_uuid, |
+ callback)); |
+} |
+ |
void BluetoothDevice::ForgetCallback(ErrorCallback error_callback, |
const dbus::ObjectPath& adapter_path, |
bool success) { |