diff options
Diffstat (limited to 'audio/headset.c')
| -rw-r--r-- | audio/headset.c | 94 | 
1 files changed, 91 insertions, 3 deletions
| diff --git a/audio/headset.c b/audio/headset.c index c08489ff..a6581df8 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -54,6 +54,8 @@  #include "manager.h"  #include "headset.h" +#define DEFAULT_HS_AG_CHANNEL 12 +  #define RING_INTERVAL 3000  typedef enum { @@ -102,6 +104,10 @@ struct headset {  static DBusHandlerResult hs_disconnect(struct headset *hs, DBusMessage *msg); +static GIOChannel *hs_server = NULL; + +static uint32_t hs_record_id = 0; +  static GSList *headsets = NULL;  static DBusConnection *connection = NULL; @@ -496,7 +502,7 @@ static void auth_callback(DBusPendingCall *call, void *data)  	dbus_message_unref(reply);  } -gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond, void *data) +static gboolean headset_server_io_cb(GIOChannel *chan, GIOCondition cond, void *data)  {  	int srv_sk, cli_sk;  	struct sockaddr_rc addr; @@ -952,7 +958,7 @@ static int create_ag_record(sdp_buf_t *buf, uint8_t ch)  	return ret;  } -uint32_t headset_add_ag_record(uint8_t channel) +static uint32_t headset_add_ag_record(uint8_t channel)  {  	DBusMessage *msg, *reply;  	DBusError derr; @@ -1668,13 +1674,95 @@ void headset_remove(char *path)  	g_free(path);  } -void headset_init(DBusConnection *conn) +static GIOChannel *server_socket(uint8_t *channel) +{ +	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; +	} + +	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 = 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; +} + +int headset_init(DBusConnection *conn)  { +	uint8_t chan = DEFAULT_HS_AG_CHANNEL; +  	connection = dbus_connection_ref(conn); + +	hs_server = server_socket(&chan); +	if (!hs_server) +		return -1; + +	if (!hs_record_id) +		hs_record_id = headset_add_ag_record(chan); + +	if (!hs_record_id) { +		error("Unable to register 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); + +	return 0;  }  void headset_exit(void)  { +	if (hs_record_id) { +		headset_remove_ag_record(hs_record_id); +		hs_record_id = 0; +	} + +	if (hs_server) { +		g_io_channel_unref(hs_server); +		hs_server = NULL; +	} +  	dbus_connection_unref(connection);  	connection = NULL;  } | 
