~cyphermox/bluez/5.23

« back to all changes in this revision

Viewing changes to proximity/monitor.c

  • Committer: Package Import Robot
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2012-01-24 05:35:09 UTC
  • mfrom: (1.5.11) (7.1.6 experimental)
  • Revision ID: package-import@ubuntu.com-20120124053509-uwpwqi783lz08wm3
Tags: 4.98-1
* New upstream release.
* Update debian/bluetooth-dbus.conf.
* Update debian/control.
  Add Multi-Arch: foreign to bluez.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <config.h>
27
27
#endif
28
28
 
 
29
#include <errno.h>
 
30
#include <fcntl.h>
29
31
#include <gdbus.h>
30
 
 
 
32
#include <stdint.h>
 
33
#include <stdio.h>
 
34
#include <stdlib.h>
 
35
#include <sys/stat.h>
 
36
 
 
37
#include <bluetooth/bluetooth.h>
 
38
#include <bluetooth/uuid.h>
 
39
 
 
40
#include "dbus-common.h"
 
41
#include "adapter.h"
 
42
#include "device.h"
 
43
#include "error.h"
31
44
#include "log.h"
32
 
 
 
45
#include "att.h"
 
46
#include "gattrib.h"
 
47
#include "gatt.h"
 
48
#include "attio.h"
33
49
#include "monitor.h"
 
50
#include "textfile.h"
34
51
 
35
52
#define PROXIMITY_INTERFACE "org.bluez.Proximity"
36
 
#define PROXIMITY_PATH "/org/bluez/proximity"
 
53
 
 
54
#define ALERT_LEVEL_CHR_UUID 0x2A06
 
55
#define POWER_LEVEL_CHR_UUID 0x2A07
 
56
 
 
57
#define IMMEDIATE_TIMEOUT       5
 
58
 
 
59
enum {
 
60
        ALERT_NONE = 0,
 
61
        ALERT_MILD,
 
62
        ALERT_HIGH,
 
63
};
 
64
 
 
65
struct monitor {
 
66
        struct btd_device *device;
 
67
        GAttrib *attrib;
 
68
        DBusConnection *conn;
 
69
        struct att_range *linkloss;
 
70
        struct att_range *txpower;
 
71
        struct att_range *immediate;
 
72
        struct enabled enabled;
 
73
        char *linklosslevel;            /* Link Loss Alert Level */
 
74
        char *fallbacklevel;            /* Immediate fallback alert level */
 
75
        char *immediatelevel;           /* Immediate Alert Level */
 
76
        char *signallevel;              /* Path Loss RSSI level */
 
77
        uint16_t linklosshandle;        /* Link Loss Characteristic
 
78
                                         * Value Handle */
 
79
        uint16_t txpowerhandle;         /* Tx Characteristic Value Handle */
 
80
        uint16_t immediatehandle;       /* Immediate Alert Value Handle */
 
81
        guint immediateto;              /* Reset Immediate Alert to "none" */
 
82
        guint attioid;
 
83
};
 
84
 
 
85
static inline int create_filename(char *buf, size_t size,
 
86
                                const bdaddr_t *bdaddr, const char *name)
 
87
{
 
88
        char addr[18];
 
89
 
 
90
        ba2str(bdaddr, addr);
 
91
 
 
92
        return create_name(buf, size, STORAGEDIR, addr, name);
 
93
}
 
94
 
 
95
static int write_proximity_config(bdaddr_t *sba, bdaddr_t *dba,
 
96
                                        const char *alert, const char *level)
 
97
{
 
98
        char filename[PATH_MAX + 1], addr[18], key[38];
 
99
 
 
100
        create_filename(filename, PATH_MAX, sba, "proximity");
 
101
 
 
102
        create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 
103
 
 
104
        ba2str(dba, addr);
 
105
 
 
106
        snprintf(key, sizeof(key), "%17s#%s", addr, alert);
 
107
 
 
108
        return textfile_put(filename, key, level);
 
109
}
 
