Integrate neard post 0.6 changes - handover code
[profile/ivi/neard.git] / src / bluetooth.c
1 /*
2  *
3  *  neard - Near Field Communication manager
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <gdbus.h>
31
32 #include "near.h"
33
34 #define BLUEZ_SERVICE                   "org.bluez"
35 #define MANAGER_INTF                    BLUEZ_SERVICE ".Manager"
36 #define ADAPTER_INTF                    BLUEZ_SERVICE ".Adapter"
37 #define OOB_INTF                        BLUEZ_SERVICE ".OutOfBand"
38 #define DEFAULT_ADAPTER                 "DefaultAdapter"
39 #define ADAPTER_REMOVED                 "AdapterRemoved"
40 #define DEFAULT_ADAPTER_CHANGED         "DefaultAdapterChanged"
41 #define MANAGER_PATH                    "/"
42 #define OOB_AGENT                       "/org/neard/agent/neard_oob"
43
44 #define BT_NOINPUTOUTPUT                "NoInputNoOutput"
45 #define BT_DISPLAY_YESNO                "DisplayYesNo"
46
47 /* BT EIR list */
48 #define EIR_UUID128_ALL         0x07 /* 128-bit UUID, all listed */
49 #define EIR_NAME_SHORT          0x08 /* shortened local name */
50 #define EIR_NAME_COMPLETE       0x09 /* complete local name */
51
52 /* Specific OOB EIRs */
53 #define EIR_CLASS_OF_DEVICE     0x0D  /* class of device */
54 #define EIR_SP_HASH             0x0E  /* simple pairing hash C */
55 #define EIR_SP_RANDOMIZER       0x0F  /* simple pairing randomizer R */
56 /* Optional EIRs */
57 #define EIR_DEVICE_ID           0x10  /* device ID */
58 #define EIR_SECURITY_MGR_FLAGS  0x11  /* security manager flags */
59
60 #define EIR_SIZE_LEN            1
61 #define EIR_HEADER_LEN          (EIR_SIZE_LEN + 1)
62 #define BT_ADDRESS_SIZE         6
63 #define COD_SIZE                3
64 #define OOB_SP_SIZE             16
65
66 #define get_unaligned(ptr)                      \
67 ({                                              \
68         struct __attribute__((packed)) {        \
69                 typeof(*(ptr)) __v;             \
70         } *__p = (typeof(__p)) (ptr);           \
71         __p->__v;                               \
72 })
73
74 struct near_oob_data {
75         char *def_adapter;
76
77         char *bd_addr;          /* oob mandatory */
78
79         /* optional */
80         char *bt_name;                  /* short or long name */
81         uint8_t bt_name_len;
82         int class_of_device;            /* Class of device */
83         near_bool_t powered;
84         near_bool_t pairable;
85         near_bool_t discoverable;
86         uint8_t *uuids;
87         int uuids_len;
88
89         uint8_t *spair_hash;                    /* OOB hash Key */
90         uint8_t *spair_randomizer;              /* OOB randomizer key */
91         uint8_t authentication[OOB_SP_SIZE];    /* On BT 2.0 */
92         uint8_t security_manager_oob_flags;     /* see BT Core 4.0 */
93 };
94
95 static DBusConnection *bt_conn;
96 static struct near_oob_data bt_def_oob_data;
97
98 static int bt_do_pairing(struct near_oob_data *oob);
99
100 static void __bt_eir_free(struct near_oob_data *oob)
101 {
102         DBG("");
103
104         if (oob->def_adapter != NULL) {
105                 g_free(oob->def_adapter);
106                 oob->def_adapter = NULL;
107         }
108
109         if (oob->bd_addr != NULL) {
110                 g_free(oob->bd_addr);
111                 oob->bd_addr = NULL;
112         }
113
114         if (oob->bt_name != NULL) {
115                 g_free(oob->bt_name);
116                 oob->bt_name = NULL;
117         }
118
119         if (oob->spair_hash != NULL) {
120                 g_free(oob->spair_hash);
121                 oob->spair_hash = NULL;
122         }
123
124         if (oob->spair_randomizer != NULL) {
125                 g_free(oob->spair_randomizer);
126                 oob->spair_randomizer = NULL;
127         }
128
129
130 }
131
132 static void bt_eir_free(struct near_oob_data *oob)
133 {
134         __bt_eir_free(oob);
135
136         g_free(oob);
137 }
138
139 /* D-Bus helper functions */
140 static int bt_generic_call(DBusConnection *conn,
141                 struct near_oob_data *oob,              /* user data */
142                 const char *dest,                       /* method call */
143                 const char *path,
144                 const char *interface,
145                 const char *method,
146                 DBusPendingCallNotifyFunction bt_cb,    /* callback */
147                 int type, ...)                          /* params */
148 {
149         DBusMessage *msg;
150         DBusPendingCall *pending;
151         va_list args;
152         int err;
153
154         DBG("%s", method);
155
156         msg = dbus_message_new_method_call(dest, path, interface, method);
157
158         if (msg == NULL) {
159                 near_error("Unable to allocate new D-Bus %s message", method);
160                 err = -ENOMEM;
161         }
162
163         va_start(args, type);
164
165         if (!dbus_message_append_args_valist(msg, type, args)) {
166                 va_end(args);
167                 err = -EIO;
168                 goto error_done;
169         }
170         va_end(args);
171
172         if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
173                 near_error("Sending %s failed", method);
174                 err = -EIO;
175                 goto error_done;
176         }
177
178         if (pending == NULL) {
179                 near_error("D-Bus connection not available");
180                 err = -EIO;
181                 goto error_done;
182         }
183
184         /* Prepare for notification */
185         dbus_pending_call_set_notify(pending, bt_cb, oob, NULL);
186         err = 0 ;
187
188 error_done:
189         dbus_message_unref(msg);
190         return err;
191 }
192
193 static void bt_create_paired_device_cb(DBusPendingCall *pending,
194                                         void *user_data)
195 {
196         DBusMessage *reply;
197         DBusError   error;
198         struct near_oob_data *oob = user_data;
199
200         DBG("");
201
202         reply = dbus_pending_call_steal_reply(pending);
203         if (reply == NULL)
204                 return;
205
206         dbus_error_init(&error);
207
208         if (dbus_set_error_from_message(&error, reply)) {
209                 near_error("%s", error.message);
210                 dbus_error_free(&error);
211                 goto cb_done;
212         }
213
214         near_info("Pairing done successfully !");
215
216 cb_done:
217         /* task completed - clean memory*/
218         bt_eir_free(oob);
219
220         dbus_message_unref(reply);
221         dbus_pending_call_unref(pending);
222
223         return;
224 }
225
226 static int bt_create_paired_device(DBusConnection *conn,
227                                 struct near_oob_data *oob,
228                                 const char *capabilities)
229 {
230         const char *agent_path = OOB_AGENT;
231
232         return bt_generic_call(bt_conn, oob, BLUEZ_SERVICE,
233                         oob->def_adapter, ADAPTER_INTF, "CreatePairedDevice",
234                         bt_create_paired_device_cb,
235                         /* params */
236                         DBUS_TYPE_STRING, &oob->bd_addr,
237                         DBUS_TYPE_OBJECT_PATH, &agent_path,
238                         DBUS_TYPE_STRING, &capabilities,
239                         DBUS_TYPE_INVALID);
240
241 }
242
243 static void bt_oob_add_remote_data_cb(DBusPendingCall *pending, void *user_data)
244 {
245         DBusMessage *reply;
246         DBusError   error;
247         struct near_oob_data *oob = user_data;
248
249         DBG("");
250
251         reply = dbus_pending_call_steal_reply(pending);
252         if (reply == NULL)
253                 return;
254
255         dbus_error_init(&error);
256
257         if (dbus_set_error_from_message(&error, reply))
258                 goto cb_fail;
259
260         near_info("OOB data added");
261
262         dbus_message_unref(reply);
263         dbus_pending_call_unref(pending);
264
265         /* Jump to the next: Pairing !!!*/
266         DBG("Try to pair devices...");
267         bt_create_paired_device(bt_conn, oob, BT_DISPLAY_YESNO);
268         return;
269
270 cb_fail:
271         near_error("%s", error.message);
272         dbus_error_free(&error);
273
274         bt_eir_free(oob);
275
276         dbus_message_unref(reply);
277         dbus_pending_call_unref(pending);
278
279         return;
280 }
281
282 static int bt_oob_add_remote_data(DBusConnection *conn,
283                                 struct near_oob_data *oob)
284 {
285         int16_t hash_len = 16;
286         int16_t rdm_len = 16;
287
288         return bt_generic_call(bt_conn, oob, BLUEZ_SERVICE,
289                         oob->def_adapter, OOB_INTF, "AddRemoteData",
290                         bt_oob_add_remote_data_cb,
291                         /* params */
292                         DBUS_TYPE_STRING, &oob->bd_addr,
293                         DBUS_TYPE_ARRAY,
294                                 DBUS_TYPE_BYTE, &oob->spair_hash, hash_len,
295                         DBUS_TYPE_ARRAY,
296                                 DBUS_TYPE_BYTE, &oob->spair_randomizer, rdm_len,
297                         DBUS_TYPE_INVALID);
298 }
299
300 /* Pairing: JustWorks or OOB  */
301 static int bt_do_pairing(struct near_oob_data *oob)
302 {
303         int err = 0;
304
305         DBG("%s", oob->bd_addr);
306
307         /* Is this a *real* oob pairing or a "JustWork" */
308         if ((oob->spair_hash) && (oob->spair_randomizer))
309                 err = bt_oob_add_remote_data(bt_conn, oob);
310         else
311                 err = bt_create_paired_device(bt_conn, oob,
312                                 BT_NOINPUTOUTPUT);
313
314         if (err < 0)
315                 near_error("Pairing failed. Err[%d]", err);
316
317         return err;
318 }
319
320 /*
321  */
322 static int extract_properties(DBusMessage *reply,
323                 struct near_oob_data *oob)
324 {
325         char *data = NULL;
326         int idata;
327         int i, j;
328
329         DBusMessageIter array, dict;
330
331         if (dbus_message_iter_init(reply, &array) == FALSE)
332                 return -1;
333
334         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
335                 return -1;
336
337         dbus_message_iter_recurse(&array, &dict);
338
339         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
340                 DBusMessageIter entry, value;
341                 const char *key;
342
343                 dbus_message_iter_recurse(&dict, &entry);
344                 dbus_message_iter_get_basic(&entry, &key);
345
346                 dbus_message_iter_next(&entry);
347                 dbus_message_iter_recurse(&entry, &value);
348
349                 if (g_str_equal(key, "Address") == TRUE) {
350                         dbus_message_iter_get_basic(&value, &data);
351
352                         /* Now, fill the local struct */
353                         oob->bd_addr = g_try_malloc0(BT_ADDRESS_SIZE);
354                         if (oob->bd_addr == NULL)
355                                 return -ENOMEM;
356
357                         /* Address is like: "ff:ee:dd:cc:bb:aa" */
358                         for (i = 5, j = 0 ; i >= 0; i--, j += 3)
359                                 oob->bd_addr[i] = strtol(data + j, NULL, 16);
360                         DBG("local address: %s", data);
361
362                 } else if (g_str_equal(key, "Name") == TRUE) {
363                         dbus_message_iter_get_basic(&value, &data);
364                         oob->bt_name = g_strdup(data);
365                         if (oob->bt_name != NULL) {
366                                 oob->bt_name_len = strlen(oob->bt_name);
367                                 DBG("local name: %s", oob->bt_name);
368                         }
369
370                 } else if (g_str_equal(key, "Class") == TRUE) {
371                         dbus_message_iter_get_basic(&value, &idata);
372                         oob->class_of_device = idata;
373
374                 } else if (g_str_equal(key, "Powered") == TRUE) {
375                         dbus_message_iter_get_basic(&value, &idata);
376                         oob->powered = idata;
377
378                 } else if (g_str_equal(key, "Discoverable") == TRUE) {
379                         dbus_message_iter_get_basic(&value, &idata);
380                         oob->discoverable = idata;
381
382                 } else if (g_str_equal(key, "Pairable") == TRUE) {
383                         dbus_message_iter_get_basic(&value, &idata);
384                         oob->pairable = idata;
385
386                 } else if (g_str_equal(key, "UUIDs") == TRUE) {
387                         oob->uuids_len = sizeof(value);
388                         oob->uuids = g_try_malloc0(oob->uuids_len);
389                         if (oob->uuids == NULL)
390                                 return -ENOMEM;
391                         memcpy(oob->uuids, &value, oob->uuids_len);
392                 }
393
394                 dbus_message_iter_next(&dict);
395         }
396
397         return 0;
398 }
399
400 static int bt_parse_properties(DBusMessage *reply, void *user_data)
401 {
402         struct near_oob_data *bt_props = user_data;
403
404         DBG("");
405
406         /* Free datas */
407         g_free(bt_props->bd_addr);
408         g_free(bt_props->bt_name);
409
410         /* Grab properties from dbus */
411         if (extract_properties(reply, bt_props) < 0)
412                 goto fail;
413
414         return 0;
415
416 fail:
417         g_free(bt_props->bd_addr);
418         bt_props->bd_addr = NULL;
419
420         g_free(bt_props->bt_name);
421         bt_props->bt_name = NULL;
422
423         return -ENOMEM;
424 }
425
426
427 /* Get default local adapter properties */
428 static void bt_get_properties_cb(DBusPendingCall *pending, void *user_data)
429 {
430         struct near_oob_data *bt_props = user_data;
431         DBusMessage *reply;
432         DBusError   error;
433         int err;
434
435         DBG("");
436
437         reply = dbus_pending_call_steal_reply(pending);
438         if (reply == NULL)
439                 return;
440
441         dbus_error_init(&error);
442
443         if (dbus_set_error_from_message(&error, reply))
444                 goto cb_fail;
445
446         err = bt_parse_properties(reply, bt_props);
447         if (err < 0)
448                 near_error("Problem parsing local properties %d", err);
449         else
450                 DBG("Get Properties complete: %s", bt_props->def_adapter);
451
452         /* clean */
453         dbus_message_unref(reply);
454         dbus_pending_call_unref(pending);
455         return;
456
457 cb_fail:
458         near_error("%s", error.message);
459         dbus_error_free(&error);
460
461         dbus_message_unref(reply);
462         dbus_pending_call_unref(pending);
463
464         return;
465 }
466
467 static void bt_get_default_adapter_cb(DBusPendingCall *pending, void *user_data)
468 {
469         struct near_oob_data *bt_props = user_data;
470         DBusMessage *reply;
471         DBusError   error;
472         gchar *path;
473
474         DBG("");
475
476         reply = dbus_pending_call_steal_reply(pending);
477         if (reply == NULL)
478                 return;
479
480         dbus_error_init(&error);
481
482         if (dbus_set_error_from_message(&error, reply))
483                 goto cb_fail;
484
485         if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH,
486                                         &path, DBUS_TYPE_INVALID) == FALSE)
487                 goto cb_fail;
488
489         /* Save the default adapter */
490         bt_props->def_adapter = g_strdup(path);
491         DBG("Using default adapter %s", bt_props->def_adapter);
492
493         /* clean */
494         dbus_message_unref(reply);
495         dbus_pending_call_unref(pending);
496
497         /* Jump on getAdapterProperties */
498         bt_generic_call(bt_conn, bt_props,
499                         BLUEZ_SERVICE,
500                         bt_props->def_adapter,
501                         ADAPTER_INTF, "GetProperties",
502                         bt_get_properties_cb,
503                         DBUS_TYPE_INVALID);
504         return;
505
506 cb_fail:
507         near_error("%s", error.message);
508         dbus_error_free(&error);
509
510         dbus_message_unref(reply);
511         dbus_pending_call_unref(pending);
512
513         return;
514 }
515
516 static int bt_refresh_adapter_props(DBusConnection *conn, void *user_data)
517 {
518         DBG("%p %p", conn, user_data);
519
520         return bt_generic_call(conn, user_data,
521                         BLUEZ_SERVICE,
522                         MANAGER_PATH, MANAGER_INTF,
523                         DEFAULT_ADAPTER,
524                         bt_get_default_adapter_cb,
525                         DBUS_TYPE_INVALID);
526 }
527
528 /* Parse and fill the bluetooth oob information block */
529 static void bt_parse_eir(uint8_t *eir_data, uint16_t eir_data_len,
530                                                 struct near_oob_data *oob)
531 {
532         char *tmp;
533         uint16_t len = 0;
534
535         DBG("total len: %u", eir_data_len);
536
537         while (len < eir_data_len - 1) {
538                 uint8_t eir_len = eir_data[0];  /* EIR field length */
539                 uint8_t eir_code;               /* EIR field type*/
540                 uint8_t data_len;               /* EIR data length */
541                 uint8_t *data;
542
543                 /* check for early termination */
544                 if (eir_len == 0)
545                         break;
546
547                 len += eir_len + 1;
548
549                 /* Do not continue EIR Data parsing if got incorrect length */
550                 if (len > eir_data_len)
551                         break;
552
553                 data_len = eir_len - 1;
554
555                 eir_code = eir_data[1]; /* EIR code */
556                 data = &eir_data[2];
557
558                 DBG("type 0x%.2X data_len %u", eir_code, data_len);
559
560                 switch (eir_code) {
561                 case EIR_NAME_SHORT:
562                 case EIR_NAME_COMPLETE:
563                         oob->bt_name = g_try_malloc0(data_len + 1); /* eos */
564                         if (oob->bt_name) {
565                                 oob->bt_name_len = data_len;
566                                 memcpy(oob->bt_name, data, oob->bt_name_len);
567                                 oob->bt_name[data_len] = 0;     /* end str*/
568                         }
569                         break;
570
571                 case EIR_CLASS_OF_DEVICE:
572                         tmp = g_strdup_printf("%02X%02X%02X",
573                                         *data, *(data + 1), *(data + 2));
574                         if (tmp != NULL)
575                                 oob->class_of_device = strtol(tmp, NULL, 16);
576                         g_free(tmp);
577                         break;
578
579                 case EIR_SP_HASH:
580                         oob->spair_hash = g_try_malloc0(OOB_SP_SIZE);
581                         if (oob->spair_hash)
582                                 memcpy(oob->spair_hash, data, OOB_SP_SIZE);
583                         break;
584
585                 case EIR_SP_RANDOMIZER:
586                         oob->spair_randomizer = g_try_malloc0(OOB_SP_SIZE);
587                         if (oob->spair_randomizer)
588                                 memcpy(oob->spair_randomizer,
589                                                 data, OOB_SP_SIZE);
590                         break;
591
592                 case EIR_SECURITY_MGR_FLAGS:
593                         oob->security_manager_oob_flags = *data;
594                         break;
595
596                 case EIR_UUID128_ALL:
597                         /* TODO: Process uuids128
598                          * */
599                         break;
600
601                 default:        /* ignore and skip */
602                         near_error("Unknown EIR x%02x (len: %d)", eir_code,
603                                                                 eir_len);
604                         break;
605                 }
606                 /* Next eir */
607                 eir_data += eir_len + 1;
608         }
609 }
610
611 /*
612  * Because of some "old" implementation, "version" will help
613  * to determine the record data structure.
614  * Some specifications are proprietary (eg. "short mode")
615  * and are not fully documented.
616  */
617 int __near_bluetooth_parse_oob_record(uint8_t version, uint8_t *bt_data,
618                 near_bool_t pair)
619 {
620         struct near_oob_data *oob;
621         uint16_t bt_oob_data_size;
622         uint8_t *ptr = bt_data;
623         uint8_t marker;
624         char *tmp;
625
626         DBG("");
627
628         oob = g_try_malloc0(sizeof(struct near_oob_data));
629
630         if (version == BT_MIME_V2_1) {
631                 /*
632                  * Total OOB data size (including size bytes)
633                  * Some implementations (e.g. Android 4.1) stores
634                  * the data_size in big endian but NDEF forum spec (BT Secure
635                  * Simple Pairing) requires a little endian. At the same time,
636                  * the NDEF forum NDEF spec define a payload length as single
637                  * byte (and the payload size IS the oob data size).
638                  */
639                 bt_oob_data_size =
640                         GUINT16_FROM_LE(get_unaligned((uint16_t *) bt_data));
641                 if (bt_oob_data_size > 0xFF)    /* Big Endian */
642                         bt_oob_data_size = GUINT16_FROM_BE(bt_oob_data_size);
643
644                 bt_oob_data_size -= 2 ; /* remove oob datas size len */
645
646                 /* First item: BD_ADDR (mandatory) */
647                 ptr = &bt_data[2];
648                 oob->bd_addr = g_strdup_printf("%02X:%02X:%02X:%02X:%02X:%02X",
649                                 ptr[5], ptr[4], ptr[3], ptr[2], ptr[1], ptr[0]);
650
651                 /* Skip to the next element (optional) */
652                 ptr += BT_ADDRESS_SIZE;
653                 bt_oob_data_size -= BT_ADDRESS_SIZE ;
654
655                 if (bt_oob_data_size)
656                         bt_parse_eir(ptr, bt_oob_data_size, oob);
657         } else if (version == BT_MIME_V2_0) {
658                 marker = *ptr++;        /* could be '$' */
659
660                 oob->bd_addr = g_strdup_printf(
661                                 "%02X:%02X:%02X:%02X:%02X:%02X",
662                                 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
663                 ptr = ptr + BT_ADDRESS_SIZE;
664
665                 /* Class of device */
666                 tmp = g_strdup_printf("%02X%02X%02X",
667                                 *ptr, *(ptr + 1), *(ptr + 2));
668                 if (tmp != NULL)
669                         oob->class_of_device = strtol(tmp, NULL, 16);
670                 g_free(tmp);
671
672                 ptr = ptr + 3;
673
674                 /* "Short mode" seems to use a 4 bytes code
675                  * instead of 16 bytes...
676                  */
677                 if (marker == '$') {   /* Short NFC */
678                         memcpy(oob->authentication, ptr, 4);
679                         ptr = ptr + 4;
680                 } else {
681                         memcpy(oob->authentication, ptr, 16);
682                         ptr = ptr + 16;
683                 }
684
685                 /* get the device name */
686                 oob->bt_name_len = *ptr++;
687                 oob->bt_name = g_try_malloc0(oob->bt_name_len+1);
688                 if (oob->bt_name) {
689                         memcpy(oob->bt_name, ptr, oob->bt_name_len);
690                         oob->bt_name[oob->bt_name_len+1] = 0;
691                 }
692                 ptr = ptr + oob->bt_name_len;
693         } else {
694                 return -EINVAL;
695         }
696
697         if (pair == FALSE)
698                 return 0;
699
700         /* check and get the default adapter */
701         oob->def_adapter = g_strdup(bt_def_oob_data.def_adapter);
702         if (oob->def_adapter == NULL) {
703                 near_error("bt_get_default_adapter failed");
704                 bt_eir_free(oob);
705                 return -EIO;
706         }
707
708         return  bt_do_pairing(oob);
709 }
710
711 int __near_bluetooth_pair(void *data)
712 {
713         struct near_oob_data *oob = data;
714
715         /* check and get the default adapter */
716         oob->def_adapter = g_strdup(bt_def_oob_data.def_adapter);
717         if (oob->bt_name == NULL) {
718                 near_error("bt_get_default_adapter failed: %d", -EIO);
719                 bt_eir_free(oob);
720                 return -EIO;
721         }
722
723         return bt_do_pairing(oob);
724 }
725
726 /* This function is synchronous as oob datas change on each session */
727 static int bt_sync_oob_readlocaldata(DBusConnection *conn, char *adapter_path,
728                 char *spair_hash,
729                 char *spair_randomizer)
730 {
731         DBusMessage *message, *reply;
732         DBusError error;
733         int hash_len, rndm_len;
734
735         message = dbus_message_new_method_call(BLUEZ_SERVICE, adapter_path,
736                         OOB_INTF, "ReadLocalData");
737         if (!message)
738                 return 0;
739
740         dbus_error_init(&error);
741
742         reply = dbus_connection_send_with_reply_and_block(conn,
743                         message, -1, &error);
744
745         dbus_message_unref(message);
746
747         if (!reply) {
748                 if (dbus_error_is_set(&error) == TRUE) {
749                         near_error("%s", error.message);
750                         dbus_error_free(&error);
751                 } else {
752                         near_error("Failed to set property");
753                 }
754                 return 0;
755         }
756
757         if (dbus_message_get_args(reply, NULL,
758                         DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, spair_hash, &hash_len,
759                         DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
760                                                 spair_randomizer, &rndm_len,
761                         DBUS_TYPE_INVALID) == FALSE)
762                 goto done;
763
764         if ((hash_len != OOB_SP_SIZE) || (rndm_len != OOB_SP_SIZE)) {
765                 DBG("no OOB data found !");
766                 goto done;
767         }
768
769         dbus_message_unref(reply);
770         DBG("OOB data found");
771         return hash_len;
772
773 done:
774         dbus_message_unref(reply);
775         return 0;
776 }
777
778 /*
779  * External API to get bt properties
780  * Prepare a "real" oob datas block
781  * */
782 uint8_t *__near_bluetooth_local_get_properties(int *bt_data_len)
783 {
784         uint8_t *bt_oob_block = NULL;
785         uint16_t bt_oob_block_size = 0;
786         int max_block_size;
787         uint8_t offset;
788
789         char hash[OOB_SP_SIZE];
790         char random[OOB_SP_SIZE];
791
792         /* Check adapter datas */
793         if (bt_def_oob_data.def_adapter == NULL) {
794                 near_error("No bt adapter info");
795                 goto fail;
796         }
797
798         /* Prepare the BT block */
799         max_block_size = sizeof(uint16_t) +             /* stored oob size */
800                         BT_ADDRESS_SIZE +
801                         EIR_HEADER_LEN + bt_def_oob_data.bt_name_len +
802                         EIR_HEADER_LEN + COD_SIZE +     /* class */
803                         EIR_HEADER_LEN + OOB_SP_SIZE +  /* oob hash */
804                         EIR_HEADER_LEN + OOB_SP_SIZE;   /* oob random */
805
806
807         bt_oob_block_size = sizeof(uint16_t)    /* stored oob size */
808                         + BT_ADDRESS_SIZE;      /* device address */
809
810         bt_oob_block = g_try_malloc0(max_block_size);
811         if (bt_oob_block == NULL)
812                 goto fail;
813         offset = sizeof(uint16_t); /* Skip size...will be filled later */
814
815         /* Now prepare data frame */
816         memcpy(bt_oob_block + offset, bt_def_oob_data.bd_addr, BT_ADDRESS_SIZE);
817         offset += BT_ADDRESS_SIZE;
818
819         /* bt name */
820         if (bt_def_oob_data.bt_name != NULL) {
821                 bt_oob_block_size += (bt_def_oob_data.bt_name_len +
822                                                                 EIR_HEADER_LEN);
823
824                 bt_oob_block[offset++] = bt_def_oob_data.bt_name_len +
825                                                                 EIR_SIZE_LEN;
826                 bt_oob_block[offset++] = EIR_NAME_COMPLETE; /* EIR data type */
827                 memcpy(bt_oob_block + offset, bt_def_oob_data.bt_name,
828                                         bt_def_oob_data.bt_name_len);
829                 offset += bt_def_oob_data.bt_name_len;
830         }
831
832         /* CoD */
833         bt_oob_block_size += COD_SIZE +  EIR_HEADER_LEN;
834
835         bt_oob_block[offset++] = COD_SIZE + EIR_SIZE_LEN;
836         bt_oob_block[offset++] = EIR_CLASS_OF_DEVICE;
837
838         memcpy(bt_oob_block + offset,
839                         (uint8_t *)&bt_def_oob_data.class_of_device, COD_SIZE);
840         offset += COD_SIZE;
841
842         /* The following data are generated dynamically
843          * so we have to read the local oob data
844          * */
845         if (bt_sync_oob_readlocaldata(bt_conn, bt_def_oob_data.def_adapter,
846                                         hash, random) == OOB_SP_SIZE) {
847                 bt_oob_block_size += 2 * (OOB_SP_SIZE + EIR_HEADER_LEN);
848
849                 /* OOB datas */
850                 if (hash != NULL) {
851                         bt_oob_block[offset++] = OOB_SP_SIZE + EIR_SIZE_LEN;
852                         bt_oob_block[offset++] = EIR_SP_HASH;
853                         memcpy(bt_oob_block + offset, hash, OOB_SP_SIZE);
854                         offset += OOB_SP_SIZE;
855                 }
856
857                 if (random != NULL) {
858                         bt_oob_block[offset++] = OOB_SP_SIZE + EIR_SIZE_LEN;
859                         bt_oob_block[offset++] = EIR_SP_RANDOMIZER;
860                         memcpy(bt_oob_block + offset, random, OOB_SP_SIZE);
861                         offset += OOB_SP_SIZE;
862                 }
863         }
864
865         *(uint16_t *)bt_oob_block = bt_oob_block_size ;
866         *bt_data_len = bt_oob_block_size;
867
868         return bt_oob_block;
869
870 fail:
871         g_free(bt_oob_block);
872         return NULL;
873 }
874
875 static void bt_connect(DBusConnection *conn, void *user_data)
876 {
877
878         DBG("connection %p with %p", conn, user_data);
879         if (bt_refresh_adapter_props(conn, user_data) < 0)
880                 near_error("bt_get_default_adapter failed");
881
882         return;
883 }
884
885 static void bt_disconnect(DBusConnection *conn, void *user_data)
886 {
887         DBG("%p", conn);
888
889         __bt_eir_free(user_data);
890 }
891
892 /* BT adapter removed handler */
893 static gboolean bt_adapter_removed(DBusConnection *conn,
894                                         DBusMessage *message,
895                                         void *user_data)
896 {
897         DBusMessageIter iter;
898         struct near_oob_data *bt_props = user_data;
899         const char *adapter_path;
900
901         DBG("");
902
903         if (bt_props->def_adapter == NULL)
904                 return TRUE;
905
906         if (dbus_message_iter_init(message, &iter) == FALSE)
907                 return TRUE;
908
909         dbus_message_iter_get_basic(&iter, &adapter_path);
910
911         if (g_strcmp0(adapter_path, bt_props->def_adapter) == 0) {
912                 near_info("Remove the default adapter [%s]", adapter_path);
913
914                 __bt_eir_free(bt_props);
915                 bt_props->def_adapter = NULL;
916         }
917
918         return TRUE;
919 }
920
921 /* BT default adapter changed handler */
922 static gboolean bt_default_adapter_changed(DBusConnection *conn,
923                                         DBusMessage *message,
924                                         void *user_data)
925 {
926         struct near_oob_data *bt_props = user_data;
927         DBusMessageIter iter;
928         const char *adapter_path;
929
930         DBG("");
931
932         if (dbus_message_iter_init(message, &iter) == FALSE)
933                 return TRUE;
934
935         dbus_message_iter_get_basic(&iter, &adapter_path);
936         DBG("New default adapter [%s]", adapter_path);
937
938         /* Disable the old one */
939         __bt_eir_free(bt_props);
940         bt_props->def_adapter = NULL;
941
942         /* Refresh */
943         bt_refresh_adapter_props(conn, user_data);
944
945         return TRUE;
946 }
947
948 static void bt_dbus_disconnect_cb(DBusConnection *conn, void *user_data)
949 {
950         near_error("D-Bus disconnect (BT)");
951         bt_conn = NULL;
952 }
953
954 static guint watch;
955 static guint removed_watch;
956 static guint adapter_watch;
957
958 static int bt_prepare_handlers(DBusConnection *conn)
959 {
960         DBG("%p", conn);
961
962         if (conn == NULL)
963                 return -EIO;
964
965         watch = g_dbus_add_service_watch(conn, BLUEZ_SERVICE,
966                                                 bt_connect,
967                                                 bt_disconnect,
968                                                 &bt_def_oob_data, NULL);
969
970         removed_watch = g_dbus_add_signal_watch(conn, NULL, NULL, MANAGER_INTF,
971                                                 ADAPTER_REMOVED,
972                                                 bt_adapter_removed,
973                                                 &bt_def_oob_data, NULL);
974
975
976         adapter_watch = g_dbus_add_signal_watch(conn, NULL, NULL, MANAGER_INTF,
977                                                 DEFAULT_ADAPTER_CHANGED,
978                                                 bt_default_adapter_changed,
979                                                 &bt_def_oob_data, NULL);
980
981         if (watch == 0 ||  removed_watch == 0 || adapter_watch == 0) {
982                 near_error("Bluez event handlers failed to register.");
983                 g_dbus_remove_watch(conn, watch);
984                 g_dbus_remove_watch(conn, removed_watch);
985                 g_dbus_remove_watch(conn, adapter_watch);
986
987                 return -EIO;
988         }
989
990         return 0;
991 }
992
993 /* Bluetooth exiting function */
994 void __near_bluetooth_cleanup(void)
995 {
996         DBG("");
997
998         if (bt_conn == NULL)
999                 return;
1000
1001         g_dbus_remove_watch(bt_conn, watch);
1002         g_dbus_remove_watch(bt_conn, removed_watch);
1003         g_dbus_remove_watch(bt_conn, adapter_watch);
1004
1005         dbus_connection_unref(bt_conn);
1006
1007         __bt_eir_free(&bt_def_oob_data);
1008
1009         return;
1010 }
1011
1012 /*
1013  * Bluetooth initialization function.
1014  *      Allocate bt local settings storage
1015  *      and setup event handlers
1016  */
1017 int __near_bluetooth_init(void)
1018 {
1019         DBusError err;
1020
1021         DBG("");
1022
1023         dbus_error_init(&err);
1024
1025         /* save the dbus connection */
1026         bt_conn = near_dbus_get_connection();
1027         if (bt_conn == NULL) {
1028                 if (dbus_error_is_set(&err) == TRUE) {
1029                         near_error("%s", err.message);
1030                         dbus_error_free(&err);
1031                 } else
1032                         near_error("Can't register with system bus\n");
1033                 return -EIO;
1034         }
1035
1036         /* dbus disconnect callback */
1037         g_dbus_set_disconnect_function(bt_conn, bt_dbus_disconnect_cb,
1038                                                 NULL, NULL);
1039
1040         /* Set bluez event handlers */
1041         return bt_prepare_handlers(bt_conn);
1042 }