Re: HID certification using PTS

Frederic Danis <[email protected]>
Newsgroups gmane.linux.bluez.devel
Organization Access Company
Message-ID <[email protected]>
Hello,

> - when kernel (2.6.22) receives a VIRTUAL_CABLE_UNPLUG from PTS (tests 
> TC_HOS_HCR_BV_02_I and TC_HOS_HCR_BV_04_I) it does not close the L2CAP 
> channels as PTS waits for.
> I take a look in 2.6.22 sources, and it seems to me this disconnection 
> should happen, am I right ?
> Is it fixed in later kernel ?

Regarding this problem I wrote a patch in kernel that allows to poll the HIDP control socket and set it to IO_HUP when receiving the virtual cable unplug command.
I update the input service to watch the HIDP control socket and close l2cap sockets if IO_HUP is set on HIDP control socket.

Is it OK ?

Regards

Fred

-- 
-----------------------------------------------
It is not by improving the oil lamp that one invents the electric bulb!
-----------------------------------------------
Danis Frederic                   Access Company
Software engineer
Mail : mailto:[email protected]
-----------------------------------------------

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

_______________________________________________
Bluez-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bluez-devel
hidp_socket.patch (text/x-patch, 3.4 KB)
diff -Naur linux-2.6.24.4/net/bluetooth/hidp.orig/core.c linux-2.6.24.4/net/bluetooth/hidp/core.c
--- linux-2.6.24.4/net/bluetooth/hidp.orig/core.c	2008-03-24 19:49:18.000000000 +0100
+++ linux-2.6.24.4/net/bluetooth/hidp/core.c	2008-04-01 11:14:05.000000000 +0200
@@ -378,8 +378,12 @@
 		skb_queue_purge(&session->ctrl_transmit);
 		skb_queue_purge(&session->intr_transmit);
 
+		if (session->hidp_sock)
+			session->hidp_sock->sk->sk_shutdown = SHUTDOWN_MASK;
+
 		/* Kill session thread */
 		atomic_inc(&session->terminate);
+		hidp_schedule(session);
 		break;
 
 	case HIDP_CTRL_HARD_RESET:
@@ -743,7 +747,7 @@
 		hid->claimed |= HID_CLAIMED_INPUT;
 }
 
-int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
+int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock, struct socket *hidp_sock)
 {
 	struct hidp_session *session, *s;
 	int err;
@@ -809,6 +813,7 @@
 
 	session->ctrl_sock = ctrl_sock;
 	session->intr_sock = intr_sock;
+	session->hidp_sock = hidp_sock;
 	session->state     = BT_CONNECTED;
 
 	init_timer(&session->timer);
@@ -952,6 +957,24 @@
 	return err;
 }
 
+void hidp_remove_hidp_sock_ref(struct socket *hidp_sock)
+{
+	struct list_head *p;
+
+	down_read(&hidp_session_sem);
+
+	list_for_each(p, &hidp_session_list) {
+		struct hidp_session *session;
+
+		session = list_entry(p, struct hidp_session, list);
+
+		if (session->hidp_sock == hidp_sock)
+			session->hidp_sock = NULL;
+	}
+
+	up_read(&hidp_session_sem);
+}
+
 static int __init hidp_init(void)
 {
 	l2cap_load();
diff -Naur linux-2.6.24.4/net/bluetooth/hidp.orig/hidp.h linux-2.6.24.4/net/bluetooth/hidp/hidp.h
--- linux-2.6.24.4/net/bluetooth/hidp.orig/hidp.h	2008-03-24 19:49:18.000000000 +0100
+++ linux-2.6.24.4/net/bluetooth/hidp/hidp.h	2008-04-01 11:14:33.000000000 +0200
@@ -117,10 +117,11 @@
 	struct hidp_conninfo __user *ci;
 };
 
