static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct hfp *hfp; struct ofono_modem *modem; struct sockaddr_rc saddr; socklen_t optlen; DBusMessageIter entry; const char *device, *driver; char local[18], remote[18]; uint16_t version = HFP_VERSION_1_5; int fd, err; DBG("Profile handler NewConnection"); if (dbus_message_iter_init(msg, &entry) == FALSE) goto invalid; if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_OBJECT_PATH) goto invalid; dbus_message_iter_get_basic(&entry, &device); dbus_message_iter_next(&entry); if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_UNIX_FD) goto invalid; dbus_message_iter_get_basic(&entry, &fd); if (fd < 0) goto invalid; dbus_message_iter_next(&entry); if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_ARRAY) goto invalid; if (get_version(&entry, &version) < 0) goto invalid; DBG("version: %hd", version); modem = ofono_modem_find(device_path_compare, (void *) device); if (modem == NULL) { close(fd); return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected", "Unknown Bluetooth device"); } err = service_level_connection(modem, fd, version); if (err < 0 && err != -EINPROGRESS) { close(fd); return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected", "Not enough resources"); } memset(&saddr, 0, sizeof(saddr)); optlen = sizeof(saddr); if (getsockname(fd, (struct sockaddr *) &saddr, &optlen) < 0) { err = errno; ofono_error("RFCOMM getsockname(): %s (%d)", strerror(err), err); close(fd); goto invalid; } bt_ba2str(&saddr.rc_bdaddr, local); memset(&saddr, 0, sizeof(saddr)); optlen = sizeof(saddr); if (getpeername(fd, (struct sockaddr *) &saddr, &optlen) < 0) { err = errno; ofono_error("RFCOMM getpeername(): %s (%d)", strerror(err), err); close(fd); goto invalid; } bt_ba2str(&saddr.rc_bdaddr, remote); hfp = ofono_modem_get_data(modem); hfp->msg = dbus_message_ref(msg); driver = NULL; if (version >= HFP_VERSION_1_6) driver = HFP16_HF_DRIVER; hfp->card = ofono_handsfree_card_create(0, driver, hfp); ofono_handsfree_card_set_data(hfp->card, hfp); ofono_handsfree_card_set_local(hfp->card, local); ofono_handsfree_card_set_remote(hfp->card, remote); return NULL; invalid: return g_dbus_create_error(msg, BLUEZ_ERROR_INTERFACE ".Rejected", "Invalid arguments in method call"); }
static gboolean sco_accept(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct ofono_handsfree_card *card; struct sockaddr_sco saddr; socklen_t alen; int sk, nsk; char local[18], remote[18]; if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) return FALSE; sk = g_io_channel_unix_get_fd(io); memset(&saddr, 0, sizeof(saddr)); alen = sizeof(saddr); nsk = accept(sk, (struct sockaddr *) &saddr, &alen); if (nsk < 0) return TRUE; if (agent == NULL) { ofono_error("Reject SCO: Agent not registered"); close(nsk); return TRUE; } bt_ba2str(&saddr.sco_bdaddr, remote); memset(&saddr, 0, sizeof(saddr)); alen = sizeof(saddr); if (getsockname(nsk, (struct sockaddr *) &saddr, &alen) < 0) { ofono_error("SCO getsockname(): %s (%d)", strerror(errno), errno); close(nsk); return TRUE; } bt_ba2str(&saddr.sco_bdaddr, local); card = card_find(remote, local); if (card == NULL || card->path == NULL) { ofono_error("Rejecting SCO: Audio Card not found!"); close(nsk); return TRUE; } if (apply_settings_from_codec(nsk, card->selected_codec) == FALSE) { close(nsk); return TRUE; } DBG("SCO connection setup between local: %s and remote: %s", local, remote); send_new_connection(card->path, nsk, card->selected_codec); close(nsk); if (card->driver->sco_connected_hint) card->driver->sco_connected_hint(card); return TRUE; }