110
 
 
111
static char *read_proximity_config(bdaddr_t *sba, bdaddr_t *dba,
 
112
                                                        const char *alert)
 
113
{
 
114
        char filename[PATH_MAX + 1], addr[18], key[38];
 
115
        char *str, *strnew;
 
116
 
 
117
        create_filename(filename, PATH_MAX, sba, "proximity");
 
118
 
 
119
        ba2str(dba, addr);
 
120
        snprintf(key, sizeof(key), "%17s#%s", addr, alert);
 
121
 
 
122
        str = textfile_caseget(filename, key);
 
123
        if (str == NULL)
 
124
                return NULL;
 
125
 
 
126
        strnew = g_strdup(str);
 
127
        free(str);
 
128
 
 
129
        return strnew;
 
130
}
 
131
 
 
132
static uint8_t str2level(const char *level)
 
133
{
 
134
        if (g_strcmp0("high", level) == 0)
 
135
                return ALERT_HIGH;
 
136
        else if (g_strcmp0("mild", level) == 0)
 
137
                return ALERT_MILD;
 
138
 
 
139
        return ALERT_NONE;
 
140
}
 
141
 
 
142
static void linkloss_written(guint8 status, const guint8 *pdu, guint16 plen,
 
143
                                                        gpointer user_data)
 
144
{
 
145
        struct monitor *monitor = user_data;
 
146
        struct btd_device *device = monitor->device;
 
147
        const char *path = device_get_path(device);
 
148
 
 
149
        if (status != 0) {
 
150
                error("Link Loss Write Request failed: %s",
 
151
                                                        att_ecode2str(status));
 
152
                return;
 
153
        }
 
154
 
 
155
        if (!dec_write_resp(pdu, plen)) {
 
156
                error("Link Loss Write Request: protocol error");
 
157
                return;
 
158
        }
 
159
 
 
160
        DBG("Link Loss Alert Level written");
 
161
 
 
162
        emit_property_changed(monitor->conn, path,
 
163
                                PROXIMITY_INTERFACE, "LinkLossAlertLevel",
 
164
                                DBUS_TYPE_STRING, &monitor->linklosslevel);
 
165
}
 
166
 
 
167
static void char_discovered_cb(GSList *characteristics, guint8 status,
 
168
                                                        gpointer user_data)
 
169
{
 
170
        struct monitor *monitor = user_data;
 
171
        struct att_char *chr;
 
172
        uint8_t value = str2level(monitor->linklosslevel);
 
173
 
 
174
        if (status) {
 
175
                error("Discover Link Loss handle: %s", att_ecode2str(status));
 
176
                return;
 
177
        }
 
178
 
 
179
        DBG("Setting alert level \"%s\" on Reporter", monitor->linklosslevel);
 
180
 
 
181
        /* Assume there is a single Alert Level characteristic */
 
182
        chr = characteristics->data;
 
183
        monitor->linklosshandle = chr->value_handle;
 
184
 
 
185
        gatt_write_char(monitor->attrib, monitor->linklosshandle, &value, 1,
 
186
                                                linkloss_written, monitor);
 
187
}
 
188
 
 
189
static int write_alert_level(struct monitor *monitor)
 
190
{
 
191
        struct att_range *linkloss = monitor->linkloss;
 
192
        bt_uuid_t uuid;
 
193
 
 
194
        if (monitor->linklosshandle) {
 
195
                uint8_t value = str2level(monitor->linklosslevel);
 
196
 
 
197
                gatt_write_char(monitor->attrib, monitor->linklosshandle,
 
198
                                        &value, 1, linkloss_written, monitor);
 
199
                return 0;
 
200
        }
 
201
 
 
202
        bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID);
 
203
 
 
204
        /* FIXME: use cache (requires service changed support) ? */
 
205
        gatt_discover_char(monitor->attrib, linkloss->start, linkloss->end,
 
206
                                        &uuid, char_discovered_cb, monitor);
 
207
 
 
208
        return 0;
 
