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.
4
5 #include "device/bluetooth/bluetooth_device.h"
6
7 #include <string>
8
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "device/bluetooth/bluetooth_gatt_service.h"
12 #include "grit/device_bluetooth_strings.h"
13 #include "ui/base/l10n/l10n_util.h"
14
15 namespace device {
16
BluetoothDevice()17 BluetoothDevice::BluetoothDevice() {
18 }
19
~BluetoothDevice()20 BluetoothDevice::~BluetoothDevice() {
21 STLDeleteValues(&gatt_services_);
22 }
23
GetName() const24 base::string16 BluetoothDevice::GetName() const {
25 std::string name = GetDeviceName();
26 if (!name.empty()) {
27 return base::UTF8ToUTF16(name);
28 } else {
29 return GetAddressWithLocalizedDeviceTypeName();
30 }
31 }
32
GetAddressWithLocalizedDeviceTypeName() const33 base::string16 BluetoothDevice::GetAddressWithLocalizedDeviceTypeName() const {
34 base::string16 address_utf16 = base::UTF8ToUTF16(GetAddress());
35 BluetoothDevice::DeviceType device_type = GetDeviceType();
36 switch (device_type) {
37 case DEVICE_COMPUTER:
38 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_COMPUTER,
39 address_utf16);
40 case DEVICE_PHONE:
41 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_PHONE,
42 address_utf16);
43 case DEVICE_MODEM:
44 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_MODEM,
45 address_utf16);
46 case DEVICE_AUDIO:
47 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_AUDIO,
48 address_utf16);
49 case DEVICE_CAR_AUDIO:
50 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_CAR_AUDIO,
51 address_utf16);
52 case DEVICE_VIDEO:
53 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_VIDEO,
54 address_utf16);
55 case DEVICE_JOYSTICK:
56 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_JOYSTICK,
57 address_utf16);
58 case DEVICE_GAMEPAD:
59 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_GAMEPAD,
60 address_utf16);
61 case DEVICE_KEYBOARD:
62 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_KEYBOARD,
63 address_utf16);
64 case DEVICE_MOUSE:
65 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_MOUSE,
66 address_utf16);
67 case DEVICE_TABLET:
68 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_TABLET,
69 address_utf16);
70 case DEVICE_KEYBOARD_MOUSE_COMBO:
71 return l10n_util::GetStringFUTF16(
72 IDS_BLUETOOTH_DEVICE_KEYBOARD_MOUSE_COMBO, address_utf16);
73 default:
74 return l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_UNKNOWN,
75 address_utf16);
76 }
77 }
78
GetDeviceType() const79 BluetoothDevice::DeviceType BluetoothDevice::GetDeviceType() const {
80 // https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
81 uint32 bluetooth_class = GetBluetoothClass();
82 switch ((bluetooth_class & 0x1f00) >> 8) {
83 case 0x01:
84 // Computer major device class.
85 return DEVICE_COMPUTER;
86 case 0x02:
87 // Phone major device class.
88 switch ((bluetooth_class & 0xfc) >> 2) {
89 case 0x01:
90 case 0x02:
91 case 0x03:
92 // Cellular, cordless and smart phones.
93 return DEVICE_PHONE;
94 case 0x04:
95 case 0x05:
96 // Modems: wired or voice gateway and common ISDN access.
97 return DEVICE_MODEM;
98 }
99 break;
100 case 0x04:
101 // Audio major device class.
102 switch ((bluetooth_class & 0xfc) >> 2) {
103 case 0x08:
104 // Car audio.
105 return DEVICE_CAR_AUDIO;
106 case 0x0b:
107 case 0x0c:
108 case 0x0d:
109 case 0x0e:
110 case 0x0f:
111 case 0x010:
112 // Video devices.
113 return DEVICE_VIDEO;
114 default:
115 return DEVICE_AUDIO;
116 }
117 break;
118 case 0x05:
119 // Peripheral major device class.
120 switch ((bluetooth_class & 0xc0) >> 6) {
121 case 0x00:
122 // "Not a keyboard or pointing device."
123 switch ((bluetooth_class & 0x01e) >> 2) {
124 case 0x01:
125 // Joystick.
126 return DEVICE_JOYSTICK;
127 case 0x02:
128 // Gamepad.
129 return DEVICE_GAMEPAD;
130 default:
131 return DEVICE_PERIPHERAL;
132 }
133 break;
134 case 0x01:
135 // Keyboard.
136 return DEVICE_KEYBOARD;
137 case 0x02:
138 // Pointing device.
139 switch ((bluetooth_class & 0x01e) >> 2) {
140 case 0x05:
141 // Digitizer tablet.
142 return DEVICE_TABLET;
143 default:
144 // Mouse.
145 return DEVICE_MOUSE;
146 }
147 break;
148 case 0x03:
149 // Combo device.
150 return DEVICE_KEYBOARD_MOUSE_COMBO;
151 }
152 break;
153 }
154
155 return DEVICE_UNKNOWN;
156 }
157
IsPairable() const158 bool BluetoothDevice::IsPairable() const {
159 DeviceType type = GetDeviceType();
160
161 // Get the vendor part of the address: "00:11:22" for "00:11:22:33:44:55"
162 std::string vendor = GetAddress().substr(0, 8);
163
164 // Verbatim "Bluetooth Mouse", model 96674
165 if (type == DEVICE_MOUSE && vendor == "00:12:A1")
166 return false;
167 // Microsoft "Microsoft Bluetooth Notebook Mouse 5000", model X807028-001
168 if (type == DEVICE_MOUSE && vendor == "7C:ED:8D")
169 return false;
170 // Sony PlayStation Dualshock3
171 if (IsTrustable())
172 return false;
173
174 // TODO: Move this database into a config file.
175
176 return true;
177 }
178
IsTrustable() const179 bool BluetoothDevice::IsTrustable() const {
180 // Sony PlayStation Dualshock3
181 if ((GetVendorID() == 0x054c && GetProductID() == 0x0268 &&
182 GetDeviceName() == "PLAYSTATION(R)3 Controller"))
183 return true;
184
185 return false;
186 }
187
188 std::vector<BluetoothGattService*>
GetGattServices() const189 BluetoothDevice::GetGattServices() const {
190 std::vector<BluetoothGattService*> services;
191 for (GattServiceMap::const_iterator iter = gatt_services_.begin();
192 iter != gatt_services_.end(); ++iter)
193 services.push_back(iter->second);
194 return services;
195 }
196
GetGattService(const std::string & identifier) const197 BluetoothGattService* BluetoothDevice::GetGattService(
198 const std::string& identifier) const {
199 GattServiceMap::const_iterator iter = gatt_services_.find(identifier);
200 if (iter != gatt_services_.end())
201 return iter->second;
202 return NULL;
203 }
204
205 // static
CanonicalizeAddress(const std::string & address)206 std::string BluetoothDevice::CanonicalizeAddress(const std::string& address) {
207 std::string canonicalized = address;
208 if (address.size() == 12) {
209 // Might be an address in the format "1A2B3C4D5E6F". Add separators.
210 for (size_t i = 2; i < canonicalized.size(); i += 3) {
211 canonicalized.insert(i, ":");
212 }
213 }
214
215 // Verify that the length matches the canonical format "1A:2B:3C:4D:5E:6F".
216 const size_t kCanonicalAddressLength = 17;
217 if (canonicalized.size() != kCanonicalAddressLength)
218 return std::string();
219
220 const char separator = canonicalized[2];
221 for (size_t i = 0; i < canonicalized.size(); ++i) {
222 bool is_separator = (i + 1) % 3 == 0;
223 if (is_separator) {
224 // All separators in the input |address| should be consistent.
225 if (canonicalized[i] != separator)
226 return std::string();
227
228 canonicalized[i] = ':';
229 } else {
230 if (!IsHexDigit(canonicalized[i]))
231 return std::string();
232
233 canonicalized[i] = base::ToUpperASCII(canonicalized[i]);
234 }
235 }
236
237 return canonicalized;
238 }
239
240 } // namespace device
241