blob: e0ba750f2972e5e347611a5df0d1e6009842d2e1 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#include "base/strings/string_number_conversions.h"
11#include "base/strings/stringprintf.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000012#include "device/bluetooth/bluetooth_init_win.h"
13#include "device/bluetooth/bluetooth_utils.h"
14
15namespace {
16
17const uint16 kProtocolDescriptorListId = 4;
18const uint16 kRfcommUuid = 3;
19const uint16 kUuidId = 1;
20
21bool 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
37void 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
64void ExtractUuid(const SDP_ELEMENT_DATA& uuid_data, std::string* uuid) {
65 HBLUETOOTH_CONTAINER_ELEMENT inner_uuid_element = NULL;
66 SDP_ELEMENT_DATA inner_uuid_data;
67 if (AdvanceToSdpType(uuid_data,
68 SDP_TYPE_UUID,
69 &inner_uuid_element,
70 &inner_uuid_data)) {
71 if (inner_uuid_data.specificType == SDP_ST_UUID16) {
72 std::string uuid_hex =
73 base::StringPrintf("%04x", inner_uuid_data.data.uuid16);
74 *uuid = device::bluetooth_utils::CanonicalUuid(uuid_hex);
75 } else if (inner_uuid_data.specificType == SDP_ST_UUID32) {
76 std::string uuid_hex =
77 base::StringPrintf("%08x", inner_uuid_data.data.uuid32);
78 *uuid = device::bluetooth_utils::CanonicalUuid(uuid_hex);
79 } else if (inner_uuid_data.specificType == SDP_ST_UUID128) {
80 *uuid = base::StringPrintf(
81 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
82 inner_uuid_data.data.uuid128.Data1,
83 inner_uuid_data.data.uuid128.Data2,
84 inner_uuid_data.data.uuid128.Data3,
85 inner_uuid_data.data.uuid128.Data4[0],
86 inner_uuid_data.data.uuid128.Data4[1],
87 inner_uuid_data.data.uuid128.Data4[2],
88 inner_uuid_data.data.uuid128.Data4[3],
89 inner_uuid_data.data.uuid128.Data4[4],
90 inner_uuid_data.data.uuid128.Data4[5],
91 inner_uuid_data.data.uuid128.Data4[6],
92 inner_uuid_data.data.uuid128.Data4[7]);
93 } else {
94 uuid->clear();
95 }
96 }
97}
98
99BTH_ADDR ConvertToBthAddr(const std::string& address) {
100 BTH_ADDR bth_addr = 0;
101 std::string numbers_only;
102 for (int i = 0; i < 6; ++i) {
103 numbers_only += address.substr(i * 3, 2);
104 }
105
106 std::vector<uint8> address_bytes;
107 base::HexStringToBytes(numbers_only, &address_bytes);
108 int byte_position = 0;
109 for (std::vector<uint8>::reverse_iterator iter = address_bytes.rbegin();
110 iter != address_bytes.rend();
111 ++iter) {
112 bth_addr += *iter * pow(256.0, byte_position);
113 byte_position++;
114 }
115 return bth_addr;
116}
117
118} // namespace
119
120namespace device {
121
122BluetoothServiceRecordWin::BluetoothServiceRecordWin(
123 const std::string& name,
124 const std::string& address,
125 uint64 blob_size,
126 uint8* blob_data) : bth_addr_(ConvertToBthAddr(address)) {
127 name_ = name;
128 address_ = address;
129 supports_rfcomm_ = false;
130 SDP_ELEMENT_DATA protocol_descriptor_list_data;
131 if (ERROR_SUCCESS == BluetoothSdpGetAttributeValue(
132 blob_data,
133 blob_size,
134 kProtocolDescriptorListId,
135 &protocol_descriptor_list_data)) {
136 ExtractChannels(protocol_descriptor_list_data,
137 &supports_rfcomm_,
138 &rfcomm_channel_);
139 }
140 SDP_ELEMENT_DATA uuid_data;
141 if (ERROR_SUCCESS == BluetoothSdpGetAttributeValue(
142 blob_data,
143 blob_size,
144 kUuidId,
145 &uuid_data)) {
146 ExtractUuid(uuid_data, &uuid_);
147 }
148}
149
150} // namespace device