209
}
 
210
 
 
211
static void tx_power_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 
212
                                                        gpointer user_data)
 
213
{
 
214
        uint8_t value[ATT_MAX_MTU];
 
215
        int vlen;
 
216
 
 
217
        if (status != 0) {
 
218
                DBG("Tx Power Level read failed: %s", att_ecode2str(status));
 
219
                return;
 
220
        }
 
221
 
 
222
        if (!dec_read_resp(pdu, plen, value, &vlen)) {
 
223
                DBG("Protocol error");
 
224
                return;
 
225
        }
 
226
 
 
227
        if (vlen != 1) {
 
228
                DBG("Invalid length for TX Power value: %d", vlen);
 
229
                return;
 
230
        }
 
231
 
 
232
        DBG("Tx Power Level: %02x", (int8_t) value[0]);
 
233
}
 
234
 
 
235
static void tx_power_handle_cb(GSList *characteristics, guint8 status,
 
236
                                                        gpointer user_data)
 
237
{
 
238
        struct monitor *monitor = user_data;
 
239
        struct att_char *chr;
 
240
 
 
241
        if (status) {
 
242
                error("Discover Tx Power handle: %s", att_ecode2str(status));
 
243
                return;
 
244
        }
 
245
 
 
246
        chr = characteristics->data;
 
247
        monitor->txpowerhandle = chr->value_handle;
 
248
 
 
249
        DBG("Tx Power handle: 0x%04x", monitor->txpowerhandle);
 
250
 
 
251
        gatt_read_char(monitor->attrib, monitor->txpowerhandle, 0,
 
252
                                                        tx_power_read_cb, monitor);
 
253
}
 
254
 
 
255
static void read_tx_power(struct monitor *monitor)
 
256
{
 
257
        struct att_range *txpower = monitor->txpower;
 
258
        bt_uuid_t uuid;
 
259
 
 
260
        if (monitor->txpowerhandle != 0) {
 
261
                gatt_read_char(monitor->attrib, monitor->txpowerhandle, 0,
 
262
                                                tx_power_read_cb, monitor);
 
263
                return;
 
264
        }
 
265
 
 
266
        bt_uuid16_create(&uuid, POWER_LEVEL_CHR_UUID);
 
267
 
 
268
        gatt_discover_char(monitor->attrib, txpower->start, txpower->end,
 
269
                                &uuid, tx_power_handle_cb, monitor);
 
270
}
 
271
 
 
272
static gboolean immediate_timeout(gpointer user_data)
 
273
{
 
274
        struct monitor *monitor = user_data;
 
275
        const char *path = device_get_path(monitor->device);
 
276
 
 
277
        monitor->immediateto = 0;
 
278
 
 
279
        if (g_strcmp0(monitor->immediatelevel, "none") == 0)
 
280
                return FALSE;
 
281
 
 
282
        if (monitor->attrib) {
 
283
                uint8_t value = ALERT_NONE;
 
284
                gatt_write_cmd(monitor->attrib, monitor->immediatehandle,
 
285
                                &value, 1, NULL, NULL);
 
286
        }
 
287
 
 
288
        g_free(monitor->immediatelevel);
 
289
        monitor->immediatelevel = g_strdup("none");
 
290
        emit_property_changed(monitor->conn, path, PROXIMITY_INTERFACE,
 
291
                                        "ImmediateAlertLevel", DBUS_TYPE_STRING,
 
292
                                        &monitor->immediatelevel);
 
293
 
 
294
        return FALSE;
 
295
}
 
296
 
 
297
static void immediate_written(gpointer user_data)
 
298
{
 
299
        struct monitor *monitor = user_data;
 
300
        const char *path = device_get_path(monitor->device);
 
301
 
 
302
        g_free(monitor->fallbacklevel);
 
303
        monitor->fallbacklevel = NULL;
 
304
 
 
305
        emit_property_changed(monitor->conn, path, PROXIMITY_INTERFACE,
 
306
                                "ImmediateAlertLevel",
 
307
                                DBUS_TYPE_STRING, &monitor->immediatelevel);
 
308
 
 
309
        monitor->immediateto = g_timeout_add_seconds(IMMEDIATE_TIMEOUT,
 
310
                                                immediate_timeout, monitor);
 
311
}
 
