1 /* DirectInput Joystick device for Mac OS/X
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2009 CodeWeavers, Aric Stewart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
26 #if defined(HAVE_CARBON_CARBON_H) && defined(HAVE_IOKIT_HID_IOHIDLIB_H)
27 #define LoadResource __carbon_LoadResource
28 #define CompareString __carbon_CompareString
29 #define GetCurrentThread __carbon_GetCurrentThread
30 #define GetCurrentProcess __carbon_GetCurrentProcess
31 #define AnimatePalette __carbon_AnimatePalette
32 #define EqualRgn __carbon_EqualRgn
33 #define FillRgn __carbon_FillRgn
34 #define FrameRgn __carbon_FrameRgn
35 #define GetPixel __carbon_GetPixel
36 #define InvertRgn __carbon_InvertRgn
37 #define LineTo __carbon_LineTo
38 #define OffsetRgn __carbon_OffsetRgn
39 #define PaintRgn __carbon_PaintRgn
40 #define Polygon __carbon_Polygon
41 #define ResizePalette __carbon_ResizePalette
42 #define SetRectRgn __carbon_SetRectRgn
43 #define ULONG __carbon_ULONG
44 #define E_INVALIDARG __carbon_E_INVALIDARG
45 #define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
46 #define E_HANDLE __carbon_E_HANDLE
47 #define E_ACCESSDENIED __carbon_E_ACCESSDENIED
48 #define E_UNEXPECTED __carbon_E_UNEXPECTED
49 #define E_FAIL __carbon_E_FAIL
50 #define E_ABORT __carbon_E_ABORT
51 #define E_POINTER __carbon_E_POINTER
52 #define E_NOINTERFACE __carbon_E_NOINTERFACE
53 #define E_NOTIMPL __carbon_E_NOTIMPL
54 #define S_FALSE __carbon_S_FALSE
55 #define S_OK __carbon_S_OK
56 #define HRESULT_FACILITY __carbon_HRESULT_FACILITY
57 #define IS_ERROR __carbon_IS_ERROR
58 #define FAILED __carbon_FAILED
59 #define SUCCEEDED __carbon_SUCCEEDED
60 #define MAKE_HRESULT __carbon_MAKE_HRESULT
61 #define HRESULT __carbon_HRESULT
62 #define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE
63 #include <Carbon/Carbon.h>
64 #include <IOKit/hid/IOHIDLib.h>
67 #undef GetCurrentThread
70 #undef GetCurrentProcess
96 #undef HRESULT_FACILITY
102 #undef STDMETHODCALLTYPE
103 #endif /* HAVE_CARBON_CARBON_H */
105 #include "wine/debug.h"
106 #include "wine/unicode.h"
109 #include "winerror.h"
113 #include "dinput_private.h"
114 #include "device_private.h"
115 #include "joystick_private.h"
117 WINE_DEFAULT_DEBUG_CHANNEL(dinput
);
119 #ifdef HAVE_IOHIDMANAGERCREATE
121 static IOHIDManagerRef gIOHIDManagerRef
= NULL
;
122 static CFArrayRef gDevices
= NULL
;
124 typedef struct JoystickImpl JoystickImpl
;
125 static const IDirectInputDevice8AVtbl JoystickAvt
;
126 static const IDirectInputDevice8WVtbl JoystickWvt
;
130 struct JoystickGenericImpl generic
;
134 CFMutableArrayRef elementCFArrayRef
;
138 static const GUID DInput_Wine_OsX_Joystick_GUID
= { /* 59CAD8F6-E617-41E2-8EB7-47B23EEEDC5A */
139 0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A}
142 static void CFSetApplierFunctionCopyToCFArray(const void *value
, void *context
)
144 CFArrayAppendValue( ( CFMutableArrayRef
) context
, value
);
147 static CFMutableDictionaryRef
creates_osx_device_match(int usage
)
149 CFMutableDictionaryRef result
;
151 result
= CFDictionaryCreateMutable( kCFAllocatorDefault
, 0,
152 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
156 int number
= kHIDPage_GenericDesktop
;
157 CFNumberRef pageCFNumberRef
= CFNumberCreate( kCFAllocatorDefault
,
158 kCFNumberIntType
, &number
);
160 if ( pageCFNumberRef
)
162 CFNumberRef usageCFNumberRef
;
164 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsagePageKey
),
166 CFRelease( pageCFNumberRef
);
168 usageCFNumberRef
= CFNumberCreate( kCFAllocatorDefault
,
169 kCFNumberIntType
, &usage
);
170 if ( usageCFNumberRef
)
172 CFDictionarySetValue( result
, CFSTR( kIOHIDDeviceUsageKey
),
174 CFRelease( usageCFNumberRef
);
178 ERR("CFNumberCreate() failed.");
184 ERR("CFNumberCreate failed.");
190 ERR("CFDictionaryCreateMutable failed.");
197 static int find_osx_devices(void)
200 CFMutableDictionaryRef result
;
204 gIOHIDManagerRef
= IOHIDManagerCreate( kCFAllocatorDefault
, 0L );
205 tIOReturn
= IOHIDManagerOpen( gIOHIDManagerRef
, 0L);
206 if ( kIOReturnSuccess
!= tIOReturn
)
208 ERR("Couldn’t open IOHIDManager.");
212 matching
= CFArrayCreateMutable( kCFAllocatorDefault
, 0,
213 &kCFTypeArrayCallBacks
);
215 /* build matching dictionary */
216 result
= creates_osx_device_match(kHIDPage_Sport
);
222 CFArrayAppendValue( ( CFMutableArrayRef
)matching
, result
);
223 result
= creates_osx_device_match(kHIDPage_Game
);
229 CFArrayAppendValue( ( CFMutableArrayRef
)matching
, result
);
231 IOHIDManagerSetDeviceMatchingMultiple( gIOHIDManagerRef
, matching
);
232 devset
= IOHIDManagerCopyDevices( gIOHIDManagerRef
);
236 gDevices
= CFArrayCreateMutable( kCFAllocatorDefault
, 0,
237 &kCFTypeArrayCallBacks
);
238 CFSetApplyFunction(devset
, CFSetApplierFunctionCopyToCFArray
, (void*)gDevices
);
239 count
= CFArrayGetCount( gDevices
);
241 count
= CFArrayGetCount( gDevices
);
243 TRACE("found %i device(s)\n",(int)count
);
250 static int get_osx_device_name(int id
, char *name
, int length
)
253 IOHIDDeviceRef tIOHIDDeviceRef
;
258 tIOHIDDeviceRef
= ( IOHIDDeviceRef
) CFArrayGetValueAtIndex( gDevices
, id
);
260 if (!tIOHIDDeviceRef
)
266 if (!tIOHIDDeviceRef
)
268 ERR("Invalid Device requested %i\n",id
);
272 str
= IOHIDDeviceGetProperty(tIOHIDDeviceRef
, CFSTR( kIOHIDProductKey
));
275 CFIndex len
= CFStringGetLength(str
);
278 CFStringGetCString(str
,name
,length
,kCFStringEncodingASCII
);
287 static void get_osx_device_elements(JoystickImpl
*device
, int axis_map
[8])
289 IOHIDDeviceRef tIOHIDDeviceRef
;
290 CFArrayRef gElementCFArrayRef
;
296 device
->elementCFArrayRef
= NULL
;
301 tIOHIDDeviceRef
= ( IOHIDDeviceRef
) CFArrayGetValueAtIndex( gDevices
, device
->id
);
303 if (!tIOHIDDeviceRef
)
306 gElementCFArrayRef
= IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef
,
309 if (gElementCFArrayRef
)
311 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
312 /* build our element array in the order that dinput expects */
313 device
->elementCFArrayRef
= CFArrayCreateMutable(NULL
,0,NULL
);
315 for ( idx
= 0; idx
< cnt
; idx
++ )
317 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
318 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
321 case kIOHIDElementTypeInput_Button
:
323 int usagePage
= IOHIDElementGetUsagePage( tIOHIDElementRef
);
324 if (usagePage
!= kHIDPage_Button
)
326 /* avoid strange elements found on the 360 controler */
332 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
+buttons
), tIOHIDElementRef
);
337 case kIOHIDElementTypeInput_Axis
:
339 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
343 case kIOHIDElementTypeInput_Misc
:
345 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
348 case kHIDUsage_GD_Hatswitch
:
350 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
), tIOHIDElementRef
);
354 case kHIDUsage_GD_Slider
:
358 /* fallthrough, sliders are axis */
362 case kHIDUsage_GD_Rx
:
363 case kHIDUsage_GD_Ry
:
364 case kHIDUsage_GD_Rz
:
366 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
367 axis_map
[axes
]=usage
;
372 FIXME("Unhandled usage %i\n",usage
);
377 FIXME("Unhandled type %i\n",eleType
);
382 device
->generic
.devcaps
.dwAxes
= axes
;
383 device
->generic
.devcaps
.dwButtons
= buttons
;
384 device
->generic
.devcaps
.dwPOVs
= povs
;
387 static void get_osx_device_elements_props(JoystickImpl
*device
)
389 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
391 if (gElementCFArrayRef
)
393 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
395 for ( idx
= 0; idx
< cnt
; idx
++ )
397 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
399 device
->generic
.props
[idx
].lDevMin
= IOHIDElementGetLogicalMin(tIOHIDElementRef
);
400 device
->generic
.props
[idx
].lDevMax
= IOHIDElementGetLogicalMax(tIOHIDElementRef
);
401 device
->generic
.props
[idx
].lMin
= 0;
402 device
->generic
.props
[idx
].lMax
= 0xffff;
403 device
->generic
.props
[idx
].lDeadZone
= 0;
404 device
->generic
.props
[idx
].lSaturation
= 0;
409 static void poll_osx_device_state(JoystickGenericImpl
*device_in
)
411 JoystickImpl
*device
= (JoystickImpl
*)device_in
;
412 IOHIDDeviceRef tIOHIDDeviceRef
;
413 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
415 TRACE("polling device %i\n",device
->id
);
420 tIOHIDDeviceRef
= ( IOHIDDeviceRef
) CFArrayGetValueAtIndex( gDevices
, device
->id
);
422 if (!tIOHIDDeviceRef
)
425 if (gElementCFArrayRef
)
430 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
432 for ( idx
= 0; idx
< cnt
; idx
++ )
434 IOHIDValueRef valueRef
;
436 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
437 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
441 case kIOHIDElementTypeInput_Button
:
444 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
445 val
= IOHIDValueGetIntegerValue(valueRef
);
446 device
->generic
.js
.rgbButtons
[button_idx
] = val
? 0x80 : 0x00;
450 case kIOHIDElementTypeInput_Misc
:
452 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
455 case kHIDUsage_GD_Hatswitch
:
457 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
458 val
= IOHIDValueGetIntegerValue(valueRef
);
460 device
->generic
.js
.rgdwPOV
[pov_idx
] = -1;
462 device
->generic
.js
.rgdwPOV
[pov_idx
] = val
* 4500;
469 case kHIDUsage_GD_Rx
:
470 case kHIDUsage_GD_Ry
:
471 case kHIDUsage_GD_Rz
:
472 case kHIDUsage_GD_Slider
:
474 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
475 val
= IOHIDValueGetIntegerValue(valueRef
);
479 device
->generic
.js
.lX
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
482 device
->generic
.js
.lY
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
485 device
->generic
.js
.lZ
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
487 case kHIDUsage_GD_Rx
:
488 device
->generic
.js
.lRx
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
490 case kHIDUsage_GD_Ry
:
491 device
->generic
.js
.lRy
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
493 case kHIDUsage_GD_Rz
:
494 device
->generic
.js
.lRz
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
496 case kHIDUsage_GD_Slider
:
497 device
->generic
.js
.rglSlider
[slider_idx
] = joystick_map_axis(&device
->generic
.props
[idx
], val
);
504 FIXME("unhandled usage %i\n",usage
);
509 FIXME("Unhandled type %i\n",eleType
);
515 static INT
find_joystick_devices(void)
517 static INT joystick_devices_count
= -1;
519 if (joystick_devices_count
!= -1) return joystick_devices_count
;
521 joystick_devices_count
= find_osx_devices();
523 return joystick_devices_count
;
526 static BOOL
joydev_enum_deviceA(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEA lpddi
, DWORD version
, int id
)
528 if (id
>= find_joystick_devices()) return FALSE
;
530 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
531 WARN("force feedback not supported\n");
535 if ((dwDevType
== 0) ||
536 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
537 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800)))
539 /* Return joystick */
540 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
541 lpddi
->guidInstance
.Data3
= id
;
542 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
543 /* we only support traditional joysticks for now */
544 if (version
>= 0x0800)
545 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
547 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
548 sprintf(lpddi
->tszInstanceName
, "Joystick %d", id
);
550 /* get the device name */
551 get_osx_device_name(id
, lpddi
->tszProductName
, MAX_PATH
);
553 lpddi
->guidFFDriver
= GUID_NULL
;
560 static BOOL
joydev_enum_deviceW(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEW lpddi
, DWORD version
, int id
)
565 if (id
>= find_joystick_devices()) return FALSE
;
567 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
568 WARN("force feedback not supported\n");
572 if ((dwDevType
== 0) ||
573 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
574 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800))) {
575 /* Return joystick */
576 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
577 lpddi
->guidInstance
.Data3
= id
;
578 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
579 /* we only support traditional joysticks for now */
580 if (version
>= 0x0800)
581 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
583 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
584 sprintf(friendly
, "Joystick %d", id
);
585 MultiByteToWideChar(CP_ACP
, 0, friendly
, -1, lpddi
->tszInstanceName
, MAX_PATH
);
586 /* get the device name */
587 get_osx_device_name(id
, name
, MAX_PATH
);
589 MultiByteToWideChar(CP_ACP
, 0, name
, -1, lpddi
->tszProductName
, MAX_PATH
);
590 lpddi
->guidFFDriver
= GUID_NULL
;
597 static HRESULT
alloc_device(REFGUID rguid
, const void *jvt
, IDirectInputImpl
*dinput
,
598 LPDIRECTINPUTDEVICEA
* pdev
, unsigned short index
)
601 JoystickImpl
* newDevice
;
604 LPDIDATAFORMAT df
= NULL
;
606 int axis_map
[8]; /* max axes */
607 int slider_count
= 0;
609 TRACE("%s %p %p %p %hu\n", debugstr_guid(rguid
), jvt
, dinput
, pdev
, index
);
611 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(JoystickImpl
));
612 if (newDevice
== 0) {
613 WARN("out of memory\n");
615 return DIERR_OUTOFMEMORY
;
618 newDevice
->id
= index
;
620 newDevice
->generic
.guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
621 newDevice
->generic
.joy_polldev
= poll_osx_device_state
;
623 /* get the device name */
624 get_osx_device_name(index
, name
, MAX_PATH
);
625 TRACE("Name %s\n",name
);
627 /* copy the device name */
628 newDevice
->generic
.name
= HeapAlloc(GetProcessHeap(),0,strlen(name
) + 1);
629 strcpy(newDevice
->generic
.name
, name
);
631 memset(axis_map
, 0, sizeof(axis_map
));
632 get_osx_device_elements(newDevice
, axis_map
);
634 TRACE("%i axes %i buttons %i povs\n",newDevice
->generic
.devcaps
.dwAxes
,newDevice
->generic
.devcaps
.dwButtons
,newDevice
->generic
.devcaps
.dwPOVs
);
636 if (newDevice
->generic
.devcaps
.dwButtons
> 128)
638 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice
->generic
.devcaps
.dwButtons
);
639 newDevice
->generic
.devcaps
.dwButtons
= 128;
642 newDevice
->generic
.base
.lpVtbl
= jvt
;
643 newDevice
->generic
.base
.ref
= 1;
644 newDevice
->generic
.base
.dinput
= dinput
;
645 newDevice
->generic
.base
.guid
= *rguid
;
646 InitializeCriticalSection(&newDevice
->generic
.base
.crit
);
647 newDevice
->generic
.base
.crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": JoystickImpl*->generic.base.crit");
649 /* Create copy of default data format */
650 if (!(df
= HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2
.dwSize
))) goto FAILED
;
651 memcpy(df
, &c_dfDIJoystick2
, c_dfDIJoystick2
.dwSize
);
653 df
->dwNumObjs
= newDevice
->generic
.devcaps
.dwAxes
+ newDevice
->generic
.devcaps
.dwPOVs
+ newDevice
->generic
.devcaps
.dwButtons
;
654 if (!(df
->rgodf
= HeapAlloc(GetProcessHeap(), 0, df
->dwNumObjs
* df
->dwObjSize
))) goto FAILED
;
656 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwAxes
; i
++)
661 case kHIDUsage_GD_X
: wine_obj
= 0; break;
662 case kHIDUsage_GD_Y
: wine_obj
= 1; break;
663 case kHIDUsage_GD_Z
: wine_obj
= 2; break;
664 case kHIDUsage_GD_Rx
: wine_obj
= 3; break;
665 case kHIDUsage_GD_Ry
: wine_obj
= 4; break;
666 case kHIDUsage_GD_Rz
: wine_obj
= 5; break;
667 case kHIDUsage_GD_Slider
:
668 wine_obj
= 6 + slider_count
;
672 if (wine_obj
< 0 ) continue;
674 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[wine_obj
], df
->dwObjSize
);
675 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
678 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwPOVs
; i
++)
680 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 8], df
->dwObjSize
);
681 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_POV
;
684 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwButtons
; i
++)
686 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 12], df
->dwObjSize
);
687 df
->rgodf
[idx
].pguid
= &GUID_Button
;
688 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_PSHBUTTON
;
690 newDevice
->generic
.base
.data_format
.wine_df
= df
;
692 /* create default properties */
693 newDevice
->generic
.props
= HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2
.dwNumObjs
*sizeof(ObjProps
));
694 if (newDevice
->generic
.props
== 0)
697 /* initialize default properties */
698 get_osx_device_elements_props(newDevice
);
700 IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A
)newDevice
->generic
.base
.dinput
);
702 newDevice
->generic
.devcaps
.dwSize
= sizeof(newDevice
->generic
.devcaps
);
703 newDevice
->generic
.devcaps
.dwFlags
= DIDC_ATTACHED
;
704 if (newDevice
->generic
.base
.dinput
->dwVersion
>= 0x0800)
705 newDevice
->generic
.devcaps
.dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
707 newDevice
->generic
.devcaps
.dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
708 newDevice
->generic
.devcaps
.dwFFSamplePeriod
= 0;
709 newDevice
->generic
.devcaps
.dwFFMinTimeResolution
= 0;
710 newDevice
->generic
.devcaps
.dwFirmwareRevision
= 0;
711 newDevice
->generic
.devcaps
.dwHardwareRevision
= 0;
712 newDevice
->generic
.devcaps
.dwFFDriverVersion
= 0;
714 if (TRACE_ON(dinput
)) {
715 _dump_DIDATAFORMAT(newDevice
->generic
.base
.data_format
.wine_df
);
716 _dump_DIDEVCAPS(&newDevice
->generic
.devcaps
);
719 *pdev
= (LPDIRECTINPUTDEVICEA
)newDevice
;
724 hr
= DIERR_OUTOFMEMORY
;
725 if (df
) HeapFree(GetProcessHeap(), 0, df
->rgodf
);
726 HeapFree(GetProcessHeap(), 0, df
);
727 release_DataFormat(&newDevice
->generic
.base
.data_format
);
728 HeapFree(GetProcessHeap(),0,newDevice
->generic
.name
);
729 HeapFree(GetProcessHeap(),0,newDevice
->generic
.props
);
730 HeapFree(GetProcessHeap(),0,newDevice
);
736 /******************************************************************************
737 * get_joystick_index : Get the joystick index from a given GUID
739 static unsigned short get_joystick_index(REFGUID guid
)
741 GUID wine_joystick
= DInput_Wine_OsX_Joystick_GUID
;
742 GUID dev_guid
= *guid
;
744 wine_joystick
.Data3
= 0;
747 /* for the standard joystick GUID use index 0 */
748 if(IsEqualGUID(&GUID_Joystick
,guid
)) return 0;
750 /* for the wine joystick GUIDs use the index stored in Data3 */
751 if(IsEqualGUID(&wine_joystick
, &dev_guid
)) return guid
->Data3
;
756 static HRESULT
joydev_create_deviceA(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEA
* pdev
)
758 unsigned short index
;
759 int joystick_devices_count
;
761 TRACE("%p %s %p %p\n",dinput
, debugstr_guid(rguid
), riid
, pdev
);
764 if ((joystick_devices_count
= find_joystick_devices()) == 0)
765 return DIERR_DEVICENOTREG
;
767 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
768 joystick_devices_count
&& index
< joystick_devices_count
)
770 if ((riid
== NULL
) ||
771 IsEqualGUID(&IID_IDirectInputDeviceA
, riid
) ||
772 IsEqualGUID(&IID_IDirectInputDevice2A
, riid
) ||
773 IsEqualGUID(&IID_IDirectInputDevice7A
, riid
) ||
774 IsEqualGUID(&IID_IDirectInputDevice8A
, riid
))
776 return alloc_device(rguid
, &JoystickAvt
, dinput
, pdev
, index
);
779 WARN("no interface\n");
780 return DIERR_NOINTERFACE
;
783 return DIERR_DEVICENOTREG
;
786 static HRESULT
joydev_create_deviceW(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEW
* pdev
)
788 unsigned short index
;
789 int joystick_devices_count
;
791 TRACE("%p %s %p %p\n",dinput
, debugstr_guid(rguid
), riid
, pdev
);
794 if ((joystick_devices_count
= find_joystick_devices()) == 0)
795 return DIERR_DEVICENOTREG
;
797 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
798 joystick_devices_count
&& index
< joystick_devices_count
)
800 if ((riid
== NULL
) ||
801 IsEqualGUID(&IID_IDirectInputDeviceW
, riid
) ||
802 IsEqualGUID(&IID_IDirectInputDevice2W
, riid
) ||
803 IsEqualGUID(&IID_IDirectInputDevice7W
, riid
) ||
804 IsEqualGUID(&IID_IDirectInputDevice8W
, riid
))
806 return alloc_device(rguid
, &JoystickWvt
, dinput
, (LPDIRECTINPUTDEVICEA
*)pdev
, index
);
808 WARN("no interface\n");
809 return DIERR_NOINTERFACE
;
812 WARN("invalid device GUID %s\n",debugstr_guid(rguid
));
813 return DIERR_DEVICENOTREG
;
816 const struct dinput_device joystick_osx_device
= {
817 "Wine OS X joystick driver",
820 joydev_create_deviceA
,
821 joydev_create_deviceW
824 static const IDirectInputDevice8AVtbl JoystickAvt
=
826 IDirectInputDevice2AImpl_QueryInterface
,
827 IDirectInputDevice2AImpl_AddRef
,
828 IDirectInputDevice2AImpl_Release
,
829 JoystickAGenericImpl_GetCapabilities
,
830 IDirectInputDevice2AImpl_EnumObjects
,
831 JoystickAGenericImpl_GetProperty
,
832 JoystickAGenericImpl_SetProperty
,
833 JoystickAGenericImpl_Acquire
,
834 JoystickAGenericImpl_Unacquire
,
835 JoystickAGenericImpl_GetDeviceState
,
836 IDirectInputDevice2AImpl_GetDeviceData
,
837 IDirectInputDevice2AImpl_SetDataFormat
,
838 IDirectInputDevice2AImpl_SetEventNotification
,
839 IDirectInputDevice2AImpl_SetCooperativeLevel
,
840 JoystickAGenericImpl_GetObjectInfo
,
841 JoystickAGenericImpl_GetDeviceInfo
,
842 IDirectInputDevice2AImpl_RunControlPanel
,
843 IDirectInputDevice2AImpl_Initialize
,
844 IDirectInputDevice2AImpl_CreateEffect
,
845 IDirectInputDevice2AImpl_EnumEffects
,
846 IDirectInputDevice2AImpl_GetEffectInfo
,
847 IDirectInputDevice2AImpl_GetForceFeedbackState
,
848 IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
849 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
850 IDirectInputDevice2AImpl_Escape
,
851 JoystickAGenericImpl_Poll
,
852 IDirectInputDevice2AImpl_SendDeviceData
,
853 IDirectInputDevice7AImpl_EnumEffectsInFile
,
854 IDirectInputDevice7AImpl_WriteEffectToFile
,
855 IDirectInputDevice8AImpl_BuildActionMap
,
856 IDirectInputDevice8AImpl_SetActionMap
,
857 IDirectInputDevice8AImpl_GetImageInfo
860 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
861 # define XCAST(fun) (typeof(JoystickWvt.fun))
863 # define XCAST(fun) (void*)
866 static const IDirectInputDevice8WVtbl JoystickWvt
=
868 IDirectInputDevice2WImpl_QueryInterface
,
869 XCAST(AddRef
)IDirectInputDevice2AImpl_AddRef
,
870 XCAST(Release
)IDirectInputDevice2AImpl_Release
,
871 XCAST(GetCapabilities
)JoystickAGenericImpl_GetCapabilities
,
872 IDirectInputDevice2WImpl_EnumObjects
,
873 XCAST(GetProperty
)JoystickAGenericImpl_GetProperty
,
874 XCAST(SetProperty
)JoystickAGenericImpl_SetProperty
,
875 XCAST(Acquire
)JoystickAGenericImpl_Acquire
,
876 XCAST(Unacquire
)JoystickAGenericImpl_Unacquire
,
877 XCAST(GetDeviceState
)JoystickAGenericImpl_GetDeviceState
,
878 XCAST(GetDeviceData
)IDirectInputDevice2AImpl_GetDeviceData
,
879 XCAST(SetDataFormat
)IDirectInputDevice2AImpl_SetDataFormat
,
880 XCAST(SetEventNotification
)IDirectInputDevice2AImpl_SetEventNotification
,
881 XCAST(SetCooperativeLevel
)IDirectInputDevice2AImpl_SetCooperativeLevel
,
882 JoystickWGenericImpl_GetObjectInfo
,
883 JoystickWGenericImpl_GetDeviceInfo
,
884 XCAST(RunControlPanel
)IDirectInputDevice2AImpl_RunControlPanel
,
885 XCAST(Initialize
)IDirectInputDevice2AImpl_Initialize
,
886 XCAST(CreateEffect
)IDirectInputDevice2AImpl_CreateEffect
,
887 IDirectInputDevice2WImpl_EnumEffects
,
888 IDirectInputDevice2WImpl_GetEffectInfo
,
889 XCAST(GetForceFeedbackState
)IDirectInputDevice2AImpl_GetForceFeedbackState
,
890 XCAST(SendForceFeedbackCommand
)IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
891 XCAST(EnumCreatedEffectObjects
)IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
892 XCAST(Escape
)IDirectInputDevice2AImpl_Escape
,
893 XCAST(Poll
)JoystickAGenericImpl_Poll
,
894 XCAST(SendDeviceData
)IDirectInputDevice2AImpl_SendDeviceData
,
895 IDirectInputDevice7WImpl_EnumEffectsInFile
,
896 IDirectInputDevice7WImpl_WriteEffectToFile
,
897 IDirectInputDevice8WImpl_BuildActionMap
,
898 IDirectInputDevice8WImpl_SetActionMap
,
899 IDirectInputDevice8WImpl_GetImageInfo
903 #else /* HAVE_IOHIDMANAGERCREATE */
905 const struct dinput_device joystick_osx_device
= {
906 "Wine OS X joystick driver",
913 #endif /* HAVE_IOHIDMANAGERCREATE */