~bluetooth/bluez/vivid-phone-overlay

« back to all changes in this revision

Viewing changes to .pc/git-a66a557-gdbus_missing_flags.patch/src/manager.c

  • Committer: Simon Fels
  • Date: 2015-09-11 09:01:46 UTC
  • Revision ID: morphis@gravedo.de-20150911090146-4c0ln9s7ec3xf0nx
Import package bluez_4.101-0ubuntu25.1~overlay4 from stable phone overlay PPA

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  BlueZ - Bluetooth protocol stack for Linux
 
4
 *
 
5
 *  Copyright (C) 2006-2010  Nokia Corporation
 
6
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 
7
 *
 
8
 *
 
9
 *  This program is free software; you can redistribute it and/or modify
 
10
 *  it under the terms of the GNU General Public License as published by
 
11
 *  the Free Software Foundation; either version 2 of the License, or
 
12
 *  (at your option) any later version.
 
13
 *
 
14
 *  This program is distributed in the hope that it will be useful,
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 *  GNU General Public License for more details.
 
18
 *
 
19
 *  You should have received a copy of the GNU General Public License
 
20
 *  along with this program; if not, write to the Free Software
 
21
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
22
 *
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#include <config.h>
 
27
#endif
 
28
 
 
29
#include <stdlib.h>
 
30
#include <stdio.h>
 
31
#include <errno.h>
 
32
#include <unistd.h>
 
33
#include <sys/ioctl.h>
 
34
#include <sys/socket.h>
 
35
 
 
36
#include <bluetooth/bluetooth.h>
 
37
#include <bluetooth/sdp.h>
 
38
#include <bluetooth/sdp_lib.h>
 
39
 
 
40
#include <glib.h>
 
41
 
 
42
#include <dbus/dbus.h>
 
43
 
 
44
#include <gdbus.h>
 
45
 
 
46
#include "glib-helper.h"
 
47
#include "hcid.h"
 
48
#include "dbus-common.h"
 
49
#include "log.h"
 
50
#include "adapter.h"
 
51
#include "error.h"
 
52
#include "manager.h"
 
53
 
 
54
static char base_path[50] = "/org/bluez";
 
55
 
 
56
static DBusConnection *connection = NULL;
 
57
static int default_adapter_id = -1;
 
58
static GSList *adapters = NULL;
 
59
 
 
60
const char *manager_get_base_path(void)
 
61
{
 
62
        return base_path;
 
63
}
 
64
 
 
65
static DBusMessage *default_adapter(DBusConnection *conn,
 
66
                                        DBusMessage *msg, void *data)
 
67
{
 
68
        DBusMessage *reply;
 
69
        struct btd_adapter *adapter;
 
70
        const gchar *path;
 
71
 
 
72
        adapter = manager_find_adapter_by_id(default_adapter_id);
 
73
        if (!adapter)
 
74
                return btd_error_no_such_adapter(msg);
 
75
 
 
76
        reply = dbus_message_new_method_return(msg);
 
77
        if (!reply)
 
78
                return NULL;
 
79
 
 
80
        path = adapter_get_path(adapter);
 
81
 
 
82
        dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
 
83
                                DBUS_TYPE_INVALID);
 
84
 
 
85
        return reply;
 
86
}
 
87
 
 
88
static DBusMessage *find_adapter(DBusConnection *conn,
 
89
                                        DBusMessage *msg, void *data)
 
90
{
 
91
        DBusMessage *reply;
 
92
        struct btd_adapter *adapter;
 
93
        const char *pattern;
 
94
        int dev_id;
 
95
        const gchar *path;
 
96
 
 
97
        if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
 
98
                                                        DBUS_TYPE_INVALID))
 
99
                return NULL;
 
100
 
 
101
        /* hci_devid() would make sense to use here, except it is
 
102
         * restricted to devices which are up */
 
103
        if (!strcmp(pattern, "any") || !strcmp(pattern, "00:00:00:00:00:00")) {
 
104
                path = adapter_any_get_path();
 
105
                if (path != NULL)
 
106
                        goto done;
 
107
                return btd_error_no_such_adapter(msg);
 
108
        } else if (!strncmp(pattern, "hci", 3) && strlen(pattern) >= 4) {
 
109
                dev_id = atoi(pattern + 3);
 
110
                adapter = manager_find_adapter_by_id(dev_id);
 
111
        } else {
 
112
                bdaddr_t bdaddr;
 
113
                str2ba(pattern, &bdaddr);
 
114
                adapter = manager_find_adapter(&bdaddr);
 
115
        }
 
116
 
 
117
        if (!adapter)
 
118
                return btd_error_no_such_adapter(msg);
 
119
 
 
120
        path = adapter_get_path(adapter);
 
121
 
 
122
done:
 
123
        reply = dbus_message_new_method_return(msg);
 
124
        if (!reply)
 
125
                return NULL;
 
126
 
 
127
        dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
 
128
                                                        DBUS_TYPE_INVALID);
 
129
 
 
130
        return reply;
 
131
}
 
132
 
 
133
static DBusMessage *list_adapters(DBusConnection *conn,
 
134
                                        DBusMessage *msg, void *data)
 
135
{
 
136
        DBusMessageIter iter;
 
137
        DBusMessageIter array_iter;
 
138
        DBusMessage *reply;
 
139
        GSList *l;
 
140
 
 
141
        reply = dbus_message_new_method_return(msg);
 
142
        if (!reply)
 
143
                return NULL;
 
144
 
 
145
        dbus_message_iter_init_append(reply, &iter);
 
146
 
 
147
        dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 
148
                                DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter);
 
149
 
 
150
        for (l = adapters; l; l = l->next) {
 
151
                struct btd_adapter *adapter = l->data;
 
152
                const gchar *path = adapter_get_path(adapter);
 
153
 
 
154
                dbus_message_iter_append_basic(&array_iter,
 
155
                                        DBUS_TYPE_OBJECT_PATH, &path);
 
156
        }
 
157
 
 
158
        dbus_message_iter_close_container(&iter, &array_iter);
 
159
 
 
160
        return reply;
 
161
}
 
162
 
 
163
static DBusMessage *get_properties(DBusConnection *conn,
 
164
                                        DBusMessage *msg, void *data)
 
165
{
 
166
        DBusMessage *reply;
 
167
        DBusMessageIter iter;
 
168
        DBusMessageIter dict;
 
169
        GSList *list;
 
170
        char **array;
 
171
        int i;
 
172
 
 
173
        reply = dbus_message_new_method_return(msg);
 
174
        if (!reply)
 
175
                return NULL;
 
176
 
 
177
        dbus_message_iter_init_append(reply, &iter);
 
178
 
 
179
        dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 
180
                        DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
 
181
                        DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
 
182
                        DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
 
183
 
 
184
        array = g_new0(char *, g_slist_length(adapters) + 1);
 
185
        for (i = 0, list = adapters; list; list = list->next) {
 
186
                struct btd_adapter *adapter = list->data;
 
187
 
 
188
                array[i] = (char *) adapter_get_path(adapter);
 
189
                i++;
 
190
        }
 
191
        dict_append_array(&dict, "Adapters", DBUS_TYPE_OBJECT_PATH, &array, i);
 
192
        g_free(array);
 
193
 
 
194
        dbus_message_iter_close_container(&iter, &dict);
 
195
 
 
196
        return reply;
 
197
}
 
198
 
 
199
static const GDBusMethodTable manager_methods[] = {
 
200
        { GDBUS_METHOD("GetProperties",
 
201
                        NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
 
202
                        get_properties) },
 
203
        { GDBUS_METHOD("DefaultAdapter",
 
204
                        NULL, GDBUS_ARGS({ "adapter", "o" }),
 
205
                        default_adapter) },
 
206
        { GDBUS_METHOD("FindAdapter",
 
207
                        GDBUS_ARGS({ "pattern", "s" }),
 
208
                        GDBUS_ARGS({ "adapter", "o" }),
 
209
                        find_adapter) },
 
210
        { GDBUS_ASYNC_METHOD("ListAdapters",
 
211
                        NULL, GDBUS_ARGS({ "adapters", "ao" }),
 
212
                        list_adapters) },
 
213
        { }
 
214
};
 
215
 
 
216
static const GDBusSignalTable manager_signals[] = {
 
217
        { GDBUS_SIGNAL("PropertyChanged",
 
218
                        GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
 
219
        { GDBUS_SIGNAL("AdapterAdded",
 
220
                        GDBUS_ARGS({ "adapter", "o" })) },
 
221
        { GDBUS_SIGNAL("AdapterRemoved",
 
222
                        GDBUS_ARGS({ "adapter", "o" })) },
 
223
        { GDBUS_SIGNAL("DefaultAdapterChanged",
 
224
                        GDBUS_ARGS({ "adapter", "o" })) },
 
225
        { }
 
226
};
 
227
 
 
228
dbus_bool_t manager_init(DBusConnection *conn, const char *path)
 
229
{
 
230
        connection = conn;
 
231
 
 
232
        snprintf(base_path, sizeof(base_path), "/org/bluez/%d", getpid());
 
233
 
 
234
        return g_dbus_register_interface(conn, "/", MANAGER_INTERFACE,
 
235
                                        manager_methods, manager_signals,
 
236
                                        NULL, NULL, NULL);
 
237
}
 
238
 
 
239
static void manager_update_adapters(void)
 
240
{
 
241
        GSList *list;
 
242
        char **array;
 
243
        int i;
 
244
 
 
245
        array = g_new0(char *, g_slist_length(adapters) + 1);
 
246
        for (i = 0, list = adapters; list; list = list->next) {
 
247
                struct btd_adapter *adapter = list->data;
 
248
 
 
249
                array[i] = (char *) adapter_get_path(adapter);
 
250
                i++;
 
251
        }
 
252
 
 
253
        emit_array_property_changed(connection, "/",
 
254
                                        MANAGER_INTERFACE, "Adapters",
 
255
                                        DBUS_TYPE_OBJECT_PATH, &array, i);
 
256
 
 
257
        g_free(array);
 
258
}
 
259
 
 
260
static void manager_set_default_adapter(int id)
 
261
{
 
262
        struct btd_adapter *adapter;
 
263
        const gchar *path;
 
264
 
 
265
        default_adapter_id = id;
 
266
 
 
267
        adapter = manager_find_adapter_by_id(id);
 
268
        if (!adapter)
 
269
                return;
 
270
 
 
271
        path = adapter_get_path(adapter);
 
272
 
 
273
        g_dbus_emit_signal(connection, "/",
 
274
                        MANAGER_INTERFACE,
 
275
                        "DefaultAdapterChanged",
 
276
                        DBUS_TYPE_OBJECT_PATH, &path,
 
277
                        DBUS_TYPE_INVALID);
 
278
}
 
279
 
 
280
struct btd_adapter *manager_get_default_adapter(void)
 
281
{
 
282
        return manager_find_adapter_by_id(default_adapter_id);
 
283
}
 
284
 
 
285
static void manager_remove_adapter(struct btd_adapter *adapter)
 
286
{
 
287
        uint16_t dev_id = adapter_get_dev_id(adapter);
 
288
        const gchar *path = adapter_get_path(adapter);
 
289
 
 
290
        adapters = g_slist_remove(adapters, adapter);
 
291
 
 
292
        manager_update_adapters();
 
293
 
 
294
        if (default_adapter_id == dev_id || default_adapter_id < 0) {
 
295
                int new_default = hci_get_route(NULL);
 
296
 
 
297
                manager_set_default_adapter(new_default);
 
298
        }
 
299
 
 
300
        g_dbus_emit_signal(connection, "/",
 
301
                        MANAGER_INTERFACE, "AdapterRemoved",
 
302
                        DBUS_TYPE_OBJECT_PATH, &path,
 
303
                        DBUS_TYPE_INVALID);
 
304
 
 
305
        adapter_remove(adapter);
 
306
        btd_adapter_unref(adapter);
 
307
 
 
308
        if (adapters == NULL)
 
309
                btd_start_exit_timer();
 
310
}
 
311
 
 
312
void manager_cleanup(DBusConnection *conn, const char *path)
 
313
{
 
314
        while (adapters) {
 
315
                struct btd_adapter *adapter = adapters->data;
 
316
 
 
317
                adapters = g_slist_remove(adapters, adapter);
 
318
                adapter_remove(adapter);
 
319
                btd_adapter_unref(adapter);
 
320
        }
 
321
 
 
322
        btd_start_exit_timer();
 
323
 
 
324
        g_dbus_unregister_interface(conn, "/", MANAGER_INTERFACE);
 
325
}
 
326
 
 
327
static gint adapter_id_cmp(gconstpointer a, gconstpointer b)
 
328
{
 
329
        struct btd_adapter *adapter = (struct btd_adapter *) a;
 
330
        uint16_t id = GPOINTER_TO_UINT(b);
 
331
        uint16_t dev_id = adapter_get_dev_id(adapter);
 
332
 
 
333
        return dev_id == id ? 0 : -1;
 
334
}
 
335
 
 
336
static gint adapter_cmp(gconstpointer a, gconstpointer b)
 
337
{
 
338
        struct btd_adapter *adapter = (struct btd_adapter *) a;
 
339
        const bdaddr_t *bdaddr = b;
 
340
        bdaddr_t src;
 
341
 
 
342
        adapter_get_address(adapter, &src);
 
343
 
 
344
        return bacmp(&src, bdaddr);
 
345
}
 
346
 
 
347
struct btd_adapter *manager_find_adapter(const bdaddr_t *sba)
 
348
{
 
349
        GSList *match;
 
350
 
 
351
        match = g_slist_find_custom(adapters, sba, adapter_cmp);
 
352
        if (!match)
 
353
                return NULL;
 
354
 
 
355
        return match->data;
 
356
}
 
357
 
 
358
struct btd_adapter *manager_find_adapter_by_id(int id)
 
359
{
 
360
        GSList *match;
 
361
 
 
362
        match = g_slist_find_custom(adapters, GINT_TO_POINTER(id),
 
363
                                                        adapter_id_cmp);
 
364
        if (!match)
 
365
                return NULL;
 
366
 
 
367
        return match->data;
 
368
}
 
369
 
 
370
void manager_foreach_adapter(adapter_cb func, gpointer user_data)
 
371
{
 
372
        g_slist_foreach(adapters, (GFunc) func, user_data);
 
373
}
 
374
 
 
375
GSList *manager_get_adapters(void)
 
376
{
 
377
        return adapters;
 
378
}
 
379
 
 
380
void manager_add_adapter(const char *path)
 
381
{
 
382
        g_dbus_emit_signal(connection, "/",
 
383
                                MANAGER_INTERFACE, "AdapterAdded",
 
384
                                DBUS_TYPE_OBJECT_PATH, &path,
 
385
                                DBUS_TYPE_INVALID);
 
386
 
 
387
        manager_update_adapters();
 
388
 
 
389
        btd_stop_exit_timer();
 
390
}
 
391
 
 
392
struct btd_adapter *btd_manager_register_adapter(int id, gboolean up)
 
393
{
 
394
        struct btd_adapter *adapter;
 
395
        const char *path;
 
396
 
 
397
        adapter = manager_find_adapter_by_id(id);
 
398
        if (adapter) {
 
399
                error("Unable to register adapter: hci%d already exist", id);
 
400
                return NULL;
 
401
        }
 
402
 
 
403
        adapter = adapter_create(connection, id);
 
404
        if (!adapter)
 
405
                return NULL;
 
406
 
 
407
        adapters = g_slist_append(adapters, adapter);
 
408
 
 
409
        if (!adapter_init(adapter, up)) {
 
410
                adapters = g_slist_remove(adapters, adapter);
 
411
                btd_adapter_unref(adapter);
 
412
                return NULL;
 
413
        }
 
414
 
 
415
        path = adapter_get_path(adapter);
 
416
        g_dbus_emit_signal(connection, "/",
 
417
                                MANAGER_INTERFACE, "AdapterAdded",
 
418
                                DBUS_TYPE_OBJECT_PATH, &path,
 
419
                                DBUS_TYPE_INVALID);
 
420
 
 
421
        manager_update_adapters();
 
422
 
 
423
        btd_stop_exit_timer();
 
424
 
 
425
        if (default_adapter_id < 0)
 
426
                manager_set_default_adapter(id);
 
427
 
 
428
        if (main_opts.did_source)
 
429
                btd_adapter_set_did(adapter, main_opts.did_vendor,
 
430
                                                main_opts.did_product,
 
431
                                                main_opts.did_version,
 
432
                                                main_opts.did_source);
 
433
 
 
434
        DBG("Adapter %s registered", path);
 
435
 
 
436
        return btd_adapter_ref(adapter);
 
437
}
 
438
 
 
439
int btd_manager_unregister_adapter(int id)
 
440
{
 
441
        struct btd_adapter *adapter;
 
442
        const gchar *path;
 
443
 
 
444
        adapter = manager_find_adapter_by_id(id);
 
445
        if (!adapter)
 
446
                return -1;
 
447
 
 
448
        path = adapter_get_path(adapter);
 
449
 
 
450
        info("Unregister path: %s", path);
 
451
 
 
452
        manager_remove_adapter(adapter);
 
453
 
 
454
        return 0;
 
455
}