43d9fb66d6b9cfe15ce7cb85b71a55518500b9f3
[platform/framework/web/crosswalk.git] / src / device / bluetooth / bluetooth_device_mac.mm
1 // Copyright 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_device_mac.h"
6
7 #include <string>
8
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/hash.h"
12 #include "base/mac/sdk_forward_declarations.h"
13 #include "base/sequenced_task_runner.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/sys_string_conversions.h"
17 #include "device/bluetooth/bluetooth_socket_mac.h"
18 #include "device/bluetooth/bluetooth_uuid.h"
19
20 // Undocumented API for accessing the Bluetooth transmit power level.
21 // Similar to the API defined here [ http://goo.gl/20Q5vE ].
22 @interface IOBluetoothHostController (UndocumentedAPI)
23 - (IOReturn)
24     BluetoothHCIReadTransmitPowerLevel:(BluetoothConnectionHandle)connection
25                                 inType:(BluetoothHCITransmitPowerLevelType)type
26                  outTransmitPowerLevel:(BluetoothHCITransmitPowerLevel*)level;
27 @end
28
29 namespace device {
30 namespace {
31
32 // Returns the first (should be, only) UUID contained within the
33 // |service_class_data|. Returns an invalid (empty) UUID if none is found.
34 BluetoothUUID ExtractUuid(IOBluetoothSDPDataElement* service_class_data) {
35   NSArray* inner_elements = [service_class_data getArrayValue];
36   IOBluetoothSDPUUID* sdp_uuid = nil;
37   for (IOBluetoothSDPDataElement* inner_element in inner_elements) {
38     if ([inner_element getTypeDescriptor] == kBluetoothSDPDataElementTypeUUID) {
39       sdp_uuid = [[inner_element getUUIDValue] getUUIDWithLength:16];
40       break;
41     }
42   }
43
44   if (!sdp_uuid)
45     return BluetoothUUID();
46
47   const uint8* uuid_bytes = reinterpret_cast<const uint8*>([sdp_uuid bytes]);
48   std::string uuid_str = base::HexEncode(uuid_bytes, 16);
49   DCHECK_EQ(uuid_str.size(), 32U);
50   uuid_str.insert(8, "-");
51   uuid_str.insert(13, "-");
52   uuid_str.insert(18, "-");
53   uuid_str.insert(23, "-");
54   return BluetoothUUID(uuid_str);
55 }
56
57 }  // namespace
58
59 BluetoothDeviceMac::BluetoothDeviceMac(IOBluetoothDevice* device)
60     : device_([device retain]) {
61 }
62
63 BluetoothDeviceMac::~BluetoothDeviceMac() {
64 }
65
66 void BluetoothDeviceMac::AddObserver(
67     device::BluetoothDevice::Observer* observer) {
68   DCHECK(observer);
69   observers_.AddObserver(observer);
70 }
71
72 void BluetoothDeviceMac::RemoveObserver(
73     device::BluetoothDevice::Observer* observer) {
74   DCHECK(observer);
75   observers_.RemoveObserver(observer);
76 }
77
78 uint32 BluetoothDeviceMac::GetBluetoothClass() const {
79   return [device_ classOfDevice];
80 }
81
82 std::string BluetoothDeviceMac::GetDeviceName() const {
83   return base::SysNSStringToUTF8([device_ name]);
84 }
85
86 std::string BluetoothDeviceMac::GetAddress() const {
87   return GetDeviceAddress(device_);
88 }
89
90 BluetoothDevice::VendorIDSource BluetoothDeviceMac::GetVendorIDSource() const {
91   return VENDOR_ID_UNKNOWN;
92 }
93
94 uint16 BluetoothDeviceMac::GetVendorID() const {
95   return 0;
96 }
97
98 uint16 BluetoothDeviceMac::GetProductID() const {
99   return 0;
100 }
101
102 uint16 BluetoothDeviceMac::GetDeviceID() const {
103   return 0;
104 }
105
106 int BluetoothDeviceMac::GetRSSI() const {
107   if (![device_ isConnected]) {
108     NOTIMPLEMENTED();
109     return kUnknownPower;
110   }
111
112   int rssi = [device_ rawRSSI];
113
114   // The API guarantees that +127 is returned in case the RSSI is not readable:
115   // http://goo.gl/bpURYv
116   if (rssi == 127)
117     return kUnknownPower;
118
119   return rssi;
120 }
121
122 int BluetoothDeviceMac::GetCurrentHostTransmitPower() const {
123   return GetHostTransmitPower(kReadCurrentTransmitPowerLevel);
124 }
125
126 int BluetoothDeviceMac::GetMaximumHostTransmitPower() const {
127   return GetHostTransmitPower(kReadMaximumTransmitPowerLevel);
128 }
129
130 bool BluetoothDeviceMac::IsPaired() const {
131   return [device_ isPaired];
132 }
133
134 bool BluetoothDeviceMac::IsConnected() const {
135   return [device_ isConnected];
136 }
137
138 bool BluetoothDeviceMac::IsConnectable() const {
139   return false;
140 }
141
142 bool BluetoothDeviceMac::IsConnecting() const {
143   return false;
144 }
145
146 BluetoothDevice::UUIDList BluetoothDeviceMac::GetUUIDs() const {
147   UUIDList uuids;
148   for (IOBluetoothSDPServiceRecord* service_record in [device_ services]) {
149     IOBluetoothSDPDataElement* service_class_data =
150         [service_record getAttributeDataElement:
151             kBluetoothSDPAttributeIdentifierServiceClassIDList];
152     if ([service_class_data getTypeDescriptor] ==
153             kBluetoothSDPDataElementTypeDataElementSequence) {
154       BluetoothUUID uuid = ExtractUuid(service_class_data);
155       if (uuid.IsValid())
156         uuids.push_back(uuid);
157     }
158   }
159   return uuids;
160 }
161
162 bool BluetoothDeviceMac::ExpectingPinCode() const {
163   NOTIMPLEMENTED();
164   return false;
165 }
166
167 bool BluetoothDeviceMac::ExpectingPasskey() const {
168   NOTIMPLEMENTED();
169   return false;
170 }
171
172 bool BluetoothDeviceMac::ExpectingConfirmation() const {
173   NOTIMPLEMENTED();
174   return false;
175 }
176
177 void BluetoothDeviceMac::Connect(
178     PairingDelegate* pairing_delegate,
179     const base::Closure& callback,
180     const ConnectErrorCallback& error_callback) {
181   NOTIMPLEMENTED();
182 }
183
184 void BluetoothDeviceMac::SetPinCode(const std::string& pincode) {
185   NOTIMPLEMENTED();
186 }
187
188 void BluetoothDeviceMac::SetPasskey(uint32 passkey) {
189   NOTIMPLEMENTED();
190 }
191
192 void BluetoothDeviceMac::ConfirmPairing() {
193   NOTIMPLEMENTED();
194 }
195
196 void BluetoothDeviceMac::RejectPairing() {
197   NOTIMPLEMENTED();
198 }
199
200 void BluetoothDeviceMac::CancelPairing() {
201   NOTIMPLEMENTED();
202 }
203
204 void BluetoothDeviceMac::Disconnect(const base::Closure& callback,
205                                     const ErrorCallback& error_callback) {
206   NOTIMPLEMENTED();
207 }
208
209 void BluetoothDeviceMac::Forget(const ErrorCallback& error_callback) {
210   NOTIMPLEMENTED();
211 }
212
213 void BluetoothDeviceMac::ConnectToService(
214     const BluetoothUUID& uuid,
215     const ConnectToServiceCallback& callback,
216     const ConnectToServiceErrorCallback& error_callback) {
217   scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket();
218   socket->Connect(
219       device_.get(), uuid, base::Bind(callback, socket), error_callback);
220 }
221
222 void BluetoothDeviceMac::CreateGattConnection(
223       const GattConnectionCallback& callback,
224       const ConnectErrorCallback& error_callback) {
225   // TODO(armansito): Implement.
226   error_callback.Run(ERROR_UNSUPPORTED_DEVICE);
227 }
228
229 void BluetoothDeviceMac::StartConnectionMonitor(
230     const base::Closure& callback,
231     const ErrorCallback& error_callback) {
232   NOTIMPLEMENTED();
233 }
234
235 int BluetoothDeviceMac::GetHostTransmitPower(
236     BluetoothHCITransmitPowerLevelType power_level_type) const {
237   IOBluetoothHostController* controller =
238       [IOBluetoothHostController defaultController];
239
240   // Bail if the undocumented API is unavailable on this machine.
241   SEL selector = @selector(
242       BluetoothHCIReadTransmitPowerLevel:inType:outTransmitPowerLevel:);
243   if (![controller respondsToSelector:selector])
244     return kUnknownPower;
245
246   BluetoothHCITransmitPowerLevel power_level;
247   IOReturn result =
248       [controller BluetoothHCIReadTransmitPowerLevel:[device_ connectionHandle]
249                                               inType:power_level_type
250                                outTransmitPowerLevel:&power_level];
251   if (result != kIOReturnSuccess)
252     return kUnknownPower;
253
254   return power_level;
255 }
256
257 // static
258 std::string BluetoothDeviceMac::GetDeviceAddress(IOBluetoothDevice* device) {
259   return CanonicalizeAddress(base::SysNSStringToUTF8([device addressString]));
260 }
261
262 }  // namespace device