• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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