dinput: Evdev joystick driver - add ability to remap axis.

This commit is contained in:
Vitaliy Margolen 2009-08-15 11:58:47 -06:00 committed by Alexandre Julliard
parent 3622b2d926
commit 167457efc1
1 changed files with 69 additions and 53 deletions

View File

@ -378,9 +378,6 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm
JoystickImpl* newDevice; JoystickImpl* newDevice;
LPDIDATAFORMAT df = NULL; LPDIDATAFORMAT df = NULL;
int i, idx = 0; int i, idx = 0;
char buffer[MAX_PATH+16];
HKEY hkey, appkey;
LONG def_deadzone = 0;
newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(JoystickImpl)); newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(JoystickImpl));
if (!newDevice) return NULL; if (!newDevice) return NULL;
@ -405,57 +402,73 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm
InitializeCriticalSection(&newDevice->generic.base.crit); InitializeCriticalSection(&newDevice->generic.base.crit);
newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
/* get options */ /* Count number of available axes - supported Axis & POVs */
get_app_key(&hkey, &appkey); for (i = 0; i < WINE_JOYSTICK_MAX_AXES; i++)
if (!get_config_key(hkey, appkey, "DefaultDeadZone", buffer, MAX_PATH))
{ {
def_deadzone = atoi(buffer); if (test_bit(newDevice->joydev->absbits, i))
TRACE("setting default deadzone to: %d\n", def_deadzone); {
newDevice->generic.device_axis_count++;
newDevice->dev_axes_to_di[i] = idx;
newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[i].minimum;
newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[i].maximum;
idx++;
} }
if (appkey) RegCloseKey(appkey); else
if (hkey) RegCloseKey(hkey); newDevice->dev_axes_to_di[i] = -1;
}
for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++)
{
if (test_bit(newDevice->joydev->absbits, ABS_HAT0X + i * 2) &&
test_bit(newDevice->joydev->absbits, ABS_HAT0Y + i * 2))
{
newDevice->generic.device_axis_count += 2;
newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[ABS_HAT0X + i * 2].minimum;
newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = idx++;
newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[ABS_HAT0Y + i * 2].maximum;
newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = idx++;
}
else
newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = -1;
}
/* do any user specified configuration */
if (setup_dinput_options(&newDevice->generic) != DI_OK) goto failed;
/* Create copy of default data format */ /* Create copy of default data format */
if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed; if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize); memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed; if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
/* Supported Axis & POVs should map 1-to-1 */
for (i = 0; i < WINE_JOYSTICK_MAX_AXES; i++) /* Construct internal data format */
/* Supported Axis & POVs */
for (i = 0, idx = 0; i < newDevice->generic.device_axis_count; i++)
{ {
if (!test_bit(newDevice->joydev->absbits, i)) { int wine_obj = newDevice->generic.axis_map[i];
newDevice->dev_axes_to_di[i] = -1;
continue; if (wine_obj < 0) continue;
memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
if (wine_obj < 8)
df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
else
{
df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
i++; /* POV takes 2 axes */
} }
memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i], df->dwObjSize);
newDevice->dev_axes_to_di[i] = idx;
newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[i].minimum;
newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[i].maximum;
newDevice->generic.props[idx].lMin = 0; newDevice->generic.props[idx].lMin = 0;
newDevice->generic.props[idx].lMax = 0xffff; newDevice->generic.props[idx].lMax = 0xffff;
newDevice->generic.props[idx].lSaturation = 0; newDevice->generic.props[idx].lSaturation = 0;
newDevice->generic.props[idx].lDeadZone = def_deadzone; newDevice->generic.props[idx].lDeadZone = newDevice->generic.deadzone;
/* Linux supports force-feedback on X & Y axes only */ /* Linux supports force-feedback on X & Y axes only */
if (newDevice->joydev->has_ff && (i == 0 || i == 1)) if (newDevice->joydev->has_ff && (i == 0 || i == 1))
df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR; df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR;
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(newDevice->generic.devcaps.dwAxes++) | DIDFT_ABSAXIS; idx++;
}
for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++)
{
if (!test_bit(newDevice->joydev->absbits, ABS_HAT0X + i * 2) ||
!test_bit(newDevice->joydev->absbits, ABS_HAT0Y + i * 2)) {
newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = -1;
continue;
}
memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + WINE_JOYSTICK_MAX_AXES], df->dwObjSize);
newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = i;
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(newDevice->generic.devcaps.dwPOVs++) | DIDFT_POV;
} }
/* Buttons can be anywhere, so check all */ /* Buttons can be anywhere, so check all */
@ -490,6 +503,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm
failed: failed:
if (df) HeapFree(GetProcessHeap(), 0, df->rgodf); if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
HeapFree(GetProcessHeap(), 0, df); HeapFree(GetProcessHeap(), 0, df);
HeapFree(GetProcessHeap(), 0, newDevice->generic.axis_map);
HeapFree(GetProcessHeap(), 0, newDevice); HeapFree(GetProcessHeap(), 0, newDevice);
return NULL; return NULL;
} }
@ -752,25 +766,27 @@ static void joy_polldev(JoystickGenericImpl *iface)
case EV_ABS: case EV_ABS:
{ {
int axis = This->dev_axes_to_di[ie.code]; int axis = This->dev_axes_to_di[ie.code];
if (axis==-1) {
break; /* User axis remapping */
} if (axis < 0) break;
inst_id = DIDFT_MAKEINSTANCE(axis) | (ie.code < ABS_HAT0X ? DIDFT_ABSAXIS : DIDFT_POV); axis = This->generic.axis_map[axis];
if (axis < 0) break;
inst_id = DIDFT_MAKEINSTANCE(axis) | (axis < 8 ? DIDFT_ABSAXIS : DIDFT_POV);
value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], ie.value); value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], ie.value);
switch (ie.code) { switch (axis) {
case ABS_X: This->generic.js.lX = value; break; case 0: This->generic.js.lX = value; break;
case ABS_Y: This->generic.js.lY = value; break; case 1: This->generic.js.lY = value; break;
case ABS_Z: This->generic.js.lZ = value; break; case 2: This->generic.js.lZ = value; break;
case ABS_RX: This->generic.js.lRx = value; break; case 3: This->generic.js.lRx = value; break;
case ABS_RY: This->generic.js.lRy = value; break; case 4: This->generic.js.lRy = value; break;
case ABS_RZ: This->generic.js.lRz = value; break; case 5: This->generic.js.lRz = value; break;
case ABS_THROTTLE: This->generic.js.rglSlider[0] = value; break; case 6: This->generic.js.rglSlider[0] = value; break;
case ABS_RUDDER: This->generic.js.rglSlider[1] = value; break; case 7: This->generic.js.rglSlider[1] = value; break;
case ABS_HAT0X: case ABS_HAT0Y: case ABS_HAT1X: case ABS_HAT1Y: case 8: case 9: case 10: case 11:
case ABS_HAT2X: case ABS_HAT2Y: case ABS_HAT3X: case ABS_HAT3Y:
{ {
int idx = (ie.code - ABS_HAT0X) / 2; int idx = axis - 8;
if (ie.code % 2) if (ie.code % 2)
This->povs[idx].y = ie.value; This->povs[idx].y = ie.value;