diff options
-rw-r--r-- | audio/headset.c | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/audio/headset.c b/audio/headset.c index d50de1a5..f26fcfed 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -50,6 +50,8 @@ #include "logging.h" #include "glib-ectomy.c" +#define RING_INTERVAL 3000 + #define HEADSET_PATH "/org/bluez/headset" static const char *hs_path = HEADSET_PATH; @@ -65,6 +67,7 @@ struct hs_connection { char address[18]; GIOChannel *rfcomm; GIOChannel *sco; + guint ring_timer; }; static gboolean connect_in_progress = FALSE; @@ -89,6 +92,7 @@ static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg, const char *address); static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg); static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg); +static DBusHandlerResult hs_cancel_ringing(DBusConnection *conn, DBusMessage *msg); static int set_nonblocking(int fd, int *err) { @@ -207,6 +211,11 @@ static gboolean rfcomm_io_cb(GIOChannel *chan, GIOCondition cond, struct hs_conn printf("%s\n", buf); } + if (connected_hs->ring_timer) { + g_timeout_remove(connected_hs->ring_timer); + connected_hs->ring_timer = 0; + } + return TRUE; failed: @@ -734,6 +743,9 @@ static DBusHandlerResult hs_message(DBusConnection *conn, if (strcmp(member, "Ring") == 0) return hs_ring(conn, msg); + if (strcmp(member, "CancelRinging") == 0) + return hs_cancel_ringing(conn, msg); + /* Handle Headset interface methods here */ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1064,11 +1076,41 @@ static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg, return DBUS_HANDLER_RESULT_HANDLED;; } +static int send_ring(GIOChannel *io) +{ + const char *ring_str = "\r\nRING\r\n"; + int sk, written, len; + + sk = g_io_channel_unix_get_fd(connected_hs->rfcomm); + + len = strlen(ring_str); + written = 0; + + while (written < len) { + int ret; + + ret = write(sk, ring_str + written, len - written); + + if (ret < 0) + return ret; + + written += ret; + } + + return 0; +} + +static gboolean ring_timer(gpointer user_data) +{ + if (send_ring(connected_hs->rfcomm) < 0) + error("Sending RING failed"); + + return TRUE; +} + static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg) { DBusMessage *reply; - const char *ring_str = "\r\nRING\r\n"; - int sk, ret; if (!connected_hs) return err_not_connected(conn, msg); @@ -1077,14 +1119,45 @@ static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg) if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - sk = g_io_channel_unix_get_fd(connected_hs->rfcomm); + if (connected_hs->ring_timer) { + debug("Got Ring method call while ringing already in progress"); + goto done; + } - ret = write(sk, ring_str, strlen(ring_str)); - if (ret < strlen(ring_str)) { + if (send_ring(connected_hs->rfcomm) < 0) { dbus_message_unref(reply); return err_failed(conn, msg); } + connected_hs->ring_timer = g_timeout_add(RING_INTERVAL, ring_timer, NULL); + +done: + dbus_connection_send(conn, reply, NULL); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult hs_cancel_ringing(DBusConnection *conn, DBusMessage *msg) +{ + DBusMessage *reply; + + if (!connected_hs) + return err_not_connected(conn, msg); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + if (!connected_hs->ring_timer) { + debug("Got CancelRinging method call but ringing is not in progress"); + goto done; + } + + g_timeout_remove(connected_hs->ring_timer); + connected_hs->ring_timer = 0; + +done: dbus_connection_send(conn, reply, NULL); dbus_message_unref(reply); |