Home | History | Annotate | Download | only in bluetooth
      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