OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "device/bluetooth/bluetooth_profile_win.h" | |
6 | |
7 #include "base/bind.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" | |
18 | |
19 namespace { | |
20 | |
21 using device::BluetoothAdapter; | |
22 using device::BluetoothDevice; | |
23 using device::BluetoothProfileWin; | |
24 using device::BluetoothSocket; | |
25 using device::BluetoothSocketWin; | |
26 | |
27 const char kNoConnectionCallback[] = "Connection callback not set"; | |
28 const char kProfileNotFound[] = "Profile not found"; | |
29 | |
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); | |
39 if (device) { | |
40 connection_callback.Run(device, socket); | |
41 callback.Run(); | |
42 } | |
43 } | |
44 | |
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, | |
54 ui_task_runner, | |
55 callback, | |
56 connection_callback, | |
57 device_address, | |
58 socket)); | |
59 } | |
60 | |
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); | |
66 } | |
67 | |
68 std::string IPEndPointToBluetoothAddress(const net::IPEndPoint& end_point) { | |
69 if (end_point.address().size() != net::kBluetoothAddressSize) | |
70 return std::string(); | |
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]); | |
81 } | |
82 | |
83 } // namespace | |
84 | |
85 namespace device { | |
86 | |
87 BluetoothProfileWin::BluetoothProfileWin() | |
88 : BluetoothProfile(), rfcomm_channel_(0), weak_ptr_factory_(this) { | |
89 } | |
90 | |
91 BluetoothProfileWin::~BluetoothProfileWin() { | |
92 } | |
93 | |
94 void BluetoothProfileWin::Unregister() { | |
95 if (profile_socket_) | |
96 profile_socket_->Close(); | |
97 | |
98 delete this; | |
99 } | |
100 | |
101 void BluetoothProfileWin::SetConnectionCallback( | |
102 const ConnectionCallback& callback) { | |
103 connection_callback_ = callback; | |
104 } | |
105 | |
106 void BluetoothProfileWin::Init(const BluetoothUUID& uuid, | |
107 const BluetoothProfile::Options& options, | |
108 const ProfileCallback& callback) { | |
109 uuid_ = uuid; | |
110 name_ = options.name; | |
111 rfcomm_channel_ = options.channel; | |
112 | |
113 BluetoothAdapterFactory::GetAdapter( | |
114 base::Bind(&BluetoothProfileWin::OnGetAdapter, | |
115 weak_ptr_factory_.GetWeakPtr(), | |
116 callback)); | |
117 } | |
118 | |
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); | |
130 return; | |
131 } | |
132 | |
133 const BluetoothServiceRecord* record = device->GetServiceRecord(uuid_); | |
134 if (!record) { | |
135 error_callback.Run(kProfileNotFound); | |
136 return; | |
137 } | |
138 | |
139 scoped_refptr<BluetoothSocketWin> socket( | |
140 BluetoothSocketWin::CreateBluetoothSocket( | |
141 ui_task_runner, socket_thread, net_log, source)); | |
142 | |
143 socket->Connect(*record, | |
144 base::Bind(&OnConnectSuccessUI, | |
145 ui_task_runner, | |
146 success_callback, | |
147 connection_callback_, | |
148 device->GetAddress(), | |
149 socket), | |
150 error_callback); | |
151 } | |
152 | |
153 void BluetoothProfileWin::OnGetAdapter( | |
154 const ProfileCallback& callback, | |
155 scoped_refptr<BluetoothAdapter> in_adapter) { | |
156 DCHECK(!adapter_); | |
157 DCHECK(!profile_socket_); | |
158 | |
159 adapter_ = in_adapter; | |
160 profile_socket_ = BluetoothSocketWin::CreateBluetoothSocket( | |
161 adapter()->ui_task_runner(), | |
162 adapter()->socket_thread(), | |
163 NULL, | |
164 net::NetLog::Source()); | |
165 profile_socket_->StartService( | |
166 uuid_, | |
167 name_, | |
168 rfcomm_channel_, | |
169 base::Bind(&BluetoothProfileWin::OnRegisterProfileSuccess, | |
170 weak_ptr_factory_.GetWeakPtr(), | |
171 callback), | |
172 base::Bind(&BluetoothProfileWin::OnRegisterProfileError, | |
173 weak_ptr_factory_.GetWeakPtr(), | |
174 callback), | |
175 base::Bind(&BluetoothProfileWin::OnNewConnection, | |
176 weak_ptr_factory_.GetWeakPtr())); | |
177 } | |
178 | |
179 void BluetoothProfileWin::OnRegisterProfileSuccess( | |
180 const ProfileCallback& callback) { | |
181 callback.Run(this); | |
182 } | |
183 | |
184 void BluetoothProfileWin::OnRegisterProfileError( | |
185 const ProfileCallback& callback, | |
186 const std::string& error_message) { | |
187 callback.Run(NULL); | |
188 delete this; | |
189 } | |
190 | |
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()) | |
196 return; | |
197 | |
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."; | |
203 return; | |
204 } | |
205 | |
206 BluetoothDevice* device = adapter_->GetDevice(device_address); | |
207 if (!device) { | |
208 LOG(WARNING) << "Failed to accept connection for profile" | |
209 << ",uuid=" << uuid_.value() | |
210 << ", unknown device=" << device_address; | |
211 return; | |
212 } | |
213 | |
214 connection_callback_.Run(device, connected); | |
215 } | |
216 | |
217 BluetoothAdapterWin* BluetoothProfileWin::adapter() const { | |
218 DCHECK(adapter_); | |
219 return static_cast<BluetoothAdapterWin*>(adapter_.get()); | |
220 } | |
221 | |
222 } // namespace device | |
OLD | NEW |