Menu

how does exclusive access work?

Help
Lex
2008-04-05
2013-04-23
  • Lex

    Lex - 2008-04-05

    I'm trying to do something pretty strange, and I think gizmo's the answer.

    A little background:  I have a razer copperhead mouse which lets me do a lot of really cool stuff like map any button to arbitrary keys.  I like to have the two side buttons (next to my thumb) mapped to Alt and Control.  The mouse registers itself as two USB devices: a mouse and a keyboard.  The configuration is stored directly on the mouse, and no drivers are needed for mappings to work.  Cool, eh?

    My configuration works fine in Windows, but it doesn't work at all in Linux.  I did a little research, and the end result is that there are two complementary bugs that work together to make this function properly in windows.  When I hold the alt button on the mouse and left-click, the mouse seems to do this:

    send a left-alt-press event
    send a left-alt-release-event AND send a left-mouse-press event pretty much simultaneously
    ...
    send a left-mouse-release event

    So it seems like the mouse stupidly releases the alt key the left mouse button is pressed.  Windows seems to consistently decide that alt was held while the left mouse was pressed, so my alt-click actions work fine.  Linux seems to consistently decide that the alt and left mouse presses are two separate events, so no alt-click actions work.  This is really frustrating, because I completely depend on this functionality (for a program called Second Life), and my dependence on this windows bug seems to be preventing me from moving to linux.  Argh.

    So, my goal is to work around this using Gizmod.  I'm pretty certain gizmod can do what I want to do.

    Here's what I tried:

    - map the side buttons to "Windows Button 4" and "Windows Button 5" in the Razer configurator.
    - use gizmod to figure out what these buttons are called in linux (BTN_SIDE and BTN_EXTRA respectively)
    - map these buttons to LEFTALT and LEFTCTRL respectively

    It looks like the mouse properly handles simultaneous button presses for BTN_SIDE and the left mouse button, so this should work beautifully.

    The only problem seems to be that the BTN_SIDE and BTN_EXTRA events are still going through, so my applications are getting confused and aren't treating my clicks as alt-clicks.  It seems like BTN_SIDE acts like a middle button and BTN_EXTRA acts like a right-click.  I think I need to suppress the original events and replace them completely, or somehow prevent my system from paying attention to BTN_SIDE and BTN_EXTRA events.

    Can anyone give me some hints on how to do this?  I'm an experienced programmer and linux sysadmin, but I don't know Python at all.  I figured out enough to piece together a script that takes these BTN_SIDE and BTN_EXTRA events and generates ALT and CTRL presses, but beyond that, I'm lost.  I think I need to somehow enable exclusive access (not sure how), and then take over complete control of the mouse in my script and generate all events, but I don't know how to do that.  Fortunately there aren't that many kinds of events on a mouse.

     
    • Lex

      Lex - 2008-04-09

      Got it!

      Here's what I added to GizmoRegistrar.py:

      if self.Device.DeviceIDVendor == 0x1532 and self.Device.DeviceIDProduct == 0x101 and self.DeviceIDVersion == 256:
              Gizmod.LexRazerDeviceID = self.Device.getDeviceID()

              self.Device.grabExclusiveAccess(True)

      elif self.Device.DeviceIDVendor == 0x45e and self.Device.DeviceIDProduct == 0x40:

              Gizmod.LexOutputDevice = self.Device

      and also a similar section in handleDeviceRemoval to call grabExclusiveAccess(False).

      Then my module script does this:

      if Gizmo.getDeviceID() != Gizmod.LexRazerDeviceID:

              return False

      if Event.Code == 0x113: # "BTN_SIDE"

              Gizmod.Keyboards[0].createEventRaw(GizmoEventType.EV_KEY, GizmoKey.KEY_LEFTALT, int(Event.Val$

      elif Event.Code == 0x114: # "BTN_EXTRA"

              Gizmod.Keyboards[0].createEventRaw(GizmoEventType.EV_KEY, GizmoKey.KEY_LEFTCTRL, int(Event.Va$

      else:

              Gizmod.LexOutputDevice.createEventRaw(Event.Type, Event.Code, Event.Value)

      Here's what I'm doing, in a nutshell:

      I learned that if gizmod grabs exclusive access on a device, nothing else will ever get events for that device, including X.  I have to generate all mouse events that I want to let through.  Unfortunately I can't just generate them back on the Razer mouse's device, because then they'll just come back to gizmod and I'll have a nice exponentially exploding infinite loop.  My solution is to plug in an old Microsoft USB mouse that I'm not using (0x45e/0x40) and generate events on its input device.  It'd be better to create some kind of new "virtual" input device, but I don't know how to do that, so this hack works for now.

      I send those Alt/Ctrl events to the first keyboard, and I send the rest of the mouse data to the Microsoft mouse.  I found out that I can store variables in Gizmod, so that makes it much easier for my processing script to figure out what events to respond to and where to send them.  All in all, this works great, and I love gizmod!  I imagine at least some of this is a hack, so let me know if I could be doing something better. 

      Also, sometimes when I control-C Gizmod, it gets stuck at "GizmoDaemon Shutting Down..." and I have to kill -9 it.  Is that a problem in my script, or is that a bug in gizmod?

       

Log in to post a comment.