summaryrefslogtreecommitdiffstats
path: root/hcid/dbus-adapter.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2007-01-03 12:14:01 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2007-01-03 12:14:01 +0000
commit6033ee0c9966238f3732e945841d85ddb5162cc2 (patch)
tree76d609cb63074d1038187bb29833105493a4517e /hcid/dbus-adapter.c
parentd21f13975ab07dcf9ec8b51fd764d1c5a9b76f92 (diff)
Add disconnection delay and RemoteDeviceDisconnectRequested signal for the DisconnectRemoteDevice method
Diffstat (limited to 'hcid/dbus-adapter.c')
-rw-r--r--hcid/dbus-adapter.c92
1 files changed, 72 insertions, 20 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c
index a36ab4fa..a4ca8712 100644
--- a/hcid/dbus-adapter.c
+++ b/hcid/dbus-adapter.c
@@ -1680,18 +1680,61 @@ static DBusHandlerResult adapter_last_used(DBusConnection *conn,
return send_message_and_unref(conn, reply);
}
-static DBusHandlerResult adapter_dc_remote_device(DBusConnection *conn,
- DBusMessage *msg, void *data)
+
+gboolean dc_pending_timeout_handler(void *data)
{
+ int dd;
+ struct adapter *adapter = data;
+ struct pending_dc_info *pending_dc = adapter->pending_dc;
DBusMessage *reply;
+ dd = hci_open_dev(adapter->dev_id);
+
+ if (dd < 0) {
+ error_no_such_adapter(pending_dc->conn,
+ pending_dc->msg);
+ dc_pending_timeout_cleanup(adapter);
+ return FALSE;
+ }
+
+ /* Send the HCI disconnect command */
+ if (hci_disconnect(dd, pending_dc->conn_handle,
+ HCI_OE_USER_ENDED_CONNECTION,
+ 500) < 0) {
+ int err = errno;
+ error("Disconnect failed");
+ error_failed(pending_dc->conn, pending_dc->msg, err);
+ } else {
+ reply = dbus_message_new_method_return(pending_dc->msg);
+ if (!reply)
+ error("Failed to allocate disconnect reply");
+ else
+ send_message_and_unref(pending_dc->conn, reply);
+ }
+
+ hci_close_dev(dd);
+ dc_pending_timeout_cleanup(adapter);
+
+ return FALSE;
+}
+
+void dc_pending_timeout_cleanup(struct adapter *adapter)
+{
+ dbus_connection_unref(adapter->pending_dc->conn);
+ dbus_message_unref(adapter->pending_dc->msg);
+ free(adapter->pending_dc);
+ adapter->pending_dc = NULL;
+}
+
+static DBusHandlerResult adapter_dc_remote_device(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
struct adapter *adapter = data;
struct slist *l = adapter->active_conn;
const char *peer_addr;
bdaddr_t peer_bdaddr;
- int dd;
- struct active_conn_info *dev;
+ DBusMessage *signal;
if (!adapter->up)
return error_not_ready(conn, msg);
@@ -1710,29 +1753,38 @@ static DBusHandlerResult adapter_dc_remote_device(DBusConnection *conn,
if (!l)
return error_not_connected(conn, msg);
- dev = l->data;
+ if(adapter->pending_dc)
+ return error_disconnect_in_progress(conn, msg);
- dd = hci_open_dev(adapter->dev_id);
- if (dd < 0)
- return error_no_such_adapter(conn, msg);
+ adapter->pending_dc = malloc(sizeof(*adapter->pending_dc));
+ if(!adapter->pending_dc)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
- /* Send the HCI disconnect command */
- if (hci_disconnect(dd, dev->handle, HCI_OE_USER_ENDED_CONNECTION,
- 500) < 0) {
- int err = errno;
- error("Disconnect failed");
- hci_close_dev(dd);
- return error_failed(conn, msg, err);
+ /* Start waiting... */
+ adapter->pending_dc->timeout_id =
+ g_timeout_add(DC_PENDING_TIMEOUT,
+ dc_pending_timeout_handler,
+ adapter);
+
+ if(!adapter->pending_dc->timeout_id) {
+ free(adapter->pending_dc);
+ adapter->pending_dc = NULL;
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
- hci_close_dev(dd);
+ adapter->pending_dc->conn = dbus_connection_ref(conn);
+ adapter->pending_dc->msg = dbus_message_ref(msg);
+ adapter->pending_dc->conn_handle =
+ ((struct active_conn_info *) l->data)->handle;
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ /* ...and send a signal */
+ signal = dev_signal_factory(adapter->dev_id, "RemoteDeviceDisconnectRequested",
+ DBUS_TYPE_STRING, &peer_addr,
+ DBUS_TYPE_INVALID);
+ send_message_and_unref(conn, signal);
- return send_message_and_unref(conn, reply);
+ return DBUS_HANDLER_RESULT_HANDLED;
}
static void reply_authentication_failure(struct bonding_request_info *bonding)