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.\n");
184 ERR("CFNumberCreate failed.\n");
190 ERR("CFDictionaryCreateMutable failed.\n");
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.\n");
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
);
263 if (!tIOHIDDeviceRef
)
265 ERR("Invalid Device requested %i\n",id
);
269 str
= IOHIDDeviceGetProperty(tIOHIDDeviceRef
, CFSTR( kIOHIDProductKey
));
272 CFIndex len
= CFStringGetLength(str
);
275 CFStringGetCString(str
,name
,length
,kCFStringEncodingASCII
);
284 static void insert_sort_button(int header
, IOHIDElementRef tIOHIDElementRef
,
285 CFMutableArrayRef elementCFArrayRef
, int index
,
288 IOHIDElementRef targetElement
;
291 CFArraySetValueAtIndex(elementCFArrayRef
, header
+index
, NULL
);
292 targetElement
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( elementCFArrayRef
, header
+target
);
293 if (targetElement
== NULL
)
295 CFArraySetValueAtIndex(elementCFArrayRef
, header
+target
,tIOHIDElementRef
);
298 usage
= IOHIDElementGetUsage( targetElement
);
299 usage
--; /* usage 1 based index */
301 insert_sort_button(header
, targetElement
, elementCFArrayRef
, target
, usage
);
302 CFArraySetValueAtIndex(elementCFArrayRef
, header
+target
,tIOHIDElementRef
);
305 static void get_osx_device_elements(JoystickImpl
*device
, int axis_map
[8])
307 IOHIDDeviceRef tIOHIDDeviceRef
;
308 CFArrayRef gElementCFArrayRef
;
314 device
->elementCFArrayRef
= NULL
;
319 tIOHIDDeviceRef
= ( IOHIDDeviceRef
) CFArrayGetValueAtIndex( gDevices
, device
->id
);
321 if (!tIOHIDDeviceRef
)
324 gElementCFArrayRef
= IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef
,
327 if (gElementCFArrayRef
)
329 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
330 /* build our element array in the order that dinput expects */
331 device
->elementCFArrayRef
= CFArrayCreateMutable(NULL
,0,NULL
);
333 for ( idx
= 0; idx
< cnt
; idx
++ )
335 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
336 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
339 case kIOHIDElementTypeInput_Button
:
341 int usagePage
= IOHIDElementGetUsagePage( tIOHIDElementRef
);
342 if (usagePage
!= kHIDPage_Button
)
344 /* avoid strange elements found on the 360 controler */
350 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
+buttons
), tIOHIDElementRef
);
355 case kIOHIDElementTypeInput_Axis
:
357 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
361 case kIOHIDElementTypeInput_Misc
:
363 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
366 case kHIDUsage_GD_Hatswitch
:
368 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
), tIOHIDElementRef
);
372 case kHIDUsage_GD_Slider
:
376 /* fallthrough, sliders are axis */
380 case kHIDUsage_GD_Rx
:
381 case kHIDUsage_GD_Ry
:
382 case kHIDUsage_GD_Rz
:
384 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
385 axis_map
[axes
]=usage
;
390 FIXME("Unhandled usage %i\n",usage
);
395 FIXME("Unhandled type %i\n",eleType
);
400 device
->generic
.devcaps
.dwAxes
= axes
;
401 device
->generic
.devcaps
.dwButtons
= buttons
;
402 device
->generic
.devcaps
.dwPOVs
= povs
;
404 /* Sort buttons into correct order */
405 for (buttons
= 0; buttons
< device
->generic
.devcaps
.dwButtons
; buttons
++)
407 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( device
->elementCFArrayRef
, axes
+povs
+buttons
);
408 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
409 usage
--; /* usage is 1 indexed we need 0 indexed */
410 if (usage
== buttons
)
413 insert_sort_button(axes
+povs
, tIOHIDElementRef
, device
->elementCFArrayRef
,buttons
,usage
);
417 static void get_osx_device_elements_props(JoystickImpl
*device
)
419 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
421 if (gElementCFArrayRef
)
423 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
425 for ( idx
= 0; idx
< cnt
; idx
++ )
427 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
429 device
->generic
.props
[idx
].lDevMin
= IOHIDElementGetLogicalMin(tIOHIDElementRef
);
430 device
->generic
.props
[idx
].lDevMax
= IOHIDElementGetLogicalMax(tIOHIDElementRef
);
431 device
->generic
.props
[idx
].lMin
= 0;
432 device
->generic
.props
[idx
].lMax
= 0xffff;
433 device
->generic
.props
[idx
].lDeadZone
= 0;
434 device
->generic
.props
[idx
].lSaturation
= 0;
439 static void poll_osx_device_state(JoystickGenericImpl
*device_in
)
441 JoystickImpl
*device
= (JoystickImpl
*)device_in
;
442 IOHIDDeviceRef tIOHIDDeviceRef
;
443 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
445 TRACE("polling device %i\n",device
->id
);
450 tIOHIDDeviceRef
= ( IOHIDDeviceRef
) CFArrayGetValueAtIndex( gDevices
, device
->id
);
452 if (!tIOHIDDeviceRef
)
455 if (gElementCFArrayRef
)
460 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
462 for ( idx
= 0; idx
< cnt
; idx
++ )
464 IOHIDValueRef valueRef
;
466 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
467 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
471 case kIOHIDElementTypeInput_Button
:
474 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
475 val
= IOHIDValueGetIntegerValue(valueRef
);
476 device
->generic
.js
.rgbButtons
[button_idx
] = val
? 0x80 : 0x00;
480 case kIOHIDElementTypeInput_Misc
:
482 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
485 case kHIDUsage_GD_Hatswitch
:
487 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
488 val
= IOHIDValueGetIntegerValue(valueRef
);
490 device
->generic
.js
.rgdwPOV
[pov_idx
] = -1;
492 device
->generic
.js
.rgdwPOV
[pov_idx
] = val
* 4500;
499 case kHIDUsage_GD_Rx
:
500 case kHIDUsage_GD_Ry
:
501 case kHIDUsage_GD_Rz
:
502 case kHIDUsage_GD_Slider
:
504 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
505 val
= IOHIDValueGetIntegerValue(valueRef
);
509 device
->generic
.js
.lX
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
512 device
->generic
.js
.lY
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
515 device
->generic
.js
.lZ
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
517 case kHIDUsage_GD_Rx
:
518 device
->generic
.js
.lRx
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
520 case kHIDUsage_GD_Ry
:
521 device
->generic
.js
.lRy
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
523 case kHIDUsage_GD_Rz
:
524 device
->generic
.js
.lRz
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
526 case kHIDUsage_GD_Slider
:
527 device
->generic
.js
.rglSlider
[slider_idx
] = joystick_map_axis(&device
->generic
.props
[idx
], val
);
534 FIXME("unhandled usage %i\n",usage
);
539 FIXME("Unhandled type %i\n",eleType
);
545 static INT
find_joystick_devices(void)
547 static INT joystick_devices_count
= -1;
549 if (joystick_devices_count
!= -1) return joystick_devices_count
;
551 joystick_devices_count
= find_osx_devices();
553 return joystick_devices_count
;
556 static BOOL
joydev_enum_deviceA(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEA lpddi
, DWORD version
, int id
)
558 if (id
>= find_joystick_devices()) return FALSE
;
560 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
561 WARN("force feedback not supported\n");
565 if ((dwDevType
== 0) ||
566 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
567 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800)))
569 /* Return joystick */
570 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
571 lpddi
->guidInstance
.Data3
= id
;
572 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
573 /* we only support traditional joysticks for now */
574 if (version
>= 0x0800)
575 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
577 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
578 sprintf(lpddi
->tszInstanceName
, "Joystick %d", id
);
580 /* get the device name */
581 get_osx_device_name(id
, lpddi
->tszProductName
, MAX_PATH
);
583 lpddi
->guidFFDriver
= GUID_NULL
;
590 static BOOL
joydev_enum_deviceW(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEW lpddi
, DWORD version
, int id
)
595 if (id
>= find_joystick_devices()) return FALSE
;
597 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
598 WARN("force feedback not supported\n");
602 if ((dwDevType
== 0) ||
603 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
604 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800))) {
605 /* Return joystick */
606 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
607 lpddi
->guidInstance
.Data3
= id
;
608 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
609 /* we only support traditional joysticks for now */
610 if (version
>= 0x0800)
611 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
613 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
614 sprintf(friendly
, "Joystick %d", id
);
615 MultiByteToWideChar(CP_ACP
, 0, friendly
, -1, lpddi
->tszInstanceName
, MAX_PATH
);
616 /* get the device name */
617 get_osx_device_name(id
, name
, MAX_PATH
);
619 MultiByteToWideChar(CP_ACP
, 0, name
, -1, lpddi
->tszProductName
, MAX_PATH
);
620 lpddi
->guidFFDriver
= GUID_NULL
;
627 static HRESULT
alloc_device(REFGUID rguid
, const void *jvt
, IDirectInputImpl
*dinput
,
628 LPDIRECTINPUTDEVICEA
* pdev
, unsigned short index
)
631 JoystickImpl
* newDevice
;
634 LPDIDATAFORMAT df
= NULL
;
636 int axis_map
[8]; /* max axes */
637 int slider_count
= 0;
639 TRACE("%s %p %p %p %hu\n", debugstr_guid(rguid
), jvt
, dinput
, pdev
, index
);
641 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(JoystickImpl
));
642 if (newDevice
== 0) {
643 WARN("out of memory\n");
645 return DIERR_OUTOFMEMORY
;
648 newDevice
->id
= index
;
650 newDevice
->generic
.guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
651 newDevice
->generic
.guidInstance
.Data3
= index
;
652 newDevice
->generic
.guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
653 newDevice
->generic
.joy_polldev
= poll_osx_device_state
;
655 /* get the device name */
656 get_osx_device_name(index
, name
, MAX_PATH
);
657 TRACE("Name %s\n",name
);
659 /* copy the device name */
660 newDevice
->generic
.name
= HeapAlloc(GetProcessHeap(),0,strlen(name
) + 1);
661 strcpy(newDevice
->generic
.name
, name
);
663 memset(axis_map
, 0, sizeof(axis_map
));
664 get_osx_device_elements(newDevice
, axis_map
);
666 TRACE("%i axes %i buttons %i povs\n",newDevice
->generic
.devcaps
.dwAxes
,newDevice
->generic
.devcaps
.dwButtons
,newDevice
->generic
.devcaps
.dwPOVs
);
668 if (newDevice
->generic
.devcaps
.dwButtons
> 128)
670 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice
->generic
.devcaps
.dwButtons
);
671 newDevice
->generic
.devcaps
.dwButtons
= 128;
674 newDevice
->generic
.base
.lpVtbl
= jvt
;
675 newDevice
->generic
.base
.ref
= 1;
676 newDevice
->generic
.base
.dinput
= dinput
;
677 newDevice
->generic
.base
.guid
= *rguid
;
678 InitializeCriticalSection(&newDevice
->generic
.base
.crit
);
679 newDevice
->generic
.base
.crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": JoystickImpl*->generic.base.crit");
681 /* Create copy of default data format */
682 if (!(df
= HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2
.dwSize
))) goto FAILED
;
683 memcpy(df
, &c_dfDIJoystick2
, c_dfDIJoystick2
.dwSize
);
685 df
->dwNumObjs
= newDevice
->generic
.devcaps
.dwAxes
+ newDevice
->generic
.devcaps
.dwPOVs
+ newDevice
->generic
.devcaps
.dwButtons
;
686 if (!(df
->rgodf
= HeapAlloc(GetProcessHeap(), 0, df
->dwNumObjs
* df
->dwObjSize
))) goto FAILED
;
688 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwAxes
; i
++)
693 case kHIDUsage_GD_X
: wine_obj
= 0; break;
694 case kHIDUsage_GD_Y
: wine_obj
= 1; break;
695 case kHIDUsage_GD_Z
: wine_obj
= 2; break;
696 case kHIDUsage_GD_Rx
: wine_obj
= 3; break;
697 case kHIDUsage_GD_Ry
: wine_obj
= 4; break;
698 case kHIDUsage_GD_Rz
: wine_obj
= 5; break;
699 case kHIDUsage_GD_Slider
:
700 wine_obj
= 6 + slider_count
;
704 if (wine_obj
< 0 ) continue;
706 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[wine_obj
], df
->dwObjSize
);
707 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
710 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwPOVs
; i
++)
712 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 8], df
->dwObjSize
);
713 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_POV
;
716 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwButtons
; i
++)
718 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 12], df
->dwObjSize
);
719 df
->rgodf
[idx
].pguid
= &GUID_Button
;
720 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_PSHBUTTON
;
722 newDevice
->generic
.base
.data_format
.wine_df
= df
;
724 /* initialize default properties */
725 get_osx_device_elements_props(newDevice
);
727 IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A
)newDevice
->generic
.base
.dinput
);
729 newDevice
->generic
.devcaps
.dwSize
= sizeof(newDevice
->generic
.devcaps
);
730 newDevice
->generic
.devcaps
.dwFlags
= DIDC_ATTACHED
;
731 if (newDevice
->generic
.base
.dinput
->dwVersion
>= 0x0800)
732 newDevice
->generic
.devcaps
.dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
734 newDevice
->generic
.devcaps
.dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
735 newDevice
->generic
.devcaps
.dwFFSamplePeriod
= 0;
736 newDevice
->generic
.devcaps
.dwFFMinTimeResolution
= 0;
737 newDevice
->generic
.devcaps
.dwFirmwareRevision
= 0;
738 newDevice
->generic
.devcaps
.dwHardwareRevision
= 0;
739 newDevice
->generic
.devcaps
.dwFFDriverVersion
= 0;
741 if (TRACE_ON(dinput
)) {
742 _dump_DIDATAFORMAT(newDevice
->generic
.base
.data_format
.wine_df
);
743 _dump_DIDEVCAPS(&newDevice
->generic
.devcaps
);
746 *pdev
= (LPDIRECTINPUTDEVICEA
)newDevice
;
751 hr
= DIERR_OUTOFMEMORY
;
752 if (df
) HeapFree(GetProcessHeap(), 0, df
->rgodf
);
753 HeapFree(GetProcessHeap(), 0, df
);
754 release_DataFormat(&newDevice
->generic
.base
.data_format
);
755 HeapFree(GetProcessHeap(),0,newDevice
->generic
.name
);
756 HeapFree(GetProcessHeap(),0,newDevice
);
762 /******************************************************************************
763 * get_joystick_index : Get the joystick index from a given GUID
765 static unsigned short get_joystick_index(REFGUID guid
)
767 GUID wine_joystick
= DInput_Wine_OsX_Joystick_GUID
;
768 GUID dev_guid
= *guid
;
770 wine_joystick
.Data3
= 0;
773 /* for the standard joystick GUID use index 0 */
774 if(IsEqualGUID(&GUID_Joystick
,guid
)) return 0;
776 /* for the wine joystick GUIDs use the index stored in Data3 */
777 if(IsEqualGUID(&wine_joystick
, &dev_guid
)) return guid
->Data3
;
782 static HRESULT
joydev_create_deviceA(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEA
* pdev
)
784 unsigned short index
;
785 int joystick_devices_count
;
787 TRACE("%p %s %p %p\n",dinput
, debugstr_guid(rguid
), riid
, pdev
);
790 if ((joystick_devices_count
= find_joystick_devices()) == 0)
791 return DIERR_DEVICENOTREG
;
793 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
794 joystick_devices_count
&& index
< joystick_devices_count
)
796 if ((riid
== NULL
) ||
797 IsEqualGUID(&IID_IDirectInputDeviceA
, riid
) ||
798 IsEqualGUID(&IID_IDirectInputDevice2A
, riid
) ||
799 IsEqualGUID(&IID_IDirectInputDevice7A
, riid
) ||
800 IsEqualGUID(&IID_IDirectInputDevice8A
, riid
))
802 return alloc_device(rguid
, &JoystickAvt
, dinput
, pdev
, index
);
805 WARN("no interface\n");
806 return DIERR_NOINTERFACE
;
809 return DIERR_DEVICENOTREG
;
812 static HRESULT
joydev_create_deviceW(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEW
* pdev
)
814 unsigned short index
;
815 int joystick_devices_count
;
817 TRACE("%p %s %p %p\n",dinput
, debugstr_guid(rguid
), riid
, pdev
);
820 if ((joystick_devices_count
= find_joystick_devices()) == 0)
821 return DIERR_DEVICENOTREG
;
823 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
824 joystick_devices_count
&& index
< joystick_devices_count
)
826 if ((riid
== NULL
) ||
827 IsEqualGUID(&IID_IDirectInputDeviceW
, riid
) ||
828 IsEqualGUID(&IID_IDirectInputDevice2W
, riid
) ||
829 IsEqualGUID(&IID_IDirectInputDevice7W
, riid
) ||
830 IsEqualGUID(&IID_IDirectInputDevice8W
, riid
))
832 return alloc_device(rguid
, &JoystickWvt
, dinput
, (LPDIRECTINPUTDEVICEA
*)pdev
, index
);
834 WARN("no interface\n");
835 return DIERR_NOINTERFACE
;
838 WARN("invalid device GUID %s\n",debugstr_guid(rguid
));
839 return DIERR_DEVICENOTREG
;
842 const struct dinput_device joystick_osx_device
= {
843 "Wine OS X joystick driver",
846 joydev_create_deviceA
,
847 joydev_create_deviceW
850 static const IDirectInputDevice8AVtbl JoystickAvt
=
852 IDirectInputDevice2AImpl_QueryInterface
,
853 IDirectInputDevice2AImpl_AddRef
,
854 IDirectInputDevice2AImpl_Release
,
855 JoystickAGenericImpl_GetCapabilities
,
856 IDirectInputDevice2AImpl_EnumObjects
,
857 JoystickAGenericImpl_GetProperty
,
858 JoystickAGenericImpl_SetProperty
,
859 IDirectInputDevice2AImpl_Acquire
,
860 IDirectInputDevice2AImpl_Unacquire
,
861 JoystickAGenericImpl_GetDeviceState
,
862 IDirectInputDevice2AImpl_GetDeviceData
,
863 IDirectInputDevice2AImpl_SetDataFormat
,
864 IDirectInputDevice2AImpl_SetEventNotification
,
865 IDirectInputDevice2AImpl_SetCooperativeLevel
,
866 JoystickAGenericImpl_GetObjectInfo
,
867 JoystickAGenericImpl_GetDeviceInfo
,
868 IDirectInputDevice2AImpl_RunControlPanel
,
869 IDirectInputDevice2AImpl_Initialize
,
870 IDirectInputDevice2AImpl_CreateEffect
,
871 IDirectInputDevice2AImpl_EnumEffects
,
872 IDirectInputDevice2AImpl_GetEffectInfo
,
873 IDirectInputDevice2AImpl_GetForceFeedbackState
,
874 IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
875 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
876 IDirectInputDevice2AImpl_Escape
,
877 JoystickAGenericImpl_Poll
,
878 IDirectInputDevice2AImpl_SendDeviceData
,
879 IDirectInputDevice7AImpl_EnumEffectsInFile
,
880 IDirectInputDevice7AImpl_WriteEffectToFile
,
881 IDirectInputDevice8AImpl_BuildActionMap
,
882 IDirectInputDevice8AImpl_SetActionMap
,
883 IDirectInputDevice8AImpl_GetImageInfo
886 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
887 # define XCAST(fun) (typeof(JoystickWvt.fun))
889 # define XCAST(fun) (void*)
892 static const IDirectInputDevice8WVtbl JoystickWvt
=
894 IDirectInputDevice2WImpl_QueryInterface
,
895 XCAST(AddRef
)IDirectInputDevice2AImpl_AddRef
,
896 XCAST(Release
)IDirectInputDevice2AImpl_Release
,
897 XCAST(GetCapabilities
)JoystickAGenericImpl_GetCapabilities
,
898 IDirectInputDevice2WImpl_EnumObjects
,
899 XCAST(GetProperty
)JoystickAGenericImpl_GetProperty
,
900 XCAST(SetProperty
)JoystickAGenericImpl_SetProperty
,
901 XCAST(Acquire
)IDirectInputDevice2AImpl_Acquire
,
902 XCAST(Unacquire
)IDirectInputDevice2AImpl_Unacquire
,
903 XCAST(GetDeviceState
)JoystickAGenericImpl_GetDeviceState
,
904 XCAST(GetDeviceData
)IDirectInputDevice2AImpl_GetDeviceData
,
905 XCAST(SetDataFormat
)IDirectInputDevice2AImpl_SetDataFormat
,
906 XCAST(SetEventNotification
)IDirectInputDevice2AImpl_SetEventNotification
,
907 XCAST(SetCooperativeLevel
)IDirectInputDevice2AImpl_SetCooperativeLevel
,
908 JoystickWGenericImpl_GetObjectInfo
,
909 JoystickWGenericImpl_GetDeviceInfo
,
910 XCAST(RunControlPanel
)IDirectInputDevice2AImpl_RunControlPanel
,
911 XCAST(Initialize
)IDirectInputDevice2AImpl_Initialize
,
912 XCAST(CreateEffect
)IDirectInputDevice2AImpl_CreateEffect
,
913 IDirectInputDevice2WImpl_EnumEffects
,
914 IDirectInputDevice2WImpl_GetEffectInfo
,
915 XCAST(GetForceFeedbackState
)IDirectInputDevice2AImpl_GetForceFeedbackState
,
916 XCAST(SendForceFeedbackCommand
)IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
917 XCAST(EnumCreatedEffectObjects
)IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
918 XCAST(Escape
)IDirectInputDevice2AImpl_Escape
,
919 XCAST(Poll
)JoystickAGenericImpl_Poll
,
920 XCAST(SendDeviceData
)IDirectInputDevice2AImpl_SendDeviceData
,
921 IDirectInputDevice7WImpl_EnumEffectsInFile
,
922 IDirectInputDevice7WImpl_WriteEffectToFile
,
923 IDirectInputDevice8WImpl_BuildActionMap
,
924 IDirectInputDevice8WImpl_SetActionMap
,
925 IDirectInputDevice8WImpl_GetImageInfo
929 #else /* HAVE_IOHIDMANAGERCREATE */
931 const struct dinput_device joystick_osx_device
= {
932 "Wine OS X joystick driver",
939 #endif /* HAVE_IOHIDMANAGERCREATE */