resend: respect ph.dwHow on SetProperty and some other transfers from joystick_linux.c

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

resend: respect ph.dwHow on SetProperty and some other transfers from joystick_linux.c

Christoph Frick-2
hi,

this is a resend of my previous patch without the change in the
acquire-code that Damien mentioned. also the tabs are removed and the
(eye-hurting) ts=8, sw=2, expandtab setting is used. the rest remains
the same - so simply the original mail from here:
------------------------------------------------------------------------

hi,

the attached patch fixes two problems with the game LFS and my wheel
when using the event joystick interface.

the game displayed the detected axes - but got no events that signaled
movement: the Poll method returns no DIERR_NOTACQUIRED if not acquired
which make LFS also get the events properly

this fix done, the axes worked in the game, but the little bars
indicating where all over the place. This was because SetProperty was
called with dwHow==2 (DIPH_BYID) and dwHow==0 (DIPH_DEVICE). The current
inmplementation only supported DIPH_BYOFFSET.

One problem i encountered by testing this: EnumObjects builds a proper
dwType - and LFS also uses it (DIPH_. But in SetDataFormat they use something
completly different in dwType. So the comparing code
(This->df->rgodf[]->dwType==dw.Obj) can not work. Is there anybody in
the realm, who knows why this is like it is (i have not yet started to
read the MSDN so feel free to push me in that direction).

This patch is basically an adaption of the things done in
joystick_linux.c because i had my wheel working using the /dev/input/js0
"emulation" - but the kernel puts a deadzone on the js-devices by
default.

I tested the patch against Live For Speed, NASCAR 2003 and Grand Prix
Legends.

ChangeLog:

- added support of ph.dwHow for SetProperty
- minor cleanups and code transfer from joystick_linux.c

--
cu

--- dlls/dinput/joystick_linuxinput.c.orig 2005-10-03 14:46:22.000000000 +0200
+++ dlls/dinput/joystick_linuxinput.c 2005-10-12 20:46:05.000000000 +0200
@@ -145,6 +145,7 @@
 };
 
 static void fake_current_js_state(JoystickImpl *ji);
+static int find_property_offset(JoystickImpl *This, LPCDIPROPHEADER ph);
 
 #define test_bit(arr,bit) (((BYTE*)arr)[bit>>3]&(1<<(bit&7)))
 
@@ -420,13 +421,35 @@
 
   _dump_DIDATAFORMAT(df);
   
+  if (df == NULL) {
+    WARN("invalid pointer\n");
+    return E_POINTER;
+  }
+
+  if (df->dwSize != sizeof(*df)) {
+    WARN("invalid argument\n");
+    return DIERR_INVALIDPARAM;
+  }
+
+  if (This->joyfd!=-1) {
+    WARN("acquired\n");
+    return DIERR_ACQUIRED;
+  }
+
   /* Store the new data format */
   This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
+  if (This->df==NULL) {
+    return DIERR_OUTOFMEMORY;
+  }
   memcpy(This->df, df, df->dwSize);
   This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
+  if (This->df->rgodf==NULL) {
+    HeapFree(GetProcessHeap(), 0, This->df);
+    return DIERR_OUTOFMEMORY;
+  }
   memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
 
-  return 0;
+  return DI_OK;
 }
 
 /******************************************************************************
@@ -593,6 +616,47 @@
  ji->js.rglSlider[1] = map_axis(ji, ABS_RUDDER,   ji->axes[ABS_RUDDER  ][AXE_ABS]);
 }
 
+static int find_property_offset(JoystickImpl *This, LPCDIPROPHEADER ph)
+{
+  int i,c;
+  switch (ph->dwHow) {
+    case DIPH_BYOFFSET:
+      for (i=0; i<This->df->dwNumObjs; i++) {
+        if (This->df->rgodf[i].dwOfs == ph->dwObj) {
+          return i;
+        }
+      }
+      break;
+    case DIPH_BYID:
+      /* XXX: this is a hack - see below */
+      c = DIDFT_GETINSTANCE(ph->dwObj)>>WINE_JOYSTICK_AXIS_BASE;
+      for (i=0; (c&1)==0 && i<0x0F; i++) {
+        c >>= 1;
+      }
+      if (i<0x0F) {
+        return i;
+      }
+
+      /* XXX - the following part wont work with LiveForSpeed
+       * - the game sets the dwTypes to something else then
+       * the ddoi.dwType set in EnumObjects
+       */
+#if 0
+      for (i=0; i<This->df->dwNumObjs; i++) {
+        TRACE("dwType='%08x'\n", This->df->rgodf[i].dwType);
+        if ((This->df->rgodf[i].dwType & 0x00ffffff) == (ph->dwObj & 0x00ffffff)) {
+          return i;
+        }
+      }
+#endif
+      break;
+    default:
+      FIXME("Unhandled ph->dwHow=='%04X'\n", (unsigned int)ph->dwHow);
+  }
+
+  return -1;
+}
+
 static void joy_polldev(JoystickImpl *This) {
     struct timeval tv;
     fd_set readfds;
@@ -799,36 +863,53 @@
     case (DWORD) DIPROP_BUFFERSIZE: {
       LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
 
-      FIXME("buffersize = %ld\n",pd->dwData);
+      TRACE("buffersize = %ld\n",pd->dwData);
+      if (This->data_queue) {
+        This->data_queue = HeapReAlloc(GetProcessHeap(),0, This->data_queue, pd->dwData * sizeof(DIDEVICEOBJECTDATA));
+      } else {
+        This->data_queue = HeapAlloc(GetProcessHeap(),0, pd->dwData * sizeof(DIDEVICEOBJECTDATA));
+      }
+      This->queue_head = 0;
+      This->queue_tail = 0;
+      This->queue_len  = pd->dwData;
       break;
     }
     case (DWORD)DIPROP_RANGE: {
       LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
 
-      FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
-      switch (ph->dwObj) {
-      case 0: /* X */
-      case 4: /* Y */
-      case 8: /* Z */
-      case 12:  /* Rx */
-      case 16:  /* Ry */
-      case 20:  /* Rz */
-      case 24:  /* Slider 0 -> Throttle */
-      case 28:  /* Slider 1 -> Rudder */
-  This->wantmin[ph->dwObj/4] = pr->lMin;
-  This->wantmax[ph->dwObj/4] = pr->lMax;
-  break;
-      default:
-  FIXME("setting proprange %ld - %ld for dwObj %ld\n",pr->lMin,pr->lMax,ph->dwObj);
+      if (ph->dwHow == DIPH_DEVICE) {
+        int i;
+        TRACE("proprange(%ld,%ld) all\n",pr->lMin,pr->lMax);
+        for (i = 0; i < This->df->dwNumObjs; i++) {
+          This->wantmin[i] = pr->lMin;
+          This->wantmax[i] = pr->lMax;
+        }
+      } else {
+        int obj = find_property_offset(This, ph);
+        TRACE("proprange(%ld,%ld) obj=%d\n",pr->lMin,pr->lMax,obj);
+        if (obj >= 0) {
+          This->wantmin[obj] = pr->lMin;
+          This->wantmax[obj] = pr->lMax;
+        }
       }
-      break;
+      return DI_OK;
     }
     case (DWORD)DIPROP_DEADZONE: {
       LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
-
-      FIXME("setting deadzone(%ld)\n",pd->dwData);
-      This->deadz[ph->dwObj/4] = pd->dwData;
-      break;
+      if (ph->dwHow == DIPH_DEVICE) {
+        int i;
+        TRACE("deadzone(%ld) all\n",pd->dwData);
+        for (i = 0; i < This->df->dwNumObjs; i++) {
+          This->deadz[i] = pd->dwData;
+        }
+      } else {
+        int obj = find_property_offset(This, ph);
+        TRACE("deadzone(%ld) obj=%d\n",pd->dwData,obj);
+        if (obj >= 0) {
+          This->deadz[obj] = pd->dwData;
+        }
+      }
+      return DI_OK;
     }
     default:
       FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
@@ -859,15 +940,13 @@
     JoystickImpl *This = (JoystickImpl *)iface;
     int xfd = This->joyfd;
     int i,axes,buttons;
-    int wasacquired = 1;
 
     TRACE("%p->(%p)\n",iface,lpDIDevCaps);
     if (xfd==-1) {
  /* yes, games assume we return something, even if unacquired */
  JoystickAImpl_Acquire(iface);
- xfd = This->joyfd;
- wasacquired = 0;
     }
+
     lpDIDevCaps->dwFlags = DIDC_ATTACHED;
     if (This->dinput->dwVersion >= 0x0800)
         lpDIDevCaps->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
@@ -885,15 +964,20 @@
     lpDIDevCaps->dwAxes = axes;
     lpDIDevCaps->dwButtons = buttons;
 
-    if (!wasacquired)
- JoystickAImpl_Unacquire(iface);
+    if (xfd==-1) {
+      JoystickAImpl_Unacquire(iface);
+    }
 
     return DI_OK;
 }
 
 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE8A iface) {
     JoystickImpl *This = (JoystickImpl *)iface;
-    TRACE("(),stub!\n");
+    TRACE("(%p)\n",This);
+
+    if (This->joyfd==-1) {
+      return DIERR_NOTACQUIRED;
+    }
 
     joy_polldev(This);
     return DI_OK;



attachment0 (169 bytes) Download Attachment