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