summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/Makefile.am3
-rw-r--r--audio/headset.c827
-rw-r--r--audio/headset.h49
-rw-r--r--audio/main.c6
-rw-r--r--audio/manager.c369
-rw-r--r--audio/manager.h67
-rw-r--r--audio/unix.c9
7 files changed, 296 insertions, 1034 deletions
diff --git a/audio/Makefile.am b/audio/Makefile.am
index 68648a16..84242544 100644
--- a/audio/Makefile.am
+++ b/audio/Makefile.am
@@ -11,7 +11,8 @@ servicedir = $(libdir)/bluetooth
service_PROGRAMS = bluetoothd-service-audio
bluetoothd_service_audio_SOURCES = main.c \
- manager.h manager.c headset.h headset.c ipc.h unix.h unix.c
+ manager.h manager.c headset.h headset.c ipc.h unix.h unix.c \
+ error.h error.c device.h device.c gateway.h gateway.c
bluetoothd_service_audio_LDADD = $(top_builddir)/common/libhelper.a \
@GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
diff --git a/audio/headset.c b/audio/headset.c
index 723bc1ab..59fe21e7 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -53,10 +53,7 @@
#include "dbus-helper.h"
#include "logging.h"
#include "manager.h"
-#include "headset.h"
-
-#define DEFAULT_HS_AG_CHANNEL 12
-#define DEFAULT_HF_AG_CHANNEL 13
+#include "error.h"
#define RING_INTERVAL 3000
@@ -65,32 +62,12 @@
#define HEADSET_GAIN_SPEAKER 'S'
#define HEADSET_GAIN_MICROPHONE 'M'
-typedef enum {
- HEADSET_EVENT_KEYPRESS,
- HEADSET_EVENT_GAIN,
- HEADSET_EVENT_UNKNOWN,
- HEADSET_EVENT_INVALID
-} headset_event_t;
-
-typedef enum {
- HEADSET_STATE_DISCONNECTED = 0,
- HEADSET_STATE_CONNECT_IN_PROGRESS,
- HEADSET_STATE_CONNECTED,
- HEADSET_STATE_PLAY_IN_PROGRESS,
- HEADSET_STATE_PLAYING,
-} headset_state_t;
-
-typedef enum {
- SVC_HEADSET,
- SVC_HANDSFREE
-} hs_type;
-
struct pending_connect {
DBusMessage *msg;
GIOChannel *io;
guint io_id;
int sock;
- struct ipc_data_cfg *cfg;
+ struct ipc_packet *pkt;
};
struct headset {
@@ -108,7 +85,7 @@ struct headset {
int data_start;
int data_length;
- hs_type type;
+ headset_type_t type;
headset_state_t state;
struct pending_connect *pending_connect;
@@ -120,17 +97,6 @@ struct headset {
static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg,
void *data);
-static gboolean disable_hfp = FALSE;
-static gboolean sco_over_hci = TRUE;
-
-static GIOChannel *hs_server = NULL;
-static GIOChannel *hf_server = NULL;
-
-static uint32_t hs_record_id = 0;
-static uint32_t hf_record_id = 0;
-
-static DBusConnection *connection = NULL;
-
static void pending_connect_free(struct pending_connect *c)
{
if (c->io)
@@ -140,7 +106,7 @@ static void pending_connect_free(struct pending_connect *c)
g_free(c);
}
-static void hs_signal_gain_setting(audio_device_t *device, const char *buf)
+static void hs_signal_gain_setting(struct device *device, const char *buf)
{
const char *name;
dbus_uint16_t gain;
@@ -175,7 +141,7 @@ static void hs_signal_gain_setting(audio_device_t *device, const char *buf)
return;
}
- dbus_connection_emit_signal(connection, device->object_path,
+ dbus_connection_emit_signal(device->conn, device->path,
AUDIO_HEADSET_INTERFACE, name,
DBUS_TYPE_UINT16, &gain,
DBUS_TYPE_INVALID);
@@ -204,7 +170,7 @@ static headset_event_t parse_headset_event(const char *buf, char *rsp,
return HEADSET_EVENT_UNKNOWN;
}
-static void close_sco(audio_device_t *device)
+static void close_sco(struct device *device)
{
struct headset *hs = device->headset;
@@ -213,13 +179,13 @@ static void close_sco(audio_device_t *device)
hs->sco = NULL;
assert(hs->rfcomm);
hs->state = HEADSET_STATE_CONNECTED;
- dbus_connection_emit_signal(connection, device->object_path,
+ dbus_connection_emit_signal(device->conn, device->path,
AUDIO_HEADSET_INTERFACE, "Stopped",
DBUS_TYPE_INVALID);
}
static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond,
- audio_device_t *device)
+ struct device *device)
{
struct headset *hs;
unsigned char buf[BUF_SIZE];
@@ -279,7 +245,7 @@ static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond,
hs->ring_timer = 0;
}
- dbus_connection_emit_signal(connection, device->object_path,
+ dbus_connection_emit_signal(device->conn, device->path,
AUDIO_HEADSET_INTERFACE,
"AnswerRequested",
DBUS_TYPE_INVALID);
@@ -322,75 +288,8 @@ failed:
return FALSE;
}
-static void send_cancel_auth(audio_device_t *device)
-{
- DBusMessage *cancel;
- char addr[18], *address = addr;
- const char *uuid;
-
- if (device->headset->type == SVC_HEADSET)
- uuid = HSP_AG_UUID;
- else
- uuid = HFP_AG_UUID;
-
- cancel = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database",
- "CancelAuthorizationRequest");
- if (!cancel) {
- error("Unable to allocate new method call");
- return;
- }
-
- ba2str(&device->bda, addr);
-
- dbus_message_append_args(cancel, DBUS_TYPE_STRING, &address,
- DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID);
-
- send_message_and_unref(connection, cancel);
-}
-
-static void auth_callback(DBusPendingCall *call, void *data)
-{
- audio_device_t *device = data;
- struct headset *hs = device->headset;
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- DBusError err;
-
- dbus_error_init(&err);
- if (dbus_set_error_from_message(&err, reply)) {
- error("Access denied: %s", err.message);
- if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
- debug("Canceling authorization request");
- send_cancel_auth(device);
- }
- dbus_error_free(&err);
- g_io_channel_close(hs->rfcomm);
- g_io_channel_unref(hs->rfcomm);
- hs->rfcomm = NULL;
- } else {
- char hs_address[18];
-
- g_io_add_watch(hs->rfcomm,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- (GIOFunc) rfcomm_io_cb, device);
-
- ba2str(&device->bda, hs_address);
-
- debug("Accepted headset connection from %s for %s", hs_address,
- device->object_path);
-
- hs->state = HEADSET_STATE_CONNECTED;
- dbus_connection_emit_signal(connection, device->object_path,
- AUDIO_HEADSET_INTERFACE,
- "Connected",
- DBUS_TYPE_INVALID);
- }
-
- dbus_message_unref(reply);
-}
-
static gboolean sco_cb(GIOChannel *chan, GIOCondition cond,
- audio_device_t *device)
+ struct device *device)
{
struct headset *hs;
@@ -407,7 +306,7 @@ static gboolean sco_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
}
-static GIOError headset_send(headset_t *hs, const char *str)
+static GIOError headset_send(struct headset *hs, const char *str)
{
GIOError err;
gsize total_written, written, count;
@@ -434,7 +333,7 @@ static GIOError headset_send(headset_t *hs, const char *str)
}
static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,
- audio_device_t *device)
+ struct device *device)
{
struct headset *hs;
int ret, sk, err, flags;
@@ -467,7 +366,7 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,
goto failed;
}
- debug("SCO socket opened for headset %s", device->object_path);
+ debug("SCO socket opened for headset %s", device->path);
info("SCO fd=%d", sk);
hs->sco = chan;
@@ -480,7 +379,13 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,
if (hs->pending_connect->msg) {
reply = dbus_message_new_method_return(hs->pending_connect->msg);
if (reply)
- send_message_and_unref(connection, reply);
+ send_message_and_unref(device->conn, reply);
+ }
+ else if (hs->pending_connect->pkt) {
+ headset_get_config(device, hs->pending_connect->sock,
+ hs->pending_connect->pkt);
+ unix_send_cfg(hs->pending_connect->sock,
+ hs->pending_connect->pkt);
}
pending_connect_free(hs->pending_connect);
@@ -489,7 +394,7 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,
fcntl(sk, F_SETFL, 0);
hs->state = HEADSET_STATE_PLAYING;
- dbus_connection_emit_signal(connection, device->object_path,
+ dbus_connection_emit_signal(device->conn, device->path,
AUDIO_HEADSET_INTERFACE,
"Playing", DBUS_TYPE_INVALID);
@@ -506,7 +411,7 @@ static gboolean sco_connect_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
failed:
- err_connect_failed(connection, hs->pending_connect->msg, err);
+ err_connect_failed(device->conn, hs->pending_connect->msg, strerror(err));
if (hs->pending_connect->io)
g_io_channel_close(hs->pending_connect->io);
pending_connect_free(hs->pending_connect);
@@ -518,7 +423,7 @@ failed:
return FALSE;
}
-static int sco_connect(audio_device_t *device, struct pending_connect *c)
+static int sco_connect(struct device *device, struct pending_connect *c)
{
struct headset *hs = device->headset;
struct sockaddr_sco addr;
@@ -583,7 +488,7 @@ static int sco_connect(audio_device_t *device, struct pending_connect *c)
}
static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond,
- audio_device_t *device)
+ struct device *device)
{
struct headset *hs;
char hs_address[18];
@@ -620,7 +525,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond,
hs->pending_connect->io = NULL;
hs->state = HEADSET_STATE_CONNECTED;
- dbus_connection_emit_signal(connection, device->object_path,
+ dbus_connection_emit_signal(device->conn, device->path,
AUDIO_HEADSET_INTERFACE,
"Connected", DBUS_TYPE_INVALID);
@@ -634,7 +539,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond,
reply = dbus_message_new_method_return(hs->pending_connect->msg);
if (reply)
- send_message_and_unref(connection, reply);
+ send_message_and_unref(device->conn, reply);
}
pending_connect_free(hs->pending_connect);
@@ -643,7 +548,7 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;
failed:
- err_connect_failed(connection, hs->pending_connect->msg, err);
+ err_connect_failed(device->conn, hs->pending_connect->msg, strerror(err));
if (hs->pending_connect->io)
g_io_channel_close(hs->pending_connect->io);
pending_connect_free(hs->pending_connect);
@@ -654,7 +559,7 @@ failed:
return FALSE;
}
-static int rfcomm_connect(audio_device_t *device, int *err)
+static int rfcomm_connect(struct device *device, int *err)
{
struct headset *hs = device->headset;
struct sockaddr_rc addr;
@@ -735,219 +640,6 @@ failed:
return -1;
}
-static int create_hsp_ag_record(sdp_buf_t *buf, uint8_t ch)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
- uuid_t l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- sdp_data_t *channel;
- int ret;
-
- memset(&record, 0, sizeof(sdp_record_t));
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &ch);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Headset Audio Gateway", 0, 0);
-
- if (sdp_gen_record_pdu(&record, buf) < 0)
- ret = -1;
- else
- ret = 0;
-
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(pfseq, 0);
- sdp_list_free(aproto, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, 0);
- sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);
- sdp_list_free(record.pattern, free);
-
- return ret;
-}
-
-static int create_hfp_ag_record(sdp_buf_t *buf, uint8_t ch)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
- uuid_t l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t record;
- uint16_t u16 = 0x0009;
- sdp_data_t *channel, *features;
- uint8_t netid = 0x01;
- sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
- int ret;
-
- memset(&record, 0, sizeof(sdp_record_t));
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(0, &root_uuid);
- sdp_set_browse_groups(&record, root);
-
- sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
- svclass_id = sdp_list_append(0, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(&record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
- profile.version = 0x0105;
- pfseq = sdp_list_append(0, &profile);
- sdp_set_profile_descs(&record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(0, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(0, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &ch);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- features = sdp_data_alloc(SDP_UINT16, &u16);
- sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(&record, aproto);
-
- sdp_set_info_attr(&record, "Hands-Free Audio Gateway", 0, 0);
-
- sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
-
- if (sdp_gen_record_pdu(&record, buf) < 0)
- ret = -1;
- else
- ret = 0;
-
- sdp_data_free(channel);
- sdp_list_free(proto[0], 0);
- sdp_list_free(proto[1], 0);
- sdp_list_free(apseq, 0);
- sdp_list_free(pfseq, 0);
- sdp_list_free(aproto, 0);
- sdp_list_free(root, 0);
- sdp_list_free(svclass_id, 0);
- sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);
- sdp_list_free(record.pattern, free);
-
- return ret;
-}
-
-static uint32_t headset_add_ag_record(uint8_t channel, sdp_buf_t *buf)
-{
- DBusMessage *msg, *reply;
- DBusError derr;
- dbus_uint32_t rec_id;
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database", "AddServiceRecord");
- if (!msg) {
- error("Can't allocate new method call");
- return 0;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
- &buf->data, buf->data_size, DBUS_TYPE_INVALID);
-
- dbus_error_init(&derr);
- reply = dbus_connection_send_with_reply_and_block(connection, msg,
- -1, &derr);
-
- dbus_message_unref(msg);
-
- if (dbus_error_is_set(&derr) ||
- dbus_set_error_from_message(&derr, reply)) {
- error("Adding service record failed: %s", derr.message);
- dbus_error_free(&derr);
- return 0;
- }
-
- dbus_message_get_args(reply, &derr, DBUS_TYPE_UINT32, &rec_id,
- DBUS_TYPE_INVALID);
-
- if (dbus_error_is_set(&derr)) {
- error("Invalid arguments to AddServiceRecord reply: %s",
- derr.message);
- dbus_message_unref(reply);
- dbus_error_free(&derr);
- return 0;
- }
-
- dbus_message_unref(reply);
-
- debug("add_ag_record: got record id 0x%x", rec_id);
-
- return rec_id;
-}
-
-int headset_remove_ag_record(uint32_t rec_id)
-{
- DBusMessage *msg, *reply;
- DBusError derr;
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database",
- "RemoveServiceRecord");
- if (!msg) {
- error("Can't allocate new method call");
- return 0;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_UINT32, &rec_id,
- DBUS_TYPE_INVALID);
-
- dbus_error_init(&derr);
- reply = dbus_connection_send_with_reply_and_block(connection, msg,
- -1, &derr);
-
- dbus_message_unref(msg);
-
- if (dbus_error_is_set(&derr)) {
- error("Removing service record 0x%x failed: %s",
- rec_id, derr.message);
- dbus_error_free(&derr);
- return 0;
- }
-
- dbus_message_unref(reply);
-
- return 0;
-}
-
static void get_record_reply(DBusPendingCall *call, void *data)
{
DBusMessage *reply;
@@ -957,7 +649,7 @@ static void get_record_reply(DBusPendingCall *call, void *data)
sdp_record_t *record = NULL;
sdp_list_t *protos, *classes = NULL;
uuid_t uuid;
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
struct pending_connect *c;
@@ -1036,8 +728,8 @@ static void get_record_reply(DBusPendingCall *call, void *data)
if (rfcomm_connect(device, &err) < 0) {
error("Unable to connect");
- if (c->msg)
- err_connect_failed(connection, c->msg, err);
+ if (c->msg)
+ err_connect_failed(device->conn, c->msg, strerror(err));
goto failed;
}
@@ -1045,13 +737,13 @@ static void get_record_reply(DBusPendingCall *call, void *data)
sdp_record_free(record);
dbus_message_unref(reply);
- finish_sdp_transaction(connection, &device->bda);
+ device_finish_sdp_transaction(device);
return;
failed_not_supported:
- if (c->msg)
- err_not_supported(connection, c->msg);
+ if (c->msg)
+ err_not_supported(device->conn, c->msg);
failed:
if (classes)
sdp_list_free(classes, free);
@@ -1062,18 +754,18 @@ failed:
pending_connect_free(hs->pending_connect);
hs->pending_connect = NULL;
hs->state = HEADSET_STATE_DISCONNECTED;
- finish_sdp_transaction(connection, &device->bda);
+ device_finish_sdp_transaction(device);
}
static DBusHandlerResult hs_stop(DBusConnection *conn, DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply = NULL;
if (!hs || !hs->sco)
- return err_not_connected(connection, msg);
+ return err_not_connected(conn, msg);
if (msg) {
reply = dbus_message_new_method_return(msg);
@@ -1085,8 +777,8 @@ static DBusHandlerResult hs_stop(DBusConnection *conn, DBusMessage *msg,
hs->pending_connect) {
g_io_channel_close(hs->pending_connect->io);
if (hs->pending_connect->msg)
- err_connect_failed(connection, hs->pending_connect->msg,
- EINTR);
+ err_connect_failed(conn, hs->pending_connect->msg,
+ strerror(EINTR));
pending_connect_free(hs->pending_connect);
hs->pending_connect = NULL;
hs->state = HEADSET_STATE_CONNECTED;
@@ -1095,7 +787,7 @@ static DBusHandlerResult hs_stop(DBusConnection *conn, DBusMessage *msg,
close_sco(device);
if (reply)
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1103,7 +795,7 @@ static DBusHandlerResult hs_stop(DBusConnection *conn, DBusMessage *msg,
static DBusHandlerResult hs_is_playing(DBusConnection *conn, DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply;
dbus_bool_t playing;
@@ -1122,7 +814,7 @@ static DBusHandlerResult hs_is_playing(DBusConnection *conn, DBusMessage *msg,
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &playing,
DBUS_TYPE_INVALID);
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1130,7 +822,7 @@ static DBusHandlerResult hs_is_playing(DBusConnection *conn, DBusMessage *msg,
static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply = NULL;
char hs_address[18];
@@ -1163,9 +855,9 @@ static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg,
if (hs->pending_connect->io_id)
g_source_remove(hs->pending_connect->io_id);
if (hs->pending_connect->msg)
- err_connect_failed(connection,
+ err_connect_failed(conn,
hs->pending_connect->msg,
- EINTR);
+ strerror(EINTR));
pending_connect_free(hs->pending_connect);
hs->pending_connect = NULL;
}
@@ -1173,9 +865,9 @@ static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg,
hs->state = HEADSET_STATE_DISCONNECTED;
ba2str(&device->bda, hs_address);
- info("Disconnected from %s, %s", hs_address, device->object_path);
+ info("Disconnected from %s, %s", hs_address, device->path);
- dbus_connection_emit_signal(connection, device->object_path,
+ dbus_connection_emit_signal(device->conn, device->path,
AUDIO_HEADSET_INTERFACE,
"Disconnected", DBUS_TYPE_INVALID);
@@ -1183,7 +875,7 @@ static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg,
hs->data_length = 0;
if (reply)
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1192,7 +884,7 @@ static DBusHandlerResult hs_is_connected(DBusConnection *conn,
DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
DBusMessage *reply;
dbus_bool_t connected;
@@ -1200,12 +892,12 @@ static DBusHandlerResult hs_is_connected(DBusConnection *conn,
if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
- connected = headset_is_connected(device->headset);
+ connected = (device->headset->state >= HEADSET_STATE_CONNECTED);
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connected,
DBUS_TYPE_INVALID);
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1215,7 +907,7 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
DBusMessage *msg = NULL, *reply;
DBusPendingCall *pending;
DBusError derr;
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
struct pending_connect *c;
char address[18], *addr_ptr = address;
@@ -1236,9 +928,10 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
if (c->msg) {
if (dbus_error_has_name(&derr,
"org.bluez.Error.ConnectionAttemptFailed"))
- err_connect_failed(connection, c->msg, EHOSTDOWN);
+ err_connect_failed(device->conn, c->msg,
+ strerror(EHOSTDOWN));
else
- err_not_supported(connection, c->msg);
+ err_not_supported(device->conn, c->msg);
}
dbus_error_free(&derr);
goto failed;
@@ -1248,37 +941,36 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
&array, &array_len,
DBUS_TYPE_INVALID)) {
-
error("Unable to get args from reply");
- if (c->msg)
- err_not_supported(connection, c->msg);
+ if (c->msg)
+ err_not_supported(device->conn, c->msg);
goto failed;
}
if (!array) {
error("get_handles_reply: Unable to get handle array from reply");
if (c->msg)
- err_not_supported(connection, c->msg);
+ err_not_supported(device->conn, c->msg);
goto failed;
}
if (array_len < 1) {
debug("No record handles found");
if (c->msg)
- err_not_supported(connection, c->msg);
+ err_not_supported(device->conn, c->msg);
goto failed;
}
if (array_len > 1)
debug("Multiple records found. Using the first one.");
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",
+ msg = dbus_message_new_method_call("org.bluez", device->adapter_path,
"org.bluez.Adapter",
"GetRemoteServiceRecord");
if (!msg) {
error("Unable to allocate new method call");
- if (c->msg)
- err_connect_failed(connection, c->msg, ENOMEM);
+ if (c->msg)
+ err_connect_failed(device->conn, c->msg, strerror(ENOMEM));
goto failed;
}
@@ -1290,10 +982,10 @@ static void get_handles_reply(DBusPendingCall *call, void *data)
DBUS_TYPE_UINT32, &handle,
DBUS_TYPE_INVALID);
- if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) {
+ if (!dbus_connection_send_with_reply(device->conn, msg, &pending, -1)) {
error("Sending GetRemoteServiceRecord failed");
if (c->msg)
- err_connect_failed(connection, c->msg, EIO);
+ err_connect_failed(device->conn, c->msg, strerror(EIO));
goto failed;
}
@@ -1315,7 +1007,7 @@ static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg,
void *data)
{
DBusPendingCall *pending;
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
const char *hs_svc;
const char *addr_ptr;
@@ -1325,7 +1017,7 @@ static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg,
assert(hs != NULL);
if (hs->state > HEADSET_STATE_DISCONNECTED || hs->pending_connect)
- return err_already_connected(connection, msg);
+ return err_already_connected(conn, msg);
hs->pending_connect = g_try_new0(struct pending_connect, 1);
if (!hs->pending_connect) {
@@ -1345,12 +1037,12 @@ static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg,
pending_connect_free(hs->pending_connect);
hs->pending_connect = NULL;
hs->state = HEADSET_STATE_DISCONNECTED;
- return err_connect_failed(conn, msg, err);
+ return err_connect_failed(conn, msg, strerror(err));
} else
return DBUS_HANDLER_RESULT_HANDLED;
}
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",
+ msg = dbus_message_new_method_call("org.bluez", device->adapter_path,
"org.bluez.Adapter",
"GetRemoteServiceHandles");
if (!msg) {
@@ -1372,13 +1064,13 @@ static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg,
DBUS_TYPE_STRING, &hs_svc,
DBUS_TYPE_INVALID);
- if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) {
+ if (!dbus_connection_send_with_reply(conn, msg, &pending, -1)) {
error("Sending GetRemoteServiceHandles failed");
pending_connect_free(hs->pending_connect);
hs->pending_connect = NULL;
hs->state = HEADSET_STATE_DISCONNECTED;
dbus_message_unref(msg);
- return err_connect_failed(connection, msg, EIO);
+ return err_connect_failed(conn, msg, strerror(EIO));
}
dbus_pending_call_set_notify(pending, get_handles_reply, device, NULL);
@@ -1390,7 +1082,7 @@ static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg,
static gboolean ring_timer_cb(gpointer data)
{
- audio_device_t *device = data;
+ struct device *device = data;
assert(device != NULL);
@@ -1403,14 +1095,14 @@ static gboolean ring_timer_cb(gpointer data)
static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply = NULL;
assert(hs != NULL);
if (hs->state < HEADSET_STATE_CONNECTED)
- return err_not_connected(connection, msg);
+ return err_not_connected(conn, msg);
if (msg) {
reply = dbus_message_new_method_return(msg);
@@ -1425,14 +1117,14 @@ static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg,
if (headset_send(device->headset, "\r\nRING\r\n") != G_IO_ERROR_NONE) {
dbus_message_unref(reply);
- return err_failed(connection, msg, "Failed");
+ return err_failed(conn, msg, "Failed");
}
hs->ring_timer = g_timeout_add(RING_INTERVAL, ring_timer_cb, device);
done:
if (reply)
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1441,12 +1133,12 @@ static DBusHandlerResult hs_cancel_ringing(DBusConnection *conn,
DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply = NULL;
if (hs->state < HEADSET_STATE_CONNECTED)
- return err_not_connected(connection, msg);
+ return err_not_connected(conn, msg);
if (msg) {
reply = dbus_message_new_method_return(msg);
@@ -1464,7 +1156,7 @@ static DBusHandlerResult hs_cancel_ringing(DBusConnection *conn,
done:
if (reply)
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1472,18 +1164,18 @@ done:
static DBusHandlerResult hs_play(DBusConnection *conn, DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
struct pending_connect *c;
if (hs->state < HEADSET_STATE_CONNECTED)
- return err_not_connected(connection, msg);
+ return err_not_connected(conn, msg);
if (hs->state >= HEADSET_STATE_PLAY_IN_PROGRESS || hs->pending_connect)
- return err_already_connected(connection, msg);
+ return err_already_connected(conn, msg);
if (hs->sco)
- return err_already_connected(connection, msg);
+ return err_already_connected(conn, msg);
c = g_try_new0(struct pending_connect, 1);
if (!c)
@@ -1506,7 +1198,7 @@ static DBusHandlerResult hs_get_speaker_gain(DBusConnection *conn,
DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply;
dbus_uint16_t gain;
@@ -1525,7 +1217,7 @@ static DBusHandlerResult hs_get_speaker_gain(DBusConnection *conn,
dbus_message_append_args(reply, DBUS_TYPE_UINT16, &gain,
DBUS_TYPE_INVALID);
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1534,7 +1226,7 @@ static DBusHandlerResult hs_get_mic_gain(DBusConnection *conn,
DBusMessage *msg,
void *data)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply;
dbus_uint16_t gain;
@@ -1553,7 +1245,7 @@ static DBusHandlerResult hs_get_mic_gain(DBusConnection *conn,
dbus_message_append_args(reply, DBUS_TYPE_UINT16, &gain,
DBUS_TYPE_INVALID);
- send_message_and_unref(connection, reply);
+ send_message_and_unref(conn, reply);
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -1562,7 +1254,7 @@ static DBusHandlerResult hs_set_gain(DBusConnection *conn,
DBusMessage *msg,
void *data, char type)
{
- audio_device_t *device = data;
+ struct device *device = data;
struct headset *hs = device->headset;
DBusMessage *reply;
DBusError derr;
@@ -1605,7 +1297,7 @@ static DBusHandlerResult hs_set_gain(DBusConnection *conn,
done:
if (type == HEADSET_GAIN_SPEAKER) {
hs->sp_gain = gain;
- dbus_connection_emit_signal(conn, device->object_path,
+ dbus_connection_emit_signal(conn, device->path,
AUDIO_HEADSET_INTERFACE,
"SpeakerGainChanged",
DBUS_TYPE_UINT16, &gain,
@@ -1613,7 +1305,7 @@ done:
}
else {
hs->mic_gain = gain;
- dbus_connection_emit_signal(conn, device->object_path,
+ dbus_connection_emit_signal(conn, device->path,
AUDIO_HEADSET_INTERFACE,
"MicrophoneGainChanged",
DBUS_TYPE_UINT16, &gain,
@@ -1666,7 +1358,7 @@ static DBusSignalVTable headset_signals[] = {
{ NULL, NULL }
};
-static void headset_set_channel(headset_t *headset, sdp_record_t *record)
+static void headset_set_channel(struct headset *headset, sdp_record_t *record)
{
int ch;
sdp_list_t *protos;
@@ -1688,16 +1380,12 @@ static void headset_set_channel(headset_t *headset, sdp_record_t *record)
error("Unable to get RFCOMM channel from Headset record");
}
-void headset_update(headset_t *headset, sdp_record_t *record, uint16_t svc)
+void headset_update(void *device, sdp_record_t *record, uint16_t svc)
{
+ struct headset *headset = ((struct device *) device)->headset;
+
switch (svc) {
case HANDSFREE_SVCLASS_ID:
- if (disable_hfp) {
- debug("Ignoring Handsfree record since HFP support"
- " has been disabled");
- return;
- }
-
if (headset->hfp_handle &&
(headset->hfp_handle != record->handle)) {
error("More than one HFP record found on device");
@@ -1730,12 +1418,12 @@ void headset_update(headset_t *headset, sdp_record_t *record, uint16_t svc)
headset_set_channel(headset, record);
}
-headset_t *headset_init(const char *object_path, sdp_record_t *record,
+struct headset *headset_init(void *device, sdp_record_t *record,
uint16_t svc)
{
- headset_t *headset;
+ struct headset *headset;
- headset = g_new0(headset_t, 1);
+ headset = g_new0(struct headset, 1);
headset->rfcomm_ch = -1;
headset->sp_gain = -1;
headset->mic_gain = -1;
@@ -1745,13 +1433,6 @@ headset_t *headset_init(const char *object_path, sdp_record_t *record,
switch (svc) {
case HANDSFREE_SVCLASS_ID:
- if (disable_hfp) {
- debug("Ignoring Handsfree record since HFP support"
- " has been disabled");
- g_free(headset);
- return NULL;
- }
-
headset->hfp_handle = record->handle;
break;
@@ -1766,7 +1447,8 @@ headset_t *headset_init(const char *object_path, sdp_record_t *record,
}
register_iface:
- if (!dbus_connection_register_interface(connection, object_path,
+ if (!dbus_connection_register_interface(((struct device *) device)->conn,
+ ((struct device *) device)->path,
AUDIO_HEADSET_INTERFACE,
headset_methods,
headset_signals, NULL)) {
@@ -1780,279 +1462,120 @@ register_iface:
return headset;
}
-void headset_free(const char *object_path)
+void headset_free(void *device)
{
- audio_device_t *device;
+ struct headset *headset = ((struct device *) device)->headset;
- if (!dbus_connection_get_object_user_data(connection, object_path,
- (void *) &device))
- return;
-
- if (device->headset->state != HEADSET_STATE_DISCONNECTED)
+ if (headset->state != HEADSET_STATE_DISCONNECTED)
hs_disconnect(NULL, NULL, device);
- g_free(device->headset);
- device->headset = NULL;
+ g_free(headset);
+ headset = NULL;
}
-static gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond,
- void *data)
+int headset_get_config(void *device, int sock, struct ipc_packet *pkt)
{
- int srv_sk, cli_sk;
- struct sockaddr_rc addr;
- socklen_t size;
- char hs_address[18], *address = hs_address;
- const char *uuid;
- audio_device_t *device;
- struct headset *hs;
- DBusMessage *auth;
- DBusPendingCall *pending;
-
- if (cond & G_IO_NVAL)
- return FALSE;
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- error("Hangup or error on rfcomm server socket");
- g_io_channel_close(chan);
- raise(SIGTERM);
- return FALSE;
- }
-
- srv_sk = g_io_channel_unix_get_fd(chan);
-
- size = sizeof(struct sockaddr_rc);
- cli_sk = accept(srv_sk, (struct sockaddr *) &addr, &size);
- if (cli_sk < 0) {
- error("accept: %s (%d)", strerror(errno), errno);
- return TRUE;
- }
-
- device = manager_headset_connected(&addr.rc_bdaddr);
- if (!device) {
- close(cli_sk);
- return TRUE;
- }
-
- hs = device->headset;
-
- if (hs->state > HEADSET_STATE_DISCONNECTED || hs->rfcomm) {
- debug("Refusing new connection since one already exists");
- close(cli_sk);
- return TRUE;
- }
-
- hs->rfcomm = g_io_channel_unix_new(cli_sk);
- if (!hs->rfcomm) {
- error("Allocating new GIOChannel failed!");
- close(cli_sk);
- return TRUE;
- }
-
- if (chan == hs_server) {
- hs->type = SVC_HEADSET;
- uuid = HSP_AG_UUID;
- } else {
- hs->type = SVC_HANDSFREE;
- uuid = HFP_AG_UUID;
- }
-
- auth = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database",
- "RequestAuthorization");
- if (!auth) {
- error("Unable to allocate RequestAuthorization method call");
- goto failed;
- }
-
- ba2str(&device->bda, hs_address);
-
- dbus_message_append_args(auth, DBUS_TYPE_STRING, &address,
- DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID);
+ struct headset *headset = ((struct device *) device)->headset;
+ struct ipc_data_cfg *cfg = (struct ipc_data_cfg *) pkt->data;
+ int err = EINVAL;
+ struct pending_connect *c;
- if (!dbus_connection_send_with_reply(connection, auth, &pending, -1)) {
- error("Sending of authorization request failed");
- goto failed;
+ if (headset->sco == NULL) {
+ c = g_try_new0(struct pending_connect, 1);
+ if (c == NULL)
+ goto error;
+ c->sock = sock;
+ c->pkt = pkt;
+ if ((err = sco_connect(device, c)) < 0)
+ goto error;
+ return 0;
}
- dbus_pending_call_set_notify(pending, auth_callback, device, NULL);
- dbus_pending_call_unref(pending);
- dbus_message_unref(auth);
-
- return TRUE;
-
-failed:
- if (hs->rfcomm) {
- g_io_channel_close(hs->rfcomm);
- g_io_channel_unref(hs->rfcomm);
- hs->rfcomm = NULL;
- }
+ cfg->fd = g_io_channel_unix_get_fd(headset->sco);
+ cfg->fd_opt = CFG_FD_OPT_READWRITE;
+ cfg->encoding = 0;
+ cfg->bitpool = 0;
+ cfg->channels = 1;
+ cfg->pkt_len = 48;
+ cfg->sample_size = 2;
+ cfg->rate = 8000;
- return TRUE;
+ return 0;
+error:
+ cfg->fd = -1;
+ return -err;
}
-static GIOChannel *server_socket(uint8_t *channel)
+headset_type_t headset_get_type(void *device)
{
- int sock, lm;
- struct sockaddr_rc addr;
- socklen_t sa_len;
- GIOChannel *io;
-
- sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (sock < 0) {
- error("server socket: %s (%d)", strerror(errno), errno);
- return NULL;
- }
+ struct headset *headset = ((struct device *) device)->headset;
- lm = RFCOMM_LM_SECURE;
- if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
- error("server setsockopt: %s (%d)", strerror(errno), errno);
- close(sock);
- return NULL;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, BDADDR_ANY);
- addr.rc_channel = channel ? *channel : 0;
-
- if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- error("server bind: %s", strerror(errno), errno);
- close(sock);
- return NULL;
- }
-
- if (listen(sock, 1) < 0) {
- error("server listen: %s", strerror(errno), errno);
- close(sock);
- return NULL;
- }
-
- sa_len = sizeof(struct sockaddr_rc);
- getsockname(sock, (struct sockaddr *) &addr, &sa_len);
- *channel = addr.rc_channel;
-
- io = g_io_channel_unix_new(sock);
- if (!io) {
- error("Unable to allocate new io channel");
- close(sock);
- return NULL;
- }
-
- return io;
+ return headset->type;
}
-gboolean headset_is_connected(headset_t *headset)
+void headset_set_type(void *device, headset_type_t type)
{
- if (headset->state >= HEADSET_STATE_CONNECTED)
- return TRUE;
- else
- return FALSE;
+ struct headset *headset = ((struct device *) device)->headset;
+
+ headset->type = type;
}
-int headset_server_init(DBusConnection *conn, gboolean no_hfp,
- gboolean sco_hci)
+int headset_connect_rfcomm(void *device, int sock)
{
- uint8_t chan = DEFAULT_HS_AG_CHANNEL;
- sdp_buf_t buf;
-
- connection = dbus_connection_ref(conn);
+ struct headset *headset = ((struct device *) device)->headset;
- hs_server = server_socket(&chan);
- if (!hs_server)
- return -1;
-
- if (create_hsp_ag_record(&buf, chan) < 0) {
- error("Unable to allocate new service record");
- return -1;
- }
-
- hs_record_id = headset_add_ag_record(chan, &buf);
- free(buf.data);
- if (!hs_record_id) {
- error("Unable to register HS AG service record");
- g_io_channel_unref(hs_server);
- hs_server = NULL;
- return -1;
- }
-
- g_io_add_watch(hs_server, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- (GIOFunc) headset_server_io_cb, NULL);
-
- disable_hfp = no_hfp;
-
- sco_over_hci = sco_hci;
-
- if (disable_hfp)
- return 0;
+ headset->rfcomm = g_io_channel_unix_new(sock);
- chan = DEFAULT_HF_AG_CHANNEL;
-
- hf_server = server_socket(&chan);
- if (!hf_server)
- return -1;
-
- if (create_hfp_ag_record(&buf, chan) < 0) {
- error("Unable to allocate new service record");
- return -1;
- }
+ return headset->rfcomm ? 0 : -EINVAL;
+}
- hf_record_id = headset_add_ag_record(chan, &buf);
- free(buf.data);
- if (!hf_record_id) {
- error("Unable to register HS AG service record");
- g_io_channel_unref(hf_server);
- hs_server = NULL;
- return -1;
- }
+int headset_close_rfcomm(void *device)
+{
+ struct headset *headset = ((struct device *) device)->headset;
- g_io_add_watch(hf_server, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- (GIOFunc) headset_server_io_cb, NULL);
+ g_io_channel_close(headset->rfcomm);
+ g_io_channel_unref(headset->rfcomm);
+ headset->rfcomm = NULL;
return 0;
}
-void headset_exit(void)
+void headset_set_state(void *device, headset_state_t state)
{
- if (hs_record_id) {
- headset_remove_ag_record(hs_record_id);
- hs_record_id = 0;
- }
+ struct headset *headset = ((struct device *) device)->headset;
- if (hs_server) {
- g_io_channel_unref(hs_server);
- hs_server = NULL;
- }
+ switch(state) {
+ case HEADSET_STATE_DISCONNECTED:
+ case HEADSET_STATE_CONNECT_IN_PROGRESS:
+ break;
+ case HEADSET_STATE_CONNECTED:
+ if (headset->rfcomm) {
+ char hs_address[18];
- if (hf_record_id) {
- headset_remove_ag_record(hf_record_id);
- hf_record_id = 0;
- }
+ g_io_add_watch(headset->rfcomm,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ (GIOFunc) rfcomm_io_cb, device);
- if (hf_server) {
- g_io_channel_unref(hf_server);
- hf_server = NULL;
+ ba2str(&((struct device *) device)->bda, hs_address);
+
+ dbus_connection_emit_signal(((struct device *) device)->conn,
+ ((struct device *) device)->path,
+ AUDIO_HEADSET_INTERFACE,
+ "Connected",
+ DBUS_TYPE_INVALID);
+ }
+ break;
+ case HEADSET_STATE_PLAY_IN_PROGRESS:
+ case HEADSET_STATE_PLAYING:
+ break;
}
- dbus_connection_unref(connection);
- connection = NULL;
+ headset->state = state;
}
-int headset_get_config(headset_t *headset, int sock, struct ipc_data_cfg *cfg)
+headset_state_t headset_get_state(void *device)
{
- if (!sco_over_hci)
- return -1;
+ struct headset *headset = ((struct device *) device)->headset;
- if (headset->sco == NULL)
- return -1;
-
- cfg->fd = g_io_channel_unix_get_fd(headset->sco);
- cfg->fd_opt = CFG_FD_OPT_READWRITE;
- cfg->encoding = 0;
- cfg->bitpool = 0;
- cfg->channels = 1;
- cfg->pkt_len = 48;
- cfg->sample_size = 2;
- cfg->rate = 8000;
-
- return 0;
+ return headset->state;
}
diff --git a/audio/headset.h b/audio/headset.h
index b420860e..470fddc8 100644
--- a/audio/headset.h
+++ b/audio/headset.h
@@ -20,10 +20,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
-#ifndef __AUDIO_HEADSET_H
-#define __AUDIO_HEADSET_H
-
-#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
@@ -33,22 +29,45 @@
#define AUDIO_HEADSET_INTERFACE "org.bluez.audio.Headset"
-typedef struct headset headset_t;
+#define DEFAULT_HS_AG_CHANNEL 12
+#define DEFAULT_HF_AG_CHANNEL 13
-headset_t *headset_init(const char *object_path, sdp_record_t *record,
- uint16_t svc);
+typedef enum {
+ HEADSET_EVENT_KEYPRESS,
+ HEADSET_EVENT_GAIN,
+ HEADSET_EVENT_UNKNOWN,
+ HEADSET_EVENT_INVALID
+} headset_event_t;
+
+typedef enum {
+ HEADSET_STATE_DISCONNECTED = 0,
+ HEADSET_STATE_CONNECT_IN_PROGRESS,
+ HEADSET_STATE_CONNECTED,
+ HEADSET_STATE_PLAY_IN_PROGRESS,
+ HEADSET_STATE_PLAYING,
+} headset_state_t;
-void headset_free(const char *object_path);
+typedef enum {
+ SVC_HEADSET,
+ SVC_HANDSFREE
+} headset_type_t;
+
+struct headset;
+
+struct headset *headset_init(void *device, sdp_record_t *record,
+ uint16_t svc);
-void headset_update(headset_t *headset, sdp_record_t *record, uint16_t svc);
+void headset_free(void *device);
-gboolean headset_is_connected(headset_t *headset);
+void headset_update(void *device, sdp_record_t *record, uint16_t svc);
-int headset_server_init(DBusConnection *conn, gboolean disable_hfp,
- gboolean sco_hci);
+int headset_get_config(void *device, int sock, struct ipc_packet *pkt);
-void headset_exit(void);
+headset_type_t headset_get_type(void *device);
+void headset_set_type(void *device, headset_type_t type);
-int headset_get_config(headset_t *headset, int sock, struct ipc_data_cfg *cfg);
+int headset_connect_rfcomm(void *device, int sock);
+int headset_close_rfcomm(void *device);
-#endif /* __AUDIO_HEADSET_H_ */
+headset_state_t headset_get_state(void *device);
+void headset_set_state(void *device, headset_state_t state);
diff --git a/audio/main.c b/audio/main.c
index 0ca8ce87..4a32a320 100644
--- a/audio/main.c
+++ b/audio/main.c
@@ -40,7 +40,7 @@
/* Configuration settings */
static gboolean disable_hfp = TRUE;
-static gboolean sco_hci = FALSE;
+static gboolean sco_hci = TRUE;
static GMainLoop *main_loop = NULL;
@@ -137,7 +137,7 @@ int main(int argc, char *argv[])
exit(1);
}
- if (headset_server_init(conn, disable_hfp, sco_hci) < 0) {
+ if (gateway_init(conn, disable_hfp, sco_hci) < 0) {
error("Headset initialization failed!");
exit(1);
}
@@ -149,7 +149,7 @@ int main(int argc, char *argv[])
audio_exit();
- headset_exit();
+ gateway_exit();
unix_exit();
diff --git a/audio/manager.c b/audio/manager.c
index 7faa0490..d8872968 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -42,12 +42,11 @@
#include <dbus/dbus.h>
-#include "dbus.h"
#include "dbus-helper.h"
#include "logging.h"
-#include "headset.h"
#include "manager.h"
+#include "error.h"
typedef enum {
HEADSET = 1 << 0,
@@ -67,7 +66,7 @@ typedef enum {
} audio_sdp_state_t;
struct audio_sdp_data {
- audio_device_t *device;
+ struct device *device;
DBusMessage *msg; /* Method call or NULL */
@@ -79,7 +78,7 @@ struct audio_sdp_data {
static DBusConnection *connection = NULL;
-static audio_device_t *default_dev = NULL;
+static struct device *default_dev = NULL;
static GSList *devices = NULL;
@@ -87,80 +86,12 @@ static void get_next_record(struct audio_sdp_data *data);
static DBusHandlerResult get_handles(const char *uuid,
struct audio_sdp_data *data);
-/* FIXME: Remove these once global error functions exist */
-static DBusHandlerResult error_reply(DBusConnection *conn, DBusMessage *msg,
- const char *name, const char *descr)
-{
- DBusMessage *derr;
-
- if (!conn || !msg)
- return DBUS_HANDLER_RESULT_HANDLED;
-
- derr = dbus_message_new_error(msg, name, descr);
- if (!derr) {
- error("Unable to allocate new error return");
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
- }
-
- return send_message_and_unref(conn, derr);
-}
-
-DBusHandlerResult err_invalid_args(DBusConnection *conn, DBusMessage *msg,
- const char *descr)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.InvalidArguments",
- descr ? descr : "Invalid arguments in method call");
-}
-
-DBusHandlerResult err_already_connected(DBusConnection *conn, DBusMessage *msg)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.AlreadyConnected",
- "Already connected to a device");
-}
-
-DBusHandlerResult err_not_connected(DBusConnection *conn, DBusMessage *msg)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.NotConnected",
- "Not connected to any device");
-}
-
-DBusHandlerResult err_not_supported(DBusConnection *conn, DBusMessage *msg)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.NotSupported",
- "The service is not supported by the remote device");
-}
-
-DBusHandlerResult err_connect_failed(DBusConnection *conn,
- DBusMessage *msg, int err)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.ConnectFailed",
- strerror(err));
-}
-
-DBusHandlerResult err_does_not_exist(DBusConnection *conn, DBusMessage *msg)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.DoesNotExist",
- "Does not exist");
-}
-
-DBusHandlerResult err_not_available(DBusConnection *conn, DBusMessage *msg)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.NotAvailable",
- "Not available");
-}
-
-DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg,
- const char *dsc)
-{
- return error_reply(conn, msg, "org.bluez.audio.Error.Failed", dsc);
-}
-
-static audio_device_t *find_device(bdaddr_t *bda)
+static struct device *find_device(bdaddr_t *bda)
{
GSList *l;
for (l = devices; l != NULL; l = l->next) {
- audio_device_t *device = l->data;
+ struct device *device = l->data;
if (bacmp(&device->bda, bda) == 0)
return device;
}
@@ -168,113 +99,25 @@ static audio_device_t *find_device(bdaddr_t *bda)
return NULL;
}
-static DBusHandlerResult device_get_address(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- audio_device_t *device = data;
- DBusMessage *reply;
- char address[18], *ptr = address;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- ba2str(&device->bda, address);
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &ptr,
- DBUS_TYPE_INVALID);
-
- return send_message_and_unref(conn, reply);
-}
-
-static DBusHandlerResult device_get_connected(DBusConnection *conn,
- DBusMessage *msg,
- void *data)
-{
- DBusMessageIter iter, array_iter;
- audio_device_t *device = data;
- DBusMessage *reply;
- const char *iface;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_STRING_AS_STRING, &array_iter);
-
- if (device->headset && headset_is_connected(device->headset)) {
- iface = AUDIO_HEADSET_INTERFACE;
- dbus_message_iter_append_basic(&array_iter,
- DBUS_TYPE_STRING, &iface);
- }
-
- dbus_message_iter_close_container(&iter, &array_iter);
-
- return send_message_and_unref(conn, reply);
-}
-
-static DBusMethodVTable device_methods[] = {
- { "GetAddress", device_get_address,
- "", "s" },
- { "GetConnectedInterfaces", device_get_connected,
- "", "s" },
- { NULL, NULL, NULL, NULL }
-};
-
-static void free_device(audio_device_t *device)
-{
- g_free(device);
-}
-
-static audio_device_t *create_device(bdaddr_t *bda)
+static struct device *create_device(bdaddr_t *bda)
{
static int device_id = 0;
- audio_device_t *device;
-
- device = g_new0(audio_device_t, 1);
+ char path[128];
- bacpy(&device->bda, bda);
-
- snprintf(device->object_path, sizeof(device->object_path) - 1,
+ snprintf(path, sizeof(path) - 1,
"%s/device%d", AUDIO_MANAGER_PATH, device_id++);
- return device;
+ return device_register(connection, path, bda);
}
-static void remove_device(audio_device_t *device)
+static void remove_device(struct device *device)
{
devices = g_slist_remove(devices, device);
- if (device->headset)
- headset_free(device->object_path);
- dbus_connection_destroy_object_path(connection, device->object_path);
- g_free(device);
+ dbus_connection_destroy_object_path(connection, device->path);
}
-
-static gboolean add_device(audio_device_t *device)
+static gboolean add_device(struct device *device)
{
- if (!dbus_connection_create_object_path(connection,
- device->object_path,
- device, NULL)) {
- error("D-Bus failed to register %s path", device->object_path);
- return FALSE;
- }
-
- if (!dbus_connection_register_interface(connection,
- device->object_path,
- AUDIO_DEVICE_INTERFACE,
- device_methods, NULL, NULL)) {
- error("Failed to register %s interface to %s",
- AUDIO_DEVICE_INTERFACE, device->object_path);
- dbus_connection_destroy_object_path(connection,
- device->object_path);
- return FALSE;
- }
-
/* First device became default */
if (g_slist_length(devices) == 0)
default_dev = device;
@@ -296,7 +139,7 @@ static uint16_t get_service_uuid(const sdp_record_t *record)
}
memcpy(&uuid, classes->data, sizeof(uuid));
-
+
if (!sdp_uuid128_to_uuid(&uuid)) {
error("Not a 16 bit UUID");
sdp_list_free(classes, free);
@@ -304,7 +147,7 @@ static uint16_t get_service_uuid(const sdp_record_t *record)
}
if (uuid.type == SDP_UUID32) {
- if (uuid.value.uuid32 > 0xFFFF) {
+ if (uuid.value.uuid32 > 0xFFFF) {
error("Not a 16 bit UUID");
goto done;
}
@@ -318,43 +161,7 @@ done:
return uuid16;
}
-void finish_sdp_transaction(DBusConnection *conn, bdaddr_t *dba)
-{
- char address[18], *addr_ptr = address;
- DBusMessage *msg, *reply;
- DBusError derr;
-
- ba2str(dba, address);
-
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",
- "org.bluez.Adapter",
- "FinishRemoteServiceTransaction");
- if (!msg) {
- error("Unable to allocate new method call");
- return;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &addr_ptr,
- DBUS_TYPE_INVALID);
-
- dbus_error_init(&derr);
- reply = dbus_connection_send_with_reply_and_block(conn, msg, -1,
- &derr);
-
- dbus_message_unref(msg);
-
- if (dbus_error_is_set(&derr) ||
- dbus_set_error_from_message(&derr, reply)) {
- error("FinishRemoteServiceTransaction(%s) failed: %s",
- address, derr.message);
- dbus_error_free(&derr);
- return;
- }
-
- dbus_message_unref(reply);
-}
-
-static void handle_record(sdp_record_t *record, audio_device_t *device)
+static void handle_record(sdp_record_t *record, struct device *device)
{
uint16_t uuid16;
@@ -364,9 +171,9 @@ static void handle_record(sdp_record_t *record, audio_device_t *device)
case HEADSET_SVCLASS_ID:
debug("Found Headset record");
if (device->headset)
- headset_update(device->headset, record, uuid16);
+ headset_update(device, record, uuid16);
else
- device->headset = headset_init(device->object_path,
+ device->headset = headset_init(device,
record, uuid16);
break;
case HEADSET_AGW_SVCLASS_ID:
@@ -375,9 +182,9 @@ static void handle_record(sdp_record_t *record, audio_device_t *device)
case HANDSFREE_SVCLASS_ID:
debug("Found Hansfree record");
if (device->headset)
- headset_update(device->headset, record, uuid16);
+ headset_update(device, record, uuid16);
else
- device->headset = headset_init(device->object_path,
+ device->headset = headset_init(device,
record, uuid16);
break;
case HANDSFREE_AGW_SVCLASS_ID:
@@ -434,8 +241,8 @@ static gint record_iface_cmp(gconstpointer a, gconstpointer b)
static void finish_sdp(struct audio_sdp_data *data, gboolean success)
{
- const char *path, *addr;
- char **required;
+ const char *addr;
+ char **required = NULL;
int required_len, i;
DBusMessage *reply = NULL;
DBusError derr;
@@ -443,7 +250,7 @@ static void finish_sdp(struct audio_sdp_data *data, gboolean success)
debug("Audio service discovery completed with %s",
success ? "success" : "failure");
- finish_sdp_transaction(connection, &data->device->bda);
+ device_finish_sdp_transaction(data->device);
if (!success)
goto done;
@@ -508,14 +315,9 @@ static void finish_sdp(struct audio_sdp_data *data, gboolean success)
debug("Required interface %s not supported", iface);
success = FALSE;
err_not_supported(connection, data->msg);
- dbus_free_string_array(required);
goto done;
}
- dbus_free_string_array(required);
-
- path = data->device->object_path;
-
reply = dbus_message_new_method_return(data->msg);
if (!reply) {
success = FALSE;
@@ -532,24 +334,27 @@ update:
dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,
AUDIO_MANAGER_INTERFACE,
"DeviceCreated",
- DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING,
+ &data->device->path,
DBUS_TYPE_INVALID);
if (data->device->headset)
- dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,
+ dbus_connection_emit_signal(connection,
+ AUDIO_MANAGER_PATH,
AUDIO_MANAGER_INTERFACE,
"HeadsetCreated",
- DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING,
+ &data->device->path,
DBUS_TYPE_INVALID);
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
+ dbus_message_append_args(reply, DBUS_TYPE_STRING,
+ &data->device->path,
+ DBUS_TYPE_INVALID);
send_message_and_unref(connection, reply);
}
done:
- if (required)
- dbus_free_string_array(required);
+ dbus_free_string_array(required);
if (!success)
- free_device(data->device);
+ remove_device(data->device);
if (data->msg)
dbus_message_unref(data->msg);
g_slist_foreach(data->handles, (GFunc) g_free, NULL);
@@ -575,7 +380,8 @@ static void get_record_reply(DBusPendingCall *call,
error("GetRemoteServiceRecord failed: %s", derr.message);
if (dbus_error_has_name(&derr,
"org.bluez.Error.ConnectionAttemptFailed"))
- err_connect_failed(connection, data->msg, EHOSTDOWN);
+ err_connect_failed(connection, data->msg,
+ strerror(EHOSTDOWN));
else
err_failed(connection, data->msg, derr.message);
dbus_error_free(&derr);
@@ -625,12 +431,13 @@ static void get_next_record(struct audio_sdp_data *data)
char address[18], *ptr = address;
dbus_uint32_t *handle;
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",
+ msg = dbus_message_new_method_call("org.bluez",
+ data->device->adapter_path,
"org.bluez.Adapter",
"GetRemoteServiceRecord");
if (!msg) {
error("Unable to allocate new method call");
- err_connect_failed(connection, data->msg, ENOMEM);
+ err_connect_failed(connection, data->msg, strerror(ENOMEM));
finish_sdp(data, FALSE);
return;
}
@@ -649,7 +456,7 @@ static void get_next_record(struct audio_sdp_data *data)
if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) {
error("Sending GetRemoteServiceRecord failed");
- err_connect_failed(connection, data->msg, EIO);
+ err_connect_failed(connection, data->msg, strerror(EIO));
finish_sdp(data, FALSE);
return;
}
@@ -687,7 +494,7 @@ static void get_handles_reply(DBusPendingCall *call,
error("GetRemoteServiceHandles failed: %s", derr.message);
if (dbus_error_has_name(&derr,
"org.bluez.Error.ConnectionAttemptFailed"))
- err_connect_failed(connection, data->msg, EHOSTDOWN);
+ err_connect_failed(connection, data->msg, strerror(EHOSTDOWN));
else
err_failed(connection, data->msg, derr.message);
dbus_error_free(&derr);
@@ -744,7 +551,8 @@ static DBusHandlerResult get_handles(const char *uuid,
const char *ptr = address;
DBusMessage *msg;
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez/hci0",
+ msg = dbus_message_new_method_call("org.bluez",
+ data->device->adapter_path,
"org.bluez.Adapter",
"GetRemoteServiceHandles");
if (!msg) {
@@ -781,7 +589,7 @@ failed:
}
static DBusHandlerResult resolve_services(DBusMessage *msg,
- audio_device_t *device)
+ struct device *device)
{
struct audio_sdp_data *sdp_data;
@@ -793,9 +601,9 @@ static DBusHandlerResult resolve_services(DBusMessage *msg,
return get_handles(GENERIC_AUDIO_UUID, sdp_data);
}
-audio_device_t *manager_headset_connected(bdaddr_t *bda)
+struct device *manager_device_connected(bdaddr_t *bda)
{
- audio_device_t *device;
+ struct device *device;
const char *path;
gboolean created = FALSE;
@@ -806,19 +614,19 @@ audio_device_t *manager_headset_connected(bdaddr_t *bda)
if (!device) {
device = create_device(bda);
if (!add_device(device)) {
- free_device(device);
+ remove_device(device);
return NULL;
}
created = TRUE;
}
if (!device->headset)
- device->headset = headset_init(device->object_path, NULL, 0);
+ device->headset = headset_init(device, NULL, 0);
if (!device->headset)
return NULL;
- path = device->object_path;
+ path = device->path;
if (created) {
dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,
@@ -847,7 +655,7 @@ audio_device_t *manager_headset_connected(bdaddr_t *bda)
return device;
}
-static gboolean device_supports_interface(audio_device_t *device,
+static gboolean device_supports_interface(struct device *device,
const char *iface)
{
if (strcmp(iface, AUDIO_HEADSET_INTERFACE) == 0)
@@ -873,7 +681,7 @@ static gboolean device_supports_interface(audio_device_t *device,
return FALSE;
}
-static gboolean device_matches(audio_device_t *device, char **interfaces)
+static gboolean device_matches(struct device *device, char **interfaces)
{
int i;
@@ -895,7 +703,7 @@ static DBusHandlerResult am_create_device(DBusConnection *conn,
char **required;
int required_len;
bdaddr_t bda;
- audio_device_t *device;
+ struct device *device;
DBusMessage *reply;
DBusError derr;
@@ -950,7 +758,7 @@ static DBusHandlerResult am_create_device(DBusConnection *conn,
dbus_free_string_array(required);
- path = device->object_path;
+ path = device->path;
reply = dbus_message_new_method_return(msg);
if (!reply)
@@ -1015,16 +823,13 @@ static DBusHandlerResult am_list_devices(DBusConnection *conn,
DBUS_TYPE_STRING_AS_STRING, &array_iter);
for (l = devices; l != NULL; l = l->next) {
- audio_device_t *device = l->data;
- const char *path;
+ struct device *device = l->data;
if (!device_matches(device, required))
continue;
- path = device->object_path;
-
dbus_message_iter_append_basic(&array_iter,
- DBUS_TYPE_STRING, &path);
+ DBUS_TYPE_STRING, &device->path);
}
dbus_message_iter_close_container(&iter, &array_iter);
@@ -1036,10 +841,10 @@ static DBusHandlerResult am_list_devices(DBusConnection *conn,
static gint device_path_cmp(gconstpointer a, gconstpointer b)
{
- const audio_device_t *device = a;
+ const struct device *device = a;
const char *path = b;
- return strcmp(device->object_path, path);
+ return strcmp(device->path, path);
}
static DBusHandlerResult am_remove_device(DBusConnection *conn,
@@ -1050,7 +855,7 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn,
DBusMessage *reply;
GSList *match;
const char *path;
- audio_device_t *device;
+ struct device *device;
dbus_error_init(&derr);
if (!dbus_message_get_args(msg, &derr,
@@ -1067,9 +872,7 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn,
match = g_slist_find_custom(devices, path, device_path_cmp);
if (!match)
- return error_reply(connection, msg,
- "org.bluez.audio.Error.DoesNotExist",
- "The device does not exist");
+ return err_does_not_exist(connection, msg);
reply = dbus_message_new_method_return(msg);
if (!reply)
@@ -1092,7 +895,7 @@ static DBusHandlerResult am_remove_device(DBusConnection *conn,
default_dev = device;
}
- param = default_dev ? default_dev->object_path : "";
+ param = default_dev ? default_dev->path : "";
dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,
AUDIO_MANAGER_INTERFACE,
@@ -1120,10 +923,10 @@ static DBusHandlerResult am_find_by_addr(DBusConnection *conn,
DBusMessage *msg,
void *data)
{
- const char *path, *address;
+ const char *address;
DBusMessage *reply;
DBusError derr;
- audio_device_t *device;
+ struct device *device;
bdaddr_t bda;
dbus_error_init(&derr);
@@ -1147,9 +950,7 @@ static DBusHandlerResult am_find_by_addr(DBusConnection *conn,
if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
- path = device->object_path;
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &path,
+ dbus_message_append_args(reply, DBUS_TYPE_STRING, &device->path,
DBUS_TYPE_INVALID);
return send_message_and_unref(conn, reply);
@@ -1160,27 +961,20 @@ static DBusHandlerResult am_default_device(DBusConnection *conn,
void *data)
{
DBusMessage *reply;
- const char *path;
if (!default_dev)
- return error_reply(connection, msg,
- "org.bluez.audio.Error.DoesNotExist",
- "There is no default device");
+ return err_does_not_exist(connection, msg);
if (default_dev->headset == NULL &&
dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,
"DefaultHeadset"))
- return error_reply(connection, msg,
- "org.bluez.audio.Error.DoesNotExist",
- "There is no default headset");
+ return err_does_not_exist(connection, msg);
reply = dbus_message_new_method_return(msg);
if (!reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
- path = default_dev->object_path;
-
- dbus_message_append_args(reply, DBUS_TYPE_STRING, &path,
+ dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_dev->path,
DBUS_TYPE_INVALID);
return send_message_and_unref(connection, reply);
@@ -1194,7 +988,7 @@ static DBusHandlerResult am_change_default_device(DBusConnection *conn,
DBusMessage *reply;
GSList *match;
const char *path;
- audio_device_t *device;
+ struct device *device;
dbus_error_init(&derr);
if (!dbus_message_get_args(msg, &derr,
@@ -1211,9 +1005,7 @@ static DBusHandlerResult am_change_default_device(DBusConnection *conn,
match = g_slist_find_custom(devices, path, device_path_cmp);
if (!match)
- return error_reply(connection, msg,
- "org.bluez.audio.Error.DoesNotExist",
- "The device does not exist");
+ return err_does_not_exist(connection, msg);
reply = dbus_message_new_method_return(msg);
if (!reply)
@@ -1221,25 +1013,21 @@ static DBusHandlerResult am_change_default_device(DBusConnection *conn,
device = match->data;
- path = device->object_path;
-
if (!dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,
"ChangeDefaultHeadset"))
dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,
AUDIO_MANAGER_INTERFACE,
"DefaultDeviceChanged",
- DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &device->path,
DBUS_TYPE_INVALID);
else if (device->headset)
dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,
AUDIO_MANAGER_INTERFACE,
"DefaultHeadsetChanged",
- DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_STRING, &device->path,
DBUS_TYPE_INVALID);
else
- return error_reply(connection, msg,
- "org.bluez.audio.Error.DoesNotExist",
- "The headset does not exist");
+ return err_does_not_exist(connection, msg);
default_dev = device;
return send_message_and_unref(connection, reply);
@@ -1316,20 +1104,7 @@ void audio_exit(void)
connection = NULL;
}
-int manager_get_device(int sock, uint8_t role, struct ipc_data_cfg *cfg)
+struct device * manager_default_device()
{
- GSList *l;
-
- if (default_dev && default_dev->headset &&
- headset_is_connected(default_dev->headset))
- return headset_get_config(default_dev->headset, sock, cfg);
-
- for (l = devices; l != NULL; l = l->next) {
- audio_device_t *dev = l->data;
-
- if (dev->headset && headset_is_connected(dev->headset))
- return headset_get_config(dev->headset, sock, cfg);
- }
-
- return -1;
+ return default_dev;
}
diff --git a/audio/manager.h b/audio/manager.h
index 5cdf2b23..65515483 100644
--- a/audio/manager.h
+++ b/audio/manager.h
@@ -21,78 +21,17 @@
*
*/
-#include <bluetooth/bluetooth.h>
-
#include <dbus/dbus.h>
-#include "headset.h"
+#include "device.h"
#define AUDIO_MANAGER_PATH "/org/bluez/audio"
#define AUDIO_MANAGER_INTERFACE "org.bluez.audio.Manager"
-#define AUDIO_DEVICE_INTERFACE "org.bluez.audio.Device"
-
-#define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805F9B34FB"
-
-#define HSP_HS_UUID "00001108-0000-1000-8000-00805F9B34FB"
-#define HSP_AG_UUID "00001112-0000-1000-8000-00805F9B34FB"
-
-#define HFP_HS_UUID "0000111E-0000-1000-8000-00805F9B34FB"
-#define HFP_AG_UUID "0000111F-0000-1000-8000-00805F9B34FB"
-
-#define ADVANCED_AUDIO_UUID "0000110D-0000-1000-8000-00805F9B34FB"
-
-#define A2DP_SOURCE_UUID "0000110A-0000-1000-8000-00805F9B34FB"
-#define A2DP_SINK_UUID "0000110B-0000-1000-8000-00805F9B34FB"
-
-#define AVRCP_REMOTE_UUID "0000110E-0000-1000-8000-00805F9B34FB"
-#define AVRCP_TARGET_UUID "0000110C-0000-1000-8000-00805F9B34FB"
-
-/* Move these to respective .h files once they exist */
-#define AUDIO_GATEWAY_INTERFACE "org.bluez.audio.Gateway"
-#define AUDIO_SINK_INTERFACE "org.bluez.audio.Sink"
-#define AUDIO_SOURCE_INTERFACE "org.bluez.audio.Source"
-#define AUDIO_CONTROL_INTERFACE "org.bluez.audio.Control"
-#define AUDIO_TARGET_INTERFACE "org.bluez.audio.Target"
-typedef struct gateway gateway_t;
-typedef struct sink sink_t;
-typedef struct source source_t;
-typedef struct control control_t;
-typedef struct target target_t;
-
-typedef struct audio_device {
- char object_path[128];
- bdaddr_t bda;
-
- headset_t *headset;
-
- gateway_t *gateway;
- sink_t *sink;
- source_t *source;
- control_t *control;
- target_t *target;
-
-} audio_device_t;
-
-audio_device_t *manager_headset_connected(bdaddr_t *bda);
-
int audio_init(DBusConnection *conn);
void audio_exit(void);
-void finish_sdp_transaction(DBusConnection *conn, bdaddr_t *dba);
-
-
-DBusHandlerResult err_invalid_args(DBusConnection *conn, DBusMessage *msg,
- const char *descr);
-DBusHandlerResult err_already_connected(DBusConnection *conn, DBusMessage *msg);
-DBusHandlerResult err_not_connected(DBusConnection *conn, DBusMessage *msg);
-DBusHandlerResult err_not_supported(DBusConnection *conn, DBusMessage *msg);
-DBusHandlerResult err_connect_failed(DBusConnection *conn,
- DBusMessage *msg, int err);
-DBusHandlerResult err_does_not_exist(DBusConnection *conn, DBusMessage *msg);
-DBusHandlerResult err_not_available(DBusConnection *conn, DBusMessage *msg);
-DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg,
- const char *dsc);
+struct device *manager_device_connected(bdaddr_t *bda);
-int manager_get_device(int sock, uint8_t role, struct ipc_data_cfg *cfg);
+struct device *manager_default_device();
diff --git a/audio/unix.c b/audio/unix.c
index 2dad00df..f17404b4 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -78,6 +78,7 @@ static int unix_sendmsg_fd(int sock, int fd, struct ipc_packet *pkt)
static gboolean unix_event(GIOChannel *chan, GIOCondition cond, gpointer data)
{
+ struct device *device;
struct sockaddr_un addr;
socklen_t addrlen;
struct ipc_packet *pkt;
@@ -118,9 +119,13 @@ static gboolean unix_event(GIOChannel *chan, GIOCondition cond, gpointer data)
cfg = (struct ipc_data_cfg *) pkt->data;
memset(cfg, 0, sizeof(struct ipc_data_cfg));
- if (manager_get_device(clisk, pkt->role, cfg) == 0)
- unix_send_cfg(clisk, pkt);
+ if ((device = manager_default_device())) {
+ if (device->headset)
+ headset_get_config(device, clisk, pkt);
+ }
+ if (cfg->fd != 0)
+ unix_send_cfg(clisk, pkt);
break;
case PKT_TYPE_STATUS_REQ:
info("Package PKT_TYPE_STATUS_REQ");