3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2013 Intel Corporation.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include "lib/bluetooth.h"
41 #include "src/plugin.h"
42 #include "src/adapter.h"
43 #include "src/device.h"
44 #include "src/service.h"
45 #include "src/profile.h"
48 #ifdef __TIZEN_PATCH__
49 #define CONTROL_CONNECT_TIMEOUT 4
50 #define TARGET_CONNECT_TIMEOUT 1
52 #define CONTROL_CONNECT_TIMEOUT 2
54 #define SOURCE_RETRY_TIMEOUT 2
55 #define SINK_RETRY_TIMEOUT SOURCE_RETRY_TIMEOUT
56 #define CT_RETRY_TIMEOUT 1
57 #define TG_RETRY_TIMEOUT CT_RETRY_TIMEOUT
58 #ifdef __TIZEN_PATCH__
59 #define SOURCE_RETRIES 0
61 #define SOURCE_RETRIES 1
63 #define SINK_RETRIES SOURCE_RETRIES
65 #define TG_RETRIES CT_RETRIES
67 struct reconnect_data {
68 struct btd_device *dev;
76 static const char *default_reconnect[] = {
77 HSP_AG_UUID, HFP_AG_UUID, A2DP_SOURCE_UUID, NULL };
78 static char **reconnect_uuids = NULL;
80 static const size_t default_attempts = 7;
81 static size_t reconnect_attempts = 0;
83 static const int default_intervals[] = { 1, 2, 4, 8, 16, 32, 64 };
84 static int *reconnect_intervals = NULL;
85 static size_t reconnect_intervals_len = 0;
87 static GSList *reconnects = NULL;
89 static unsigned int service_id = 0;
90 static GSList *devices = NULL;
92 static bool auto_enable = false;
95 struct btd_device *dev;
98 uint8_t source_retries;
100 uint8_t sink_retries;
107 static void policy_connect(struct policy_data *data,
108 struct btd_service *service)
110 struct btd_profile *profile = btd_service_get_profile(service);
112 DBG("%s profile %s", device_get_path(data->dev), profile->name);
114 btd_service_connect(service);
117 static void policy_disconnect(struct policy_data *data,
118 struct btd_service *service)
120 struct btd_profile *profile = btd_service_get_profile(service);
122 DBG("%s profile %s", device_get_path(data->dev), profile->name);
124 btd_service_disconnect(service);
127 static gboolean policy_connect_ct(gpointer user_data)
129 struct policy_data *data = user_data;
130 struct btd_service *service;
135 service = btd_device_get_service(data->dev, AVRCP_REMOTE_UUID);
137 policy_connect(data, service);
142 static void policy_set_ct_timer(struct policy_data *data, int timeout)
144 if (data->ct_timer > 0)
145 g_source_remove(data->ct_timer);
147 data->ct_timer = g_timeout_add_seconds(timeout, policy_connect_ct,
151 static struct policy_data *find_data(struct btd_device *dev)
155 for (l = devices; l; l = l->next) {
156 struct policy_data *data = l->data;
158 if (data->dev == dev)
165 static void policy_remove(void *user_data)
167 struct policy_data *data = user_data;
169 if (data->source_timer > 0)
170 g_source_remove(data->source_timer);
172 if (data->sink_timer > 0)
173 g_source_remove(data->sink_timer);
175 if (data->ct_timer > 0)
176 g_source_remove(data->ct_timer);
178 if (data->tg_timer > 0)
179 g_source_remove(data->tg_timer);
184 static struct policy_data *policy_get_data(struct btd_device *dev)
186 struct policy_data *data;
188 data = find_data(dev);
192 data = g_new0(struct policy_data, 1);
195 devices = g_slist_prepend(devices, data);
200 static gboolean policy_connect_sink(gpointer user_data)
202 struct policy_data *data = user_data;
203 struct btd_service *service;
205 data->source_timer = 0;
206 data->sink_retries++;
208 service = btd_device_get_service(data->dev, A2DP_SINK_UUID);
210 policy_connect(data, service);
215 static void policy_set_sink_timer(struct policy_data *data)
217 if (data->sink_timer > 0)
218 g_source_remove(data->sink_timer);
220 data->sink_timer = g_timeout_add_seconds(SINK_RETRY_TIMEOUT,
225 static void sink_cb(struct btd_service *service, btd_service_state_t old_state,
226 btd_service_state_t new_state)
228 struct btd_device *dev = btd_service_get_device(service);
229 struct policy_data *data;
230 struct btd_service *controller;
232 controller = btd_device_get_service(dev, AVRCP_REMOTE_UUID);
233 if (controller == NULL)
236 data = policy_get_data(dev);
239 case BTD_SERVICE_STATE_UNAVAILABLE:
240 if (data->sink_timer > 0) {
241 g_source_remove(data->sink_timer);
242 data->sink_timer = 0;
245 case BTD_SERVICE_STATE_DISCONNECTED:
246 if (old_state == BTD_SERVICE_STATE_CONNECTING) {
247 int err = btd_service_get_error(service);
249 if (err == -EAGAIN) {
250 if (data->sink_retries < SINK_RETRIES)
251 policy_set_sink_timer(data);
253 data->sink_retries = 0;
255 } else if (data->sink_timer > 0) {
256 g_source_remove(data->sink_timer);
257 data->sink_timer = 0;
261 if (data->ct_timer > 0) {
262 g_source_remove(data->ct_timer);
264 } else if (btd_service_get_state(controller) !=
265 BTD_SERVICE_STATE_DISCONNECTED)
266 policy_disconnect(data, controller);
268 case BTD_SERVICE_STATE_CONNECTING:
270 case BTD_SERVICE_STATE_CONNECTED:
271 if (data->sink_timer > 0) {
272 g_source_remove(data->sink_timer);
273 data->sink_timer = 0;
276 /* Check if service initiate the connection then proceed
277 * immediatelly otherwise set timer
279 if (old_state == BTD_SERVICE_STATE_CONNECTING)
280 #ifdef __TIZEN_PATCH__
281 /* Set timer as most of the devices initiate
282 * avrcp connection immediately; irrespective of local
283 * or remote initiated a2dp connection
285 policy_set_ct_timer(data, CONTROL_CONNECT_TIMEOUT);
287 policy_connect(data, controller);
289 else if (btd_service_get_state(controller) !=
290 BTD_SERVICE_STATE_CONNECTED)
291 policy_set_ct_timer(data, CONTROL_CONNECT_TIMEOUT);
293 case BTD_SERVICE_STATE_DISCONNECTING:
298 static gboolean policy_connect_tg(gpointer user_data)
300 struct policy_data *data = user_data;
301 struct btd_service *service;
306 service = btd_device_get_service(data->dev, AVRCP_TARGET_UUID);
308 policy_connect(data, service);
313 static void policy_set_tg_timer(struct policy_data *data, int timeout)
315 if (data->tg_timer > 0)
316 g_source_remove(data->tg_timer);
319 #ifdef __TIZEN_PATCH__
320 data->tg_timer = g_timeout_add_seconds(TARGET_CONNECT_TIMEOUT,
324 data->tg_timer = g_timeout_add_seconds(timeout, policy_connect_tg,
329 static gboolean policy_connect_source(gpointer user_data)
331 struct policy_data *data = user_data;
332 struct btd_service *service;
334 data->source_timer = 0;
335 data->source_retries++;
337 service = btd_device_get_service(data->dev, A2DP_SOURCE_UUID);
339 policy_connect(data, service);
344 static void policy_set_source_timer(struct policy_data *data)
346 if (data->source_timer > 0)
347 g_source_remove(data->source_timer);
349 data->source_timer = g_timeout_add_seconds(SOURCE_RETRY_TIMEOUT,
350 policy_connect_source,
354 static void source_cb(struct btd_service *service,
355 btd_service_state_t old_state,
356 btd_service_state_t new_state)
358 struct btd_device *dev = btd_service_get_device(service);
359 struct policy_data *data;
360 struct btd_service *target;
362 target = btd_device_get_service(dev, AVRCP_TARGET_UUID);
366 data = policy_get_data(dev);
369 case BTD_SERVICE_STATE_UNAVAILABLE:
370 if (data->source_timer > 0) {
371 g_source_remove(data->source_timer);
372 data->source_timer = 0;
375 case BTD_SERVICE_STATE_DISCONNECTED:
376 if (old_state == BTD_SERVICE_STATE_CONNECTING) {
377 int err = btd_service_get_error(service);
379 if (err == -EAGAIN) {
380 if (data->source_retries < SOURCE_RETRIES)
381 policy_set_source_timer(data);
383 data->source_retries = 0;
385 } else if (data->source_timer > 0) {
386 g_source_remove(data->source_timer);
387 data->source_timer = 0;
391 if (data->tg_timer > 0) {
392 g_source_remove(data->tg_timer);
394 #if defined __TIZEN_PATCH__ && defined BT_QUALIFICATION
397 } else if (btd_service_get_state(target) !=
398 BTD_SERVICE_STATE_DISCONNECTED)
399 policy_disconnect(data, target);
402 case BTD_SERVICE_STATE_CONNECTING:
404 case BTD_SERVICE_STATE_CONNECTED:
405 if (data->source_timer > 0) {
406 g_source_remove(data->source_timer);
407 data->source_timer = 0;
410 /* Check if service initiate the connection then proceed
411 * immediatelly otherwise set timer
413 if (old_state == BTD_SERVICE_STATE_CONNECTING)
414 policy_connect(data, target);
415 else if (btd_service_get_state(target) !=
416 BTD_SERVICE_STATE_CONNECTED)
417 policy_set_tg_timer(data, CONTROL_CONNECT_TIMEOUT);
419 case BTD_SERVICE_STATE_DISCONNECTING:
424 static void controller_cb(struct btd_service *service,
425 btd_service_state_t old_state,
426 btd_service_state_t new_state)
428 struct btd_device *dev = btd_service_get_device(service);
429 struct policy_data *data;
431 data = find_data(dev);
436 case BTD_SERVICE_STATE_UNAVAILABLE:
437 if (data->ct_timer > 0) {
438 g_source_remove(data->ct_timer);
442 case BTD_SERVICE_STATE_DISCONNECTED:
443 if (old_state == BTD_SERVICE_STATE_CONNECTING) {
444 int err = btd_service_get_error(service);
446 if (err == -EAGAIN) {
447 if (data->ct_retries < CT_RETRIES)
448 policy_set_ct_timer(data,
451 data->ct_retries = 0;
453 } else if (data->ct_timer > 0) {
454 g_source_remove(data->ct_timer);
457 } else if (old_state == BTD_SERVICE_STATE_CONNECTED) {
458 data->ct_retries = 0;
461 case BTD_SERVICE_STATE_CONNECTING:
463 case BTD_SERVICE_STATE_CONNECTED:
464 if (data->ct_timer > 0) {
465 g_source_remove(data->ct_timer);
469 case BTD_SERVICE_STATE_DISCONNECTING:
474 static void target_cb(struct btd_service *service,
475 btd_service_state_t old_state,
476 btd_service_state_t new_state)
478 struct btd_device *dev = btd_service_get_device(service);
479 struct policy_data *data;
481 data = find_data(dev);
486 case BTD_SERVICE_STATE_UNAVAILABLE:
487 if (data->tg_timer > 0) {
488 g_source_remove(data->tg_timer);
492 case BTD_SERVICE_STATE_DISCONNECTED:
493 if (old_state == BTD_SERVICE_STATE_CONNECTING) {
494 int err = btd_service_get_error(service);
496 if (err == -EAGAIN) {
497 if (data->tg_retries < TG_RETRIES)
498 policy_set_tg_timer(data,
501 data->tg_retries = 0;
503 } else if (data->tg_timer > 0) {
504 g_source_remove(data->tg_timer);
507 } else if (old_state == BTD_SERVICE_STATE_CONNECTED) {
508 data->tg_retries = 0;
511 case BTD_SERVICE_STATE_CONNECTING:
513 case BTD_SERVICE_STATE_CONNECTED:
514 if (data->tg_timer > 0) {
515 g_source_remove(data->tg_timer);
519 case BTD_SERVICE_STATE_DISCONNECTING:
524 static void reconnect_reset(struct reconnect_data *reconnect)
526 reconnect->attempt = 0;
528 if (reconnect->timer > 0) {
529 g_source_remove(reconnect->timer);
530 reconnect->timer = 0;
534 static bool reconnect_match(const char *uuid)
538 if (!reconnect_uuids)
541 for (str = reconnect_uuids; *str; str++) {
542 if (!bt_uuid_strcmp(uuid, *str))
549 static struct reconnect_data *reconnect_find(struct btd_device *dev)
553 for (l = reconnects; l; l = g_slist_next(l)) {
554 struct reconnect_data *reconnect = l->data;
556 if (reconnect->dev == dev)
563 static struct reconnect_data *reconnect_add(struct btd_service *service)
565 struct btd_device *dev = btd_service_get_device(service);
566 struct reconnect_data *reconnect;
568 reconnect = reconnect_find(dev);
570 reconnect = g_new0(struct reconnect_data, 1);
571 reconnect->dev = dev;
572 reconnects = g_slist_append(reconnects, reconnect);
575 if (g_slist_find(reconnect->services, service))
578 reconnect->services = g_slist_append(reconnect->services,
579 btd_service_ref(service));
584 static void reconnect_destroy(gpointer data)
586 struct reconnect_data *reconnect = data;
588 if (reconnect->timer > 0)
589 g_source_remove(reconnect->timer);
591 g_slist_free_full(reconnect->services,
592 (GDestroyNotify) btd_service_unref);
596 static void reconnect_remove(struct btd_service *service)
598 struct btd_device *dev = btd_service_get_device(service);
599 struct reconnect_data *reconnect;
602 reconnect = reconnect_find(dev);
606 l = g_slist_find(reconnect->services, service);
610 reconnect->services = g_slist_delete_link(reconnect->services, l);
611 btd_service_unref(service);
613 if (reconnect->services)
616 reconnects = g_slist_remove(reconnects, reconnect);
618 if (reconnect->timer > 0)
619 g_source_remove(reconnect->timer);
624 static void service_cb(struct btd_service *service,
625 btd_service_state_t old_state,
626 btd_service_state_t new_state,
629 struct btd_profile *profile = btd_service_get_profile(service);
630 struct reconnect_data *reconnect;
632 if (g_str_equal(profile->remote_uuid, A2DP_SINK_UUID))
633 sink_cb(service, old_state, new_state);
634 else if (g_str_equal(profile->remote_uuid, A2DP_SOURCE_UUID))
635 source_cb(service, old_state, new_state);
636 else if (g_str_equal(profile->remote_uuid, AVRCP_REMOTE_UUID))
637 controller_cb(service, old_state, new_state);
638 else if (g_str_equal(profile->remote_uuid, AVRCP_TARGET_UUID))
639 target_cb(service, old_state, new_state);
642 * Return if the reconnection feature is not enabled (all
643 * subsequent code in this function is about that).
645 if (!reconnect_uuids || !reconnect_uuids[0])
649 * We're only interested in reconnecting profiles which have set
650 * auto_connect to true.
652 if (!profile->auto_connect)
656 * If the service went away remove it from the reconnection
657 * tracking. The function will remove the entire tracking data
658 * if this was the last service for the device.
660 if (new_state == BTD_SERVICE_STATE_UNAVAILABLE) {
661 reconnect_remove(service);
665 if (new_state != BTD_SERVICE_STATE_CONNECTED)
669 * Add an entry to track reconnections. The function will return
670 * an existing entry if there is one.
672 reconnect = reconnect_add(service);
674 reconnect->active = false;
675 reconnect_reset(reconnect);
678 * Should this device be reconnected? A matching UUID might not
679 * be the first profile that's connected so we might have an
680 * entry but with the reconnect flag set to false.
682 if (!reconnect->reconnect)
683 reconnect->reconnect = reconnect_match(profile->remote_uuid);
685 DBG("Added %s reconnect %u", profile->name, reconnect->reconnect);
688 static gboolean reconnect_timeout(gpointer data)
690 struct reconnect_data *reconnect = data;
693 DBG("Reconnecting profiles");
695 /* Mark the GSource as invalid */
696 reconnect->timer = 0;
698 err = btd_device_connect_services(reconnect->dev, reconnect->services);
700 error("Reconnecting services failed: %s (%d)",
701 strerror(-err), -err);
702 reconnect_reset(reconnect);
706 reconnect->active = true;
707 reconnect->attempt++;
712 static void reconnect_set_timer(struct reconnect_data *reconnect)
714 static int timeout = 0;
716 reconnect->attempt++;
718 if (reconnect->attempt < reconnect_intervals_len)
719 timeout = reconnect_intervals[reconnect->attempt];
721 DBG("%d seconds", timeout);
723 reconnect->timer = g_timeout_add_seconds(timeout, reconnect_timeout,
727 static void disconnect_cb(struct btd_device *dev, uint8_t reason)
729 struct reconnect_data *reconnect;
731 DBG("reason %u", reason);
733 if (reason != MGMT_DEV_DISCONN_TIMEOUT)
736 reconnect = reconnect_find(dev);
737 if (!reconnect || !reconnect->reconnect)
740 DBG("Device %s identified for auto-reconnection",
741 device_get_path(dev));
743 reconnect_set_timer(reconnect);
746 static void conn_fail_cb(struct btd_device *dev, uint8_t status)
748 struct reconnect_data *reconnect;
750 DBG("status %u", status);
752 reconnect = reconnect_find(dev);
753 if (!reconnect || !reconnect->reconnect)
756 if (!reconnect->active)
759 reconnect->active = false;
761 /* Give up if we were powered off */
762 if (status == MGMT_STATUS_NOT_POWERED) {
763 reconnect_reset(reconnect);
767 /* Reset if ReconnectAttempts was reached */
768 if (reconnect->attempt == reconnect_attempts) {
769 reconnect_reset(reconnect);
773 reconnect_set_timer(reconnect);
776 static int policy_adapter_probe(struct btd_adapter *adapter)
780 btd_adapter_restore_powered(adapter);
785 static struct btd_adapter_driver policy_driver = {
787 .probe = policy_adapter_probe,
790 static int policy_init(void)
795 service_id = btd_service_add_state_cb(service_cb, NULL);
797 conf = btd_get_main_conf();
799 reconnect_uuids = g_strdupv((char **) default_reconnect);
800 reconnect_attempts = default_attempts;
801 reconnect_intervals_len = sizeof(default_intervals) /
802 sizeof(*reconnect_intervals);
803 reconnect_intervals = g_memdup(default_intervals,
804 reconnect_intervals_len);
808 reconnect_uuids = g_key_file_get_string_list(conf, "Policy",
812 g_clear_error(&gerr);
813 reconnect_uuids = g_strdupv((char **) default_reconnect);
816 reconnect_attempts = g_key_file_get_integer(conf, "Policy",
820 g_clear_error(&gerr);
821 reconnect_attempts = default_attempts;
824 reconnect_intervals = g_key_file_get_integer_list(conf, "Policy",
825 "ReconnectIntervals",
826 (size_t *) &reconnect_intervals_len,
829 g_clear_error(&gerr);
830 reconnect_intervals_len = sizeof(default_intervals);
831 reconnect_intervals = g_memdup(default_intervals,
832 reconnect_intervals_len);
835 auto_enable = g_key_file_get_boolean(conf, "Policy", "AutoEnable",
839 if (reconnect_uuids && reconnect_uuids[0] && reconnect_attempts) {
840 btd_add_disconnect_cb(disconnect_cb);
841 btd_add_conn_fail_cb(conn_fail_cb);
845 btd_register_adapter_driver(&policy_driver);
850 static void policy_exit(void)
852 btd_remove_disconnect_cb(disconnect_cb);
853 btd_remove_conn_fail_cb(conn_fail_cb);
856 g_strfreev(reconnect_uuids);
858 g_free(reconnect_intervals);
860 g_slist_free_full(reconnects, reconnect_destroy);
862 g_slist_free_full(devices, policy_remove);
864 btd_service_remove_state_cb(service_id);
867 btd_unregister_adapter_driver(&policy_driver);
870 BLUETOOTH_PLUGIN_DEFINE(policy, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
871 policy_init, policy_exit)