public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
       [not found] <20041123212813.GA3196@spacedout.fries.net>
@ 2005-02-01 14:52 ` David Fries
  2005-02-01 15:24   ` Dmitry Torokhov
  0 siblings, 1 reply; 9+ messages in thread
From: David Fries @ 2005-02-01 14:52 UTC (permalink / raw)
  To: Vojtech Pavlik; +Cc: Linus Torvalds, trivial, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2682 bytes --]

Currently a blocking read, select, or poll call will not return if a
joystick device is unplugged.  This patch allows them to return.

This patch adds a wake_up_interruptible call to the joydev_disconnect
to interrupt both a blocking read and a blocking poll call.  The read
routine was already setup to handle this situation, just nothing was
waking it up.  The poll routine required only minimal changes to
report the error condition.  It is important to find out when the
joystick has been disconnected instead of blocking forever.

I tested it with a USB joystick, or rather I keep on getting the
following messages and my application needed to know when the joystick
was removed to close the port and re-open it when the USB system has
completed rediscovering it.

hub 4-0:1.0: port 1 enable change, status 00000101
hub 4-0:1.0: port 1 disabled by hub (EMI?), re-enabling...
hub 4-0:1.0: port 1, status 0101, change 0002, 12 Mb/s
usb 4-1: USB disconnect, address 39
usb 4-1: usb_disable_device nuking all URBs

I can reliably enough reproduce the problem by standing up as the
static on my cloth chair followed by a discharge to the chair is
enough to cause the joystick to be disabled by the USB HUB even if I'm
only touching the chair and floor!  The kernel then removes the old
joystick and redetects it as a new joystick.

I've also included a test program to verify that a blocking select,
poll, and read call will return if the joystick is unplugged.

-- 
David Fries <dfries@mail.win.org>
http://fries.net/~david/pgpkey.txt



Signed-off-by: David Fries <dfries@mail.win.org>

