Linux: Depend on liberation-fonts package for RPMs.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_device.cc
blob34b2260059f1895a515b2dc7d127d89b7f5f1a48
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"
7 #include <string>
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"
19 namespace device {
21 BluetoothDevice::BluetoothDevice(BluetoothAdapter* adapter)
22 : adapter_(adapter), services_data_(new base::DictionaryValue()) {}
24 BluetoothDevice::~BluetoothDevice() {
25 STLDeleteValues(&gatt_services_);
26 DidDisconnectGatt();
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)
36 : rssi(rssi),
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();
44 if (!name.empty()) {
45 return base::UTF8ToUTF16(name);
46 } else {
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) {
55 case DEVICE_COMPUTER:
56 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_COMPUTER,
57 address_utf16);
58 case DEVICE_PHONE:
59 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_PHONE,
60 address_utf16);
61 case DEVICE_MODEM:
62 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_MODEM,
63 address_utf16);
64 case DEVICE_AUDIO:
65 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_AUDIO,
66 address_utf16);
67 case DEVICE_CAR_AUDIO:
68 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_CAR_AUDIO,
69 address_utf16);
70 case DEVICE_VIDEO:
71 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_VIDEO,
72 address_utf16);
73 case DEVICE_JOYSTICK:
74 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_JOYSTICK,
75 address_utf16);
76 case DEVICE_GAMEPAD:
77 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_GAMEPAD,
78 address_utf16);
79 case DEVICE_KEYBOARD:
80 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_KEYBOARD,
81 address_utf16);
82 case DEVICE_MOUSE:
83 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_MOUSE,
84 address_utf16);
85 case DEVICE_TABLET:
86 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_TABLET,
87 address_utf16);
88 case DEVICE_KEYBOARD_MOUSE_COMBO:
89 return l10n_util::GetStringFUTF16(
90 IDS_BLUETOOTH_DEVICE_KEYBOARD_MOUSE_COMBO, address_utf16);
91 default:
92 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_UNKNOWN,
93 address_utf16);
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) {
101 case 0x01:
102 // Computer major device class.
103 return DEVICE_COMPUTER;
104 case 0x02:
105 // Phone major device class.
106 switch ((bluetooth_class & 0xfc) >> 2) {
107 case 0x01:
108 case 0x02:
109 case 0x03:
110 // Cellular, cordless and smart phones.
111 return DEVICE_PHONE;
112 case 0x04:
113 case 0x05:
114 // Modems: wired or voice gateway and common ISDN access.
115 return DEVICE_MODEM;
117 break;
118 case 0x04:
119 // Audio major device class.
120 switch ((bluetooth_class & 0xfc) >> 2) {
121 case 0x08:
122 // Car audio.
123 return DEVICE_CAR_AUDIO;
124 case 0x0b:
125 case 0x0c:
126 case 0x0d:
127 case 0x0e:
128 case 0x0f:
129 case 0x010:
130 // Video devices.
131 return DEVICE_VIDEO;
132 default:
133 return DEVICE_AUDIO;
135 break;
136 case 0x05:
137 // Peripheral major device class.
138 switch ((bluetooth_class & 0xc0) >> 6) {
139 case 0x00:
140 // "Not a keyboard or pointing device."
141 switch ((bluetooth_class & 0x01e) >> 2) {
142 case 0x01:
143 // Joystick.
144 return DEVICE_JOYSTICK;
145 case 0x02:
146 // Gamepad.
147 return DEVICE_GAMEPAD;
148 default:
149 return DEVICE_PERIPHERAL;
151 break;
152 case 0x01:
153 // Keyboard.
154 return DEVICE_KEYBOARD;
155 case 0x02:
156 // Pointing device.
157 switch ((bluetooth_class & 0x01e) >> 2) {
158 case 0x05:
159 // Digitizer tablet.
160 return DEVICE_TABLET;
161 default:
162 // Mouse.
163 return DEVICE_MOUSE;
165 break;
166 case 0x03:
167 // Combo device.
168 return DEVICE_KEYBOARD_MOUSE_COMBO;
170 break;
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")
184 return false;
185 // Microsoft "Microsoft Bluetooth Notebook Mouse 5000", model X807028-001
186 if (type == DEVICE_MOUSE && vendor == "7C:ED:8D")
187 return false;
188 // Sony PlayStation Dualshock3
189 if (IsTrustable())
190 return false;
192 // TODO: Move this database into a config file.
194 return true;
197 bool BluetoothDevice::IsTrustable() const {
198 // Sony PlayStation Dualshock3
199 if ((GetVendorID() == 0x054c && GetProductID() == 0x0268 &&
200 GetDeviceName() == "PLAYSTATION(R)3 Controller"))
201 return true;
203 return false;
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())
213 DidConnectGatt();
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);
224 return services;
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())
231 return iter->second;
232 return NULL;
235 // static
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;
253 if (is_separator) {
254 // All separators in the input |address| should be consistent.
255 if (canonicalized[i] != separator)
256 return std::string();
258 canonicalized[i] = ':';
259 } else {
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))
276 return NULL;
277 return 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);
286 iter.Advance();
288 return uuids;
291 void BluetoothDevice::DidConnectGatt() {
292 for (const auto& callback : create_gatt_connection_success_callbacks_) {
293 callback.Run(
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)
334 DisconnectGatt();
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