Added support for X11 keysyms in --ui-buttonmap

This commit is contained in:
Ingo Ruhnke 2009-01-14 06:47:38 +01:00
parent 87955f3ac0
commit 1e6a3cc6ff
6 changed files with 138 additions and 2 deletions

11
NEWS
View file

@ -1,7 +1,18 @@
xboxdrv 0.4.3 - (??/Jan/2009)
=============================
* support for X11 keysym in --ui-buttonmap
xboxdrv 0.4.2 - (11/Jan/2009)
============================
* fixed --dpad-only
xboxdrv 0.4.1 - (08/Jan/2009)
============================
* workaround for KEY_MEDIA_REPEAT
xboxdrv 0.4 - (07/Jan/2009)
===========================

31
README
View file

@ -128,6 +128,20 @@ your Xbox360 controller from blinking:
For rumble to work make sure you have connected the controller to a
USB port that has enough power, i.e. an unpowered USB hub might not
work.
[[ Deadzone ]]
--------------
The deadzone is the area at which the sticks do not report any
events. The default is zero, which gives the best sensitifity but
might also cause trouble in some games in that the character or camera
might move without moving the stick. To fix this one has to set the
value to something higher:
% ./xboxdrv --deadzone 4000
A value of 4000 works quite well for most games.
[[ Square Axis ]]
-----------------
@ -228,6 +242,17 @@ Except that the right hand side is an event name from
/usr/include/linux/input.h. You can use all KEY_ or BTN_ codes for
--ui-buttonmap and all ABS_ and REL_ ones for --ui-axismap.
Instead of the low level KEY_ names, which represent keycodes, you can
also use the higher level X11 keysyms XK_, the keysyms have the
advantage that they map directly to the key you expect, while a KEY_
name gets mungled by the X11 keymap and will often not report what you
expect in case you use a keymap that is different then your keyboard
(i.e. dvorak on a qwerty keyboard).
A full list of X11 keysyms is available at
/usr/include/X11/keysymdef.h, note that you can only use those that
are reachable by your current.
When you try to let a gamepad key send a keyboard event you might run
into trouble with Xorg, for possible fixes see the section further down.
@ -248,6 +273,7 @@ optional:
--ui-buttonmap X1=REL_???:VALUE:REPEAT
VALUE: the of the event (default: 10)
REPEAT: number of milisecond to pass before the event is fired again (default: 5)
[[ Running InputDrv ]]
----------------------
@ -402,6 +428,8 @@ Sauerbraten
-----------
First analogstick gets mapped te cursor keys, second analogstick gets mapped to mouse.
Note: This is just an incomplete example, not a perfectly playable
configuration, you have to do tweaking yourself.
% ./xboxdrv \
--ui-axismap x2=REL_X:10,y2=REL_Y:-10,x1=KEY_LEFT:KEY_RIGHT,y1=KEY_UP:KEY_DOWN \
@ -414,6 +442,9 @@ First analogstick gets mapped te cursor keys, second analogstick gets mapped to
Warsow
------
Note: This is just an incomplete example, not a perfectly playable
configuration, you have to do tweaking yourself.
% ./xboxdrv \
--ui-axismap x2=REL_X:10,y2=REL_Y:-10,x1=KEY_A:KEY_D,y1=KEY_W:KEY_S \
--ui-buttonmap a=KEY_LEFTSHIFT,b=BTN_C,x=BTN_EXTRA,y=KEY_C \

View file