--- drivers/input/joydev.c.orig	Tue Feb  1 08:39:52 2005
+++ drivers/input/joydev.c	Tue Feb  1 08:40:15 2005
@@ -279,11 +279,14 @@ static ssize_t joydev_read(struct file *
 /* No kernel lock - fine */
 static unsigned int joydev_poll(struct file *file, poll_table *wait)
 {
+	int mask = 0;
 	struct joydev_list *list = file->private_data;
 	poll_wait(file, &list->joydev->wait, wait);
-	if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	if(!list->joydev->exist)
+		mask |= POLLERR;
+	if(list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
+		mask |= POLLIN | POLLRDNORM;
+	return mask;
 }
 
 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -469,9 +472,14 @@ static void joydev_disconnect(struct inp
 	joydev->exist = 0;
 
 	if (joydev->open)
+	{
 		input_close_device(handle);
+		wake_up_interruptible(&joydev->wait);
+	}
 	else
+	{
 		joydev_free(joydev);
+	}
 }
 
 static struct input_device_id joydev_blacklist[] = {

[-- Attachment #2: joystick_select.c --]
[-- Type: text/x-csrc, Size: 3582 bytes --]

#include <sys/poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/joystick.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

//#define UFDS_COUNT 10
#define UFDS_COUNT 1

void select_call(const char *device)
{
	int result, fd;
	fd_set tmpfds, readfds, writefds, exceptfds;

	fd = open(device, O_RDONLY | O_NONBLOCK);
	if(fd == -1)
	{
		fprintf(stderr, "Error opening %s: %s\n",
			device, strerror(errno));
		exit(1);
	}

	FD_ZERO(&tmpfds);
	FD_SET(fd, &tmpfds);
	for(;;)
	{
		writefds = exceptfds = readfds = tmpfds;
		result = select(fd+1, &readfds, &writefds, &exceptfds, NULL);
		if(result == -1)
		{
			perror("Select error");
			exit(1);
		}
		if(FD_ISSET(fd, &readfds))
		{
			struct js_event event;
			int size;
			printf("%s readable\n", __FUNCTION__);
			size = read(fd, &event, sizeof(event));
			if(size == -1)
			{
				fprintf(stderr, "%s Error reading data\n",
					__FUNCTION__);
				if(errno == ENODEV)
					exit(1);
			}
		}
		if(FD_ISSET(fd, &writefds))
		{
			printf("%s writable\n", __FUNCTION__);
		}
		if(FD_ISSET(fd, &exceptfds))
		{
			printf("%s exception\n", __FUNCTION__);
			break;
		}
	}
}

void poll_call(const char *device)
{
	int i, result, fd;
	struct pollfd ufds[UFDS_COUNT];
	fd = open(device, O_RDONLY | O_NONBLOCK);
	if(fd == -1)
	{
		fprintf(stderr, "Error opening %s: %s\n",
			device, strerror(errno));
		exit(1);
	}
	for(i=0; i<UFDS_COUNT; i++)
	{
		ufds[i].fd = fd;
		ufds[i].events = POLLIN | POLLPRI | POLLOUT | POLLERR |
			POLLHUP | POLLNVAL;
		ufds[i].revents = 0;
	}
	for(;;)
	{
		result = poll(ufds, UFDS_COUNT, -1);
		if(result == -1)
		{
			perror("poll error");
			exit(1);
		}
		for(i=0; i<result; i++)
		{
			printf("poll %d, ", i);
			if(ufds[i].revents & POLLIN ||
				ufds[i].revents & POLLERR)
			{
				struct js_event event;
				int size;
				if(ufds[i].revents & POLLIN)
					printf("POLLIN There is data to read");
				else if(ufds[i].revents & POLLERR)
					printf("POLLERR Error condition");
				size = read(fd, &event, sizeof(event));
				if(size == -1)
				{
					fprintf(stderr,
						"%s Error reading data\n",
						__FUNCTION__);
					if(errno == ENODEV)
						exit(1);
				}
			}
			if(ufds[i].revents & POLLPRI)
				printf("POLLPRI There is urgent data to read");
			if(ufds[i].revents & POLLOUT)
				printf("POLLOUT Writing now will not block");
			if(ufds[i].revents & POLLHUP)
				printf("POLLHUP Hung up");
			if(ufds[i].revents & POLLNVAL)
				printf("POLLNVAL Invalid request: fd not open");
			printf("\n");
		}
	}
}

void read_call(const char *device)
{
	struct js_event event;
	int size, fd;
	/* Don't block here. */
	fd = open(device, O_RDONLY);
	if(fd == -1)
	{
		fprintf(stderr, "Error opening %s: %s\n",
			device, strerror(errno));
		exit(1);
	}
	for(;;)
	{
		size = read(fd, &event, sizeof(event));
		if(size == -1)
		{
			fprintf(stderr, "%s Error reading data: %s\n",
				__FUNCTION__, strerror(errno));
			exit(1);
		}
		else
		{
			printf("%s read %d bytes\n", __FUNCTION__, size);
		}
	}
}

int main(int argc, char **argv)
{
	int result;
	const char *device;
	if(argc != 2)
	{
		fprintf(stderr, "Usage: %s /dev/jsN\n", argv[0]);
		return -1;
	}
	device = argv[1];

	result = fork();
	if(result==-1)
	{
		perror("Error on fork.");
		return -1;
	}
	if(result)
	{
		result = fork();
		if(result == -1)
		{
			perror("Error on fork.");
			return -1;
		}
		if(result)
		{
			select_call(device);
		}
		else
		{
			read_call(device);
		}
	}
	else
	{
		poll_call(device);
	}
	return 0;
}

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-01 14:52 ` [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2 David Fries
@ 2005-02-01 15:24   ` Dmitry Torokhov
  2005-02-06 13:12     ` Vojtech Pavlik
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry Torokhov @ 2005-02-01 15:24 UTC (permalink / raw)
  To: David Fries; +Cc: Vojtech Pavlik, Linus Torvalds, trivial, linux-kernel

On Tue, 1 Feb 2005 08:52:15 -0600, David Fries <dfries@mail.win.org> wrote:
> Currently a blocking read, select, or poll call will not return if a
> joystick device is unplugged.  This patch allows them to return.
> 
...
> static unsigned int joydev_poll(struct file *file, poll_table *wait)
> {
> +       int mask = 0;
>        struct joydev_list *list = file->private_data;
>        poll_wait(file, &list->joydev->wait, wait);
> -       if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
> -               return POLLIN | POLLRDNORM;
> -       return 0;
> +       if(!list->joydev->exist)
> +               mask |= POLLERR;

Probably need POLLHUP in addition (or instead of POLLERR).

>        if (joydev->open)
> +       {
>                input_close_device(handle);
> +               wake_up_interruptible(&joydev->wait);
> +       }
>        else
> +       {
>                joydev_free(joydev);
> +       }

Opening braces should go on the same line as the statement (if (...) {).
-- 
Dmitry

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-01 15:24   ` Dmitry Torokhov
@ 2005-02-06 13:12     ` Vojtech Pavlik
  2005-02-07  1:21       ` Dmitry Torokhov
  0 siblings, 1 reply; 9+ messages in thread
From: Vojtech Pavlik @ 2005-02-06 13:12 UTC (permalink / raw)
  To: dtor_core; +Cc: David Fries, linux-kernel

On Tue, Feb 01, 2005 at 10:24:39AM -0500, Dmitry Torokhov wrote:
> On Tue, 1 Feb 2005 08:52:15 -0600, David Fries <dfries@mail.win.org> wrote:
> > Currently a blocking read, select, or poll call will not return if a
> > joystick device is unplugged.  This patch allows them to return.
> > 
> ...
> > static unsigned int joydev_poll(struct file *file, poll_table *wait)
> > {
> > +       int mask = 0;
> >        struct joydev_list *list = file->private_data;
> >        poll_wait(file, &list->joydev->wait, wait);
> > -       if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
> > -               return POLLIN | POLLRDNORM;
> > -       return 0;
> > +       if(!list->joydev->exist)
> > +               mask |= POLLERR;
> 
> Probably need POLLHUP in addition (or instead of POLLERR).
> 
> >        if (joydev->open)
> > +       {
> >                input_close_device(handle);
> > +               wake_up_interruptible(&joydev->wait);
> > +       }
> >        else
> > +       {
> >                joydev_free(joydev);
> > +       }
> 
> Opening braces should go on the same line as the statement (if (...) {).
 
How about this patch?


ChangeSet@1.2116, 2005-02-06 13:58:37+01:00, vojtech@silver.ucw.cz
  input: Fix poll() behavior of input handlers on disconnect.
  
  Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>


 evdev.c    |    5 ++---
 joydev.c   |   10 +++++-----
 mousedev.c |    6 +++---
 tsdev.c    |    6 ++----
 4 files changed, 12 insertions(+), 15 deletions(-)


diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c
--- a/drivers/input/evdev.c	2005-02-06 14:12:04 +01:00
+++ b/drivers/input/evdev.c	2005-02-06 14:12:04 +01:00
@@ -199,9 +199,8 @@
 {
 	struct evdev_list *list = file->private_data;
 	poll_wait(file, &list->evdev->wait, wait);
-	if (list->head != list->tail)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	2005-02-06 14:12:04 +01:00
+++ b/drivers/input/joydev.c	2005-02-06 14:12:04 +01:00
@@ -281,9 +281,8 @@
 {
 	struct joydev_list *list = file->private_data;
 	poll_wait(file, &list->joydev->wait, wait);
-	if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? 
+		(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -468,9 +467,10 @@
 	devfs_remove("input/js%d", joydev->minor);
 	joydev->exist = 0;
 
-	if (joydev->open)
+	if (joydev->open) {
 		input_close_device(handle);
-	else
+		wake_up_interruptible(&joydev->wait);
+	} else
 		joydev_free(joydev);
 }
 
diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c
--- a/drivers/input/mousedev.c	2005-02-06 14:12:04 +01:00
+++ b/drivers/input/mousedev.c	2005-02-06 14:12:04 +01:00
@@ -595,9 +595,8 @@
 {
 	struct mousedev_list *list = file->private_data;
 	poll_wait(file, &list->mousedev->wait, wait);
-	if (list->ready || list->buffer)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
+		(list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static struct file_operations mousedev_fops = {
@@ -660,6 +659,7 @@
 
 	if (mousedev->open) {
 		input_close_device(handle);
+		wake_up_interruptible(&mousedev->wait);
 	} else {
 		if (mousedev_mix.open)
 			input_close_device(handle);
diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c
--- a/drivers/input/tsdev.c	2005-02-06 14:12:04 +01:00
+++ b/drivers/input/tsdev.c	2005-02-06 14:12:04 +01:00
@@ -232,11 +232,9 @@
 static unsigned int tsdev_poll(struct file *file, poll_table * wait)
 {
 	struct tsdev_list *list = file->private_data;
-
 	poll_wait(file, &list->tsdev->wait, wait);
-	if (list->head != list->tail)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int tsdev_ioctl(struct inode *inode, struct file *file,

-- 
Vojtech Pavlik
SuSE Labs, SuSE CR

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-06 13:12     ` Vojtech Pavlik
@ 2005-02-07  1:21       ` Dmitry Torokhov
  2005-02-07  6:59         ` Vojtech Pavlik
  2005-02-07 12:20         ` Vojtech Pavlik
  0 siblings, 2 replies; 9+ messages in thread
From: Dmitry Torokhov @ 2005-02-07  1:21 UTC (permalink / raw)
  To: Vojtech Pavlik; +Cc: David Fries, linux-kernel

On Sunday 06 February 2005 08:12, Vojtech Pavlik wrote:
> On Tue, Feb 01, 2005 at 10:24:39AM -0500, Dmitry Torokhov wrote:
> > On Tue, 1 Feb 2005 08:52:15 -0600, David Fries <dfries@mail.win.org> wrote:
> > > Currently a blocking read, select, or poll call will not return if a
> > > joystick device is unplugged.  This patch allows them to return.
> > > 
> > ...
> > > static unsigned int joydev_poll(struct file *file, poll_table *wait)
> > > {
> > > +       int mask = 0;
> > >        struct joydev_list *list = file->private_data;
> > >        poll_wait(file, &list->joydev->wait, wait);
> > > -       if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
> > > -               return POLLIN | POLLRDNORM;
> > > -       return 0;
> > > +       if(!list->joydev->exist)
> > > +               mask |= POLLERR;
> > 
> > Probably need POLLHUP in addition (or instead of POLLERR).
> > 
> > >        if (joydev->open)
> > > +       {
> > >                input_close_device(handle);
> > > +               wake_up_interruptible(&joydev->wait);
> > > +       }
> > >        else
> > > +       {
> > >                joydev_free(joydev);
> > > +       }
> > 
> > Opening braces should go on the same line as the statement (if (...) {).
>  
> How about this patch?

Looks fine now. Hmm, wait a sec... Don't we also need kill_fasync calls in
disconnect routines as well?

-- 
Dmitry

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-07  1:21       ` Dmitry Torokhov
@ 2005-02-07  6:59         ` Vojtech Pavlik
  2005-02-07 12:20         ` Vojtech Pavlik
  1 sibling, 0 replies; 9+ messages in thread
From: Vojtech Pavlik @ 2005-02-07  6:59 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: David Fries, linux-kernel

On Sun, Feb 06, 2005 at 08:21:13PM -0500, Dmitry Torokhov wrote:
> On Sunday 06 February 2005 08:12, Vojtech Pavlik wrote:
> > On Tue, Feb 01, 2005 at 10:24:39AM -0500, Dmitry Torokhov wrote:
> > > On Tue, 1 Feb 2005 08:52:15 -0600, David Fries <dfries@mail.win.org> wrote:
> > > > Currently a blocking read, select, or poll call will not return if a
> > > > joystick device is unplugged.  This patch allows them to return.
> > > > 
> > > ...
> > > > static unsigned int joydev_poll(struct file *file, poll_table *wait)
> > > > {
> > > > +       int mask = 0;
> > > >        struct joydev_list *list = file->private_data;
> > > >        poll_wait(file, &list->joydev->wait, wait);
> > > > -       if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
> > > > -               return POLLIN | POLLRDNORM;
> > > > -       return 0;
> > > > +       if(!list->joydev->exist)
> > > > +               mask |= POLLERR;
> > > 
> > > Probably need POLLHUP in addition (or instead of POLLERR).
> > > 
> > > >        if (joydev->open)
> > > > +       {
> > > >                input_close_device(handle);
> > > > +               wake_up_interruptible(&joydev->wait);
> > > > +       }
> > > >        else
> > > > +       {
> > > >                joydev_free(joydev);
> > > > +       }
> > > 
> > > Opening braces should go on the same line as the statement (if (...) {).
> >  
> > How about this patch?
> 
> Looks fine now. Hmm, wait a sec... Don't we also need kill_fasync calls in
> disconnect routines as well?

Yes, we do.

-- 
Vojtech Pavlik
SuSE Labs, SuSE CR

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-07  1:21       ` Dmitry Torokhov
  2005-02-07  6:59         ` Vojtech Pavlik
@ 2005-02-07 12:20         ` Vojtech Pavlik
  2005-02-07 14:22           ` Dmitry Torokhov
  2005-02-08 15:29           ` David Fries
  1 sibling, 2 replies; 9+ messages in thread
From: Vojtech Pavlik @ 2005-02-07 12:20 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Vojtech Pavlik, David Fries, linux-kernel

On Sun, Feb 06, 2005 at 08:21:13PM -0500, Dmitry Torokhov wrote:
> > > Opening braces should go on the same line as the statement (if (...) {).
> >  
> > How about this patch?
> 
> Looks fine now. Hmm, wait a sec... Don't we also need kill_fasync calls in
> disconnect routines as well?

This should do it:


ChangeSet@1.2130, 2005-02-07 13:19:59+01:00, vojtech@suse.cz
  input: Do a kill_fasync() in input handlers on device disconnect
         to notify a client using poll() that the device is gone.
  
  Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>


 evdev.c    |    3 +++
 joydev.c   |    3 +++
 mousedev.c |    3 +++
 tsdev.c    |    3 +++
 4 files changed, 12 insertions(+)


diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c
--- a/drivers/input/evdev.c	2005-02-07 13:20:15 +01:00
+++ b/drivers/input/evdev.c	2005-02-07 13:20:15 +01:00
@@ -440,6 +440,7 @@
 static void evdev_disconnect(struct input_handle *handle)
 {
 	struct evdev *evdev = handle->private;
+	struct evdev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	devfs_remove("input/event%d", evdev->minor);
@@ -448,6 +449,8 @@
 	if (evdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
+		list_for_each_entry(list, &evdev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLLHUP | POLLERR);
 	} else
 		evdev_free(evdev);
 }
diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	2005-02-07 13:20:15 +01:00
+++ b/drivers/input/joydev.c	2005-02-07 13:20:15 +01:00
@@ -462,6 +462,7 @@
 static void joydev_disconnect(struct input_handle *handle)
 {
 	struct joydev *joydev = handle->private;
+	struct joydev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	devfs_remove("input/js%d", joydev->minor);
@@ -470,6 +471,8 @@
 	if (joydev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&joydev->wait);
+		list_for_each_entry(list, &joydev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLLHUP | POLLERR);
 	} else
 		joydev_free(joydev);
 }
diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c
--- a/drivers/input/mousedev.c	2005-02-07 13:20:15 +01:00
+++ b/drivers/input/mousedev.c	2005-02-07 13:20:15 +01:00
@@ -652,6 +652,7 @@
 static void mousedev_disconnect(struct input_handle *handle)
 {
 	struct mousedev *mousedev = handle->private;
+	struct mousedev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 	devfs_remove("input/mouse%d", mousedev->minor);
@@ -660,6 +661,8 @@
 	if (mousedev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&mousedev->wait);
+		list_for_each_entry(list, &mousedev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLLHUP | POLLERR);
 	} else {
 		if (mousedev_mix.open)
 			input_close_device(handle);
diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c
--- a/drivers/input/tsdev.c	2005-02-07 13:20:15 +01:00
+++ b/drivers/input/tsdev.c	2005-02-07 13:20:15 +01:00
@@ -424,6 +424,7 @@
 static void tsdev_disconnect(struct input_handle *handle)
 {
 	struct tsdev *tsdev = handle->private;
+	struct tsdev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	devfs_remove("input/ts%d", tsdev->minor);
@@ -433,6 +434,8 @@
 	if (tsdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&tsdev->wait);
+		list_for_each_entry(list, &tsdev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLLHUP | POLLERR);
 	} else
 		tsdev_free(tsdev);
 }

-- 
Vojtech Pavlik
SuSE Labs, SuSE CR

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-07 12:20         ` Vojtech Pavlik
@ 2005-02-07 14:22           ` Dmitry Torokhov
  2005-02-07 18:51             ` Vojtech Pavlik
  2005-02-08 15:29           ` David Fries
  1 sibling, 1 reply; 9+ messages in thread
From: Dmitry Torokhov @ 2005-02-07 14:22 UTC (permalink / raw)
  To: Vojtech Pavlik; +Cc: Vojtech Pavlik, David Fries, linux-kernel

On Mon, 7 Feb 2005 13:20:33 +0100, Vojtech Pavlik <vojtech@suse.cz> wrote:
> On Sun, Feb 06, 2005 at 08:21:13PM -0500, Dmitry Torokhov wrote:
> > > > Opening braces should go on the same line as the statement (if (...) {).
> > >  
> > > How about this patch?
> >
> > Looks fine now. Hmm, wait a sec... Don't we also need kill_fasync calls in
> > disconnect routines as well?
> 
> This should do it:
> 

Not quite...

> +               list_for_each_entry(list, &evdev->list, node)
> +                       kill_fasync(&list->fasync, SIGIO, POLLHUP | POLLERR);

Wrong band constants - for SIGIO POLL_HUP and POLL_ERR should be used.

/*
 * SIGPOLL si_codes
 */
#define POLL_IN         (__SI_POLL|1)   /* data input available */
#define POLL_OUT        (__SI_POLL|2)   /* output buffers available */
#define POLL_MSG        (__SI_POLL|3)   /* input message available */
#define POLL_ERR        (__SI_POLL|4)   /* i/o error */
#define POLL_PRI        (__SI_POLL|5)   /* high priority input available */
#define POLL_HUP        (__SI_POLL|6)   /* device disconnected */

-- 
Dmitry

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-07 14:22           ` Dmitry Torokhov
@ 2005-02-07 18:51             ` Vojtech Pavlik
  0 siblings, 0 replies; 9+ messages in thread
From: Vojtech Pavlik @ 2005-02-07 18:51 UTC (permalink / raw)
  To: dtor_core; +Cc: David Fries, linux-kernel

On Mon, Feb 07, 2005 at 09:22:19AM -0500, Dmitry Torokhov wrote:

> On Mon, 7 Feb 2005 13:20:33 +0100, Vojtech Pavlik <vojtech@suse.cz> wrote:
> > On Sun, Feb 06, 2005 at 08:21:13PM -0500, Dmitry Torokhov wrote:
> > > > > Opening braces should go on the same line as the statement (if (...) {).
> > > >  
> > > > How about this patch?
> > >
> > > Looks fine now. Hmm, wait a sec... Don't we also need kill_fasync calls in
> > > disconnect routines as well?
> > 
> > This should do it:
> > 
> 
> Not quite...
> 
> > +               list_for_each_entry(list, &evdev->list, node)
> > +                       kill_fasync(&list->fasync, SIGIO, POLLHUP | POLLERR);
> 
> Wrong band constants - for SIGIO POLL_HUP and POLL_ERR should be used.

Obviously only one of them, since they're not designed for ORing. I used POLL_HUP then.

> /*
>  * SIGPOLL si_codes
>  */
> #define POLL_IN         (__SI_POLL|1)   /* data input available */
> #define POLL_OUT        (__SI_POLL|2)   /* output buffers available */
> #define POLL_MSG        (__SI_POLL|3)   /* input message available */
> #define POLL_ERR        (__SI_POLL|4)   /* i/o error */
> #define POLL_PRI        (__SI_POLL|5)   /* high priority input available */
> #define POLL_HUP        (__SI_POLL|6)   /* device disconnected */
 

-- 
Vojtech Pavlik
SuSE Labs, SuSE CR

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2
  2005-02-07 12:20         ` Vojtech Pavlik
  2005-02-07 14:22           ` Dmitry Torokhov
@ 2005-02-08 15:29           ` David Fries
  1 sibling, 0 replies; 9+ messages in thread
From: David Fries @ 2005-02-08 15:29 UTC (permalink / raw)
  To: Vojtech Pavlik

On Mon, Feb 07, 2005 at 01:20:33PM +0100, Vojtech Pavlik wrote:
> On Sun, Feb 06, 2005 at 08:21:13PM -0500, Dmitry Torokhov wrote:
> 
> This should do it:
> 
> ChangeSet@1.2130, 2005-02-07 13:19:59+01:00, vojtech@suse.cz
>   input: Do a kill_fasync() in input handlers on device disconnect
>          to notify a client using poll() that the device is gone.
>   
>   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
...
> 
> -- 
> Vojtech Pavlik
> SuSE Labs, SuSE CR

I just checked it against my joystick_select test program which I
included in an earlier e-mail and the blocking read, poll, and select
return when I unplug the joystick.  Thanks for fixing the other
drivers, I didn't think of looking at them.

-- 
David Fries <dfries@mail.win.org>
http://fries.net/~david/pgpkey.txt

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2005-02-08 22:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20041123212813.GA3196@spacedout.fries.net>
2005-02-01 14:52 ` [PATCH] Linux joydev joystick disconnect patch 2.6.11-rc2 David Fries
2005-02-01 15:24   ` Dmitry Torokhov
2005-02-06 13:12     ` Vojtech Pavlik
2005-02-07  1:21       ` Dmitry Torokhov
2005-02-07  6:59         ` Vojtech Pavlik
2005-02-07 12:20         ` Vojtech Pavlik
2005-02-07 14:22           ` Dmitry Torokhov
2005-02-07 18:51             ` Vojtech Pavlik
2005-02-08 15:29           ` David Fries

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox