Home | History | Annotate | Download | only in bluetooth
      1 // Copyright (c) 2013 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_service_record_win.h"
      6 
      7 #include <string>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "device/bluetooth/bluetooth_init_win.h"
     13 #include "device/bluetooth/bluetooth_uuid.h"
     14 
     15 namespace {
     16 
     17 const uint16 kProtocolDescriptorListId = 4;
     18 const uint16 kRfcommUuid = 3;
     19 const uint16 kUuidId = 1;
     20 
     21 bool AdvanceToSdpType(const SDP_ELEMENT_DATA& sequence_data,
     22                       SDP_TYPE type,
     23                       HBLUETOOTH_CONTAINER_ELEMENT* element,
     24                       SDP_ELEMENT_DATA* sdp_data) {
     25   while (ERROR_SUCCESS == BluetoothSdpGetContainerElementData(
     26       sequence_data.data.sequence.value,
     27       sequence_data.data.sequence.length,
     28       element,
     29       sdp_data)) {
     30     if (sdp_data->type == type) {
     31       return true;
     32     }
     33   }
     34   return false;
     35 }
     36 
     37 void ExtractChannels(const SDP_ELEMENT_DATA& protocol_descriptor_list_data,
     38                      bool* supports_rfcomm,
     39                      uint8* rfcomm_channel) {
     40   HBLUETOOTH_CONTAINER_ELEMENT sequence_element = NULL;
     41   SDP_ELEMENT_DATA sequence_data;
     42   while (AdvanceToSdpType(protocol_descriptor_list_data,
     43                           SDP_TYPE_SEQUENCE,
     44                           &sequence_element,
     45                           &sequence_data)) {
     46     HBLUETOOTH_CONTAINER_ELEMENT inner_sequence_element = NULL;
     47     SDP_ELEMENT_DATA inner_sequence_data;
     48     if (AdvanceToSdpType(sequence_data,
     49                          SDP_TYPE_UUID,
     50                          &inner_sequence_element,
     51                          &inner_sequence_data) &&
     52         inner_sequence_data.data.uuid32 == kRfcommUuid &&
     53         AdvanceToSdpType(sequence_data,
     54                          SDP_TYPE_UINT,
     55                          &inner_sequence_element,
     56                          &inner_sequence_data) &&
     57         inner_sequence_data.specificType == SDP_ST_UINT8) {
     58       *rfcomm_channel = inner_sequence_data.data.uint8;
     59       *supports_rfcomm = true;
     60     }
     61   }
     62 }
     63 
     64 void ExtractUuid(const SDP_ELEMENT_DATA& uuid_data,
     65                  device::BluetoothUUID* uuid) {
     66   HBLUETOOTH_CONTAINER_ELEMENT inner_uuid_element = NULL;
     67   SDP_ELEMENT_DATA inner_uuid_data;
     68   if (AdvanceToSdpType(uuid_data,
     69                        SDP_TYPE_UUID,
     70                        &inner_uuid_element,
     71                        &inner_uuid_data)) {
     72     if (inner_uuid_data.specificType == SDP_ST_UUID16) {
     73       std::string uuid_hex =
     74           base::StringPrintf("%04x", inner_uuid_data.data.uuid16);
     75       *uuid = device::BluetoothUUID(uuid_hex);
     76     } else if (inner_uuid_data.specificType == SDP_ST_UUID32) {
     77       std::string uuid_hex =
     78           base::StringPrintf("%08x", inner_uuid_data.data.uuid32);
     79       *uuid = device::BluetoothUUID(uuid_hex);
     80     } else if (inner_uuid_data.specificType == SDP_ST_UUID128) {
     81       *uuid = device::BluetoothUUID(base::StringPrintf(
     82           "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
     83           inner_uuid_data.data.uuid128.Data1,
     84           inner_uuid_data.data.uuid128.Data2,
     85           inner_uuid_data.data.uuid128.Data3,
     86           inner_uuid_data.data.uuid128.Data4[0],
     87           inner_uuid_data.data.uuid128.Data4[1],
     88           inner_uuid_data.data.uuid128.Data4[2],
     89           inner_uuid_data.data.uuid128.Data4[3],
     90           inner_uuid_data.data.uuid128.Data4[4],
     91           inner_uuid_data.data.uuid128.Data4[5],
     92           inner_uuid_data.data.uuid128.Data4[6],
     93           inner_uuid_data.data.uuid128.Data4[7]));
     94     } else {
     95       *uuid = device::BluetoothUUID();
     96     }
     97   }
     98 }
     99 
    100 BTH_ADDR ConvertToBthAddr(const std::string& address) {
    101   BTH_ADDR bth_addr = 0;
    102   std::string numbers_only;
    103   for (int i = 0; i < 6; ++i) {
    104     numbers_only += address.substr(i * 3, 2);
    105   }
    106 
    107   std::vector<uint8> address_bytes;
    108   base::HexStringToBytes(numbers_only, &address_bytes);
    109   int byte_position = 0;
    110   for (std::vector<uint8>::reverse_iterator iter = address_bytes.rbegin();
    111       iter != address_bytes.rend();
    112       ++iter) {
    113     bth_addr += *iter * pow(256.0, byte_position);
    114     byte_position++;
    115   }
    116   return bth_addr;
    117 }
    118 
    119 }  // namespace
    120 
    121 namespace device {
    122 
    123 BluetoothServiceRecordWin::BluetoothServiceRecordWin(
    124     const std::string& device_address,
    125     const std::string& name,
    126     const std::vector<uint8>& sdp_bytes,
    127     const BluetoothUUID& gatt_uuid)
    128     : device_bth_addr_(ConvertToBthAddr(device_address)),
    129       device_address_(device_address),
    130       name_(name),
    131       uuid_(gatt_uuid),
    132       supports_rfcomm_(false),
    133       rfcomm_channel_(0xFF) {
    134   // Bluetooth 2.0
    135   if (sdp_bytes.size() > 0) {
    136     LPBYTE blob_data = const_cast<LPBYTE>(&sdp_bytes[0]);
    137     ULONG blob_size = static_cast<ULONG>(sdp_bytes.size());
    138     SDP_ELEMENT_DATA protocol_descriptor_list_data;
    139     if (ERROR_SUCCESS ==
    140         BluetoothSdpGetAttributeValue(blob_data,
    141                                       blob_size,
    142                                       kProtocolDescriptorListId,
    143                                       &protocol_descriptor_list_data)) {
    144       ExtractChannels(
    145           protocol_descriptor_list_data, &supports_rfcomm_, &rfcomm_channel_);
    146     }
    147     SDP_ELEMENT_DATA uuid_data;
    148     if (ERROR_SUCCESS == BluetoothSdpGetAttributeValue(
    149                              blob_data, blob_size, kUuidId, &uuid_data)) {
    150       ExtractUuid(uuid_data, &uuid_);
    151     }
    152   }
    153 }
    154 
    155 bool BluetoothServiceRecordWin::IsEqual(
    156     const BluetoothServiceRecordWin& other) {
    157   return device_address_ == other.device_address_ && name_ == other.name_ &&
    158          uuid_ == other.uuid_ && supports_rfcomm_ == other.supports_rfcomm_ &&
    159          rfcomm_channel_ == other.rfcomm_channel_;
    160 }
    161 
    162 }  // namespace device
    163