static DBusMessage *sink_connect(DBusConnection *conn, DBusMessage *msg, void *data) { struct audio_device *dev = data; struct sink *sink = dev->sink; struct pending_request *pending; if (!sink->session) sink->session = avdtp_get(&dev->src, &dev->dst); if (!sink->session) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Unable to get a session"); if (sink->connect || sink->disconnect) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "%s", strerror(EBUSY)); if (sink->state >= AVDTP_STATE_OPEN) return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyConnected", "Device Already Connected"); pending = g_new0(struct pending_request, 1); pending->conn = dbus_connection_ref(conn); pending->msg = dbus_message_ref(msg); sink->connect = pending; avdtp_discover(sink->session, discovery_complete, sink); debug("stream creation in progress"); return NULL; }
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data) { uint16_t imtu, omtu; GError *gerr = NULL; int fd; if (err) { printf("%s\n", err->message); g_main_loop_quit(mainloop); return; } bt_io_get(chan, &gerr, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_OMTU, &omtu, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_INVALID); if (gerr) { printf("%s\n", gerr->message); g_main_loop_quit(mainloop); return; } printf("Connected (imtu=%d omtu=%d)\n", imtu, omtu); fd = g_io_channel_unix_get_fd(chan); if (avdtp && avdtp_stream) { if (!avdtp_stream_set_transport(avdtp_stream, fd, imtu, omtu)) { printf("avdtp_stream_set_transport: failed\n"); g_main_loop_quit(mainloop); } g_io_channel_set_close_on_unref(chan, FALSE); send_command(); return; } avdtp = avdtp_new(fd, imtu, omtu, version); if (!avdtp) { printf("Failed to create avdtp instance\n"); g_main_loop_quit(mainloop); return; } avdtp_add_disconnect_cb(avdtp, disconnect_cb, NULL); if (preconf) { int ret; ret = avdtp_discover(avdtp, discover_cb, NULL); if (ret < 0) { printf("avdtp_discover failed: %s", strerror(-ret)); g_main_loop_quit(mainloop); } } }
static void signaling_connect_cb(GIOChannel *chan, GError *err, gpointer user_data) { struct a2dp_device *dev = user_data; uint16_t imtu, omtu; GError *gerr = NULL; int fd; if (err) { bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED); error("%s", err->message); return; } bt_io_get(chan, &gerr, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_OMTU, &omtu, BT_IO_OPT_INVALID); if (gerr) { error("%s", gerr->message); g_error_free(gerr); goto failed; } fd = g_io_channel_unix_get_fd(chan); /* FIXME: Add proper version */ dev->session = avdtp_new(fd, imtu, omtu, 0x0100); if (!dev->session) goto failed; avdtp_add_disconnect_cb(dev->session, disconnect_cb, dev); /* Proceed to stream setup if initiator */ if (dev->io) { int perr; g_io_channel_unref(dev->io); dev->io = NULL; perr = avdtp_discover(dev->session, discover_cb, dev); if (perr < 0) { error("avdtp_discover: %s", strerror(-perr)); goto failed; } bt_avrcp_connect(&dev->dst); } else /* Init idle timeout to discover */ dev->idle_id = g_timeout_add_seconds(IDLE_TIMEOUT, idle_timeout, dev); return; failed: bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED); }
int main(int argc, char *argv[]) { bdaddr_t src, dst; int opt, sk, dev_id; if (argc < 2) { usage(); exit(0); } bacpy(&src, BDADDR_ANY); dev_id = hci_get_route(&src); if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) { printf("Cannot find any local adapter\n"); exit(-1); } while ((opt = getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { switch (opt) { case 'i': if (!strncmp(optarg, "hci", 3)) hci_devba(atoi(optarg + 3), &src); else str2ba(optarg, &src); break; case 'h': default: usage(); exit(0); } } printf("Connecting ... \n"); if (bachk(argv[optind]) < 0) { printf("Invalid argument\n"); exit(1); } str2ba(argv[optind], &dst); sk = l2cap_connect(&src, &dst); if (sk < 0) exit(1); if (avdtp_discover(sk) < 0) exit(1); return 0; }
static gboolean idle_timeout(gpointer user_data) { struct a2dp_device *dev = user_data; int err; dev->idle_id = 0; err = avdtp_discover(dev->session, discover_cb, dev); if (err == 0) return FALSE; error("avdtp_discover: %s", strerror(-err)); bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED); return FALSE; }
gboolean source_setup_stream(struct source *source, struct avdtp *session) { if (source->connect_id > 0 || source->disconnect_id > 0) return FALSE; if (session && !source->session) source->session = avdtp_ref(session); if (!source->session) return FALSE; if (avdtp_discover(source->session, discovery_complete, source) < 0) return FALSE; return TRUE; }
gboolean sink_setup_stream(struct sink *sink, struct avdtp *session) { if (sink->connect_id > 0 || sink->disconnect_id > 0) return FALSE; if (session && !sink->session) sink->session = avdtp_ref(session); if (!sink->session) return FALSE; if (avdtp_discover(sink->session, discovery_complete, sink) < 0) return FALSE; return TRUE; }
static void start_discovery(struct audio_device *dev, struct unix_client *client) { struct a2dp_data *a2dp; int err = 0; switch (client->type) { case TYPE_SINK: case TYPE_SOURCE: a2dp = &client->d.a2dp; if (!a2dp->session) a2dp->session = avdtp_get(&dev->src, &dev->dst); if (!a2dp->session) { error("Unable to get a session"); goto failed; } err = avdtp_discover(a2dp->session, a2dp_discovery_complete, client); if (err) { if (a2dp->session) { avdtp_unref(a2dp->session); a2dp->session = NULL; } goto failed; } break; case TYPE_HEADSET: case TYPE_GATEWAY: headset_discovery_complete(dev, client); break; default: error("No known services for device"); goto failed; } client->dev = dev; return; failed: unix_ipc_error(client, BT_GET_CAPABILITIES, err ? : EIO); }
gboolean sink_setup_stream(struct btd_service *service, struct avdtp *session) { struct sink *sink = btd_service_get_user_data(service); if (sink->connect_id > 0 || sink->disconnect_id > 0) return FALSE; if (session && !sink->session) sink->session = avdtp_ref(session); if (!sink->session) return FALSE; if (avdtp_discover(sink->session, discovery_complete, sink) < 0) return FALSE; return TRUE; }
gboolean sink_setup_stream(struct sink *sink, struct avdtp *session) { if (sink->connect || sink->disconnect) return FALSE; if (session && !sink->session) sink->session = avdtp_ref(session); if (!sink->session) return FALSE; avdtp_set_auto_disconnect(sink->session, FALSE); if (avdtp_discover(sink->session, discovery_complete, sink) < 0) return FALSE; sink->connect = g_new0(struct pending_request, 1); return TRUE; }