dinput: Evdev joystick driver - add ability to remap axis.
This commit is contained in:
parent
3622b2d926
commit
167457efc1
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue