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& name,
    125     const std::string& address,
    126     uint64 blob_size,
    127     uint8* blob_data) : bth_addr_(ConvertToBthAddr(address)) {
    128   name_ = name;
    129   address_ = address;
    130   supports_rfcomm_ = false;
    131   SDP_ELEMENT_DATA protocol_descriptor_list_data;
    132   if (ERROR_SUCCESS == BluetoothSdpGetAttributeValue(
    133       blob_data,
    134       blob_size,
    135       kProtocolDescriptorListId,
    136       &protocol_descriptor_list_data)) {
    137     ExtractChannels(protocol_descriptor_list_data,
    138                     &supports_rfcomm_,
    139                     &rfcomm_channel_);
    140   }
    141   SDP_ELEMENT_DATA uuid_data;
    142   if (ERROR_SUCCESS == BluetoothSdpGetAttributeValue(
    143       blob_data,
    144       blob_size,
    145       kUuidId,
    146       &uuid_data)) {
    147     ExtractUuid(uuid_data, &uuid_);
    148   }
    149 }
    150 
    151 }  // namespace device
    152