[dinput][joystick_linuxinput] make axes work, that are "not in a row"

Christoph Frick frick at sc-networks.de
Fri Jan 12 03:59:17 CST 2007


On Thu, Jan 11, 2007 at 10:25:51AM -0700, Vitaliy Margolen wrote:

attached a patch with all the suggestions for Vitaliy.

> Christoph Frick wrote:
> > 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
> That's a good news. I was hopping not to brake too many things while
> reorganizing the dinput.
> 
> > @@ -128,11 +122,20 @@ struct JoystickImpl
> >  	/* The 'parent' DInput */
> >  	IDirectInputImpl               *dinput;
> >  
> > +	/* autodetecting ranges per axe by following movement */
> > +	LONG				havemax[8];
> > +	LONG				havemin[8];
> I could never understood why we need these? In other joystick_linux the
> range assumed to be 0 - 0xffff.
> 
> >  	/* 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];
> Can we move these into separate struct like it's done in joystick_linux?
> It's much cleaner end eventually will allow a better integration of two.
> 
> And can you use spaces instead of tabs please?
> 
> > @@ -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;
> > +        }
> Can you please don't brake the good readable style? Please put that
> curly bracket into separate line, and use 4 space indentation.
> 
> 
> > +    fake_current_js_state(newDevice);
> > +
> Can you explain what this suppose to do? Why do we need to "fake current
> state" everywhere?
> 
> > +            int axe = This->axes[ie.code];
> It's an "axis" not an "axe" :)

-- 

diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index e2f77f8..640c8d9 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,15 @@ 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 ObjProps
+{
+        LONG havemin;
+        LONG havemax;
+        LONG wantmin;
+        LONG wantmax;
+        LONG deadzone;
 };
 
 struct JoystickImpl
@@ -128,11 +131,13 @@ struct JoystickImpl
 	/* The 'parent' DInput */
 	IDirectInputImpl               *dinput;
 
-	/* joystick private */
-	/* what range and deadzone the game wants */
-	LONG				wantmin[ABS_MAX];
-	LONG				wantmax[ABS_MAX];
-	LONG				deadz[ABS_MAX];
+        struct ObjProps                 props[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 +182,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;
@@ -246,7 +251,7 @@ static void find_joydevs(void)
 	for (j=0;j<ABS_MAX;j++) {
 	  if (test_bit(joydev.absbits,j)) {
 	    if (-1!=ioctl(fd,EVIOCGABS(j),&(joydev.axes[j]))) {
-	      TRACE(" ... with axe %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n",
+	      TRACE(" ... with axis %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n",
 		  j,
 		  joydev.axes[j][AXE_ABS],
 		  joydev.axes[j][AXE_ABSMIN],
@@ -254,21 +259,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 +351,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 +366,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 +375,31 @@ 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->props[idx].havemin = newDevice->props[idx].wantmin = newDevice->joydev->axes[i][AXE_ABSMIN];
+        newDevice->props[idx].havemax = newDevice->props[idx].wantmax = newDevice->joydev->axes[i][AXE_ABSMAX];
+        newDevice->props[idx].deadzone = 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))
+        {
+            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 +407,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;
@@ -578,28 +573,24 @@ static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
 
 /*
  * This maps the read value (from the input event) to a value in the
- * 'wanted' range. It also autodetects the possible range of the axe and
+ * 'wanted' range. It also autodetects the possible range of the axis and
  * adapts values accordingly.
  */
 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	wmin = This->wantmin[axis];
-    int	wmax = This->wantmax[axis];
+    int hmin = This->props[axis].havemin;
+    int hmax = This->props[axis].havemax;
+    int	wmin = This->props[axis].wantmin;
+    int	wmax = This->props[axis].wantmax;
     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->props[axis].havemin = hmin = val;
+    if (val > hmax) This->props[axis].havemax = 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 +610,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 +649,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 +677,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 +689,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 axis = This->axes[ie.code];
+            if (axis==-1) {
+                break;
+            }
+            inst_id = DIDFT_MAKEINSTANCE(axis) | (ie.code < ABS_HAT0X ? DIDFT_ABSAXIS : DIDFT_POV);
+            value = map_axis(This, axis, ie.value);
 
 	    switch (ie.code) {
             case ABS_X:         This->js.lX  = value; break;
@@ -768,10 +723,11 @@ static void joy_polldev(JoystickImpl *This)
                 This->js.rgdwPOV[3] = value  = map_pov(ie.value, ie.code==ABS_HAT3X);
                 break;
 	    default:
-		FIXME("unhandled joystick axe event (code %d, value %d)\n",ie.code,ie.value);
+		FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value);
 		break;
 	    }
 	    break;
+        }
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
 	case EV_FF_STATUS:
 	    This->ff_state = ie.value;
@@ -844,16 +800,16 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
         int i;
         TRACE("proprange(%d,%d) all\n", pr->lMin, pr->lMax);
         for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) {
-          This->wantmin[i] = pr->lMin;
-          This->wantmax[i] = pr->lMax;
+          This->props[i].wantmin = pr->lMin;
+          This->props[i].wantmax = pr->lMax;
         }
       } else {
         int obj = find_property(&This->base.data_format, ph);
 
         TRACE("proprange(%d,%d) obj=%d\n", pr->lMin, pr->lMax, obj);
         if (obj >= 0) {
-          This->wantmin[obj] = pr->lMin;
-          This->wantmax[obj] = pr->lMax;
+          This->props[obj].wantmin = pr->lMin;
+          This->props[obj].wantmax = pr->lMax;
         }
       }
       fake_current_js_state(This);
@@ -865,14 +821,14 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
         int i;
         TRACE("deadzone(%d) all\n", pd->dwData);
         for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) {
-          This->deadz[i] = pd->dwData;
+          This->props[i].deadzone = pd->dwData;
         }
       } else {
         int obj = find_property(&This->base.data_format, ph);
 
         TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj);
         if (obj >= 0) {
-          This->deadz[obj] = pd->dwData;
+          This->props[obj].deadzone = pd->dwData;
         }
       }
       fake_current_js_state(This);
@@ -982,8 +938,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->props[obj].havemin;
+	pr->lMax = This->props[obj].havemax;
 	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/20070112/1e7d0ed6/attachment.pgp


More information about the wine-patches mailing list