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 void avctp_confirm_cb(GIOChannel *chan, gpointer data) { struct avctp *session; struct audio_device *dev; 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 = adapter_find_device(adapter_find(&src), &dst); if (!device) return; session = avctp_get_internal(device); if (session == NULL) return; dev = manager_get_audio_device(device, TRUE); if (!dev) { error("Unable to get audio device object for %s", address); goto drop; } if (dev->control == NULL) { btd_device_add_uuid(dev->btd_dev, AVRCP_REMOTE_UUID); if (dev->control == NULL) goto drop; } switch (psm) { case AVCTP_CONTROL_PSM: avctp_control_confirm(session, chan, dev); break; case AVCTP_BROWSING_PSM: avctp_browsing_confirm(session, chan, dev); break; } return; drop: if (psm == AVCTP_CONTROL_PSM) avctp_set_state(session, AVCTP_STATE_DISCONNECTED); }
static void avctp_confirm_cb(GIOChannel *chan, gpointer data) { struct control *control = NULL; struct audio_device *dev; char address[18]; bdaddr_t src, dst; GError *err = NULL; bt_io_get(chan, BT_IO_L2CAP, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); g_io_channel_shutdown(chan, TRUE, NULL); return; } dev = manager_get_device(&src, &dst, TRUE); if (!dev) { error("Unable to get audio device object for %s", address); goto drop; } if (!dev->control) { btd_device_add_uuid(dev->btd_dev, AVRCP_REMOTE_UUID); if (!dev->control) goto drop; } control = dev->control; if (control->io) { error("Refusing unexpected connect from %s", address); goto drop; } avctp_set_state(control, AVCTP_STATE_CONNECTING); control->io = g_io_channel_ref(chan); if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID, auth_cb, dev->control) < 0) goto drop; control->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL, control_cb, control); return; drop: if (!control || !control->io) g_io_channel_shutdown(chan, TRUE, NULL); if (control) avctp_set_state(control, AVCTP_STATE_DISCONNECTED); }
static void hf_io_cb(GIOChannel *chan, gpointer data) { bdaddr_t src, dst; GError *err = NULL; uint8_t ch; const char *server_uuid, *remote_uuid; struct audio_device *device; int perr; bt_io_get(chan, BT_IO_RFCOMM, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_CHANNEL, &ch, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); return; } server_uuid = HFP_AG_UUID; remote_uuid = HFP_HS_UUID; device = manager_get_device(&src, &dst, TRUE); if (!device) goto drop; if (!device->gateway) { btd_device_add_uuid(device->btd_dev, remote_uuid); if (!device->gateway) goto drop; } if (gateway_is_connected(device)) { DBG("Refusing new connection since one already exists"); goto drop; } if (gateway_connect_rfcomm(device, chan) < 0) { error("Allocating new GIOChannel failed!"); goto drop; } perr = audio_device_request_authorization(device, server_uuid, gateway_auth_cb, device); if (perr < 0) { DBG("Authorization denied!"); goto drop; } return; drop: g_io_channel_shutdown(chan, TRUE, NULL); }
static void avctp_confirm_cb(GIOChannel *chan, gpointer data) { struct avctp *session; struct audio_device *dev; char address[18]; bdaddr_t src, dst; GError *err = NULL; bt_io_get(chan, BT_IO_L2CAP, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_DEST, address, 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); session = avctp_get_internal(&src, &dst); if (!session) goto drop; dev = manager_get_device(&src, &dst, FALSE); if (!dev) { dev = manager_get_device(&src, &dst, TRUE); if (!dev) { error("Unable to get audio device object for %s", address); goto drop; } } if (dev->control == NULL) { btd_device_add_uuid(dev->btd_dev, AVRCP_REMOTE_UUID); if (dev->control == NULL) goto drop; } if (session->io) { /* AVCTP collision fix. (Collision was found with Sony headset DR-BT30Q). */ DBG("Canceling outgoing and accepting incoming connection from %s", address); avctp_disconnected(session); session = avctp_get_internal(&src, &dst); if (!session) goto drop; } avctp_set_state(session, AVCTP_STATE_CONNECTING); session->io = g_io_channel_ref(chan); if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID, auth_cb, session) < 0) goto drop; session->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL, session_cb, session); return; drop: if (!session || !session->io) g_io_channel_shutdown(chan, TRUE, NULL); if (session) avctp_set_state(session, AVCTP_STATE_DISCONNECTED); }
static void ag_confirm(GIOChannel *chan, gpointer data) { const char *server_uuid, *remote_uuid; struct audio_device *device; gboolean hfp_active; bdaddr_t src, dst; int perr; GError *err = NULL; uint8_t ch; bt_io_get(chan, BT_IO_RFCOMM, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_CHANNEL, &ch, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); goto drop; } if (ch == DEFAULT_HS_AG_CHANNEL) { hfp_active = FALSE; server_uuid = HSP_AG_UUID; remote_uuid = HSP_HS_UUID; } else { hfp_active = TRUE; server_uuid = HFP_AG_UUID; remote_uuid = HFP_HS_UUID; } device = manager_get_device(&src, &dst, TRUE); if (!device) goto drop; if (!manager_allow_headset_connection(device)) { DBG("Refusing headset: too many existing connections"); goto drop; } if (!device->headset) { btd_device_add_uuid(device->btd_dev, remote_uuid); if (!device->headset) goto drop; } if (headset_get_state(device) > HEADSET_STATE_DISCONNECTED) { DBG("Refusing new connection since one already exists"); goto drop; } set_hfp_active(device, hfp_active); if (headset_connect_rfcomm(device, chan) < 0) { error("headset_connect_rfcomm failed"); goto drop; } headset_set_state(device, HEADSET_STATE_CONNECTING); perr = audio_device_request_authorization(device, server_uuid, headset_auth_cb, device); if (perr < 0) { DBG("Authorization denied: %s", strerror(-perr)); headset_set_state(device, HEADSET_STATE_DISCONNECTED); return; } device->hs_preauth_id = g_io_add_watch(chan, G_IO_NVAL | G_IO_HUP | G_IO_ERR, hs_preauth_cb, device); device->auto_connect = auto_connect; return; drop: g_io_channel_shutdown(chan, TRUE, NULL); }