312
 
 
313
static void write_immediate_alert(struct monitor *monitor)
 
314
{
 
315
        uint8_t value = str2level(monitor->immediatelevel);
 
316
 
 
317
        gatt_write_cmd(monitor->attrib, monitor->immediatehandle, &value, 1,
 
318
                                                immediate_written, monitor);
 
319
}
 
320
 
 
321
static void immediate_handle_cb(GSList *characteristics, guint8 status,
 
322
                                                        gpointer user_data)
 
323
{
 
324
        struct monitor *monitor = user_data;
 
325
        struct att_char *chr;
 
326
 
 
327
        if (status) {
 
328
                error("Discover Immediate Alert handle: %s",
 
329
                                                att_ecode2str(status));
 
330
                return;
 
331
        }
 
332
 
 
333
        chr = characteristics->data;
 
334
        monitor->immediatehandle = chr->value_handle;
 
335
 
 
336
        DBG("Immediate Alert handle: 0x%04x", monitor->immediatehandle);
 
337
 
 
338
        if (monitor->fallbacklevel)
 
339
                write_immediate_alert(monitor);
 
340
}
 
341
 
 
342
static void discover_immediate_handle(struct monitor *monitor)
 
343
{
 
344
        struct att_range *immediate = monitor->immediate;
 
345
        bt_uuid_t uuid;
 
346
 
 
347
        bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID);
 
348
 
 
349
        gatt_discover_char(monitor->attrib, immediate->start, immediate->end,
 
350
                                        &uuid, immediate_handle_cb, monitor);
 
351
}
 
352
 
 
353
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
 
354
{
 
355
        struct monitor *monitor = user_data;
 
356
 
 
357
        monitor->attrib = g_attrib_ref(attrib);
 
358
 
 
359
        if (monitor->enabled.linkloss)
 
360
                write_alert_level(monitor);
 
361
 
 
362
        if (monitor->enabled.pathloss)
 
363
                read_tx_power(monitor);
 
364
 
 
365
        if (monitor->immediatehandle == 0) {
 
366
                if(monitor->enabled.pathloss || monitor->enabled.findme)
 
367
                        discover_immediate_handle(monitor);
 
368
        } else if (monitor->fallbacklevel)
 
369
                write_immediate_alert(monitor);
 
370
}
 
371
 
 
372
static void attio_disconnected_cb(gpointer user_data)
 
373
{
 
374
        struct monitor *monitor = user_data;
 
375
        const char *path = device_get_path(monitor->device);
 
376
 
 
377
        g_attrib_unref(monitor->attrib);
 
378
        monitor->attrib = NULL;
 
379
 
 
380
        if (monitor->immediateto == 0)
 
381
                return;
 
382
 
 
383
        g_source_remove(monitor->immediateto);
 
384
        monitor->immediateto = 0;
 
385
 
 
386
        if (g_strcmp0(monitor->immediatelevel, "none") == 0)
 
387
                return;
 
388
 
 
389
        g_free(monitor->immediatelevel);
 
390
        monitor->immediatelevel = g_strdup("none");
 
391
        emit_property_changed(monitor->conn, path, PROXIMITY_INTERFACE,
 
392
                                        "ImmediateAlertLevel", DBUS_TYPE_STRING,
 
393
                                        &monitor->immediatelevel);
 
394
}
 
395
 
 
396
static gboolean level_is_valid(const char *level)
 
397
{
 
398
        return (g_str_equal("none", level) ||
 
399
                        g_str_equal("mild", level) ||
 
400
                        g_str_equal("high", level));
 
401
}
 
402
 
 
403
static DBusMessage *set_link_loss_alert(DBusConnection *conn, DBusMessage *msg,
 
404
                                                const char *level, void *data)
 
