gboolean sink_shutdown(struct sink *sink) { if (!sink->session) return FALSE; avdtp_set_device_disconnect(sink->session, TRUE); /* cancel pending connect */ if (sink->connect) { struct pending_request *pending = sink->connect; if (pending->msg) error_failed(pending->conn, pending->msg, "Stream setup failed"); pending_request_free(sink->dev, pending); sink->connect = NULL; avdtp_unref(sink->session); sink->session = NULL; return TRUE; } /* disconnect already ongoing */ if (sink->disconnect) return TRUE; if (!sink->stream) return FALSE; if (avdtp_close(sink->session, sink->stream, FALSE) < 0) return FALSE; return TRUE; }
int source_disconnect(struct btd_service *service) { struct source *source = btd_service_get_user_data(service); if (!source->session) return -ENOTCONN; /* cancel pending connect */ if (source->connect_id > 0) { a2dp_cancel(source->connect_id); source->connect_id = 0; btd_service_connecting_complete(source->service, -ECANCELED); avdtp_unref(source->session); source->session = NULL; return 0; } /* disconnect already ongoing */ if (source->disconnect_id > 0) return -EBUSY; if (!source->stream) return -ENOTCONN; return avdtp_close(source->session, source->stream, FALSE); }
static DBusMessage *sink_disconnect(DBusConnection *conn, DBusMessage *msg, void *data) { struct audio_device *device = data; struct sink *sink = device->sink; struct pending_request *pending; int err; if (!sink->session) return btd_error_not_connected(msg); if (sink->connect || sink->disconnect) return btd_error_busy(msg); if (sink->stream_state < AVDTP_STATE_OPEN) { DBusMessage *reply = dbus_message_new_method_return(msg); if (!reply) return NULL; avdtp_unref(sink->session); sink->session = NULL; return reply; } err = avdtp_close(sink->session, sink->stream, FALSE); if (err < 0) return btd_error_failed(msg, strerror(-err)); pending = g_new0(struct pending_request, 1); pending->conn = dbus_connection_ref(conn); pending->msg = dbus_message_ref(msg); sink->disconnect = pending; return NULL; }
static void bt_stream_close(const void *buf, uint16_t len) { const struct audio_cmd_close_stream *cmd = buf; struct a2dp_setup *setup; int err; DBG(""); setup = find_setup(cmd->id); if (!setup) { error("Unable to find stream for endpoint %u", cmd->id); goto failed; } err = avdtp_close(setup->dev->session, setup->stream, FALSE); if (err < 0) { error("avdtp_close: %s", strerror(-err)); goto failed; } ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_CLOSE_STREAM, AUDIO_STATUS_SUCCESS); return; failed: ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_CLOSE_STREAM, AUDIO_STATUS_FAILED); }
static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data) { struct a2dp_sep *a2dp_sep = user_data; struct a2dp_setup *setup; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: ReConfigure_Cfm", sep); else debug("Source %p: ReConfigure_Cfm", sep); setup = find_setup_by_session(session); if (!setup) return; if (setup->canceled) { if (!err) avdtp_close(session, stream); setup_unref(setup); return; } if (err) { setup->stream = NULL; setup->err = err; } finalize_config(setup); }
int source_disconnect(struct audio_device *dev, gboolean shutdown) { struct source *source = dev->source; if (!source->session) return -ENOTCONN; if (shutdown) avdtp_set_device_disconnect(source->session, TRUE); /* cancel pending connect */ if (source->connect_id > 0) { a2dp_cancel(dev, source->connect_id); source->connect_id = 0; audio_source_connected(dev->btd_dev, -ECANCELED); avdtp_unref(source->session); source->session = NULL; return 0; } /* disconnect already ongoing */ if (source->disconnect_id > 0) return -EBUSY; if (!source->stream) return -ENOTCONN; return avdtp_close(source->session, source->stream, FALSE); }
static void send_command(void) { avdtp_state_t state = avdtp_sep_get_state(local_sep); switch (command) { case CMD_GET_CONF: avdtp_get_configuration(avdtp, avdtp_stream); break; case CMD_OPEN: if (state == AVDTP_STATE_CONFIGURED) avdtp_open(avdtp, avdtp_stream); break; case CMD_START: if (state == AVDTP_STATE_OPEN) avdtp_start(avdtp, avdtp_stream); break; case CMD_SUSPEND: if (state == AVDTP_STATE_STREAMING) avdtp_suspend(avdtp , avdtp_stream); break; case CMD_CLOSE: if (state == AVDTP_STATE_STREAMING) avdtp_close(avdtp, avdtp_stream, FALSE); break; case CMD_ABORT: avdtp_abort(avdtp , avdtp_stream); break; case CMD_DELAY: avdtp_delay_report(avdtp , avdtp_stream , 250); break; default: break; } }
int sink_disconnect(struct audio_device *dev, gboolean shutdown) { struct sink *sink = dev->sink; if (!sink->session) return -ENOTCONN; if (shutdown) avdtp_set_device_disconnect(sink->session, TRUE); /* cancel pending connect */ if (sink->connect_id > 0) { a2dp_cancel(dev, sink->connect_id); sink->connect_id = 0; btd_service_connecting_complete(sink->service, -ECANCELED); avdtp_unref(sink->session); sink->session = NULL; return 0; } /* disconnect already ongoing */ if (sink->disconnect_id > 0) return -EBUSY; if (!sink->stream) return -ENOTCONN; return avdtp_close(sink->session, sink->stream, FALSE); }
gboolean sink_shutdown(struct sink *sink) { if (!sink->stream) return FALSE; if (avdtp_close(sink->session, sink->stream, FALSE) < 0) return FALSE; return TRUE; }
static void disconnect_cb(struct btd_device *btd_dev, gboolean removal, void *user_data) { struct audio_device *device = user_data; struct sink *sink = device->sink; DBG("Sink: disconnect %s", device->path); avdtp_close(sink->session, sink->stream, TRUE); }
gboolean source_shutdown(struct source *source) { if (!source->stream) return FALSE; if (avdtp_close(source->session, source->stream) < 0) return FALSE; return TRUE; }
static void disconnect_cb(struct btd_device *btd_dev, gboolean removal, void *user_data) { struct audio_device *device = user_data; struct source *source = device->source; debug("Source: disconnect %s", device->path); avdtp_close(source->session, source->stream); }
void avdtp_free(avdtp_t *avdtp) { struct avdtp_session *session; if (!avdtp) return; session = avdtp; avdtp_close(avdtp); memset(session, 0, sizeof(*session)); free(session); }
static DBusMessage *sink_disconnect(DBusConnection *conn, DBusMessage *msg, void *data) { struct audio_device *device = data; struct sink *sink = device->sink; struct pending_request *pending; int err; if (!sink->session) return g_dbus_create_error(msg, ERROR_INTERFACE ".NotConnected", "Device not Connected"); if (sink->connect || sink->disconnect) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "%s", strerror(EBUSY)); if (sink->state < AVDTP_STATE_OPEN) { DBusMessage *reply = dbus_message_new_method_return(msg); if (!reply) return NULL; avdtp_unref(sink->session); sink->session = NULL; return reply; } err = avdtp_close(sink->session, sink->stream); if (err < 0) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "%s", strerror(-err)); pending = g_new0(struct pending_request, 1); pending->conn = dbus_connection_ref(conn); pending->msg = dbus_message_ref(msg); sink->disconnect = pending; return NULL; }