@ -1,7 +1,7 @@
# -*- python -*-
# env = Environment(CPPFLAGS=["-g", "-O2", "-Wall", "-ansi", "-pedantic"], LIBS=["usb"])
env = Environment(CPPFLAGS=["-g", "-O2"], LIBS=["usb"])
env = Environment(CPPFLAGS=["-g", "-O2"], LIBS=["usb", "X11"])
env.Program("xboxdrv", ["src/xboxdrv.cpp",
"src/xboxmsg.cpp",
"src/uinput.cpp",

27
TODO
View file

@ -8,6 +8,33 @@
Stuff to do before 0.5 release:
===============================
Example config for flash game:
./xboxdrv --dpad-as-button --ui-buttonmap du=KEY_UP,dd=KEY_DOWN,dl=KEY_LEFT,dr=KEY_RIGHT,a=KEY_A,x=KEY_SEMICOLON -s --deadzone 16000
* add a way to ignore axis or button
* add a way to not create a joystick device
* add translation for xmodmap
XKeysymToString
XStringToKeysym
NoSymbol
XGetKeyboardMapping (dpy, min_keycode,
(max_keycode - min_keycode + 1),
&keysyms_per_keycode);
XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
experimental/xkeys.h
* figure out what jscal does and if it can break stuff
1) jscal uses the joystick interface, not the event interface
* different xbox controller use different endpoints for read/write, solution:
1) make endpoints variables
2) check if endpoints are available on start
3) if not, then use different one, seems to be just 1 or 2
* implement basic rumble force feedback support
fixme:dinput:joy_polldev joystick cannot handle type 21 event (code 0) <- 21 == EV_FF (status report?)

View file

@ -16,7 +16,9 @@
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <X11/Xlib.h>
#include <linux/input.h>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <map>
@ -580,6 +582,65 @@ public:
}
} evdev_btn_names;
class Keysym2Keycode
{
public:
std::map<KeySym, int> mapping;
Keysym2Keycode()
{
//std::cout << "Initing Keysym2Keycode" << std::endl;
Display* dpy = XOpenDisplay(NULL);
if (!dpy)
{
throw std::runtime_error("Keysym2Keycode: Couldn't open X11 display");
}
else
{
process_keymap(dpy);
XCloseDisplay(dpy);
}
}
void process_keymap(Display* dpy)
{
int min_keycode, max_keycode;
XDisplayKeycodes(dpy, &min_keycode, &max_keycode);
int num_keycodes = max_keycode - min_keycode + 1;
int keysyms_per_keycode;
KeySym* keymap = XGetKeyboardMapping(dpy, min_keycode,
num_keycodes,
&keysyms_per_keycode);
for(int i = 0; i < num_keycodes; ++i)
{
if (keymap[i*keysyms_per_keycode] != NoSymbol)
mapping[keymap[i*keysyms_per_keycode]] = i;
}
XFree(keymap);
}
};
int xkeysym2keycode(const std::string& name)
{
static Keysym2Keycode sym2code;
KeySym keysym = XStringToKeysym(name.substr(3).c_str());
if (keysym == NoSymbol)
{
throw std::runtime_error("xkeysym2keycode: Couldn't convert name '" + name + "' to xkeysym");
}
std::map<KeySym, int>::iterator i = sym2code.mapping.find(keysym);
if (i == sym2code.mapping.end())
throw std::runtime_error("xkeysym2keycode: Couldn't convert xkeysym '" + name + "' to evdev keycode");
else
return i->second;
}
bool str2event(const std::string& name, int& type, int& code)
{
if (name.compare(0, 3, "REL") == 0)
@ -588,13 +649,18 @@ bool str2event(const std::string& name, int& type, int& code)
code = evdev_rel_names[name];
return true;
}
else if (name.compare(0, 3, "ABS") == 0)
{
type = EV_ABS;
code = evdev_abs_names[name];
return true;
}
else if (name.compare(0, 2, "XK") == 0)
{
type = EV_KEY;
code = xkeysym2keycode(name);
return true;
}
else if (name.compare(0, 3, "KEY") == 0 ||
name.compare(0, 3, "BTN") == 0)
{

View file

@ -5,5 +5,6 @@ env.Program("jstest", ["jstest.c"])
env.Program("evtest", ["evtest.c"])
env.Program("usbcat", ["usbcat.cpp"], LIBS = ["usb"])
env.Program("usbdebug", ["usbdebug.cpp"], LIBS = ["usb", "pthread"])
env.Program("evtestplus", ["evtestplus.cpp"])
# EOF #