[dinput][joystick_linuxinput] make axes work,
that are "not in a row"
Christoph Frick
frick at sc-networks.de
Thu Jan 11 03:56:36 CST 2007
hiho
with Vitaliy's patches i tried my games yesterday and everything seemed
ok (RBR works again). but my clutch on the wheel did not work and also
some cog on the flight-stick.
the problem was, that the axes got assigned their id just in the order
they came. this did not work if there are "gaps" between them. e.g. my
wheel has: ABS_X, ABS_Y, ABS_Z, ABS_RZ.
so what this patch does in general is fix this by the following steps:
- move the "wine" relevant stuff back in from the joydev into the impl
(button, have(min|max))
- fix the used offsets to represent the actual offsets for the first
POV in the c_dfDIJoystick2 and the first button there
- remember - like for the buttons - where we put a axis (idx) (the same
applies here also for a pov - but it dont know any device that has
more than one pov - and if if it would have gaps between them, i
doubt)
- get rid of lxinput_to_user_index - it was added as an convinience
method to be sure to wrap the defines from linux/input.h to be sure
not to introduce problems when they change; but it was used only axes
anyhow so i dropped it
with this patch applied on top of the ten from Vitaliy i tested the
folling games with wheel and joystick (together) in the following games
and everything now works like it worked before:
- Grand Prix Legends (good test as it is a win95 game - also since some
earlier of Vitaliy's patches the game now also detects the analog axes
on the 1+n devices)
- Life For Speed (shows all devices ingame with their current state;
good test for working SetProperty)
- IL2 (test for POV)
- Richard Burns Rally (had an regression after the initial patches and
no controller at all was working due to the missing instance-values in
the internal format; this game wants to set a dataformat composed of
the data we deliver by EnumObjects)
--
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index e2f77f8..3e8a796 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -70,8 +70,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
/* Wine joystick driver object instances */
#define WINE_JOYSTICK_AXIS_BASE 0
-#define WINE_JOYSTICK_POV_BASE 6
-#define WINE_JOYSTICK_BUTTON_BASE 8
+#define WINE_JOYSTICK_POV_BASE 8
+#define WINE_JOYSTICK_BUTTON_BASE 12
typedef struct EffectListItem EffectListItem;
struct EffectListItem
@@ -111,12 +111,6 @@ struct JoyDev {
/* data returned by the EVIOCGABS() ioctl */
int axes[ABS_MAX][5];
- /* LUT for KEY_ to offset in rgbButtons */
- BYTE buttons[KEY_MAX];
-
- /* autodetecting ranges per axe by following movement */
- LONG havemax[ABS_MAX];
- LONG havemin[ABS_MAX];
};
struct JoystickImpl
@@ -128,11 +122,20 @@ struct JoystickImpl
/* The 'parent' DInput */
IDirectInputImpl *dinput;
+ /* autodetecting ranges per axe by following movement */
+ LONG havemax[8];
+ LONG havemin[8];
/* joystick private */
/* what range and deadzone the game wants */
- LONG wantmin[ABS_MAX];
- LONG wantmax[ABS_MAX];
- LONG deadz[ABS_MAX];
+ LONG wantmin[8];
+ LONG wantmax[8];
+ LONG deadz[8];
+
+ /* LUT for the mapping of used axes */
+ int axes[ABS_MAX];
+
+ /* LUT for KEY_ to offset in rgbButtons */
+ BYTE buttons[KEY_MAX];
int joyfd;
@@ -177,7 +180,7 @@ static void find_joydevs(void)
struct JoyDev joydev = {0};
int fd;
int no_ff_check = 0;
- int j, buttons;
+ int j;
snprintf(buf,MAX_PATH,EVDEVPREFIX"%d",i);
buf[MAX_PATH-1] = 0;
@@ -254,21 +257,10 @@ static void find_joydevs(void)
joydev.axes[j][AXE_ABSFUZZ],
joydev.axes[j][AXE_ABSFLAT]
);
- joydev.havemin[j] = joydev.axes[j][AXE_ABSMIN];
- joydev.havemax[j] = joydev.axes[j][AXE_ABSMAX];
}
}
}
- buttons = 0;
- for (j=0;j<KEY_MAX;j++) {
- if (test_bit(joydev.keybits,j)) {
- TRACE(" ... with button %d: %d\n", j, buttons);
- joydev.buttons[j] = 0x80 | buttons;
- buttons++;
- }
- }
-
if (have_joydevs==0) {
joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev));
} else {
@@ -357,8 +349,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm
{
JoystickImpl* newDevice;
LPDIDATAFORMAT df = NULL;
- int i, idx = 0;
- int axis = 0, pov = 0, btn = 0;
+ int i, idx = 0, btn=0;
newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(JoystickImpl));
if (!newDevice) return NULL;
@@ -373,19 +364,6 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm
#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
newDevice->ff_state = FF_STATUS_STOPPED;
#endif
- for (i=0;i<ABS_MAX;i++) {
- /* apps expect the range to be the same they would get from the
- * GetProperty/range method */
- newDevice->wantmin[i] = newDevice->joydev->havemin[i];
- newDevice->wantmax[i] = newDevice->joydev->havemax[i];
- /* TODO:
- * direct input defines a default for the deadzone somewhere; but as long
- * as in map_axis the code for the dead zone is commented out its no
- * problem
- */
- newDevice->deadz[i] = 0;
- }
- fake_current_js_state(newDevice);
/* Create copy of default data format */
if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
@@ -395,19 +373,29 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm
/* Supported Axis & POVs should map 1-to-1 */
for (i = 0; i < 8; i++)
{
- if (!test_bit(newDevice->joydev->absbits, i)) continue;
+ if (!test_bit(newDevice->joydev->absbits, i)) {
+ newDevice->axes[i] = -1;
+ continue;
+ }
- memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[axis + WINE_JOYSTICK_AXIS_BASE], df->dwObjSize);
- df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(axis++) | DIDFT_ABSAXIS;
+ memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i], df->dwObjSize);
+ newDevice->axes[i] = idx;
+ newDevice->havemin[idx] = newDevice->wantmin[idx] = newDevice->joydev->axes[i][AXE_ABSMIN];
+ newDevice->havemax[idx] = newDevice->wantmax[idx] = newDevice->joydev->axes[i][AXE_ABSMAX];
+ newDevice->deadz[idx] = 0;
+ df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_ABSAXIS;
}
for (i = 0; i < 4; i++)
{
if (!test_bit(newDevice->joydev->absbits, ABS_HAT0X + i * 2) ||
- !test_bit(newDevice->joydev->absbits, ABS_HAT0Y + i * 2))
- continue;
+ !test_bit(newDevice->joydev->absbits, ABS_HAT0Y + i * 2)) {
+ newDevice->axes[ABS_HAT0X + i * 2] = newDevice->axes[ABS_HAT0Y + i * 2] = -1;
+ continue;
+ }
- memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[pov + WINE_JOYSTICK_POV_BASE], df->dwObjSize);
- df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(pov++) | DIDFT_POV;
+ memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + WINE_JOYSTICK_POV_BASE], df->dwObjSize);
+ newDevice->axes[ABS_HAT0X + i * 2] = newDevice->axes[ABS_HAT0Y + i * 2] = i;
+ df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_POV;
}
/* Buttons can be anywhere, so check all */
for (i = 0; i < KEY_MAX && btn < 128; i++)
@@ -415,10 +403,13 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm
if (!test_bit(newDevice->joydev->keybits, i)) continue;
memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[btn + WINE_JOYSTICK_BUTTON_BASE], df->dwObjSize);
+ newDevice->buttons[i] = 0x80 | btn;
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(btn++) | DIDFT_PSHBUTTON;
}
df->dwNumObjs = idx;
+ fake_current_js_state(newDevice);
+
newDevice->base.data_format.wine_df = df;
IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput);
return newDevice;
@@ -583,23 +574,19 @@ static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
*/
static int
map_axis(JoystickImpl* This, int axis, int val) {
- int xmin = This->joydev->axes[axis][AXE_ABSMIN];
- int xmax = This->joydev->axes[axis][AXE_ABSMAX];
- int hmax = This->joydev->havemax[axis];
- int hmin = This->joydev->havemin[axis];
+ int hmin = This->havemin[axis];
+ int hmax = This->havemax[axis];
int wmin = This->wantmin[axis];
int wmax = This->wantmax[axis];
int ret;
- if (val > hmax) This->joydev->havemax[axis] = hmax = val;
- if (val < hmin) This->joydev->havemin[axis] = hmin = val;
-
- if (xmin == xmax) return val;
+ if (val < hmin) This->havemin[axis] = hmin = val;
+ if (val > hmax) This->havemax[axis] = hmax = val;
/* map the value from the hmin-hmax range into the wmin-wmax range */
ret = MulDiv( val - hmin, wmax - wmin, hmax - hmin ) + wmin;
- TRACE("xmin=%d xmax=%d hmin=%d hmax=%d wmin=%d wmax=%d val=%d ret=%d\n", xmin, xmax, hmin, hmax, wmin, wmax, val, ret);
+ TRACE("hmin=%d hmax=%d wmin=%d wmax=%d val=%d ret=%d\n", hmin, hmax, wmin, wmax, val, ret);
#if 0
/* deadzone doesn't work comfortably enough right now. needs more testing*/
@@ -619,14 +606,14 @@ static void fake_current_js_state(JoystickImpl *ji)
{
int i;
/* center the axes */
- ji->js.lX = test_bit(ji->joydev->absbits, ABS_X) ? map_axis(ji, ABS_X, ji->joydev->axes[ABS_X ][AXE_ABS]) : 0;
- ji->js.lY = test_bit(ji->joydev->absbits, ABS_Y) ? map_axis(ji, ABS_Y, ji->joydev->axes[ABS_Y ][AXE_ABS]) : 0;
- ji->js.lZ = test_bit(ji->joydev->absbits, ABS_Z) ? map_axis(ji, ABS_Z, ji->joydev->axes[ABS_Z ][AXE_ABS]) : 0;
- ji->js.lRx = test_bit(ji->joydev->absbits, ABS_RX) ? map_axis(ji, ABS_RX, ji->joydev->axes[ABS_RX ][AXE_ABS]) : 0;
- ji->js.lRy = test_bit(ji->joydev->absbits, ABS_RY) ? map_axis(ji, ABS_RY, ji->joydev->axes[ABS_RY ][AXE_ABS]) : 0;
- ji->js.lRz = test_bit(ji->joydev->absbits, ABS_RZ) ? map_axis(ji, ABS_RZ, ji->joydev->axes[ABS_RZ ][AXE_ABS]) : 0;
- ji->js.rglSlider[0] = test_bit(ji->joydev->absbits, ABS_THROTTLE) ? map_axis(ji, ABS_THROTTLE, ji->joydev->axes[ABS_THROTTLE][AXE_ABS]) : 0;
- ji->js.rglSlider[1] = test_bit(ji->joydev->absbits, ABS_RUDDER) ? map_axis(ji, ABS_RUDDER, ji->joydev->axes[ABS_RUDDER ][AXE_ABS]) : 0;
+ ji->js.lX = test_bit(ji->joydev->absbits, ABS_X) ? map_axis(ji, ji->axes[ABS_X], ji->joydev->axes[ABS_X ][AXE_ABS]) : 0;
+ ji->js.lY = test_bit(ji->joydev->absbits, ABS_Y) ? map_axis(ji, ji->axes[ABS_Y], ji->joydev->axes[ABS_Y ][AXE_ABS]) : 0;
+ ji->js.lZ = test_bit(ji->joydev->absbits, ABS_Z) ? map_axis(ji, ji->axes[ABS_Z], ji->joydev->axes[ABS_Z ][AXE_ABS]) : 0;
+ ji->js.lRx = test_bit(ji->joydev->absbits, ABS_RX) ? map_axis(ji, ji->axes[ABS_RX], ji->joydev->axes[ABS_RX ][AXE_ABS]) : 0;
+ ji->js.lRy = test_bit(ji->joydev->absbits, ABS_RY) ? map_axis(ji, ji->axes[ABS_RY], ji->joydev->axes[ABS_RY ][AXE_ABS]) : 0;
+ ji->js.lRz = test_bit(ji->joydev->absbits, ABS_RZ) ? map_axis(ji, ji->axes[ABS_RZ], ji->joydev->axes[ABS_RZ ][AXE_ABS]) : 0;
+ ji->js.rglSlider[0] = test_bit(ji->joydev->absbits, ABS_THROTTLE) ? map_axis(ji, ji->axes[ABS_THROTTLE], ji->joydev->axes[ABS_THROTTLE][AXE_ABS]) : 0;
+ ji->js.rglSlider[1] = test_bit(ji->joydev->absbits, ABS_RUDDER) ? map_axis(ji, ji->axes[ABS_RUDDER], ji->joydev->axes[ABS_RUDDER ][AXE_ABS]) : 0;
/* POV center is -1 */
for (i=0; i<4; i++) {
ji->js.rgdwPOV[i] = -1;
@@ -658,45 +645,6 @@ static DWORD map_pov(int event_value, int is_x)
return ret;
}
-/* defines how the linux input system offset mappings into c_dfDIJoystick2 */
-static int lxinput_to_user_index(JoystickImpl *This, int ie_type, int ie_code )
-{
- int offset = -1;
- switch (ie_type) {
- case EV_ABS:
- switch (ie_code) {
- case ABS_X: offset = 0; break;
- case ABS_Y: offset = 1; break;
- case ABS_Z: offset = 2; break;
- case ABS_RX: offset = 3; break;
- case ABS_RY: offset = 4; break;
- case ABS_RZ: offset = 5; break;
- case ABS_THROTTLE: offset = 6; break;
- case ABS_RUDDER: offset = 7; break;
- case ABS_HAT0X: case ABS_HAT0Y: offset = 8; break;
- case ABS_HAT1X: case ABS_HAT1Y: offset = 9; break;
- case ABS_HAT2X: case ABS_HAT2Y: offset = 10; break;
- case ABS_HAT3X: case ABS_HAT3Y: offset = 11; break;
- /* XXX when adding new axes here also fix the offset for the buttons bellow */
- default:
- FIXME("Unhandled EV_ABS(0x%02X)\n", ie_code);
- return -1;
- }
- break;
- case EV_KEY:
- if (ie_code >= 128) {
- WARN("DX8 does not support more than 128 buttons\n");
- return -1;
- }
- offset = 12 + ie_code; /* XXX */
- break;
- default:
- FIXME("Unhandled type(0x%02X)\n", ie_type);
- return -1;
- }
- return offset;
-}
-
/* convert wine format offset to user format object index */
static void joy_polldev(JoystickImpl *This)
{
@@ -725,7 +673,7 @@ static void joy_polldev(JoystickImpl *This)
switch (ie.type) {
case EV_KEY: /* button */
{
- int btn = This->joydev->buttons[ie.code];
+ int btn = This->buttons[ie.code];
TRACE("(%p) %d -> %d\n", This, ie.code, btn);
if (btn & 0x80)
@@ -737,10 +685,13 @@ static void joy_polldev(JoystickImpl *This)
break;
}
case EV_ABS:
- if ((inst_id = lxinput_to_user_index(This, ie.type, ie.code)) == -1)
- return;
- inst_id = DIDFT_MAKEINSTANCE(inst_id) | (inst_id < ABS_HAT0X ? DIDFT_AXIS : DIDFT_POV);
- value = map_axis(This, ie.code, ie.value);
+ {
+ int axe = This->axes[ie.code];
+ if (axe==-1) {
+ break;
+ }
+ inst_id = DIDFT_MAKEINSTANCE(axe) | (ie.code < ABS_HAT0X ? DIDFT_ABSAXIS : DIDFT_POV);
+ value = map_axis(This, axe, ie.value);
switch (ie.code) {
case ABS_X: This->js.lX = value; break;
@@ -772,6 +723,7 @@ static void joy_polldev(JoystickImpl *This)
break;
}
break;
+ }
#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
case EV_FF_STATUS:
This->ff_state = ie.value;
@@ -982,8 +934,8 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
int obj = find_property(&This->base.data_format, pdiph);
if (obj >= 0) {
- pr->lMin = This->joydev->havemin[obj];
- pr->lMax = This->joydev->havemax[obj];
+ pr->lMin = This->havemin[obj];
+ pr->lMax = This->havemax[obj];
TRACE("range(%d, %d) obj=%d\n", pr->lMin, pr->lMax, obj);
}
break;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 163 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20070111/af93ee0c/attachment-0001.pgp
More information about the wine-patches
mailing list