static void avctp_confirm_cb(GIOChannel *chan, gpointer data) { struct avctp *session; char address[18]; bdaddr_t src, dst; GError *err = NULL; uint16_t psm; struct btd_device *device; bt_io_get(chan, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_DEST, address, BT_IO_OPT_PSM, &psm, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); g_io_channel_shutdown(chan, TRUE, NULL); return; } DBG("AVCTP: incoming connect from %s", address); device = btd_adapter_find_device(adapter_find(&src), &dst, BDADDR_BREDR); if (!device) return; session = avctp_get_internal(device); if (session == NULL) return; if (btd_device_get_service(device, AVRCP_REMOTE_UUID) == NULL) btd_device_add_uuid(device, AVRCP_REMOTE_UUID); if (btd_device_get_service(device, AVRCP_TARGET_UUID) == NULL) btd_device_add_uuid(device, AVRCP_TARGET_UUID); switch (psm) { case AVCTP_CONTROL_PSM: avctp_control_confirm(session, chan, device); break; case AVCTP_BROWSING_PSM: avctp_browsing_confirm(session, chan, device); break; } return; }
static int media_transport_init_sink(struct media_transport *transport) { struct btd_service *service; struct a2dp_transport *a2dp; service = btd_device_get_service(transport->device, A2DP_SOURCE_UUID); if (service == NULL) return -EINVAL; a2dp = g_new0(struct a2dp_transport, 1); transport->resume = resume_a2dp; transport->suspend = suspend_a2dp; transport->cancel = cancel_a2dp; transport->data = a2dp; transport->destroy = destroy_a2dp; a2dp->volume = 127; avrcp_set_volume(transport->device, a2dp->volume); transport->source_watch = source_add_state_cb(service, source_state_changed, transport); return 0; }
static void source_cb(struct btd_service *service, btd_service_state_t old_state, btd_service_state_t new_state) { struct btd_device *dev = btd_service_get_device(service); struct policy_data *data; struct btd_service *target; target = btd_device_get_service(dev, AVRCP_TARGET_UUID); if (target == NULL) return; data = policy_get_data(dev); switch (new_state) { case BTD_SERVICE_STATE_UNAVAILABLE: case BTD_SERVICE_STATE_DISCONNECTED: if (old_state == BTD_SERVICE_STATE_CONNECTING) { int err = btd_service_get_error(service); if (err == -EAGAIN) { if (data->source_retries < SOURCE_RETRIES) policy_set_source_timer(data); else data->source_retries = 0; break; } else if (data->source_timer > 0) { g_source_remove(data->source_timer); data->source_timer = 0; } } if (data->tg_timer > 0) { g_source_remove(data->tg_timer); data->tg_timer = 0; } else if (btd_service_get_state(target) != BTD_SERVICE_STATE_DISCONNECTED) policy_disconnect(data, target); break; case BTD_SERVICE_STATE_CONNECTING: break; case BTD_SERVICE_STATE_CONNECTED: if (data->source_timer > 0) { g_source_remove(data->source_timer); data->source_timer = 0; } /* Check if service initiate the connection then proceed * immediatelly otherwise set timer */ if (old_state == BTD_SERVICE_STATE_CONNECTING) policy_connect(data, target); else if (btd_service_get_state(target) != BTD_SERVICE_STATE_CONNECTED) policy_set_tg_timer(data); break; case BTD_SERVICE_STATE_DISCONNECTING: break; } }
static gboolean auto_config(gpointer data) { struct a2dp_setup *setup = data; struct btd_device *dev = avdtp_get_device(setup->session); struct btd_service *service; /* Check if configuration was aborted */ if (setup->sep->stream == NULL) return FALSE; if (setup->err != NULL) goto done; avdtp_stream_add_cb(setup->session, setup->stream, stream_state_changed, setup->sep); if (setup->sep->type == AVDTP_SEP_TYPE_SOURCE) { service = btd_device_get_service(dev, A2DP_SINK_UUID); sink_new_stream(service, setup->session, setup->stream); } else { service = btd_device_get_service(dev, A2DP_SOURCE_UUID); source_new_stream(service, setup->session, setup->stream); } done: if (setup->setconf_cb) setup->setconf_cb(setup->session, setup->stream, setup->err); finalize_config(setup); if (setup->err) { g_free(setup->err); setup->err = NULL; } setup_unref(setup); return FALSE; }
static gboolean policy_connect_tg(gpointer user_data) { struct policy_data *data = user_data; struct btd_service *service; data->tg_timer = 0; service = btd_device_get_service(data->dev, AVRCP_TARGET_UUID); if (service != NULL) policy_connect(data, service); return FALSE; }
static gboolean policy_connect_source(gpointer user_data) { struct policy_data *data = user_data; struct btd_service *service; data->source_timer = 0; data->source_retries++; service = btd_device_get_service(data->dev, A2DP_SOURCE_UUID); if (service != NULL) policy_connect(data, service); return FALSE; }
static gboolean policy_connect_ct(gpointer user_data) { struct policy_data *data = user_data; struct btd_service *service; data->ct_timer = 0; data->ct_retries++; service = btd_device_get_service(data->dev, AVRCP_REMOTE_UUID); if (service != NULL) policy_connect(data, service); return FALSE; }
static struct input_device *find_device(const bdaddr_t *src, const bdaddr_t *dst) { struct btd_device *device; struct btd_service *service; device = btd_adapter_find_device(adapter_find(src), dst); if (device == NULL) return NULL; service = btd_device_get_service(device, HID_UUID); if (service == NULL) return NULL; return btd_service_get_user_data(service); }
static DBusMessage *local_connect(DBusConnection *conn, DBusMessage *msg, void *data) { struct network_peer *peer = data; struct btd_service *service; struct network_conn *nc; const char *svc; const char *uuid; uint16_t id; int err; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc, DBUS_TYPE_INVALID) == FALSE) return btd_error_invalid_args(msg); id = bnep_service_id(svc); uuid = bnep_uuid(id); if (uuid == NULL) return btd_error_invalid_args(msg); service = btd_device_get_service(peer->device, uuid); if (service == NULL) return btd_error_not_supported(msg); nc = btd_service_get_user_data(service); if (nc->connect != NULL) return btd_error_busy(msg); err = connection_connect(nc->service); if (err < 0) return btd_error_failed(msg, strerror(-err)); nc->connect = dbus_message_ref(msg); return NULL; }
static void sink_cb(struct btd_service *service, btd_service_state_t old_state, btd_service_state_t new_state) { struct btd_device *dev = btd_service_get_device(service); struct policy_data *data; struct btd_service *controller; controller = btd_device_get_service(dev, AVRCP_REMOTE_UUID); if (controller == NULL) return; data = policy_get_data(dev); switch (new_state) { case BTD_SERVICE_STATE_UNAVAILABLE: if (data->sink_timer > 0) { g_source_remove(data->sink_timer); data->sink_timer = 0; } break; case BTD_SERVICE_STATE_DISCONNECTED: if (old_state == BTD_SERVICE_STATE_CONNECTING) { int err = btd_service_get_error(service); if (err == -EAGAIN) { if (data->sink_retries < SINK_RETRIES) policy_set_sink_timer(data); else data->sink_retries = 0; break; } else if (data->sink_timer > 0) { g_source_remove(data->sink_timer); data->sink_timer = 0; } } if (data->ct_timer > 0) { g_source_remove(data->ct_timer); data->ct_timer = 0; } else if (btd_service_get_state(controller) != BTD_SERVICE_STATE_DISCONNECTED) policy_disconnect(data, controller); break; case BTD_SERVICE_STATE_CONNECTING: break; case BTD_SERVICE_STATE_CONNECTED: if (data->sink_timer > 0) { g_source_remove(data->sink_timer); data->sink_timer = 0; } /* Check if service initiate the connection then proceed * immediatelly otherwise set timer */ if (old_state == BTD_SERVICE_STATE_CONNECTING) policy_connect(data, controller); else if (btd_service_get_state(controller) != BTD_SERVICE_STATE_CONNECTED) policy_set_ct_timer(data, CONTROL_CONNECT_TIMEOUT); break; case BTD_SERVICE_STATE_DISCONNECTING: break; } }