-int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
+int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock, struct socket *hidp_sock);
 int hidp_del_connection(struct hidp_conndel_req *req);
 int hidp_get_connlist(struct hidp_connlist_req *req);
 int hidp_get_conninfo(struct hidp_conninfo *ci);
+void hidp_remove_hidp_sock_ref(struct socket *hidp_sock);
 
 /* HIDP session defines */
 struct hidp_session {
@@ -128,6 +129,7 @@
 
 	struct socket *ctrl_sock;
 	struct socket *intr_sock;
+	struct socket *hidp_sock;
 
 	bdaddr_t bdaddr;
 
diff -Naur linux-2.6.24.4/net/bluetooth/hidp.orig/sock.c linux-2.6.24.4/net/bluetooth/hidp/sock.c
--- linux-2.6.24.4/net/bluetooth/hidp.orig/sock.c	2008-03-24 19:49:18.000000000 +0100
+++ linux-2.6.24.4/net/bluetooth/hidp/sock.c	2008-04-01 11:15:33.000000000 +0200
@@ -56,6 +56,8 @@
 	sock_orphan(sk);
 	sock_put(sk);
 
+	hidp_remove_hidp_sock_ref(sock);
+
 	return 0;
 }
 
@@ -96,7 +98,7 @@
 			return -EBADFD;
 		}
 
-		err = hidp_add_connection(&ca, csock, isock);
+		err = hidp_add_connection(&ca, csock, isock, sock);
 		if (!err) {
 			if (copy_to_user(argp, &ca, sizeof(ca)))
 				err = -EFAULT;
@@ -229,7 +231,7 @@
 	.getname	= sock_no_getname,
 	.sendmsg	= sock_no_sendmsg,
 	.recvmsg	= sock_no_recvmsg,
-	.poll		= sock_no_poll,
+	.poll		= bt_sock_poll,
 	.listen		= sock_no_listen,
 	.shutdown	= sock_no_shutdown,
 	.setsockopt	= sock_no_setsockopt,
virtual_cable_unplug.patch (text/x-patch, 3.9 KB)
Index: device.c
===================================================================
RCS file: /cvsroot/bluez/utils/input/device.c,v
retrieving revision 1.71
diff -a -u -r1.71 device.c
--- device.c	14 Mar 2008 18:44:00 -0000	1.71
+++ device.c	1 Apr 2008 15:42:26 -0000
@@ -78,8 +78,10 @@
 	char			*path;
 	int			ctrl_sk;
 	int			intr_sk;
+	int			hidp_sk;
 	guint			ctrl_watch;
 	guint			intr_watch;
+	guint			hidp_watch;
 };
 
 GSList *devices = NULL;
@@ -524,8 +526,10 @@
 			DBUS_TYPE_INVALID);
 
 	g_source_remove(idev->ctrl_watch);
+	g_source_remove(idev->hidp_watch);
 	idev->ctrl_watch = 0;
 	idev->intr_watch = 0;
+	idev->hidp_watch = 0;
 
 	/* Close control channel */
 	if (idev->ctrl_sk > 0) {
@@ -533,6 +537,12 @@
 		idev->ctrl_sk = -1;
 	}
 
+	/* Close hidp channel */
+	if (idev->hidp_sk > 0) {
+		close(idev->hidp_sk);
+		idev->hidp_sk = -1;
+	}
+
 	return FALSE;
 
 }
@@ -551,8 +561,10 @@
 			DBUS_TYPE_INVALID);
 
 	g_source_remove(idev->intr_watch);
+	g_source_remove(idev->hidp_watch);
 	idev->intr_watch = 0;
 	idev->ctrl_watch = 0;
+	idev->hidp_watch = 0;
 
 	/* Close interrupt channel */
 	if (idev->intr_sk > 0) {
@@ -560,6 +572,47 @@
 		idev->intr_sk = -1;
 	}
 
