bool connecting;
int fd;
- uint8_t codec;
+ int (*acquire)(struct hf_audio_card *card);
pa_bluetooth_transport *transport;
};
return p;
}
+static DBusMessage *card_send(struct hf_audio_card *card, const char *method, DBusError *err)
+{
+ pa_bluetooth_transport *t = card->transport;
+ DBusMessage *m, *r;
+
+ pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.ofono.HandsfreeAudioCard", method));
+ r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(card->backend->connection), m, -1, err);
+ dbus_message_unref(m);
+
+ return r;
+}
+
+static int card_connect(struct hf_audio_card *card) {
+ DBusMessage *r;
+ DBusError err;
+
+ if (card->connecting)
+ return -EAGAIN;
+
+ card->connecting = true;
+
+ dbus_error_init(&err);
+ r = card_send(card, "Connect", &err);
+
+ if (!r) {
+ pa_log_error("Failed to connect %s: %s", err.name, err.message);
+ card->connecting = false;
+ dbus_error_free(&err);
+ return -1;
+ }
+
+ dbus_message_unref(r);
+
+ if (card->connecting)
+ return -EAGAIN;
+
+ return 0;
+}
+
+static int card_acquire(struct hf_audio_card *card) {
+ int fd;
+ uint8_t codec;
+ DBusMessage *r;
+ DBusError err;
+
+ /* Try acquiring the stream first which was introduced in 1.21 */
+ dbus_error_init(&err);
+ r = card_send(card, "Acquire", &err);
+
+ if (!r) {
+ if (!pa_streq(err.name, DBUS_ERROR_UNKNOWN_METHOD)) {
+ pa_log_error("Failed to acquire %s: %s", err.name, err.message);
+ dbus_error_free(&err);
+ return -1;
+ }
+ dbus_error_free(&err);
+ /* Fallback to Connect as this might be an old version of ofono */
+ card->acquire = card_connect;
+ return card_connect(card);
+ }
+
+ if ((dbus_message_get_args(r, NULL, DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_BYTE, &codec,
+ DBUS_TYPE_INVALID) == true)) {
+ dbus_message_unref(r);
+ if (codec != HFP_AUDIO_CODEC_CVSD) {
+ pa_log_error("Invalid codec: %u", codec);
+ /* shutdown to make sure connection is dropped immediately */
+ shutdown(fd, SHUT_RDWR);
+ close(fd);
+ return -1;
+ }
+ card->transport->codec = codec;
+ card->fd = fd;
+ return 0;
+ }
+
+ pa_log_error("Unable to acquire");
+ dbus_message_unref(r);
+ return -1;
+}
+
static struct hf_audio_card *hf_audio_card_new(pa_bluetooth_backend *backend, const char *path) {
struct hf_audio_card *card = pa_xnew0(struct hf_audio_card, 1);
card->path = pa_xstrdup(path);
card->backend = backend;
card->fd = -1;
+ card->acquire = card_acquire;
return card;
}
pa_assert(card);
if (!optional && card->fd < 0) {
- DBusMessage *m, *r;
- DBusError derr;
-
- if (card->connecting)
- return -EAGAIN;
-
- card->connecting = true;
-
- dbus_error_init(&derr);
- pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.ofono.HandsfreeAudioCard", "Connect"));
- r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(card->backend->connection), m, -1, &derr);
- dbus_message_unref(m);
- m = NULL;
-
- if (!r)
- return -1;
-
- dbus_message_unref(r);
- r = NULL;
-
- if (card->connecting)
- return -EAGAIN;
+ err = card->acquire(card);
+ if (err < 0)
+ return err;
}
/* The correct block size should take into account the SCO MTU from
if (omtu)
*omtu = 48;
- t->codec = card->codec;
-
err = socket_accept(card->fd);
if (err < 0) {
pa_log_error("Deferred setup failed on fd %d: %s", card->fd, pa_cstrerror(-err));