ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

joystick_linux.c
Go to the documentation of this file.
00001 /*      DirectInput Joystick device
00002  *
00003  * Copyright 1998 Marcus Meissner
00004  * Copyright 1998,1999 Lionel Ulmer
00005  * Copyright 2000-2001 TransGaming Technologies Inc.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 /*
00023  * To Do:
00024  *  dead zone
00025  *  force feedback
00026  */
00027 
00028 #include "config.h"
00029 #include "wine/port.h"
00030 
00031 #include <stdarg.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <time.h>
00035 #ifdef HAVE_UNISTD_H
00036 # include <unistd.h>
00037 #endif
00038 #ifdef HAVE_SYS_TIME_H
00039 # include <sys/time.h>
00040 #endif
00041 #include <fcntl.h>
00042 #ifdef HAVE_SYS_IOCTL_H
00043 # include <sys/ioctl.h>
00044 #endif
00045 #include <errno.h>
00046 #ifdef HAVE_SYS_ERRNO_H
00047 # include <sys/errno.h>
00048 #endif
00049 #ifdef HAVE_LINUX_IOCTL_H
00050 # include <linux/ioctl.h>
00051 #endif
00052 #ifdef HAVE_LINUX_JOYSTICK_H
00053 # include <linux/joystick.h>
00054 # undef SW_MAX
00055 #endif
00056 #ifdef HAVE_SYS_POLL_H
00057 # include <sys/poll.h>
00058 #endif
00059 
00060 #include "wine/debug.h"
00061 #include "wine/unicode.h"
00062 #include "windef.h"
00063 #include "winbase.h"
00064 #include "winerror.h"
00065 #include "winreg.h"
00066 #include "dinput.h"
00067 
00068 #include "dinput_private.h"
00069 #include "device_private.h"
00070 
00071 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
00072 
00073 #ifdef HAVE_LINUX_22_JOYSTICK_API
00074 
00075 #define JOYDEV_NEW "/dev/input/js"
00076 #define JOYDEV_OLD "/dev/js"
00077 
00078 typedef struct JoystickImpl JoystickImpl;
00079 static const IDirectInputDevice8AVtbl JoystickAvt;
00080 static const IDirectInputDevice8WVtbl JoystickWvt;
00081 struct JoystickImpl
00082 {
00083         struct IDirectInputDevice2AImpl base;
00084 
00085     char                dev[32];
00086 
00087     /* joystick private */
00088     int             joyfd;
00089     DIJOYSTATE2         js;     /* wine data */
00090     ObjProps            *props;
00091     char                *name;
00092     DIDEVCAPS           devcaps;
00093     LONG                deadzone;
00094     int             *axis_map;
00095     int             axes;
00096         POINTL                          povs[4];
00097 };
00098 
00099 static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
00100   0x9e573ed9,
00101   0x7734,
00102   0x11d2,
00103   {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
00104 };
00105 
00106 static void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps)
00107 {
00108     TRACE("dwSize: %d\n", lpDIDevCaps->dwSize);
00109     TRACE("dwFlags: %08x\n", lpDIDevCaps->dwFlags);
00110     TRACE("dwDevType: %08x %s\n", lpDIDevCaps->dwDevType,
00111           lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
00112           lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
00113           lpDIDevCaps->dwDevType == DIDEVTYPE_MOUSE ? "DIDEVTYPE_MOUSE" :
00114           lpDIDevCaps->dwDevType == DIDEVTYPE_KEYBOARD ? "DIDEVTYPE_KEYBOARD" :
00115           lpDIDevCaps->dwDevType == DIDEVTYPE_JOYSTICK ? "DIDEVTYPE_JOYSTICK" :
00116           lpDIDevCaps->dwDevType == DIDEVTYPE_HID ? "DIDEVTYPE_HID" : "UNKNOWN");
00117     TRACE("dwAxes: %d\n", lpDIDevCaps->dwAxes);
00118     TRACE("dwButtons: %d\n", lpDIDevCaps->dwButtons);
00119     TRACE("dwPOVs: %d\n", lpDIDevCaps->dwPOVs);
00120     if (lpDIDevCaps->dwSize > sizeof(DIDEVCAPS_DX3)) {
00121         TRACE("dwFFSamplePeriod: %d\n", lpDIDevCaps->dwFFSamplePeriod);
00122         TRACE("dwFFMinTimeResolution: %d\n", lpDIDevCaps->dwFFMinTimeResolution);
00123         TRACE("dwFirmwareRevision: %d\n", lpDIDevCaps->dwFirmwareRevision);
00124         TRACE("dwHardwareRevision: %d\n", lpDIDevCaps->dwHardwareRevision);
00125         TRACE("dwFFDriverVersion: %d\n", lpDIDevCaps->dwFFDriverVersion);
00126     }
00127 }
00128 
00129 #define MAX_JOYSTICKS 64
00130 static INT joystick_devices_count = -1;
00131 static LPSTR joystick_devices[MAX_JOYSTICKS];
00132 
00133 static INT find_joystick_devices(void)
00134 {
00135     INT i;
00136 
00137     if (joystick_devices_count != -1) return joystick_devices_count;
00138 
00139     joystick_devices_count = 0;
00140     for (i = 0; i < MAX_JOYSTICKS; i++)
00141     {
00142         CHAR device_name[MAX_PATH], *str;
00143         INT len;
00144         int fd;
00145 
00146         len = sprintf(device_name, "%s%d", JOYDEV_NEW, i) + 1;
00147         if ((fd = open(device_name, O_RDONLY)) < 0)
00148         {
00149             len = sprintf(device_name, "%s%d", JOYDEV_OLD, i) + 1;
00150             if ((fd = open(device_name, O_RDONLY)) < 0) continue;
00151         }
00152 
00153         close(fd);
00154 
00155         if (!(str = HeapAlloc(GetProcessHeap(), 0, len))) break;
00156         memcpy(str, device_name, len);
00157 
00158         joystick_devices[joystick_devices_count++] = str;
00159     }
00160 
00161     return joystick_devices_count;
00162 }
00163 
00164 static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
00165 {
00166     int fd = -1;
00167 
00168     if (id >= find_joystick_devices()) return FALSE;
00169 
00170     if (dwFlags & DIEDFL_FORCEFEEDBACK) {
00171         WARN("force feedback not supported\n");
00172         return FALSE;
00173     }
00174 
00175     if ((dwDevType == 0) ||
00176     ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
00177     (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
00178         /* check whether we have a joystick */
00179         if ((fd = open(joystick_devices[id], O_RDONLY)) < 0)
00180         {
00181             WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id], strerror(errno));
00182             return FALSE;
00183         }
00184 
00185         /* Return joystick */
00186         lpddi->guidInstance = DInput_Wine_Joystick_GUID;
00187         lpddi->guidInstance.Data3 = id;
00188         lpddi->guidProduct = DInput_Wine_Joystick_GUID;
00189         /* we only support traditional joysticks for now */
00190         if (version >= 0x0800)
00191             lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
00192         else
00193             lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
00194         sprintf(lpddi->tszInstanceName, "Joystick %d", id);
00195 #if defined(JSIOCGNAME)
00196         if (ioctl(fd,JSIOCGNAME(sizeof(lpddi->tszProductName)),lpddi->tszProductName) < 0) {
00197             WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", joystick_devices[id], strerror(errno));
00198             strcpy(lpddi->tszProductName, "Wine Joystick");
00199         }
00200 #else
00201         strcpy(lpddi->tszProductName, "Wine Joystick");
00202 #endif
00203 
00204         lpddi->guidFFDriver = GUID_NULL;
00205         close(fd);
00206         TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id], lpddi->tszProductName);
00207         return TRUE;
00208     }
00209 
00210     return FALSE;
00211 }
00212 
00213 static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
00214 {
00215     int fd = -1;
00216     char name[MAX_PATH];
00217     char friendly[32];
00218 
00219     if (id >= find_joystick_devices()) return FALSE;
00220 
00221     if (dwFlags & DIEDFL_FORCEFEEDBACK) {
00222         WARN("force feedback not supported\n");
00223         return FALSE;
00224     }
00225 
00226     if ((dwDevType == 0) ||
00227     ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
00228     (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
00229         /* check whether we have a joystick */
00230         if ((fd = open(joystick_devices[id], O_RDONLY)) < 0)
00231         {
00232             WARN("open(%s,O_RDONLY) failed: %s\n", joystick_devices[id], strerror(errno));
00233             return FALSE;
00234         }
00235 
00236         /* Return joystick */
00237         lpddi->guidInstance = DInput_Wine_Joystick_GUID;
00238         lpddi->guidInstance.Data3 = id;
00239         lpddi->guidProduct = DInput_Wine_Joystick_GUID;
00240         /* we only support traditional joysticks for now */
00241         if (version >= 0x0800)
00242             lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
00243         else
00244             lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
00245         sprintf(friendly, "Joystick %d", id);
00246         MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH);
00247 #if defined(JSIOCGNAME)
00248         if (ioctl(fd,JSIOCGNAME(sizeof(name)),name) < 0) {
00249             WARN("ioctl(%s, JSIOCGNAME) failed: %s\n", joystick_devices[id], strerror(errno));
00250             strcpy(name, "Wine Joystick");
00251         }
00252 #else
00253         strcpy(name, "Wine Joystick");
00254 #endif
00255         MultiByteToWideChar(CP_ACP, 0, name, -1, lpddi->tszProductName, MAX_PATH);
00256         lpddi->guidFFDriver = GUID_NULL;
00257         close(fd);
00258         TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id], name);
00259         return TRUE;
00260     }
00261 
00262     return FALSE;
00263 }
00264 
00265 /*
00266  * Setup the dinput options.
00267  */
00268 
00269 static HRESULT setup_dinput_options(JoystickImpl * device)
00270 {
00271     char buffer[MAX_PATH+16];
00272     HKEY hkey, appkey;
00273     int tokens = 0;
00274     int axis = 0;
00275     int pov = 0;
00276 
00277     buffer[MAX_PATH]='\0';
00278 
00279     get_app_key(&hkey, &appkey);
00280 
00281     /* get options */
00282 
00283     if (!get_config_key( hkey, appkey, "DefaultDeadZone", buffer, MAX_PATH )) {
00284         device->deadzone = atoi(buffer);
00285         TRACE("setting default deadzone to: \"%s\" %d\n", buffer, device->deadzone);
00286     }
00287 
00288     device->axis_map = HeapAlloc(GetProcessHeap(), 0, device->axes * sizeof(int));
00289     if (!device->axis_map) return DIERR_OUTOFMEMORY;
00290 
00291     if (!get_config_key( hkey, appkey, device->name, buffer, MAX_PATH )) {
00292         static const char *axis_names[] = {"X", "Y", "Z", "Rx", "Ry", "Rz",
00293                                            "Slider1", "Slider2",
00294                                            "POV1", "POV2", "POV3", "POV4"};
00295         const char *delim = ",";
00296         char * ptr;
00297         TRACE("\"%s\" = \"%s\"\n", device->name, buffer);
00298 
00299         if ((ptr = strtok(buffer, delim)) != NULL) {
00300             do {
00301                 int i;
00302 
00303                 for (i = 0; i < sizeof(axis_names) / sizeof(axis_names[0]); i++)
00304                     if (!strcmp(ptr, axis_names[i]))
00305                     {
00306                         if (!strncmp(ptr, "POV", 3))
00307                         {
00308                             if (pov >= 4)
00309                             {
00310                                 WARN("Only 4 POVs supported - ignoring extra\n");
00311                                 i = -1;
00312                             }
00313                             else
00314                             {
00315                                 /* Pov takes two axes */
00316                                 device->axis_map[tokens++] = i;
00317                                 pov++;
00318                             }
00319                         }
00320                         else
00321                         {
00322                             if (axis >= 8)
00323                             {
00324                                 FIXME("Only 8 Axes supported - ignoring extra\n");
00325                                 i = -1;
00326                             }
00327                             else
00328                                 axis++;
00329                         }
00330                         break;
00331                     }
00332 
00333                 if (i == sizeof(axis_names) / sizeof(axis_names[0]))
00334                 {
00335                     ERR("invalid joystick axis type: \"%s\"\n", ptr);
00336                     i = -1;
00337                 }
00338 
00339                 device->axis_map[tokens] = i;
00340                 tokens++;
00341             } while ((ptr = strtok(NULL, delim)) != NULL);
00342 
00343             if (tokens != device->axes) {
00344                 ERR("not all joystick axes mapped: %d axes(%d,%d), %d arguments\n", device->axes, axis, pov,tokens);
00345                 while (tokens < device->axes) {
00346                     device->axis_map[tokens] = -1;
00347                     tokens++;
00348                 }
00349             }
00350         }
00351     }
00352     else
00353     {
00354         for (tokens = 0; tokens < device->axes; tokens++)
00355         {
00356             if (tokens < 8)
00357                 device->axis_map[tokens] = axis++;
00358             else if (tokens < 16)
00359             {
00360                 device->axis_map[tokens++] = 8 + pov;
00361                 device->axis_map[tokens  ] = 8 + pov++;
00362             }
00363             else
00364                 device->axis_map[tokens] = -1;
00365         }
00366     }
00367     device->devcaps.dwAxes = axis;
00368     device->devcaps.dwPOVs = pov;
00369 
00370     if (appkey)
00371         RegCloseKey( appkey );
00372 
00373     if (hkey)
00374         RegCloseKey( hkey );
00375 
00376     return DI_OK;
00377 }
00378 
00379 static HRESULT alloc_device(REFGUID rguid, const void *jvt, IDirectInputImpl *dinput,
00380     LPDIRECTINPUTDEVICEA* pdev, unsigned short index)
00381 {
00382     DWORD i;
00383     JoystickImpl* newDevice;
00384     char name[MAX_PATH];
00385     HRESULT hr;
00386     LPDIDATAFORMAT df = NULL;
00387     int idx = 0;
00388 
00389     TRACE("%s %p %p %p %hu\n", debugstr_guid(rguid), jvt, dinput, pdev, index);
00390 
00391     newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
00392     if (newDevice == 0) {
00393         WARN("out of memory\n");
00394         *pdev = 0;
00395         return DIERR_OUTOFMEMORY;
00396     }
00397 
00398     if (!lstrcpynA(newDevice->dev, joystick_devices[index], sizeof(newDevice->dev)) ||
00399         (newDevice->joyfd = open(newDevice->dev, O_RDONLY)) < 0)
00400     {
00401         WARN("open(%s, O_RDONLY) failed: %s\n", newDevice->dev, strerror(errno));
00402         HeapFree(GetProcessHeap(), 0, newDevice);
00403         return DIERR_DEVICENOTREG;
00404     }
00405 
00406     /* get the device name */
00407 #if defined(JSIOCGNAME)
00408     if (ioctl(newDevice->joyfd,JSIOCGNAME(MAX_PATH),name) < 0) {
00409         WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", newDevice->dev, strerror(errno));
00410         strcpy(name, "Wine Joystick");
00411     }
00412 #else
00413     strcpy(name, "Wine Joystick");
00414 #endif
00415 
00416     /* copy the device name */
00417     newDevice->name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
00418     strcpy(newDevice->name, name);
00419 
00420 #ifdef JSIOCGAXES
00421     if (ioctl(newDevice->joyfd,JSIOCGAXES,&newDevice->axes) < 0) {
00422         WARN("ioctl(%s,JSIOCGAXES) failed: %s, defauting to 2\n", newDevice->dev, strerror(errno));
00423         newDevice->axes = 2;
00424     }
00425 #endif
00426 #ifdef JSIOCGBUTTONS
00427     if (ioctl(newDevice->joyfd, JSIOCGBUTTONS, &newDevice->devcaps.dwButtons) < 0) {
00428         WARN("ioctl(%s,JSIOCGBUTTONS) failed: %s, defauting to 2\n", newDevice->dev, strerror(errno));
00429         newDevice->devcaps.dwButtons = 2;
00430     }
00431 #endif
00432 
00433     if (newDevice->devcaps.dwButtons > 128)
00434     {
00435         WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->devcaps.dwButtons);
00436         newDevice->devcaps.dwButtons = 128;
00437     }
00438 
00439     newDevice->base.lpVtbl = jvt;
00440     newDevice->base.ref = 1;
00441     newDevice->base.dinput = dinput;
00442     newDevice->base.guid = *rguid;
00443     InitializeCriticalSection(&newDevice->base.crit);
00444     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
00445 
00446     /* setup_dinput_options may change these */
00447     newDevice->deadzone = 0;
00448 
00449     /* do any user specified configuration */
00450     hr = setup_dinput_options(newDevice);
00451     if (hr != DI_OK)
00452         goto FAILED1;
00453 
00454     /* Create copy of default data format */
00455     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
00456     memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
00457 
00458     df->dwNumObjs = newDevice->devcaps.dwAxes + newDevice->devcaps.dwPOVs + newDevice->devcaps.dwButtons;
00459     if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
00460 
00461     for (i = 0; i < newDevice->axes; i++)
00462     {
00463         int wine_obj = newDevice->axis_map[i];
00464 
00465         if (wine_obj < 0) continue;
00466 
00467         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
00468         if (wine_obj < 8)
00469             df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
00470         else
00471         {
00472             df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
00473             i++; /* POV takes 2 axes */
00474         }
00475     }
00476     for (i = 0; i < newDevice->devcaps.dwButtons; i++)
00477     {
00478         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
00479         df->rgodf[idx  ].pguid = &GUID_Button;
00480         df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
00481     }
00482     newDevice->base.data_format.wine_df = df;
00483 
00484     /* create default properties */
00485     newDevice->props = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwNumObjs*sizeof(ObjProps));
00486     if (newDevice->props == 0)
00487         goto FAILED;
00488 
00489     /* initialize default properties */
00490     for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
00491         newDevice->props[i].lDevMin = -32767;
00492         newDevice->props[i].lDevMax = +32767;
00493         newDevice->props[i].lMin = 0;
00494         newDevice->props[i].lMax = 0xffff;
00495         newDevice->props[i].lDeadZone = newDevice->deadzone;    /* % * 1000 */
00496         newDevice->props[i].lSaturation = 0;
00497     }
00498 
00499     IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput);
00500 
00501     newDevice->devcaps.dwSize = sizeof(newDevice->devcaps);
00502     newDevice->devcaps.dwFlags = DIDC_ATTACHED;
00503     if (newDevice->base.dinput->dwVersion >= 0x0800)
00504         newDevice->devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
00505     else
00506         newDevice->devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
00507     newDevice->devcaps.dwFFSamplePeriod = 0;
00508     newDevice->devcaps.dwFFMinTimeResolution = 0;
00509     newDevice->devcaps.dwFirmwareRevision = 0;
00510     newDevice->devcaps.dwHardwareRevision = 0;
00511     newDevice->devcaps.dwFFDriverVersion = 0;
00512 
00513     if (TRACE_ON(dinput)) {
00514         _dump_DIDATAFORMAT(newDevice->base.data_format.wine_df);
00515        for (i = 0; i < (newDevice->axes); i++)
00516            TRACE("axis_map[%d] = %d\n", i, newDevice->axis_map[i]);
00517         _dump_DIDEVCAPS(&newDevice->devcaps);
00518     }
00519 
00520     *pdev = (LPDIRECTINPUTDEVICEA)newDevice;
00521 
00522     return DI_OK;
00523 
00524 FAILED:
00525     hr = DIERR_OUTOFMEMORY;
00526 FAILED1:
00527     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
00528     HeapFree(GetProcessHeap(), 0, df);
00529     release_DataFormat(&newDevice->base.data_format);
00530     HeapFree(GetProcessHeap(),0,newDevice->axis_map);
00531     HeapFree(GetProcessHeap(),0,newDevice->name);
00532     HeapFree(GetProcessHeap(),0,newDevice->props);
00533     HeapFree(GetProcessHeap(),0,newDevice);
00534     *pdev = 0;
00535 
00536     return hr;
00537 }
00538 
00539 /******************************************************************************
00540   *     get_joystick_index : Get the joystick index from a given GUID
00541   */
00542 static unsigned short get_joystick_index(REFGUID guid)
00543 {
00544     GUID wine_joystick = DInput_Wine_Joystick_GUID;
00545     GUID dev_guid = *guid;
00546 
00547     wine_joystick.Data3 = 0;
00548     dev_guid.Data3 = 0;
00549 
00550     /* for the standard joystick GUID use index 0 */
00551     if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
00552 
00553     /* for the wine joystick GUIDs use the index stored in Data3 */
00554     if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
00555 
00556     return MAX_JOYSTICKS;
00557 }
00558 
00559 static HRESULT joydev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
00560 {
00561     unsigned short index;
00562 
00563     TRACE("%p %s %p %p\n",dinput, debugstr_guid(rguid), riid, pdev);
00564     find_joystick_devices();
00565     *pdev = NULL;
00566 
00567     if ((index = get_joystick_index(rguid)) < MAX_JOYSTICKS &&
00568         joystick_devices_count && index < joystick_devices_count)
00569     {
00570         if ((riid == NULL) ||
00571         IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
00572         IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
00573         IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
00574         IsEqualGUID(&IID_IDirectInputDevice8A, riid))
00575         {
00576             return alloc_device(rguid, &JoystickAvt, dinput, pdev, index);
00577         }
00578 
00579         WARN("no interface\n");
00580         return DIERR_NOINTERFACE;
00581     }
00582 
00583     return DIERR_DEVICENOTREG;
00584 }
00585 
00586 static HRESULT joydev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
00587 {
00588     unsigned short index;
00589 
00590     TRACE("%p %s %p %p\n",dinput, debugstr_guid(rguid), riid, pdev);
00591     find_joystick_devices();
00592     *pdev = NULL;
00593 
00594     if ((index = get_joystick_index(rguid)) < MAX_JOYSTICKS &&
00595         joystick_devices_count && index < joystick_devices_count)
00596     {
00597         if ((riid == NULL) ||
00598         IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
00599         IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
00600         IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
00601         IsEqualGUID(&IID_IDirectInputDevice8W, riid))
00602         {
00603             return alloc_device(rguid, &JoystickWvt, dinput, (LPDIRECTINPUTDEVICEA *)pdev, index);
00604         }
00605         WARN("no interface\n");
00606         return DIERR_NOINTERFACE;
00607     }
00608 
00609     WARN("invalid device GUID %s\n",debugstr_guid(rguid));
00610     return DIERR_DEVICENOTREG;
00611 }
00612 
00613 #undef MAX_JOYSTICKS
00614 
00615 const struct dinput_device joystick_linux_device = {
00616   "Wine Linux joystick driver",
00617   joydev_enum_deviceA,
00618   joydev_enum_deviceW,
00619   joydev_create_deviceA,
00620   joydev_create_deviceW
00621 };
00622 
00623 /******************************************************************************
00624   *     Acquire : gets exclusive control of the joystick
00625   */
00626 static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
00627 {
00628     JoystickImpl *This = (JoystickImpl *)iface;
00629 
00630     TRACE("(%p)\n",This);
00631 
00632     if (This->base.acquired) {
00633         WARN("already acquired\n");
00634         return S_FALSE;
00635     }
00636 
00637     /* open the joystick device */
00638     if (This->joyfd==-1) {
00639         TRACE("opening joystick device %s\n", This->dev);
00640 
00641         This->joyfd=open(This->dev,O_RDONLY);
00642         if (This->joyfd==-1) {
00643             ERR("open(%s) failed: %s\n", This->dev, strerror(errno));
00644             return DIERR_NOTFOUND;
00645         }
00646     }
00647 
00648     This->base.acquired = 1;
00649 
00650     return DI_OK;
00651 }
00652 
00653 /******************************************************************************
00654   *     Unacquire : frees the joystick
00655   */
00656 static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
00657 {
00658     JoystickImpl *This = (JoystickImpl *)iface;
00659     HRESULT res;
00660 
00661     TRACE("(%p)\n",This);
00662 
00663     if ((res = IDirectInputDevice2AImpl_Unacquire(iface)) != DI_OK) return res;
00664 
00665     if (This->joyfd!=-1) {
00666         TRACE("closing joystick device\n");
00667         close(This->joyfd);
00668         This->joyfd = -1;
00669         return DI_OK;
00670     }
00671 
00672     return DI_NOEFFECT;
00673 }
00674 
00675 static void joy_polldev(JoystickImpl *This) {
00676     struct pollfd plfd;
00677     struct  js_event jse;
00678     TRACE("(%p)\n", This);
00679 
00680     if (This->joyfd==-1) {
00681         WARN("no device\n");
00682         return;
00683     }
00684     while (1)
00685     {
00686         LONG value;
00687         int inst_id = -1;
00688 
00689     plfd.fd = This->joyfd;
00690     plfd.events = POLLIN;
00691     if (poll(&plfd,1,0) != 1)
00692         return;
00693     /* we have one event, so we can read */
00694     if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
00695         return;
00696     }
00697         TRACE("js_event: type 0x%x, number %d, value %d\n",
00698               jse.type,jse.number,jse.value);
00699         if (jse.type & JS_EVENT_BUTTON)
00700         {
00701             if (jse.number >= This->devcaps.dwButtons) return;
00702 
00703             inst_id = DIDFT_MAKEINSTANCE(jse.number) | DIDFT_PSHBUTTON;
00704             This->js.rgbButtons[jse.number] = value = jse.value ? 0x80 : 0x00;
00705         }
00706         else if (jse.type & JS_EVENT_AXIS)
00707         {
00708             int number = This->axis_map[jse.number];    /* wine format object index */
00709 
00710             if (number < 0) return;
00711             inst_id = DIDFT_MAKEINSTANCE(number) | (number < 8 ? DIDFT_ABSAXIS : DIDFT_POV);
00712             value = joystick_map_axis(&This->props[id_to_object(This->base.data_format.wine_df, inst_id)], jse.value);
00713 
00714             TRACE("changing axis %d => %d\n", jse.number, number);
00715             switch (number)
00716             {
00717                 case 0: This->js.lX  = value; break;
00718                 case 1: This->js.lY  = value; break;
00719                 case 2: This->js.lZ  = value; break;
00720                 case 3: This->js.lRx = value; break;
00721                 case 4: This->js.lRy = value; break;
00722                 case 5: This->js.lRz = value; break;
00723                 case 6: This->js.rglSlider[0] = value; break;
00724                 case 7: This->js.rglSlider[1] = value; break;
00725                 case 8: case 9: case 10: case 11:
00726                 {
00727                     int idx = number - 8;
00728 
00729                     if (jse.number % 2)
00730                         This->povs[idx].y = jse.value;
00731                     else
00732                         This->povs[idx].x = jse.value;
00733 
00734                     This->js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
00735                     break;
00736                 }
00737                 default:
00738                     WARN("axis %d not supported\n", number);
00739             }
00740         }
00741         if (inst_id >= 0)
00742             queue_event((LPDIRECTINPUTDEVICE8A)This,
00743                         id_to_offset(&This->base.data_format, inst_id),
00744                         value, jse.time, This->base.dinput->evsequence++);
00745     }
00746 }
00747 
00748 /******************************************************************************
00749   *     GetDeviceState : returns the "state" of the joystick.
00750   *
00751   */
00752 static HRESULT WINAPI JoystickAImpl_GetDeviceState(
00753     LPDIRECTINPUTDEVICE8A iface,
00754     DWORD len,
00755     LPVOID ptr)
00756 {
00757     JoystickImpl *This = (JoystickImpl *)iface;
00758 
00759     TRACE("(%p,0x%08x,%p)\n", This, len, ptr);
00760 
00761     if (!This->base.acquired) {
00762         WARN("not acquired\n");
00763         return DIERR_NOTACQUIRED;
00764     }
00765 
00766     /* update joystick state */
00767     joy_polldev(This);
00768 
00769     /* convert and copy data to user supplied buffer */
00770     fill_DataFormat(ptr, len, &This->js, &This->base.data_format);
00771 
00772     return DI_OK;
00773 }
00774 
00775 /******************************************************************************
00776   *     SetProperty : change input device properties
00777   */
00778 static HRESULT WINAPI JoystickAImpl_SetProperty(
00779     LPDIRECTINPUTDEVICE8A iface,
00780     REFGUID rguid,
00781     LPCDIPROPHEADER ph)
00782 {
00783     JoystickImpl *This = (JoystickImpl *)iface;
00784     DWORD i;
00785 
00786     TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
00787 
00788     if (ph == NULL) {
00789         WARN("invalid parameter: ph == NULL\n");
00790         return DIERR_INVALIDPARAM;
00791     }
00792 
00793     if (TRACE_ON(dinput))
00794         _dump_DIPROPHEADER(ph);
00795 
00796     if (!HIWORD(rguid)) {
00797         switch (LOWORD(rguid)) {
00798         case (DWORD_PTR)DIPROP_RANGE: {
00799             LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
00800             if (ph->dwHow == DIPH_DEVICE) {
00801                 TRACE("proprange(%d,%d) all\n", pr->lMin, pr->lMax);
00802                 for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) {
00803                     This->props[i].lMin = pr->lMin;
00804                     This->props[i].lMax = pr->lMax;
00805                 }
00806             } else {
00807                 int obj = find_property(&This->base.data_format, ph);
00808 
00809                 TRACE("proprange(%d,%d) obj=%d\n", pr->lMin, pr->lMax, obj);
00810                 if (obj >= 0) {
00811                     This->props[obj].lMin = pr->lMin;
00812                     This->props[obj].lMax = pr->lMax;
00813                     return DI_OK;
00814                 }
00815             }
00816             break;
00817         }
00818         case (DWORD_PTR)DIPROP_DEADZONE: {
00819             LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
00820             if (ph->dwHow == DIPH_DEVICE) {
00821                 TRACE("deadzone(%d) all\n", pd->dwData);
00822                 for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++)
00823                     This->props[i].lDeadZone  = pd->dwData;
00824             } else {
00825                 int obj = find_property(&This->base.data_format, ph);
00826 
00827                 TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj);
00828                 if (obj >= 0) {
00829                     This->props[obj].lDeadZone  = pd->dwData;
00830                     return DI_OK;
00831                 }
00832             }
00833             break;
00834         }
00835         case (DWORD_PTR)DIPROP_SATURATION: {
00836             LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
00837             if (ph->dwHow == DIPH_DEVICE) {
00838                 TRACE("saturation(%d) all\n", pd->dwData);
00839                 for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++)
00840                     This->props[i].lSaturation = pd->dwData;
00841             } else {
00842                 int obj = find_property(&This->base.data_format, ph);
00843 
00844                 TRACE("saturation(%d) obj=%d\n", pd->dwData, obj);
00845                 if (obj >= 0) {
00846                     This->props[obj].lSaturation = pd->dwData;
00847                     return DI_OK;
00848                 }
00849             }
00850             break;
00851         }
00852         default:
00853             return IDirectInputDevice2AImpl_SetProperty(iface, rguid, ph);
00854         }
00855     }
00856 
00857     return DI_OK;
00858 }
00859 
00860 static HRESULT WINAPI JoystickAImpl_GetCapabilities(
00861     LPDIRECTINPUTDEVICE8A iface,
00862     LPDIDEVCAPS lpDIDevCaps)
00863 {
00864     JoystickImpl *This = (JoystickImpl *)iface;
00865     int size;
00866 
00867     TRACE("%p->(%p)\n",iface,lpDIDevCaps);
00868 
00869     if (lpDIDevCaps == NULL) {
00870         WARN("invalid pointer\n");
00871         return E_POINTER;
00872     }
00873 
00874     size = lpDIDevCaps->dwSize;
00875 
00876     if (!(size == sizeof(DIDEVCAPS) || size == sizeof(DIDEVCAPS_DX3))) {
00877         WARN("invalid parameter\n");
00878         return DIERR_INVALIDPARAM;
00879     }
00880 
00881     CopyMemory(lpDIDevCaps, &This->devcaps, size);
00882     lpDIDevCaps->dwSize = size;
00883 
00884     if (TRACE_ON(dinput))
00885         _dump_DIDEVCAPS(lpDIDevCaps);
00886 
00887     return DI_OK;
00888 }
00889 
00890 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
00891 {
00892     JoystickImpl *This = (JoystickImpl *)iface;
00893 
00894     TRACE("(%p)\n",This);
00895 
00896     if (!This->base.acquired) {
00897         WARN("not acquired\n");
00898         return DIERR_NOTACQUIRED;
00899     }
00900 
00901     joy_polldev(This);
00902     return DI_OK;
00903 }
00904 
00905 /******************************************************************************
00906   *     GetProperty : get input device properties
00907   */
00908 static HRESULT WINAPI JoystickAImpl_GetProperty(
00909     LPDIRECTINPUTDEVICE8A iface,
00910     REFGUID rguid,
00911     LPDIPROPHEADER pdiph)
00912 {
00913     JoystickImpl *This = (JoystickImpl *)iface;
00914 
00915     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph);
00916 
00917     if (TRACE_ON(dinput))
00918         _dump_DIPROPHEADER(pdiph);
00919 
00920     if (!HIWORD(rguid)) {
00921         switch (LOWORD(rguid)) {
00922         case (DWORD_PTR) DIPROP_RANGE: {
00923             LPDIPROPRANGE pr = (LPDIPROPRANGE)pdiph;
00924             int obj = find_property(&This->base.data_format, pdiph);
00925 
00926             /* The app is querying the current range of the axis
00927              * return the lMin and lMax values */
00928             if (obj >= 0) {
00929                 pr->lMin = This->props[obj].lMin;
00930                 pr->lMax = This->props[obj].lMax;
00931                 TRACE("range(%d, %d) obj=%d\n", pr->lMin, pr->lMax, obj);
00932                 return DI_OK;
00933             }
00934             break;
00935         }
00936         case (DWORD_PTR) DIPROP_DEADZONE: {
00937             LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
00938             int obj = find_property(&This->base.data_format, pdiph);
00939 
00940             if (obj >= 0) {
00941                 pd->dwData = This->props[obj].lDeadZone;
00942                 TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj);
00943                 return DI_OK;
00944             }
00945             break;
00946         }
00947         case (DWORD_PTR) DIPROP_SATURATION: {
00948             LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
00949             int obj = find_property(&This->base.data_format, pdiph);
00950 
00951             if (obj >= 0) {
00952                 pd->dwData = This->props[obj].lSaturation;
00953                 TRACE("saturation(%d) obj=%d\n", pd->dwData, obj);
00954                 return DI_OK;
00955             }
00956             break;
00957         }
00958         default:
00959             return IDirectInputDevice2AImpl_GetProperty(iface, rguid, pdiph);
00960         }
00961     }
00962 
00963     return DI_OK;
00964 }
00965 
00966 /******************************************************************************
00967   *     GetObjectInfo : get object info
00968   */
00969 static HRESULT WINAPI JoystickWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
00970         LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow)
00971 {
00972     static const WCHAR axisW[] = {'A','x','i','s',' ','%','d',0};
00973     static const WCHAR povW[] = {'P','O','V',' ','%','d',0};
00974     static const WCHAR buttonW[] = {'B','u','t','t','o','n',' ','%','d',0};
00975     HRESULT res;
00976 
00977     res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow);
00978     if (res != DI_OK) return res;
00979 
00980     if      (pdidoi->dwType & DIDFT_AXIS)
00981         sprintfW(pdidoi->tszName, axisW, DIDFT_GETINSTANCE(pdidoi->dwType));
00982     else if (pdidoi->dwType & DIDFT_POV)
00983         sprintfW(pdidoi->tszName, povW, DIDFT_GETINSTANCE(pdidoi->dwType));
00984     else if (pdidoi->dwType & DIDFT_BUTTON)
00985         sprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType));
00986 
00987     _dump_OBJECTINSTANCEW(pdidoi);
00988     return res;
00989 }
00990 
00991 static HRESULT WINAPI JoystickAImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,
00992         LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
00993 {
00994     HRESULT res;
00995     DIDEVICEOBJECTINSTANCEW didoiW;
00996     DWORD dwSize = pdidoi->dwSize;
00997 
00998     didoiW.dwSize = sizeof(didoiW);
00999     res = JoystickWImpl_GetObjectInfo((LPDIRECTINPUTDEVICE8W)iface, &didoiW, dwObj, dwHow);
01000     if (res != DI_OK) return res;
01001 
01002     memset(pdidoi, 0, pdidoi->dwSize);
01003     memcpy(pdidoi, &didoiW, FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, tszName));
01004     pdidoi->dwSize = dwSize;
01005     WideCharToMultiByte(CP_ACP, 0, didoiW.tszName, -1, pdidoi->tszName,
01006                         sizeof(pdidoi->tszName), NULL, NULL);
01007 
01008     return res;
01009 }
01010 
01011 /******************************************************************************
01012   *     GetDeviceInfo : get information about a device's identity
01013   */
01014 static HRESULT WINAPI JoystickAImpl_GetDeviceInfo(
01015     LPDIRECTINPUTDEVICE8A iface,
01016     LPDIDEVICEINSTANCEA pdidi)
01017 {
01018     JoystickImpl *This = (JoystickImpl *)iface;
01019 
01020     TRACE("(%p,%p)\n", iface, pdidi);
01021 
01022     if (pdidi == NULL) {
01023         WARN("invalid pointer\n");
01024         return E_POINTER;
01025     }
01026 
01027     if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) &&
01028         (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA))) {
01029         WARN("invalid parameter: pdidi->dwSize = %d\n", pdidi->dwSize);
01030         return DIERR_INVALIDPARAM;
01031     }
01032 
01033     /* Return joystick */
01034     pdidi->guidInstance = GUID_Joystick;
01035     pdidi->guidProduct = DInput_Wine_Joystick_GUID;
01036     /* we only support traditional joysticks for now */
01037     pdidi->dwDevType = This->devcaps.dwDevType;
01038     strcpy(pdidi->tszInstanceName, "Joystick");
01039     strcpy(pdidi->tszProductName, This->name);
01040     if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3A)) {
01041         pdidi->guidFFDriver = GUID_NULL;
01042         pdidi->wUsagePage = 0;
01043         pdidi->wUsage = 0;
01044     }
01045 
01046     return DI_OK;
01047 }
01048 
01049 /******************************************************************************
01050   *     GetDeviceInfo : get information about a device's identity
01051   */
01052 static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(
01053     LPDIRECTINPUTDEVICE8W iface,
01054     LPDIDEVICEINSTANCEW pdidi)
01055 {
01056     JoystickImpl *This = (JoystickImpl *)iface;
01057 
01058     TRACE("(%p,%p)\n", iface, pdidi);
01059 
01060     if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) &&
01061         (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW))) {
01062         WARN("invalid parameter: pdidi->dwSize = %d\n", pdidi->dwSize);
01063         return DIERR_INVALIDPARAM;
01064     }
01065 
01066     /* Return joystick */
01067     pdidi->guidInstance = GUID_Joystick;
01068     pdidi->guidProduct = DInput_Wine_Joystick_GUID;
01069     /* we only support traditional joysticks for now */
01070     pdidi->dwDevType = This->devcaps.dwDevType;
01071     MultiByteToWideChar(CP_ACP, 0, "Joystick", -1, pdidi->tszInstanceName, MAX_PATH);
01072     MultiByteToWideChar(CP_ACP, 0, This->name, -1, pdidi->tszProductName, MAX_PATH);
01073     if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3W)) {
01074         pdidi->guidFFDriver = GUID_NULL;
01075         pdidi->wUsagePage = 0;
01076         pdidi->wUsage = 0;
01077     }
01078 
01079     return DI_OK;
01080 }
01081 
01082 static const IDirectInputDevice8AVtbl JoystickAvt =
01083 {
01084     IDirectInputDevice2AImpl_QueryInterface,
01085     IDirectInputDevice2AImpl_AddRef,
01086         IDirectInputDevice2AImpl_Release,
01087     JoystickAImpl_GetCapabilities,
01088         IDirectInputDevice2AImpl_EnumObjects,
01089     JoystickAImpl_GetProperty,
01090     JoystickAImpl_SetProperty,
01091     JoystickAImpl_Acquire,
01092     JoystickAImpl_Unacquire,
01093     JoystickAImpl_GetDeviceState,
01094     IDirectInputDevice2AImpl_GetDeviceData,
01095     IDirectInputDevice2AImpl_SetDataFormat,
01096     IDirectInputDevice2AImpl_SetEventNotification,
01097     IDirectInputDevice2AImpl_SetCooperativeLevel,
01098     JoystickAImpl_GetObjectInfo,
01099     JoystickAImpl_GetDeviceInfo,
01100     IDirectInputDevice2AImpl_RunControlPanel,
01101     IDirectInputDevice2AImpl_Initialize,
01102     IDirectInputDevice2AImpl_CreateEffect,
01103     IDirectInputDevice2AImpl_EnumEffects,
01104     IDirectInputDevice2AImpl_GetEffectInfo,
01105     IDirectInputDevice2AImpl_GetForceFeedbackState,
01106     IDirectInputDevice2AImpl_SendForceFeedbackCommand,
01107     IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
01108     IDirectInputDevice2AImpl_Escape,
01109     JoystickAImpl_Poll,
01110     IDirectInputDevice2AImpl_SendDeviceData,
01111     IDirectInputDevice7AImpl_EnumEffectsInFile,
01112     IDirectInputDevice7AImpl_WriteEffectToFile,
01113     IDirectInputDevice8AImpl_BuildActionMap,
01114     IDirectInputDevice8AImpl_SetActionMap,
01115     IDirectInputDevice8AImpl_GetImageInfo
01116 };
01117 
01118 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
01119 # define XCAST(fun) (typeof(JoystickWvt.fun))
01120 #else
01121 # define XCAST(fun) (void*)
01122 #endif
01123 
01124 static const IDirectInputDevice8WVtbl JoystickWvt =
01125 {
01126     IDirectInputDevice2WImpl_QueryInterface,
01127     XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
01128         XCAST(Release)IDirectInputDevice2AImpl_Release,
01129     XCAST(GetCapabilities)JoystickAImpl_GetCapabilities,
01130         IDirectInputDevice2WImpl_EnumObjects,
01131     XCAST(GetProperty)JoystickAImpl_GetProperty,
01132     XCAST(SetProperty)JoystickAImpl_SetProperty,
01133     XCAST(Acquire)JoystickAImpl_Acquire,
01134     XCAST(Unacquire)JoystickAImpl_Unacquire,
01135     XCAST(GetDeviceState)JoystickAImpl_GetDeviceState,
01136     XCAST(GetDeviceData)IDirectInputDevice2AImpl_GetDeviceData,
01137     XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
01138     XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
01139     XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
01140         JoystickWImpl_GetObjectInfo,
01141     JoystickWImpl_GetDeviceInfo,
01142     XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
01143     XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
01144     XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
01145     IDirectInputDevice2WImpl_EnumEffects,
01146     IDirectInputDevice2WImpl_GetEffectInfo,
01147     XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
01148     XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
01149     XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
01150     XCAST(Escape)IDirectInputDevice2AImpl_Escape,
01151     XCAST(Poll)JoystickAImpl_Poll,
01152     XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
01153         IDirectInputDevice7WImpl_EnumEffectsInFile,
01154         IDirectInputDevice7WImpl_WriteEffectToFile,
01155         IDirectInputDevice8WImpl_BuildActionMap,
01156         IDirectInputDevice8WImpl_SetActionMap,
01157         IDirectInputDevice8WImpl_GetImageInfo
01158 };
01159 #undef XCAST
01160 
01161 #else  /* HAVE_LINUX_22_JOYSTICK_API */
01162 
01163 const struct dinput_device joystick_linux_device = {
01164   "Wine Linux joystick driver",
01165   NULL,
01166   NULL,
01167   NULL,
01168   NULL
01169 };
01170 
01171 #endif  /* HAVE_LINUX_22_JOYSTICK_API */

Generated on Sun May 27 2012 04:21:32 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.