405
{
 
406
        struct monitor *monitor = data;
 
407
        struct btd_device *device = monitor->device;
 
408
        bdaddr_t sba, dba;
 
409
 
 
410
        if (!level_is_valid(level))
 
411
                return btd_error_invalid_args(msg);
 
412
 
 
413
        if (g_strcmp0(monitor->linklosslevel, level) == 0)
 
414
                return dbus_message_new_method_return(msg);
 
415
 
 
416
        g_free(monitor->linklosslevel);
 
417
        monitor->linklosslevel = g_strdup(level);
 
418
 
 
419
        adapter_get_address(device_get_adapter(device), &sba);
 
420
        device_get_address(device, &dba, NULL);
 
421
 
 
422
        write_proximity_config(&sba, &dba, "LinkLossAlertLevel", level);
 
423
 
 
424
        if (monitor->attrib)
 
425
                write_alert_level(monitor);
 
426
 
 
427
        return dbus_message_new_method_return(msg);
 
428
}
 
429
 
 
430
static DBusMessage *set_immediate_alert(DBusConnection *conn, DBusMessage *msg,
 
431
                                                const char *level, void *data)
 
432
{
 
433
        struct monitor *monitor = data;
 
434
 
 
435
        if (!level_is_valid(level))
 
436
                return btd_error_invalid_args(msg);
 
437
 
 
438
        if (g_strcmp0(monitor->immediatelevel, level) == 0)
 
439
                return dbus_message_new_method_return(msg);
 
440
 
 
441
        if (monitor->immediateto) {
 
442
                g_source_remove(monitor->immediateto);
 
443
                monitor->immediateto = 0;
 
444
        }
 
445
 
 
446
        /* Previous Immediate Alert level if connection/write fails */
 
447
        g_free(monitor->fallbacklevel);
 
448
        monitor->fallbacklevel = monitor->immediatelevel;
 
449
 
 
450
        monitor->immediatelevel = g_strdup(level);
 
451
 
 
452
        /*
 
453
         * Means that Link/Path Loss are disabled or there is a pending
 
454
         * writting for Find Me(Immediate Alert characteristic value).
 
455
         * If enabled, Path Loss always registers a connection callback
 
456
         * when the Proximity Monitor starts.
 
457
         */
 
458
        if (monitor->attioid == 0)
 
459
                monitor->attioid = btd_device_add_attio_callback(monitor->device,
 
460
                                                        attio_connected_cb,
 
461
                                                        attio_disconnected_cb,
 
462
                                                        monitor);
 
463
        else if (monitor->attrib)
 
464
                write_immediate_alert(monitor);
 
465
 
 
466
        return dbus_message_new_method_return(msg);
 
467
}
37
468
 
38
469
static DBusMessage *get_properties(DBusConnection *conn,
39
470
                                        DBusMessage *msg, void *data)
40
471
{
41
 
        return dbus_message_new_method_return(msg);
 
472
        struct monitor *monitor = data;
 
473
        DBusMessageIter iter;
 
474
        DBusMessageIter dict;
 
475
        DBusMessage *reply;
 
476
 
 
477
        reply = dbus_message_new_method_return(msg);
 
478
        if (!reply)
 
479
                return NULL;
 
480
 
 
481
        dbus_message_iter_init_append(reply, &iter);
 
482
 
 
483
        dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 
484
                        DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
 
485
                        DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
 
486
                        DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
 
487
 
 
488
        if (monitor->enabled.linkloss)
 
489
                dict_append_entry(&dict, "LinkLossAlertLevel",
 
490
                                DBUS_TYPE_STRING, &monitor->linklosslevel);
 
491
 
 
492
        if (monitor->enabled.findme || monitor->enabled.pathloss)
 
493
                dict_append_entry(&dict, "ImmediateAlertLevel",
 
494
                                DBUS_TYPE_STRING, &monitor->immediatelevel);
 
495
 
 
496
        if (monitor->enabled.pathloss)
 
497
                dict_append_entry(&dict, "SignalLevel",
 
498
                                DBUS_TYPE_STRING, &monitor->signallevel);
 
499
 
 
500
        dbus_message_iter_close_container(&iter, &dict);
 
501
 
 
502
        return reply;
42
503
}
43
504
 