+	/* Close hidp channel */
+	if (idev->hidp_sk > 0) {
+		close(idev->hidp_sk);
+		idev->hidp_sk = -1;
+	}
+
+	return FALSE;
+}
+
+static gboolean hidp_watch_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+	struct device *idev = data;
+
+	if (cond & (G_IO_HUP | G_IO_ERR)) {
+		g_io_channel_close(chan);
+	}
+
+	dbus_connection_emit_signal(idev->conn,
+			idev->path,
+			INPUT_DEVICE_INTERFACE,
+			"Disconnected",
+			DBUS_TYPE_INVALID);
+
+	g_source_remove(idev->intr_watch);
+	g_source_remove(idev->ctrl_watch);
+	idev->intr_watch = 0;
+	idev->ctrl_watch = 0;
+	idev->hidp_watch = 0;
+
+	/* Close interrupt channel */
+	if (idev->intr_sk > 0) {
+		close(idev->intr_sk);
+		idev->intr_sk = -1;
+	}
+
+	/* Close control channel */
+	if (idev->ctrl_sk > 0) {
+		close(idev->ctrl_sk);
+		idev->ctrl_sk = -1;
+	}
+
 	return FALSE;
 }
 
@@ -620,12 +673,10 @@
 
 	err = ioctl(ctl, HIDPCONNADD, &req);
 cleanup:
-	close(ctl);
-
 	if (req.rd_data)
 		free(req.rd_data);
 
-	return err;
+	return ctl;
 }
 
 static gboolean interrupt_connect_cb(GIOChannel *chan,
@@ -663,13 +714,14 @@
 	}
 
 	idev->intr_sk = isk;
-	err = hidp_connadd(&idev->src, &idev->dst,
+	idev->hidp_sk = hidp_connadd(&idev->src, &idev->dst,
 			idev->ctrl_sk, idev->intr_sk, idev->name);
-	if (err < 0)
+	if (idev->hidp_sk < 0)
 		goto failed;
 
 	idev->intr_watch = create_watch(idev->intr_sk, intr_watch_cb, idev);
 	idev->ctrl_watch = create_watch(idev->ctrl_sk, ctrl_watch_cb, idev);
+	idev->hidp_watch = create_watch(idev->hidp_sk, hidp_watch_cb, idev);
 	dbus_connection_emit_signal(idev->conn,
 			idev->path,
 			INPUT_DEVICE_INTERFACE,
@@ -802,10 +854,15 @@
 		idev->intr_sk = -1;
 	}
 
-	ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP);
-	if (ctl < 0) {
-		error("Can't open HIDP control socket");
-		return -errno;
+	if (idev->hidp_sk >= 0) {
+		ctl = idev->hidp_sk;
+		idev->hidp_sk = -1;
+	} else {
+		ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP);
+		if (ctl < 0) {
+			error("Can't open HIDP control socket");
+			return -errno;
+		}
 	}
 
 	memset(&ci, 0, sizeof(ci));
@@ -1181,6 +1238,9 @@
 	 * to access the D-Bus data assigned to this path
 	 * because the object path data was destroyed.
 	 */
+	if (idev->hidp_watch)
+		g_source_remove(idev->hidp_watch);
+
 	if (idev->ctrl_watch)
 		g_source_remove(idev->ctrl_watch);
 
@@ -1364,8 +1424,15 @@
 		fake->disconnect = fake_hid_disconnect;
 		fake->priv = fake_hid;
 		err = fake_hid_connadd(fake, idev->intr_sk, fake_hid);
-	} else
-		err = hidp_connadd(src, dst, idev->ctrl_sk, idev->intr_sk, idev->name);
+	} else {
+		idev->hidp_sk = hidp_connadd(src, dst, idev->ctrl_sk, idev->intr_sk, idev->name);
+		if (idev->hidp_sk < 0) {
+			err = idev->hidp_sk;
+		} else {
+			err = 0;
+			idev->hidp_watch = create_watch(idev->hidp_sk, hidp_watch_cb, idev);
+		}
+	}
 	if (err < 0)
 		goto error;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.