Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenjoystick_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
1.7.6.1
|