Skip to contentSkip to conversation

New RemoteDeviceDisconnectionRequested signal implementation

PATCH In review Luciano Coelho 2 participants 2 messages Dec 28, 2006 Bluetooth drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 New RemoteDeviceDisconnectionRequested signal implementation

Hi Marcel (and others),

As agreed last week, I've implemented a new D-Bus signal in hcid that allows upper-level applications to disconnect gracefuly before the ACL connection is terminated as a result of a call to RemoteDeviceDisconnect.

So, this is how it works: when the RemoteDeviceDisconnect is called, we send the new signal RemoteDeviceDisconnectionRequested(string bdaddr) and wait for 2 seconds before sending the disconnection command to the controller. This enables the service implementations to disconnect in a nicer way, as specified in the profile specs (eg. in SIM Access Profile, a SIM_DISCONNECT_REQ can be sent by the client).

The change is not very big and should be backwards compatible, except for the fact that disconnections will take 2 seconds longer than before.

I also updated the documentation and the apitest script.

Please let me know what you think.

Cheers,
Luca.

Index: hcid/dbus-adapter.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-adapter.c,v retrieving revision 1.141

dbus-adapter.c +73 -21
diff -u -r1.141 dbus-adapter.c
@@ -1680,18 +1680,61 @@
 	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 @@
 	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);
-
-	reply = dbus_message_new_method_return(msg);
-	if (!reply)
-		return DBUS_HANDLER_RESULT_NEED_MEMORY;
+	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;
+
+	/* ...and send a signal */
+	signal = dev_signal_factory(adapter->dev_id, "RemoteDeviceDisconnectionRequested",
+						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)

Index: hcid/dbus-adapter.h
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-adapter.h,v retrieving revision 1.1

dbus-adapter.h +12 -0
diff -u -r1.1 dbus-adapter.h
@@ -34,6 +34,8 @@
 
 #define BONDING_TIMEOUT         45000 /* 45 sec */
 
+#define DC_PENDING_TIMEOUT      2000  /* 2 secs */
+
 /* Discover types */
 #define DISCOVER_TYPE_NONE	0x00
 #define STD_INQUIRY		0x01
@@ -77,6 +79,13 @@
 	uint16_t handle;
 };
 
+struct pending_dc_info {
+	DBusConnection *conn;
+	DBusMessage *msg;
+	uint16_t conn_handle;
+	guint timeout_id;
+};
+
 struct adapter {
 	uint16_t dev_id;
 	int up;
@@ -100,6 +109,7 @@
 	struct slist *active_conn;
 	struct bonding_request_info *bonding;
 	struct slist *pin_reqs;
+	struct pending_dc_info *pending_dc;
 };
 
 DBusHandlerResult handle_adapter_method(DBusConnection *conn, DBusMessage *msg, void *data);
@@ -112,4 +122,6 @@
 
 int pending_remote_name_cancel(struct adapter *adapter);
 
+void dc_pending_timeout_cleanup(struct adapter *adapter);
+
 #endif /* __ADAPTER_H */

Index: hcid/dbus-api.txt
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-api.txt,v retrieving revision 1.91

dbus-api.txt +30 -17

77 lines not on this page · raw message

Index: hcid/dbus-error.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-error.c,v retrieving revision 1.33

dbus-error.c +5 -0
diff -u -r1.33 dbus-error.c
@@ -278,6 +278,11 @@
 	return error_does_not_exist(conn, msg, "Trusted device does not exist");
 }
 
+DBusHandlerResult error_disconnect_in_progress(DBusConnection *conn, DBusMessage *msg)
+{
+	return error_in_progress(conn, msg, "Disconnection in progress");
+}
+
 
 static const char *strsdperror(int err)
 {

Index: hcid/dbus-error.h
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-error.h,v retrieving revision 1.3

dbus-error.h +1 -0
diff -u -r1.3 dbus-error.h
@@ -65,5 +65,6 @@
 DBusHandlerResult error_audit_already_exists(DBusConnection *conn, DBusMessage *msg);
 DBusHandlerResult error_trusted_device_already_exists(DBusConnection *conn, DBusMessage *msg);
 DBusHandlerResult error_trusted_device_does_not_exists(DBusConnection *conn, DBusMessage *msg);
+DBusHandlerResult error_disconnect_in_progress(DBusConnection *conn, DBusMessage *msg);
 
 #endif /* __BLUEZ_DBUS_ERROR_H */

Index: hcid/dbus-hci.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-hci.c,v
retrieving revision 1.5

dbus-hci.c +22 -0
diff -u -r1.5 dbus-hci.c
@@ -473,6 +473,14 @@
 		adapter->active_conn = NULL;
 	}
 
+	/* Check if there is a pending RemoteDeviceDisconnect request */
+	if (adapter->pending_dc) {
+ 		error_no_such_adapter(adapter->pending_dc->conn,
+				      adapter->pending_dc->msg);
+		g_timeout_remove(adapter->pending_dc->timeout_id);
+		dc_pending_timeout_cleanup(adapter);
+	}
+
 	free (adapter);
 
 unreg:
@@ -1742,6 +1750,20 @@
 		adapter->bonding = NULL;
 	}
 
+	/* Check if there is a pending RemoteDeviceDisconnect request */
+	if (adapter->pending_dc) {
+		DBusMessage *reply;
+
+		reply = dbus_message_new_method_return(adapter->pending_dc->msg);
+		if (!reply)
+			error("Failed to allocate disconnect reply");
+		else
+			send_message_and_unref(adapter->pending_dc->conn, reply);
+
+		g_timeout_remove(adapter->pending_dc->timeout_id);
+		dc_pending_timeout_cleanup(adapter);
+	}
+
 	/* Send the remote device disconnected signal */
 	message = dev_signal_factory(adapter->dev_id,
 					"RemoteDeviceDisconnected",

Index: test/apitest
===================================================================
RCS file: /cvsroot/bluez/utils/test/apitest,v
retrieving revision 1.3

apitest +1 -0
diff -u -r1.3 apitest
@@ -69,6 +69,7 @@
                 "RemoteAliasChanged"
                 "RemoteAliasCleared",
                 "RemoteDeviceConnected",
+                "RemoteDeviceDisconnectionRequested",
                 "RemoteDeviceDisconnected",
                 "BondingCreated",
                 "BondingRemoved" ]

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel

#1 lore raw

Hi Luca,

Quoted 11 lines · Luciano Coelho

As agreed last week, I've implemented a new D-Bus signal in hcid that allows upper-level applications to disconnect gracefuly before the ACL connection is terminated as a result of a call to RemoteDeviceDisconnect.

So, this is how it works: when the RemoteDeviceDisconnect is called, we send the new signal RemoteDeviceDisconnectionRequested(string bdaddr) and wait for 2 seconds before sending the disconnection command to the controller. This enables the service implementations to disconnect in a nicer way, as specified in the profile specs (eg. in SIM Access Profile, a SIM_DISCONNECT_REQ can be sent by the client).

Quoted 6 lines

The change is not very big and should be backwards compatible, except for the fact that disconnections will take 2 seconds longer than before.

I also updated the documentation and the apitest script.

Please let me know what you think.

Looks good to me.

Johan

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel