1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/bluetooth/bluetooth_profile_win.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/strings/stringprintf.h"
12 #include "device/bluetooth/bluetooth_adapter_factory.h"
13 #include "device/bluetooth/bluetooth_adapter_win.h"
14 #include "device/bluetooth/bluetooth_device_win.h"
15 #include "device/bluetooth/bluetooth_service_record.h"
16 #include "device/bluetooth/bluetooth_socket_thread.h"
17 #include "device/bluetooth/bluetooth_socket_win.h"
21 using device::BluetoothAdapter
;
22 using device::BluetoothDevice
;
23 using device::BluetoothProfileWin
;
24 using device::BluetoothSocket
;
25 using device::BluetoothSocketWin
;
27 const char kNoConnectionCallback
[] = "Connection callback not set";
28 const char kProfileNotFound
[] = "Profile not found";
30 void OnConnectSuccessUIWithAdapter(
31 scoped_refptr
<base::SequencedTaskRunner
> ui_task_runner
,
32 const base::Closure
& callback
,
33 const BluetoothProfileWin::ConnectionCallback
& connection_callback
,
34 const std::string
& device_address
,
35 scoped_refptr
<BluetoothSocketWin
> socket
,
36 scoped_refptr
<BluetoothAdapter
> adapter
) {
37 DCHECK(ui_task_runner
->RunsTasksOnCurrentThread());
38 const BluetoothDevice
* device
= adapter
->GetDevice(device_address
);
40 connection_callback
.Run(device
, socket
);
45 void OnConnectSuccessUI(
46 scoped_refptr
<base::SequencedTaskRunner
> ui_task_runner
,
47 const base::Closure
& callback
,
48 const BluetoothProfileWin::ConnectionCallback
& connection_callback
,
49 const std::string
& device_address
,
50 scoped_refptr
<BluetoothSocketWin
> socket
) {
51 DCHECK(ui_task_runner
->RunsTasksOnCurrentThread());
52 device::BluetoothAdapterFactory::GetAdapter(
53 base::Bind(&OnConnectSuccessUIWithAdapter
,
61 void OnConnectErrorUI(scoped_refptr
<base::SequencedTaskRunner
> ui_task_runner
,
62 const BluetoothProfileWin::ErrorCallback
& error_callback
,
63 const std::string
& error
) {
64 DCHECK(ui_task_runner
->RunsTasksOnCurrentThread());
65 error_callback
.Run(error
);
68 std::string
IPEndPointToBluetoothAddress(const net::IPEndPoint
& end_point
) {
69 if (end_point
.address().size() != net::kBluetoothAddressSize
)
71 // The address is copied from BTH_ADDR field of SOCKADDR_BTH, which is a
72 // 64-bit ULONGLONG that stores Bluetooth address in little-endian. Print in
73 // reverse order to preserve the correct ordering.
74 return base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
75 end_point
.address()[5],
76 end_point
.address()[4],
77 end_point
.address()[3],
78 end_point
.address()[2],
79 end_point
.address()[1],
80 end_point
.address()[0]);
87 BluetoothProfileWin::BluetoothProfileWin()
88 : BluetoothProfile(), rfcomm_channel_(0), weak_ptr_factory_(this) {
91 BluetoothProfileWin::~BluetoothProfileWin() {
94 void BluetoothProfileWin::Unregister() {
96 profile_socket_
->Close();
101 void BluetoothProfileWin::SetConnectionCallback(
102 const ConnectionCallback
& callback
) {
103 connection_callback_
= callback
;
106 void BluetoothProfileWin::Init(const BluetoothUUID
& uuid
,
107 const BluetoothProfile::Options
& options
,
108 const ProfileCallback
& callback
) {
110 name_
= options
.name
;
111 rfcomm_channel_
= options
.channel
;
113 BluetoothAdapterFactory::GetAdapter(
114 base::Bind(&BluetoothProfileWin::OnGetAdapter
,
115 weak_ptr_factory_
.GetWeakPtr(),
119 void BluetoothProfileWin::Connect(
120 const BluetoothDeviceWin
* device
,
121 scoped_refptr
<base::SequencedTaskRunner
> ui_task_runner
,
122 scoped_refptr
<BluetoothSocketThread
> socket_thread
,
123 net::NetLog
* net_log
,
124 const net::NetLog::Source
& source
,
125 const base::Closure
& success_callback
,
126 const ErrorCallback
& error_callback
) {
127 DCHECK(ui_task_runner
->RunsTasksOnCurrentThread());
128 if (connection_callback_
.is_null()) {
129 error_callback
.Run(kNoConnectionCallback
);
133 const BluetoothServiceRecord
* record
= device
->GetServiceRecord(uuid_
);
135 error_callback
.Run(kProfileNotFound
);
139 scoped_refptr
<BluetoothSocketWin
> socket(
140 BluetoothSocketWin::CreateBluetoothSocket(
141 ui_task_runner
, socket_thread
, net_log
, source
));
143 socket
->Connect(*record
,
144 base::Bind(&OnConnectSuccessUI
,
147 connection_callback_
,
148 device
->GetAddress(),
153 void BluetoothProfileWin::OnGetAdapter(
154 const ProfileCallback
& callback
,
155 scoped_refptr
<BluetoothAdapter
> in_adapter
) {
157 DCHECK(!profile_socket_
);
159 adapter_
= in_adapter
;
160 profile_socket_
= BluetoothSocketWin::CreateBluetoothSocket(
161 adapter()->ui_task_runner(),
162 adapter()->socket_thread(),
164 net::NetLog::Source());
165 profile_socket_
->StartService(
169 base::Bind(&BluetoothProfileWin::OnRegisterProfileSuccess
,
170 weak_ptr_factory_
.GetWeakPtr(),
172 base::Bind(&BluetoothProfileWin::OnRegisterProfileError
,
173 weak_ptr_factory_
.GetWeakPtr(),
175 base::Bind(&BluetoothProfileWin::OnNewConnection
,
176 weak_ptr_factory_
.GetWeakPtr()));
179 void BluetoothProfileWin::OnRegisterProfileSuccess(
180 const ProfileCallback
& callback
) {
184 void BluetoothProfileWin::OnRegisterProfileError(
185 const ProfileCallback
& callback
,
186 const std::string
& error_message
) {
191 void BluetoothProfileWin::OnNewConnection(
192 scoped_refptr
<BluetoothSocketWin
> connected
,
193 const net::IPEndPoint
& peer_address
) {
194 DCHECK(adapter()->ui_task_runner()->RunsTasksOnCurrentThread());
195 if (connection_callback_
.is_null())
198 std::string device_address
= IPEndPointToBluetoothAddress(peer_address
);
199 if (device_address
.empty()) {
200 LOG(WARNING
) << "Failed to accept connection for profile "
201 << "uuid=" << uuid_
.value()
202 << ", unexpected peer device address.";
206 BluetoothDevice
* device
= adapter_
->GetDevice(device_address
);
208 LOG(WARNING
) << "Failed to accept connection for profile"
209 << ",uuid=" << uuid_
.value()
210 << ", unknown device=" << device_address
;
214 connection_callback_
.Run(device
, connected
);
217 BluetoothAdapterWin
* BluetoothProfileWin::adapter() const {
219 return static_cast<BluetoothAdapterWin
*>(adapter_
.get());
222 } // namespace device