Thread (18 messages) 18 messages, 5 authors, 2011-06-08

Re: Linux Force Feedback for Saitek Cyborg Evo Force

From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Date: 2009-12-21 08:23:07
Subsystem: input (keyboard, mouse, joystick, touchscreen) drivers, the rest · Maintainers: Dmitry Torokhov, Linus Torvalds

Possibly related (same subject, not in this thread)

On Sun, Dec 20, 2009 at 11:44:19PM -0800, Dmitry Torokhov wrote:
On Sun, Dec 20, 2009 at 12:36:23AM +0100, Johannes Ebke wrote:
quoted
Hi,

It seems that the force feedback works well, I have ported the force
feedback for my favorite game to linux now, and it works well.

What does not work is updating effects - there just nothing happens, and
the old event is played. I have circumvented this by
deleting/re-uploading the effect, but this should probably been made to
work. Does it work well with other hardware?

Thirdly, I have re-discovered one kernel oops that occurs if the
joystick is unplugged if some process still has the event device open.
Steps to reproduce:
* plug joystick in
* fftest /dev/input/eventXX
* unplug joystick

(kern.log extract attached)

Sometimes this just gives an oops, sometimes it escalates into a kernel
panic.
Hmm, it looks like iforce unbinding is completely busted:

static void iforce_usb_disconnect(struct usb_interface *intf)
{
        struct iforce *iforce = usb_get_intfdata(intf);
        int open = 0; /* FIXME! iforce->dev.handle->open; */
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        usb_set_intfdata(intf, NULL);
        if (iforce) {
                iforce->usbdev = NULL;
                input_unregister_device(iforce->dev);

                if (!open) {
                        iforce_delete_device(iforce);
                        kfree(iforce);
                }
        }
}


Any chance you could fix that FIXME ;) ?
Actually, does the below fixes it for you?

-- 
Dmitry

Input: iforce - fix oops on device disconnect

Reported-by: Johannes Ebke <redacted>
Signed-off-by: Dmitry Torokhov <redacted>
---

 drivers/input/joystick/iforce/iforce-main.c |   26 +++++--------------------
 drivers/input/joystick/iforce/iforce-usb.c  |   28 +++++++--------------------
 drivers/input/joystick/iforce/iforce.h      |    2 --
 3 files changed, 12 insertions(+), 44 deletions(-)

diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 47d8c43..df142df 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -218,7 +218,7 @@ static int iforce_open(struct input_dev *dev)
 	return 0;
 }
 
-static void iforce_release(struct input_dev *dev)
+static void iforce_close(struct input_dev *dev)
 {
 	struct iforce *iforce = input_get_drvdata(dev);
 	int i;
@@ -240,26 +240,10 @@ static void iforce_release(struct input_dev *dev)
 
 	switch (iforce->bus) {
 #ifdef CONFIG_JOYSTICK_IFORCE_USB
-		case IFORCE_USB:
-			usb_kill_urb(iforce->irq);
-
-			/* The device was unplugged before the file
-			 * was released */
-			if (iforce->usbdev == NULL) {
-				iforce_delete_device(iforce);
-				kfree(iforce);
-			}
-		break;
-#endif
-	}
-}
-
-void iforce_delete_device(struct iforce *iforce)
-{
-	switch (iforce->bus) {
-#ifdef CONFIG_JOYSTICK_IFORCE_USB
 	case IFORCE_USB:
-		iforce_usb_delete(iforce);
+		usb_kill_urb(iforce->irq);
+		usb_kill_urb(iforce->out);
+		usb_kill_urb(iforce->ctrl);
 		break;
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
@@ -311,7 +295,7 @@ int iforce_init_device(struct iforce *iforce)
 
 	input_dev->name = "Unknown I-Force device";
 	input_dev->open = iforce_open;
-	input_dev->close = iforce_release;
+	input_dev->close = iforce_close;
 
 /*
  * On-device memory allocation.
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index ae2e8c6..3fc9f46 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -186,33 +186,19 @@ fail:
 	return err;
 }
 
-/* Called by iforce_delete() */
-void iforce_usb_delete(struct iforce* iforce)
-{
-	usb_kill_urb(iforce->irq);
-	usb_kill_urb(iforce->out);
-	usb_kill_urb(iforce->ctrl);
-
-	usb_free_urb(iforce->irq);
-	usb_free_urb(iforce->out);
-	usb_free_urb(iforce->ctrl);
-}
-
 static void iforce_usb_disconnect(struct usb_interface *intf)
 {
 	struct iforce *iforce = usb_get_intfdata(intf);
-	int open = 0; /* FIXME! iforce->dev.handle->open; */
 
 	usb_set_intfdata(intf, NULL);
-	if (iforce) {
-		iforce->usbdev = NULL;
-		input_unregister_device(iforce->dev);
 
-		if (!open) {
-			iforce_delete_device(iforce);
-			kfree(iforce);
-		}
-	}
+	input_unregister_device(iforce->dev);
+
+	usb_free_urb(iforce->irq);
+	usb_free_urb(iforce->out);
+	usb_free_urb(iforce->ctrl);
+
+	kfree(iforce);
 }
 
 static struct usb_device_id iforce_usb_ids [] = {
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index 1a76ca1..7fa7b5d 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -151,11 +151,9 @@ void iforce_serial_xmit(struct iforce *iforce);
 
 /* iforce-usb.c */
 void iforce_usb_xmit(struct iforce *iforce);
-void iforce_usb_delete(struct iforce *iforce);
 
 /* iforce-main.c */
 int iforce_init_device(struct iforce *iforce);
-void iforce_delete_device(struct iforce *iforce);
 
 /* iforce-packets.c */
 int iforce_control_playback(struct iforce*, u16 id, unsigned int);
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help