Updated this component to use Bluez 5 API calls. This fixes TIVI-2936
[profile/ivi/wrt-plugins-ivi-bt.git] / src / BluetoothDevice.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include <PlatformException.h>
19 #include <JSUtil.h>
20
21 #include "plugin_config.h"
22 #include "BluetoothDevice.h"
23 #include "BluetoothAdapter.h"
24 #include "JSBluetoothClass.h"
25
26 #include <Logger.h>
27
28 //BLUEZ
29 #define BLUEZ_PREFIX            "org.bluez"
30 #define BLUEZ_SERVICE           BLUEZ_PREFIX
31 #define BLUEZ_ADAPTER_IFACE     BLUEZ_PREFIX ".Adapter1"
32 #define BLUEZ_DEVICE_IFACE      BLUEZ_PREFIX ".Device1"
33 //BLUEZ
34
35 using namespace DeviceAPI::Common;
36
37 namespace DeviceAPI
38 {
39 namespace Bluetooth
40 {
41
42 BluetoothDevice::BluetoothDevice(bt_adapter_device_discovery_info_s *discoveryInfo, char *devicePath)
43 {
44         mName = std::string(discoveryInfo->remote_name);
45         mAddress = std::string(discoveryInfo->remote_address);
46         mDevicePath = devicePath?strdup(devicePath):NULL;
47         mDeviceClass = BluetoothClassSharedPtr(new BluetoothClass(discoveryInfo->bt_class));
48         for(int i = 0; i < discoveryInfo->service_count; i++)
49         {
50                 mUUIDs.push_back(std::string(discoveryInfo->service_uuid[i]));
51         }
52         isUpdated = true;
53 }
54
55 BluetoothDevice::BluetoothDevice(bt_device_info_s *deviceInfo, char *devicePath)
56 {
57         mName = std::string(deviceInfo->remote_name);
58         mAddress = std::string(deviceInfo->remote_address);
59         mDevicePath = devicePath?strdup(devicePath):NULL;
60         mDeviceClass = BluetoothClassSharedPtr(new BluetoothClass(deviceInfo->bt_class));
61         for(int i = 0; i < deviceInfo->service_count; i++)
62         {
63                 mUUIDs.push_back(std::string(deviceInfo->service_uuid[i]));
64         }
65         isUpdated = true;
66 }
67
68 BluetoothDevice::~BluetoothDevice()
69 {
70         BluetoothAdapter::getInstance()->removeConnReq(mAddress);
71         delete mDevicePath;
72 }
73
74 void BluetoothDevice::updateInfo(bt_device_info_s *deviceInfo)
75 {
76         mName = std::string(deviceInfo->remote_name);
77         mUUIDs.clear();
78         for(int i = 0; i < deviceInfo->service_count; i++)
79         {
80                 mUUIDs.push_back(std::string(deviceInfo->service_uuid[i]));
81         }
82         isUpdated = true;
83 }
84
85 std::string BluetoothDevice::getName() const
86 {
87         return mName;
88 }
89
90 std::string BluetoothDevice::getAddress() const
91 {
92         return mAddress;
93 }
94
95 JSValueRef BluetoothDevice::getDeviceClass(JSContextRef context)
96 {
97         return JSBluetoothClass::createJSObject(context, mDeviceClass);
98 }
99
100 gchar* BluetoothDevice::getDefaultAdapter() const
101 {
102         char *result;
103         bool done = false;
104
105         GError * error = nullptr;
106         GDBusProxy * managerProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL,
107                                     "org.bluez",
108                                     "/",
109                                     "org.freedesktop.DBus.ObjectManager",
110                                     nullptr,&error);
111         if(error)
112         {
113                 LoggerE("could not create ObjManager proxy");
114                 // DebugOut(DebugOut::Error)<<"Could not create ObjectManager proxy for Bluez: "<<error->message<<endl;
115                 g_error_free(error);
116                 return "";
117         }
118
119         GVariant * objectMap = g_dbus_proxy_call_sync(managerProxy, "GetManagedObjects",nullptr, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
120
121         if(error)
122         {
123                 LoggerE("failed to get GetManagedObj");
124                 //DebugOut(DebugOut::Error)<<"Failed call to GetManagedObjects: "<<error->message<<endl;
125                 g_object_unref(managerProxy);
126                 g_error_free(error);
127                 return "";
128         }
129
130         GVariantIter* iter;
131         char* objPath;
132         GVariantIter* level2Dict;
133
134         g_variant_get(objectMap, "(a{oa{sa{sv}}})",&iter);
135
136         while(g_variant_iter_next(iter, "{oa{sa{sv}}}",&objPath, &level2Dict))
137         {
138                 char * interfaceName;
139                 GVariantIter* innerDict;
140                 while(g_variant_iter_next(level2Dict, "{sa{sv}}", &interfaceName, &innerDict))
141                 {
142                         if(!strcmp(interfaceName, "org.bluez.Adapter1"))
143                         {
144                                 char* propertyName;
145                                 GVariant* value;
146
147                                 while(done == false && g_variant_iter_next(innerDict,"{sv}", &propertyName, &value))
148                                 {
149                                         if(!strcmp(propertyName, "Address"))
150                                         {
151                                                 char* addr;
152                                                 g_variant_get(value,"s",&addr);
153
154                                                 result = objPath?strdup(objPath):NULL;
155                                                 done = true;
156
157                                                 g_free(addr);
158                                         }
159                                         g_free(propertyName);
160                                         g_variant_unref(value);
161                                 }
162                         }
163                         g_free(interfaceName);
164                         g_variant_iter_free(innerDict);
165                 }
166                 g_free(objPath);
167                 g_variant_iter_free(level2Dict);
168         }
169         g_variant_iter_free(iter);
170
171         return result;
172 }
173
174 char* BluetoothDevice::deviceFromAddress() const
175 {
176         char *result = NULL;
177         bool done = false;
178
179         GError * error = nullptr;
180         GDBusProxy * managerProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL,
181                                     "org.bluez",
182                                     "/",
183                                     "org.freedesktop.DBus.ObjectManager",
184                                     nullptr,&error);
185         if(error)
186         {
187                 LoggerE("could not create ObjManager proxy");
188                 // DebugOut(DebugOut::Error)<<"Could not create ObjectManager proxy for Bluez: "<<error->message<<endl;
189                 g_error_free(error);
190                 return "";
191         }
192
193         GVariant * objectMap = g_dbus_proxy_call_sync(managerProxy, "GetManagedObjects",nullptr, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
194
195         if(error)
196         {
197                 LoggerE("failed to get GetManagedObj");
198                 //DebugOut(DebugOut::Error)<<"Failed call to GetManagedObjects: "<<error->message<<endl;
199                 g_object_unref(managerProxy);
200                 g_error_free(error);
201                 return "";
202         }
203
204         GVariantIter* iter;
205         char* objPath;
206         GVariantIter* level2Dict;
207
208         g_variant_get(objectMap, "(a{oa{sa{sv}}})",&iter);
209
210         while(g_variant_iter_next(iter, "{oa{sa{sv}}}",&objPath, &level2Dict))
211         {
212                 char * interfaceName;
213                 GVariantIter* innerDict;
214                 while(g_variant_iter_next(level2Dict, "{sa{sv}}", &interfaceName, &innerDict))
215                 {
216                         if(!strcmp(interfaceName, "org.bluez.Device1"))
217                         {
218                                 char* propertyName;
219                                 GVariant* value;
220
221                                 while(done == false && g_variant_iter_next(innerDict,"{sv}", &propertyName, &value))
222                                 {
223                                         if(!strcmp(propertyName, "Address"))
224                                         {
225                                                 char* addr;
226                                                 g_variant_get(value,"s",&addr);
227
228                                                 if(addr && std::string(addr) == mAddress)
229                                                 {
230                                                         result = objPath?strdup(objPath):NULL;
231                                                         done = true;
232                                                 }
233
234                                                 g_free(addr);
235                                         }
236                                         g_free(propertyName);
237                                         g_variant_unref(value);
238                                 }
239                         }
240                         g_free(interfaceName);
241                         g_variant_iter_free(innerDict);
242                 }
243                 g_free(objPath);
244                 g_variant_iter_free(level2Dict);
245         }
246         g_variant_iter_free(iter);
247
248         return result;
249 }
250
251
252 char *BluetoothDevice::getDevice() const
253 {
254         if(!strcmp(mAddress.c_str(), ""))
255         {
256                 LoggerE("Invalid address");
257                 return NULL;
258         }
259
260         char *device = deviceFromAddress();
261         char *result = device?strdup(device):NULL;
262         /*
263             char *adapter = getDefaultAdapter();
264             if(!adapter) {
265                 LoggerE("Failed to get default adapter");
266                 return NULL;
267             }
268
269             GError *err = NULL;
270             GVariant *reply = NULL;
271             reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
272                     BLUEZ_SERVICE,
273                     adapter,
274                     BLUEZ_ADAPTER_IFACE,
275                     "FindDevice",
276                     g_variant_new("(s)", mAddress.c_str()),
277                     NULL,
278                     G_DBUS_CALL_FLAGS_NONE,
279                     -1,
280                     NULL,
281                     &err);
282
283             if(err || !reply) {
284                 //LoggerE("Failed to find " << mAddress << " device: " << (err?err->message:"Invalid reply"));
285                 if(err)
286                     g_error_free(err);
287                 free(adapter);
288                 return NULL;
289             }
290
291             char *device = NULL;
292             g_variant_get(reply, "(o)", &device);
293
294             // make a copy of adapter, 'cause it will be destroyed when 'reply' is un-refed
295             char *result = device?strdup(device):NULL;
296
297             g_variant_unref(reply);
298             free(adapter);
299         */
300         return result;
301 }
302
303 bool BluetoothDevice::isBonded() const
304 {
305         char *device = getDevice();
306         if(!device)
307         {
308                 return false;
309         }
310
311         GError *err = NULL;
312         GVariant *reply = NULL;
313         reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
314                                              BLUEZ_SERVICE,
315                                              device,
316                                              "org.freedesktop.DBus.Properties",
317                                              "Get",
318                                              g_variant_new("(ss)", "org.bluez.Device1", "Paired"),
319                                              NULL,
320                                              G_DBUS_CALL_FLAGS_NONE,
321                                              -1,
322                                              NULL,
323                                              &err);
324
325         if(err || !reply)
326         {
327                 if(err)
328                         g_error_free(err);
329                 return false;
330         }
331
332         bool paired = false;
333         GVariant *value;
334         g_variant_get(reply, "(v)", &value);
335         paired = g_variant_get_boolean(value);
336
337         g_variant_unref(reply);
338
339         return paired;
340 }
341
342 bool BluetoothDevice::isTrusted() const
343 {
344         char *device = getDevice();
345         if(!device)
346         {
347                 //LoggerE("Failed to get device object");
348                 return false;
349         }
350
351         GError *err = NULL;
352         GVariant *reply = NULL;
353         reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
354                                              BLUEZ_SERVICE,
355                                              device,
356                                              "org.freedesktop.DBus.Properties",
357                                              "Get",
358                                              g_variant_new("(ss)", "org.bluez.Device1", "Trusted"),
359                                              NULL,
360                                              G_DBUS_CALL_FLAGS_NONE,
361                                              -1,
362                                              NULL,
363                                              &err);
364
365         if(err || !reply)
366         {
367                 if(err)
368                         g_error_free(err);
369                 return false;
370         }
371
372         bool trusted = false;
373         GVariant *value;
374         g_variant_get(reply, "(v)", &value);
375         trusted = g_variant_get_boolean(value);
376
377         g_variant_unref(reply);
378
379         free(device);
380
381         return trusted;
382 }
383
384 bool BluetoothDevice::isConnected() const
385 {
386         char *device = getDevice();
387         if(!device)
388         {
389                 return false;
390         }
391
392         GError *err = NULL;
393         GVariant *reply = NULL;
394         reply = g_dbus_connection_call_sync( g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL),
395                                              BLUEZ_SERVICE,
396                                              device,
397                                              "org.freedesktop.DBus.Properties",
398                                              "Get",
399                                              g_variant_new("(ss)", "org.bluez.Device1", "Connected"),
400                                              NULL,
401                                              G_DBUS_CALL_FLAGS_NONE,
402                                              -1,
403                                              NULL,
404                                              &err);
405
406         if(err || !reply)
407         {
408                 if(err)
409                         g_error_free(err);
410                 return false;
411         }
412
413         bool connected = false;
414         GVariant *value;
415         g_variant_get(reply, "(v)", &value);
416         connected = g_variant_get_boolean(value);
417
418         g_variant_unref(reply);
419         free(device);
420
421         return connected;
422 }
423
424 JSValueRef BluetoothDevice::getUUIDs(JSContextRef context)
425 {
426         return JSUtil::toJSValueRef(context, mUUIDs);
427 }
428
429 } // Bluetooth
430 } // DeviceAPI
431