Announcement

Collapse
No announcement yet.

Touchscreen changing usb event device on power on/off

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Touchscreen changing usb event device on power on/off

    (was USB devices powering off in Linux)

    I have done some more investigation into my usb touchscreen becoming unresponsive when I turn it off and back on.

    When my PC boots up the usb touchscreen is assigned event1.

    When I power off the touchscreen and power it back on the usb touchscreen is reassigned event3.

    This becomes a problem because my XF86Config-4 file has the CorePointer set to Device "/dev/input/event1". When the device changes X can no longer use the usb touchscreen because the device is now "/dev/input/event3".

    Does anyone know if there is a way to either always assign the same event # to a device, or to set X to use multiple Devices for the same pointer (two "Device" settings in the same pointer will just use the first)? Or maybe I am overlooking something?

    Thanks
    -pkg

    Check out my tC: http://publicjestering.com/tc
    Check out my site: http://publicjestering.com

  • #2
    Originally posted by pkg
    (was USB devices powering off in Linux)

    I have done some more investigation into my usb touchscreen becoming unresponsive when I turn it off and back on.

    When my PC boots up the usb touchscreen is assigned event1.

    When I power off the touchscreen and power it back on the usb touchscreen is reassigned event3.

    This becomes a problem because my XF86Config-4 file has the CorePointer set to Device "/dev/input/event1". When the device changes X can no longer use the usb touchscreen because the device is now "/dev/input/event3".

    Does anyone know if there is a way to either always assign the same event # to a device, or to set X to use multiple Devices for the same pointer (two "Device" settings in the same pointer will just use the first)? Or maybe I am overlooking something?

    Thanks

    maybe this will help

    http://gentoo-wiki.com/HARDWARE_Synaptics_Touchpad

    Comment


    • #3
      Unfortunately the link above does not solve my problem but it is great info!

      So I have been thinking of some of the possible ways I could address the problem that I am seeing. Here is the brain-dump:

      - Configure X to use both /dev/input/eventX devices as 2
      ponter devices:
      --- It seems as though X is limited to only allow
      multiple pointers that use the same event interface?
      X locks up when 2 pointers are configured with
      different event interfaces

      - Remove /dev/input/event3 from the system:
      --- No luck so far. After deleting the device from the
      /dev filesystem the touchscreen was still assigned
      event3 on reconnect.

      - Force the touchscreen to only use event1:
      --- Ideal fix. No information found on how to lock a
      USB device to a single event interface.

      So if any of you have any ideas I would love to hear.
      -pkg

      Check out my tC: http://publicjestering.com/tc
      Check out my site: http://publicjestering.com

      Comment


      • #4
        I have good news for you. There are two ways you can make this work:

        1) edit your /etc/udev/rules.d/ rules files to statically assign the event device to the same event every time. I've had troubles with this but I haven't messed with it alot either.

        2) Create a script that runs when you boot to read /proc/bus/input/devices and get the event number for your touchscreen there, then have the script change your XF86Config file before X starts.

        I am using a Lola RF remote that exhibits the same behaviour. It is annoying too that the driver module gets reset after a hibernation so my software has to take that into account since I'm using a signalling system that reads /dev/input/eventX. I have it set up so the fontend app gets signalled at the end of the "unhibernate" sequence that sets in motion a series of events to reload the module and update its reference to /dev/input/eventX via /proc/bus/input/devices. It works great so far with zero problems (other than a short delay of unresponsiveness to the remote after unhibernation).

        Hope that helps.
        Silverwolf 2 is dead.
        Silverwolf 3...?

        Comment


        • #5
          Originally posted by intuitionsys
          I have good news for you. There are two ways you can make this work:

          1) edit your /etc/udev/rules.d/ rules files to statically assign the event device to the same event every time. I've had troubles with this but I haven't messed with it alot either.

          2) Create a script that runs when you boot to read /proc/bus/input/devices and get the event number for your touchscreen there, then have the script change your XF86Config file before X starts.

          I am using a Lola RF remote that exhibits the same behaviour. It is annoying too that the driver module gets reset after a hibernation so my software has to take that into account since I'm using a signalling system that reads /dev/input/eventX. I have it set up so the fontend app gets signalled at the end of the "unhibernate" sequence that sets in motion a series of events to reload the module and update its reference to /dev/input/eventX via /proc/bus/input/devices. It works great so far with zero problems (other than a short delay of unresponsiveness to the remote after unhibernation).

          Hope that helps.

          not a bad idea. Get event from proc (grep) then have a script copy over or edit a line in xorg.conf. (might be easier to have multi xorg.conf scripts already edited) then have the script launch X

          Comment


          • #6
            I was talking to a friend of mine who is quite linux savvy. udev rules are the way to go in this situation. I will post what I find out.

            Since X would need to be restarted each time the touchscreen gets powered on I think this would cause some undesirable interruptions of music/maps/etc. Having a non-X application that can switch event interfaces on the fly would not be too affected by the scripts you mentioned though.

            Thanks for the input. More soon,
            -pkg

            Check out my tC: http://publicjestering.com/tc
            Check out my site: http://publicjestering.com

            Comment


            • #7
              Originally posted by DigitalExpl0it
              not a bad idea. Get event from proc (grep) then have a script copy over or edit a line in xorg.conf. (might be easier to have multi xorg.conf scripts already edited) then have the script launch X
              renaming files would be tragically simple in this case.
              -pkg

              Check out my tC: http://publicjestering.com/tc
              Check out my site: http://publicjestering.com

              Comment


              • #8
                Originally posted by pkg
                renaming files would be tragically simple in this case.
                true but only if X is running.

                Comment


                • #9
                  So I have finally came up with a fix, there were a few things that were all tied up

                  I was originally NOT running udev on my system. This was a problem because the behavior of the Linux event interface system is to not constrain a device to a single event device in case the event is in use. So, udev is the solution.

                  I installed udev. Incredibly easy on Debian (# apt-get install udev [doesn't get any easier than that!]). I then created a udev rule in the /etc/udev/udev.rules file:

                  BUS="usb", KERNEL="event[0-3]*", SYSFS{product}="USB TouchController", SYMLINK="input/touchscreen"

                  The rule above creates a symlink from whatever event device file the Linux kernel assigns to the touchscreen to /dev/input/touchscreen.
                  "/dev/input/touchscreen" is the device that is used in the XF86Config-4 file for the touchscreen.

                  Originally I had left out the KERNEL directive in the rule. This was causing udev to default to the /dev/input/ts0 device for the symlink. This does not work. Adding the KERNEL directive for the event devices fixed this problem and the symlink points to /dev/input/event1 (or event3 depending).

                  I was then running into a problem with the pointer not working when the touchscreen would power back on. After doing A LOT of reading I came across the same bug that occurs when the system comes out of hibernation. X loses the pointer!.

                  The solution to X losing the pointer was to switch virtual terminals out of X and then back in. ctrl+alt+F1, ctrl+alt+F7. This was not going to work in a keyboard-less system! I then came across a scriptable command "chvt". So, now that I could script the VT change I just needed a way to launch the script when the touchscreen was powered up. This is where hotplug comes in for linux.

                  As some of you may know hotplug has the perfect facility for this type of thing (heck, it is what it was made for). So, I added a hotplug "handmap" to the system. I created a new file named touchkitusb in the /etc/hotplug/usb/ directory. This file is a bash script that (essentially) contains the commands: chvt 6; chvt 7. (This script is currently set SUID root though this is not the best way to do it. I will be doing sudo chvt inside of the script instead.)

                  So what did this do? When the touchscreen is turned back on udev assigns the /dev/input/hotplug to the correct event# device. Hotplug then detects the device as coming up and executes the touchkitusb script. The system then changes to VT6 and then back to VT7, making the touchscreen work on a power off/power on!

                  So what next? There was some mention of a kernel bug in 2.6.9 causing this behavior but I haven't seen any real reference to it yet. I will look into a kernel upgrade at some point. Those of you not using X will probably not have this problem. The udev configuration is mandatory for this situation, the hotplug script is a workaround for the pointer "bug".

                  Hope this helps someone
                  -pkg

                  Check out my tC: http://publicjestering.com/tc
                  Check out my site: http://publicjestering.com

                  Comment


                  • #10
                    Good work! I'd be interested in seeing your final udev rule. I'll be implementing a touchscreen overlay in my system (same driver as yours but just an overlay since my car has an OEM monitor built into the dash already) and this will undoubtedly save me some time getting it working A-OK.

                    By the way if anyone uses the ati_remote driver, you need to remove and re-insert the driver after hibernation. I made a hokey workaround for it by having the resume_after_suspend_to_disk script touch a file that my frontend checks for every ten seconds. When the app resumes after hibernation it finds this file and performs the system calls to remove and modprobe the driver and reset the event file it's monitoring.
                    Silverwolf 2 is dead.
                    Silverwolf 3...?

                    Comment


                    • #11
                      Updated my post above with the rule from my udev.rules file
                      -pkg

                      Check out my tC: http://publicjestering.com/tc
                      Check out my site: http://publicjestering.com

                      Comment


                      • #12
                        Wow, have I been struggling with this one for the past week! Basically, all info here is good info. Yes, udev is one way to make the device name persistent. Problem is, once the USB device disconnects (happens for me every time I even start to close my in-dash display), even though it gets the same name again through udev, X seems to lose track of it, and it stops working (or reverts to the mouse device if you have that one enabled).

                        Today I finally solved it!

                        It involved a bit of kernel hacking, but I finally realized that the only solid solution is to mimic the /dev/input/mice device. This is a "mixer" device that catches all events from all mice. And the device is there from boot onward, even if no USB device is attached, so X never "loses" it.

                        Of course, you cannot use /dev/input/mice, since the output is not the right format for a touch screen... Sooooo, I hacked "evdev.c", which is the counterpart to "mousedev.c", in the kernel, and I added a new mixer device called /dev/input/events (this goes in xorg.conf under the touchscreen section - note that I am using the evtouch X driver to translate events). I plan to confer with the developer of these kernel drivers to make sure what I did is OK (it's a bit hard to comprehend the whole workings of these quickly). I had to do a few things that were not obvious to avoid crashes (null pointers) - not issues in mousedev.c.

                        But it works, at least so far, and no need for any udev rules or switching of virtual terminals (which I tried, but I found it did not always work right, and it causes lots of flashing on boot). If anyone wants the new evdev.c, email me. You'd need to get kernel source and rebuild the kernel, but it's worth it to have this working!

                        -Joe



                        Originally posted by pkg
                        So I have finally came up with a fix, there were a few things that were all tied up

                        I was originally NOT running udev on my system. This was a problem because the behavior of the Linux event interface system is to not constrain a device to a single event device in case the event is in use. So, udev is the solution.

                        I installed udev. Incredibly easy on Debian (# apt-get install udev [doesn't get any easier than that!]). I then created a udev rule in the /etc/udev/udev.rules file:

                        BUS="usb", KERNEL="event[0-3]*", SYSFS{product}="USB TouchController", SYMLINK="input/touchscreen"

                        The rule above creates a symlink from whatever event device file the Linux kernel assigns to the touchscreen to /dev/input/touchscreen.
                        "/dev/input/touchscreen" is the device that is used in the XF86Config-4 file for the touchscreen.

                        Originally I had left out the KERNEL directive in the rule. This was causing udev to default to the /dev/input/ts0 device for the symlink. This does not work. Adding the KERNEL directive for the event devices fixed this problem and the symlink points to /dev/input/event1 (or event3 depending).

                        I was then running into a problem with the pointer not working when the touchscreen would power back on. After doing A LOT of reading I came across the same bug that occurs when the system comes out of hibernation. X loses the pointer!.

                        The solution to X losing the pointer was to switch virtual terminals out of X and then back in. ctrl+alt+F1, ctrl+alt+F7. This was not going to work in a keyboard-less system! I then came across a scriptable command "chvt". So, now that I could script the VT change I just needed a way to launch the script when the touchscreen was powered up. This is where hotplug comes in for linux.

                        As some of you may know hotplug has the perfect facility for this type of thing (heck, it is what it was made for). So, I added a hotplug "handmap" to the system. I created a new file named touchkitusb in the /etc/hotplug/usb/ directory. This file is a bash script that (essentially) contains the commands: chvt 6; chvt 7. (This script is currently set SUID root though this is not the best way to do it. I will be doing sudo chvt inside of the script instead.)

                        So what did this do? When the touchscreen is turned back on udev assigns the /dev/input/hotplug to the correct event# device. Hotplug then detects the device as coming up and executes the touchkitusb script. The system then changes to VT6 and then back to VT7, making the touchscreen work on a power off/power on!

                        So what next? There was some mention of a kernel bug in 2.6.9 causing this behavior but I haven't seen any real reference to it yet. I will look into a kernel upgrade at some point. Those of you not using X will probably not have this problem. The udev configuration is mandatory for this situation, the hotplug script is a workaround for the pointer "bug".

                        Hope this helps someone

                        Comment


                        • #13
                          Awesome,

                          This is a really good fix. Sounds like the TS problems are the same thing that made /dev/input/mice be created back in the day.

                          Could you post a diff of your changes to evdev.c? It would be great to get this in the kernel as we have shown this to be a problem with touchscreens.

                          I have limited my project to only use distro kernels so hopefully we can get this in.

                          Good work!
                          -pkg

                          Check out my tC: http://publicjestering.com/tc
                          Check out my site: http://publicjestering.com

                          Comment


                          • #14
                            Originally posted by pkg
                            Awesome,

                            This is a really good fix. Sounds like the TS problems are the same thing that made /dev/input/mice be created back in the day.

                            Could you post a diff of your changes to evdev.c? It would be great to get this in the kernel as we have shown this to be a problem with touchscreens.

                            I have limited my project to only use distro kernels so hopefully we can get this in.

                            Good work!
                            No problem - see below. Note that I still want to check with the devloper, since I am not convinced all of my changes are completely without issues.

                            -Joe

                            Code:
                            10a11,18
                            > /*
                            >  * Modified 2005-8-12  Joe Peterson
                            >  *
                            >  *     - Added persistent mixer device "/dev/input/events"
                            >  *       (analogous to mousedev.c's "/dev/input/mice")
                            >  *
                            >  */
                            >
                            12a21
                            > #define EVDEV_MIX               31
                            44a54,55
                            > static struct input_handler evdev_handler;
                            >
                            45a57
                            > static struct evdev evdev_mix;
                            47c59
                            < static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
                            ---
                            > static void evdev_handle_event(struct evdev *evdev, unsigned int type, unsigned int code, int value)
                            49d60
                            <       struct evdev *evdev = handle->private;
                            76a88,95
                            > static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
                            > {
                            >       struct evdev *evdev = handle->private;
                            >
                            >         evdev_handle_event(evdev, type, code, value);
                            >         evdev_handle_event(&evdev_mix, type, code, value);
                            > }
                            >
                            89c108,111
                            <       return input_flush_device(&list->evdev->handle, file);
                            ---
                            >         if (list->evdev->handle.dev)
                            >             return input_flush_device(&list->evdev->handle, file);
                            >         else
                            >             return 0;
                            97a120,137
                            > static int mixdev_release(void)
                            > {
                            >       struct input_handle *handle;
                            >
                            >       list_for_each_entry(handle, &evdev_handler.h_list, h_node) {
                            >               struct evdev *evdev = handle->private;
                            >
                            >               if (!evdev->open) {
                            >                       if (evdev->exist)
                            >                               input_close_device(&evdev->handle);
                            >                       else
                            >                               evdev_free(evdev);
                            >               }
                            >       }
                            >
                            >       return 0;
                            > }
                            >
                            111,114c151,159
                            <               if (list->evdev->exist)
                            <                       input_close_device(&list->evdev->handle);
                            <               else
                            <                       evdev_free(list->evdev);
                            ---
                            >               if (list->evdev->minor == EVDEV_MIX)
                            >                       return mixdev_release();
                            >
                            >               if (!evdev_mix.open) {
                            >                       if (list->evdev->exist)
                            >                               input_close_device(&list->evdev->handle);
                            >                       else
                            >                               evdev_free(list->evdev);
                            >               }
                            123a169,170
                            >       struct input_handle *handle;
                            >       struct evdev *evdev;
                            130c177,178
                            <       if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
                            ---
                            >         if (evdev_table[i]->handle.dev)
                            >             if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
                            141,144c189,200
                            <       if (!list->evdev->open++)
                            <               if (list->evdev->exist)
                            <                       input_open_device(&list->evdev->handle);
                            <
                            ---
                            >       if (!list->evdev->open++) {
                            >               if (list->evdev->minor == EVDEV_MIX) {
                            >                       list_for_each_entry(handle, &evdev_handler.h_list, h_node) {
                            >                               evdev = handle->private;
                            >                               if (!evdev->open && evdev->exist)
                            >                                       input_open_device(handle);
                            >                       }
                            >               } else
                            >                       if (!evdev_mix.open && list->evdev->exist)
                            >                               input_open_device(&list->evdev->handle);
                            >         }
                            >
                            160c216,217
                            <               input_event(list->evdev->handle.dev, event.type, event.code, event.value);
                            ---
                            >                 if (list->evdev->handle.dev)
                            >                     input_event(list->evdev->handle.dev, event.type, event.code, event.value);
                            271c328,329
                            <                       if (arg) {
                            ---
                            >                         if (evdev->handle.dev) {
                            >                             if (arg) {
                            278c336
                            <                       } else {
                            ---
                            >                           } else {
                            284c342,345
                            <                       }
                            ---
                            >                           }
                            >                         } else {
                            >                             return 0;
                            >                         }
                            429a491,493
                            >       if (evdev_mix.open)
                            >               input_open_device(&evdev->handle);
                            >
                            455c519,521
                            <       } else
                            ---
                            >       } else {
                            >               if (evdev_mix.open)
                            >                       input_close_device(handle);
                            456a523
                            >         }
                            478a546,560
                            >
                            >       memset(&evdev_mix, 0, sizeof(struct evdev));
                            >       INIT_LIST_HEAD(&evdev_mix.list);
                            >       init_waitqueue_head(&evdev_mix.wait);
                            >       evdev_table[EVDEV_MIX] = &evdev_mix;
                            >       evdev_mix.exist = 1;
                            >       evdev_mix.minor = EVDEV_MIX;
                            >
                            >       devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + EVDEV_MIX),
                            >                       S_IFCHR|S_IRUGO|S_IWUSR, "input/events");
                            >       class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + EVDEV_MIX),
                            >                               NULL, "events");
                            >
                            >       printk(KERN_INFO "events: event device common for all events\n");
                            >
                            483a566,567
                            >       devfs_remove("input/events");
                            >       class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + EVDEV_MIX));

                            Comment


                            • #15
                              Originally posted by pkg
                              Awesome,

                              This is a really good fix. Sounds like the TS problems are the same thing that made /dev/input/mice be created back in the day.

                              Could you post a diff of your changes to evdev.c? It would be great to get this in the kernel as we have shown this to be a problem with touchscreens.

                              I have limited my project to only use distro kernels so hopefully we can get this in.

                              Good work!
                              Well, a little bit of bad news: I had a discussion on the kernel mailing lists today with the author of evdev.c, and he feels that /dev/input/mice is actually a hack, and that X windows should fix it on their end (i.e. be hotplug friendly). He does not want to add another similar hack for events.

                              Also, he says events can't mix the same way mouse events can. I know this does not affect us, since we will only have one touch screen and no mice, but in any case, it looks like this "feature" won't make it into the kernel distributions. I will look into other solutions, but for now you can always rebuild your kernel and use my patch. He suggested trying to create a "repeater daemon" using a uinput device. I did try, before modifying evdev, to create a fifo device to work like this, but I didn't spend long on it. Another idea he had was doing something like synaptics does in their X driver, auto-detecting the event device. I looked through their source, and I am not sure it would solve the issue of disconnecting and reconnecting or booting without the USB on, though. But a fix, using a similar idea, to evtouch.c might be possible. This is something I'd like to hack on, but I need to find the time!

                              -Joe

                              Comment

                              Working...
                              X