44
505
static DBusMessage *set_property(DBusConnection *conn,
45
506
                                        DBusMessage *msg, void *data)
46
507
{
47
 
        return dbus_message_new_method_return(msg);
 
508
        struct monitor *monitor = data;
 
509
        const char *property;
 
510
        DBusMessageIter iter;
 
511
        DBusMessageIter sub;
 
512
        const char *level;
 
513
 
 
514
        if (!dbus_message_iter_init(msg, &iter))
 
515
                return btd_error_invalid_args(msg);
 
516
 
 
517
        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 
518
                return btd_error_invalid_args(msg);
 
519
 
 
520
        dbus_message_iter_get_basic(&iter, &property);
 
521
        dbus_message_iter_next(&iter);
 
522
 
 
523
        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
 
524
                return btd_error_invalid_args(msg);
 
525
 
 
526
        dbus_message_iter_recurse(&iter, &sub);
 
527
 
 
528
        if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING)
 
529
                return btd_error_invalid_args(msg);
 
530
 
 
531
        dbus_message_iter_get_basic(&sub, &level);
 
532
 
 
533
        if (g_str_equal("ImmediateAlertLevel", property)) {
 
534
                if (monitor->enabled.findme == FALSE &&
 
535
                                monitor->enabled.pathloss == FALSE)
 
536
                        return btd_error_not_available(msg);
 
537
 
 
538
                return set_immediate_alert(conn, msg, level, data);
 
539
        } else if (g_str_equal("LinkLossAlertLevel", property)) {
 
540
                if (monitor->enabled.linkloss == FALSE)
 
541
                        return btd_error_not_available(msg);
 
542
 
 
543
                return set_link_loss_alert(conn, msg, level, data);
 
544
        }
 
545
 
 
546
        return btd_error_invalid_args(msg);
48
547
}
49
548
 
50
549
static GDBusMethodTable monitor_methods[] = {
59
558
        { }
60
559
};
61
560
 
62
 
int monitor_register(DBusConnection *conn)
63
 
{
64
 
        int ret = -1;
65
 
 
66
 
        if (g_dbus_register_interface(conn, PROXIMITY_PATH,
67
 
                                        PROXIMITY_INTERFACE,
68
 
                                        monitor_methods, monitor_signals,
69
 
                                        NULL, NULL, NULL) == TRUE) {
70
 
                DBG("Registered interface %s on path %s", PROXIMITY_INTERFACE,
71
 
                                                        PROXIMITY_PATH);
72
 
                ret = 0;
73
 
 
74
 
        }
75
 
 
76
 
        error("D-Bus failed to register %s interface", PROXIMITY_INTERFACE);
77
 
 
78
 
        return ret;
79
 
}
80
 
 
81
 
void monitor_unregister(DBusConnection *conn)
82
 
{
83
 
        g_dbus_unregister_interface(conn, PROXIMITY_PATH, PROXIMITY_INTERFACE);
 
561
static void monitor_destroy(gpointer user_data)
 
562
{
 
563
        struct monitor *monitor = user_data;
 
564
 
 
565
        if (monitor->immediateto)
 
566
                g_source_remove(monitor->immediateto);
 
567
 
 
568
        if (monitor->attioid)
 
569
                btd_device_remove_attio_callback(monitor->device,
 
570
                                                monitor->attioid);
 
571
        if (monitor->attrib)
 
572
                g_attrib_unref(monitor->attrib);
 
573
 
 
574
        dbus_connection_unref(monitor->conn);
 
575
        btd_device_unref(monitor->device);
 
576
        g_free(monitor->linkloss);
 
577
        g_free(monitor->immediate);
 
578
        g_free(monitor->txpower);
 
579
        g_free(monitor->linklosslevel);
 
580
        g_free(monitor->immediatelevel);
 
581
        g_free(monitor->signallevel);
 
582
        g_free(monitor);
 
583
}
 
584
 
 
585
int monitor_register(DBusConnection *conn, struct btd_device *device,
 
586
                struct att_primary *linkloss, struct att_primary *txpower,
 
587
                struct att_primary *immediate, struct enabled *enabled)
 
588
{
 
589
        const char *path = device_get_path(device);
 
590
        struct monitor *monitor;
 
591
        bdaddr_t sba, dba;
 
592
        char *level;
 
593
 
 
594
        adapter_get_address(device_get_adapter(device), &sba);
 
595
        device_get_address(device, &dba, NULL);
 
596
 
 
597
        level = read_proximity_config(&sba, &dba, "LinkLossAlertLevel");
 
598
 
 
599
        monitor = g_new0(struct monitor, 1);
 
600
        monitor->device = btd_device_ref(device);
 
601
        monitor->conn = dbus_connection_ref(conn);
 
602
        monitor->linklosslevel = (level ? : g_strdup("high"));
 
603
        monitor->signallevel = g_strdup("unknown");
 
604
        monitor->immediatelevel = g_strdup("none");
 
605
 
 
606
        if (g_dbus_register_interface(conn, path,
 
607
                                PROXIMITY_INTERFACE,
 
608
                                monitor_methods, monitor_signals,
 
609
                                NULL, monitor, monitor_destroy) == FALSE) {
 
610
                error("D-Bus failed to register %s interface",
 
611
                                                PROXIMITY_INTERFACE);
 
612
                monitor_destroy(monitor);
 
613
                return -1;
 
614
        }
 
615
 
 
616
        DBG("Registered interface %s on path %s", PROXIMITY_INTERFACE, path);
 
617
 
 
618
        if (linkloss && enabled->linkloss) {
 
619
                monitor->linkloss = g_new0(struct att_range, 1);
 
620
                monitor->linkloss->start = linkloss->start;
 
621
                monitor->linkloss->end = linkloss->end;
 
622
 
 
623
                monitor->enabled.linkloss = TRUE;
 
624
        }
 
625
 
 
626
        if (immediate) {
 
627
                if (txpower && enabled->pathloss) {
 
628
                        monitor->txpower = g_new0(struct att_range, 1);
 
629
                        monitor->txpower->start = txpower->start;
 
630
                        monitor->txpower->end = txpower->end;
 
631
 
 
632
                        monitor->enabled.pathloss = TRUE;
 
633
                }
 
634
 
 
635
                if (enabled->pathloss || enabled->findme) {
 
636
                        monitor->immediate = g_new0(struct att_range, 1);
 
637
                        monitor->immediate->start = immediate->start;
 
638
                        monitor->immediate->end = immediate->end;
 
639
                }
 
640
 
 
641
                monitor->enabled.findme = enabled->findme;
 
642
        }
 
643
 
 
644
        DBG("Link Loss: %s, Path Loss: %s, FindMe: %s",
 
645
                                monitor->enabled.linkloss ? "TRUE" : "FALSE",
 
646
                                monitor->enabled.pathloss ? "TRUE" : "FALSE",
 
647
                                monitor->enabled.findme ? "TRUE" : "FALSE");
 
648
 
 
649
        if (monitor->enabled.linkloss || monitor->enabled.pathloss)
 
650
                monitor->attioid = btd_device_add_attio_callback(device,
 
651
                                                        attio_connected_cb,
 
652
                                                        attio_disconnected_cb,
 
653
                                                        monitor);
 
654
 
 
655
        return 0;
 
656
}
 
657
 
 
658
void monitor_unregister(DBusConnection *conn, struct btd_device *device)
 
659
{
 
660
        const char *path = device_get_path(device);
 
661
 
 
662
        g_dbus_unregister_interface(conn, path, PROXIMITY_INTERFACE);
84
663
}