diff options
-rw-r--r-- | audio/Makefile.am | 3 | ||||
-rw-r--r-- | audio/headset.c | 827 | ||||
-rw-r--r-- | audio/headset.h | 49 | ||||
-rw-r--r-- | audio/main.c | 6 | ||||
-rw-r--r-- | audio/manager.c | 369 | ||||
-rw-r--r-- | audio/manager.h | 67 | ||||
-rw-r--r-- | audio/unix.c | 9 |
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"); |