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