1 // Copyright (c) 2012 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_device.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "device/bluetooth/bluetooth_adapter.h"
14 #include "device/bluetooth/bluetooth_gatt_connection.h"
15 #include "device/bluetooth/bluetooth_gatt_service.h"
16 #include "grit/bluetooth_strings.h"
17 #include "ui/base/l10n/l10n_util.h"
21 BluetoothDevice::BluetoothDevice(BluetoothAdapter
* adapter
)
22 : adapter_(adapter
), services_data_(new base::DictionaryValue()) {}
24 BluetoothDevice::~BluetoothDevice() {
25 STLDeleteValues(&gatt_services_
);
29 BluetoothDevice::ConnectionInfo::ConnectionInfo()
30 : rssi(kUnknownPower
),
31 transmit_power(kUnknownPower
),
32 max_transmit_power(kUnknownPower
) {}
34 BluetoothDevice::ConnectionInfo::ConnectionInfo(
35 int rssi
, int transmit_power
, int max_transmit_power
)
37 transmit_power(transmit_power
),
38 max_transmit_power(max_transmit_power
) {}
40 BluetoothDevice::ConnectionInfo::~ConnectionInfo() {}
42 base::string16
BluetoothDevice::GetName() const {
43 std::string name
= GetDeviceName();
45 return base::UTF8ToUTF16(name
);
47 return GetAddressWithLocalizedDeviceTypeName();
51 base::string16
BluetoothDevice::GetAddressWithLocalizedDeviceTypeName() const {
52 base::string16 address_utf16
= base::UTF8ToUTF16(GetAddress());
53 BluetoothDevice::DeviceType device_type
= GetDeviceType();
54 switch (device_type
) {
56 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_COMPUTER
,
59 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_PHONE
,
62 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_MODEM
,
65 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_AUDIO
,
67 case DEVICE_CAR_AUDIO
:
68 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_CAR_AUDIO
,
71 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_VIDEO
,
74 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_JOYSTICK
,
77 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_GAMEPAD
,
80 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_KEYBOARD
,
83 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_MOUSE
,
86 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_TABLET
,
88 case DEVICE_KEYBOARD_MOUSE_COMBO
:
89 return l10n_util::GetStringFUTF16(
90 IDS_BLUETOOTH_DEVICE_KEYBOARD_MOUSE_COMBO
, address_utf16
);
92 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_UNKNOWN
,
97 BluetoothDevice::DeviceType
BluetoothDevice::GetDeviceType() const {
98 // https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
99 uint32 bluetooth_class
= GetBluetoothClass();
100 switch ((bluetooth_class
& 0x1f00) >> 8) {
102 // Computer major device class.
103 return DEVICE_COMPUTER
;
105 // Phone major device class.
106 switch ((bluetooth_class
& 0xfc) >> 2) {
110 // Cellular, cordless and smart phones.
114 // Modems: wired or voice gateway and common ISDN access.
119 // Audio major device class.
120 switch ((bluetooth_class
& 0xfc) >> 2) {
123 return DEVICE_CAR_AUDIO
;
137 // Peripheral major device class.
138 switch ((bluetooth_class
& 0xc0) >> 6) {
140 // "Not a keyboard or pointing device."
141 switch ((bluetooth_class
& 0x01e) >> 2) {
144 return DEVICE_JOYSTICK
;
147 return DEVICE_GAMEPAD
;
149 return DEVICE_PERIPHERAL
;
154 return DEVICE_KEYBOARD
;
157 switch ((bluetooth_class
& 0x01e) >> 2) {
160 return DEVICE_TABLET
;
168 return DEVICE_KEYBOARD_MOUSE_COMBO
;
173 return DEVICE_UNKNOWN
;
176 bool BluetoothDevice::IsPairable() const {
177 DeviceType type
= GetDeviceType();
179 // Get the vendor part of the address: "00:11:22" for "00:11:22:33:44:55"
180 std::string vendor
= GetAddress().substr(0, 8);
182 // Verbatim "Bluetooth Mouse", model 96674
183 if (type
== DEVICE_MOUSE
&& vendor
== "00:12:A1")
185 // Microsoft "Microsoft Bluetooth Notebook Mouse 5000", model X807028-001
186 if (type
== DEVICE_MOUSE
&& vendor
== "7C:ED:8D")
188 // Sony PlayStation Dualshock3
192 // TODO: Move this database into a config file.
197 bool BluetoothDevice::IsTrustable() const {
198 // Sony PlayStation Dualshock3
199 if ((GetVendorID() == 0x054c && GetProductID() == 0x0268 &&
200 GetDeviceName() == "PLAYSTATION(R)3 Controller"))
206 void BluetoothDevice::CreateGattConnection(
207 const GattConnectionCallback
& callback
,
208 const ConnectErrorCallback
& error_callback
) {
209 create_gatt_connection_success_callbacks_
.push_back(callback
);
210 create_gatt_connection_error_callbacks_
.push_back(error_callback
);
212 if (IsGattConnected())
215 CreateGattConnectionImpl();
218 std::vector
<BluetoothGattService
*>
219 BluetoothDevice::GetGattServices() const {
220 std::vector
<BluetoothGattService
*> services
;
221 for (GattServiceMap::const_iterator iter
= gatt_services_
.begin();
222 iter
!= gatt_services_
.end(); ++iter
)
223 services
.push_back(iter
->second
);
227 BluetoothGattService
* BluetoothDevice::GetGattService(
228 const std::string
& identifier
) const {
229 GattServiceMap::const_iterator iter
= gatt_services_
.find(identifier
);
230 if (iter
!= gatt_services_
.end())
236 std::string
BluetoothDevice::CanonicalizeAddress(const std::string
& address
) {
237 std::string canonicalized
= address
;
238 if (address
.size() == 12) {
239 // Might be an address in the format "1A2B3C4D5E6F". Add separators.
240 for (size_t i
= 2; i
< canonicalized
.size(); i
+= 3) {
241 canonicalized
.insert(i
, ":");
245 // Verify that the length matches the canonical format "1A:2B:3C:4D:5E:6F".
246 const size_t kCanonicalAddressLength
= 17;
247 if (canonicalized
.size() != kCanonicalAddressLength
)
248 return std::string();
250 const char separator
= canonicalized
[2];
251 for (size_t i
= 0; i
< canonicalized
.size(); ++i
) {
252 bool is_separator
= (i
+ 1) % 3 == 0;
254 // All separators in the input |address| should be consistent.
255 if (canonicalized
[i
] != separator
)
256 return std::string();
258 canonicalized
[i
] = ':';
260 if (!base::IsHexDigit(canonicalized
[i
]))
261 return std::string();
263 canonicalized
[i
] = base::ToUpperASCII(canonicalized
[i
]);
267 return canonicalized
;
270 std::string
BluetoothDevice::GetIdentifier() const { return GetAddress(); }
272 base::BinaryValue
* BluetoothDevice::GetServiceData(
273 BluetoothUUID serviceUUID
) const {
274 base::BinaryValue
* value
;
275 if (!services_data_
->GetBinary(serviceUUID
.value(), &value
))
280 BluetoothDevice::UUIDList
BluetoothDevice::GetServiceDataUUIDs() const {
281 std::vector
<device::BluetoothUUID
> uuids
;
282 base::DictionaryValue::Iterator
iter(*services_data_
);
283 while (!iter
.IsAtEnd()) {
284 BluetoothUUID
uuid(iter
.key());
285 uuids
.push_back(uuid
);
291 void BluetoothDevice::DidConnectGatt() {
292 for (const auto& callback
: create_gatt_connection_success_callbacks_
) {
294 make_scoped_ptr(new BluetoothGattConnection(adapter_
, GetAddress())));
296 create_gatt_connection_success_callbacks_
.clear();
297 create_gatt_connection_error_callbacks_
.clear();
300 void BluetoothDevice::DidFailToConnectGatt(ConnectErrorCode error
) {
301 for (const auto& error_callback
: create_gatt_connection_error_callbacks_
)
302 error_callback
.Run(error
);
303 create_gatt_connection_success_callbacks_
.clear();
304 create_gatt_connection_error_callbacks_
.clear();
307 void BluetoothDevice::DidDisconnectGatt() {
308 // Pending calls to connect GATT are not expected, if they were then
309 // DidFailToConnectGatt should be called. But in case callbacks exist
310 // flush them to ensure a consistent state.
311 if (create_gatt_connection_error_callbacks_
.size() > 0) {
312 VLOG(1) << "Unexpected / unexplained DidDisconnectGatt call while "
313 "create_gatt_connection_error_callbacks_ are pending.";
315 DidFailToConnectGatt(ERROR_FAILED
);
317 // Invalidate all BluetoothGattConnection objects.
318 for (BluetoothGattConnection
* connection
: gatt_connections_
) {
319 connection
->InvalidateConnectionReference();
321 gatt_connections_
.clear();
324 void BluetoothDevice::AddGattConnection(BluetoothGattConnection
* connection
) {
325 auto result
= gatt_connections_
.insert(connection
);
326 DCHECK(result
.second
); // Check insert happened; there was no duplicate.
329 void BluetoothDevice::RemoveGattConnection(
330 BluetoothGattConnection
* connection
) {
331 size_t erased_count
= gatt_connections_
.erase(connection
);
332 DCHECK(erased_count
);
333 if (gatt_connections_
.size() == 0)
337 void BluetoothDevice::ClearServiceData() { services_data_
->Clear(); }
339 void BluetoothDevice::SetServiceData(BluetoothUUID serviceUUID
,
340 const char* buffer
, size_t size
) {
341 services_data_
->Set(serviceUUID
.value(),
342 base::BinaryValue::CreateWithCopiedBuffer(buffer
, size
));
345 } // namespace device