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 17 BluetoothDevice::BluetoothDevice() { 18 } 19 20 BluetoothDevice::~BluetoothDevice() { 21 STLDeleteValues(&gatt_services_); 22 } 23 24 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 33 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 79 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 158 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 179 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*> 189 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 197 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 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