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.");
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 insert_sort_button(int header
, IOHIDElementRef tIOHIDElementRef
,
288 CFMutableArrayRef elementCFArrayRef
, int index
,
291 IOHIDElementRef targetElement
;
294 CFArraySetValueAtIndex(elementCFArrayRef
, header
+index
, NULL
);
295 targetElement
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( elementCFArrayRef
, header
+target
);
296 if (targetElement
== NULL
)
298 CFArraySetValueAtIndex(elementCFArrayRef
, header
+target
,tIOHIDElementRef
);
301 usage
= IOHIDElementGetUsage( targetElement
);
302 usage
--; /* usage 1 based index */
304 insert_sort_button(header
, targetElement
, elementCFArrayRef
, target
, usage
);
305 CFArraySetValueAtIndex(elementCFArrayRef
, header
+target
,tIOHIDElementRef
);
308 static void get_osx_device_elements(JoystickImpl
*device
, int axis_map
[8])
310 IOHIDDeviceRef tIOHIDDeviceRef
;
311 CFArrayRef gElementCFArrayRef
;
317 device
->elementCFArrayRef
= NULL
;
322 tIOHIDDeviceRef
= ( IOHIDDeviceRef
) CFArrayGetValueAtIndex( gDevices
, device
->id
);
324 if (!tIOHIDDeviceRef
)
327 gElementCFArrayRef
= IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef
,
330 if (gElementCFArrayRef
)
332 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
333 /* build our element array in the order that dinput expects */
334 device
->elementCFArrayRef
= CFArrayCreateMutable(NULL
,0,NULL
);
336 for ( idx
= 0; idx
< cnt
; idx
++ )
338 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
339 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
342 case kIOHIDElementTypeInput_Button
:
344 int usagePage
= IOHIDElementGetUsagePage( tIOHIDElementRef
);
345 if (usagePage
!= kHIDPage_Button
)
347 /* avoid strange elements found on the 360 controler */
353 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
+buttons
), tIOHIDElementRef
);
358 case kIOHIDElementTypeInput_Axis
:
360 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
364 case kIOHIDElementTypeInput_Misc
:
366 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
369 case kHIDUsage_GD_Hatswitch
:
371 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, (axes
+povs
), tIOHIDElementRef
);
375 case kHIDUsage_GD_Slider
:
379 /* fallthrough, sliders are axis */
383 case kHIDUsage_GD_Rx
:
384 case kHIDUsage_GD_Ry
:
385 case kHIDUsage_GD_Rz
:
387 CFArrayInsertValueAtIndex(device
->elementCFArrayRef
, axes
, tIOHIDElementRef
);
388 axis_map
[axes
]=usage
;
393 FIXME("Unhandled usage %i\n",usage
);
398 FIXME("Unhandled type %i\n",eleType
);
403 device
->generic
.devcaps
.dwAxes
= axes
;
404 device
->generic
.devcaps
.dwButtons
= buttons
;
405 device
->generic
.devcaps
.dwPOVs
= povs
;
407 /* Sort buttons into correct order */
408 for (buttons
= 0; buttons
< device
->generic
.devcaps
.dwButtons
; buttons
++)
410 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( device
->elementCFArrayRef
, axes
+povs
+buttons
);
411 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
412 usage
--; /* usage is 1 indexed we need 0 indexed */
413 if (usage
== buttons
)
416 insert_sort_button(axes
+povs
, tIOHIDElementRef
, device
->elementCFArrayRef
,buttons
,usage
);
420 static void get_osx_device_elements_props(JoystickImpl
*device
)
422 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
424 if (gElementCFArrayRef
)
426 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
428 for ( idx
= 0; idx
< cnt
; idx
++ )
430 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
432 device
->generic
.props
[idx
].lDevMin
= IOHIDElementGetLogicalMin(tIOHIDElementRef
);
433 device
->generic
.props
[idx
].lDevMax
= IOHIDElementGetLogicalMax(tIOHIDElementRef
);
434 device
->generic
.props
[idx
].lMin
= 0;
435 device
->generic
.props
[idx
].lMax
= 0xffff;
436 device
->generic
.props
[idx
].lDeadZone
= 0;
437 device
->generic
.props
[idx
].lSaturation
= 0;
442 static void poll_osx_device_state(JoystickGenericImpl
*device_in
)
444 JoystickImpl
*device
= (JoystickImpl
*)device_in
;
445 IOHIDDeviceRef tIOHIDDeviceRef
;
446 CFArrayRef gElementCFArrayRef
= device
->elementCFArrayRef
;
448 TRACE("polling device %i\n",device
->id
);
453 tIOHIDDeviceRef
= ( IOHIDDeviceRef
) CFArrayGetValueAtIndex( gDevices
, device
->id
);
455 if (!tIOHIDDeviceRef
)
458 if (gElementCFArrayRef
)
463 CFIndex idx
, cnt
= CFArrayGetCount( gElementCFArrayRef
);
465 for ( idx
= 0; idx
< cnt
; idx
++ )
467 IOHIDValueRef valueRef
;
469 IOHIDElementRef tIOHIDElementRef
= ( IOHIDElementRef
) CFArrayGetValueAtIndex( gElementCFArrayRef
, idx
);
470 int eleType
= IOHIDElementGetType( tIOHIDElementRef
);
474 case kIOHIDElementTypeInput_Button
:
477 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
478 val
= IOHIDValueGetIntegerValue(valueRef
);
479 device
->generic
.js
.rgbButtons
[button_idx
] = val
? 0x80 : 0x00;
483 case kIOHIDElementTypeInput_Misc
:
485 uint32_t usage
= IOHIDElementGetUsage( tIOHIDElementRef
);
488 case kHIDUsage_GD_Hatswitch
:
490 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
491 val
= IOHIDValueGetIntegerValue(valueRef
);
493 device
->generic
.js
.rgdwPOV
[pov_idx
] = -1;
495 device
->generic
.js
.rgdwPOV
[pov_idx
] = val
* 4500;
502 case kHIDUsage_GD_Rx
:
503 case kHIDUsage_GD_Ry
:
504 case kHIDUsage_GD_Rz
:
505 case kHIDUsage_GD_Slider
:
507 IOHIDDeviceGetValue(tIOHIDDeviceRef
, tIOHIDElementRef
, &valueRef
);
508 val
= IOHIDValueGetIntegerValue(valueRef
);
512 device
->generic
.js
.lX
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
515 device
->generic
.js
.lY
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
518 device
->generic
.js
.lZ
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
520 case kHIDUsage_GD_Rx
:
521 device
->generic
.js
.lRx
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
523 case kHIDUsage_GD_Ry
:
524 device
->generic
.js
.lRy
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
526 case kHIDUsage_GD_Rz
:
527 device
->generic
.js
.lRz
= joystick_map_axis(&device
->generic
.props
[idx
], val
);
529 case kHIDUsage_GD_Slider
:
530 device
->generic
.js
.rglSlider
[slider_idx
] = joystick_map_axis(&device
->generic
.props
[idx
], val
);
537 FIXME("unhandled usage %i\n",usage
);
542 FIXME("Unhandled type %i\n",eleType
);
548 static INT
find_joystick_devices(void)
550 static INT joystick_devices_count
= -1;
552 if (joystick_devices_count
!= -1) return joystick_devices_count
;
554 joystick_devices_count
= find_osx_devices();
556 return joystick_devices_count
;
559 static BOOL
joydev_enum_deviceA(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEA lpddi
, DWORD version
, int id
)
561 if (id
>= find_joystick_devices()) return FALSE
;
563 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
564 WARN("force feedback not supported\n");
568 if ((dwDevType
== 0) ||
569 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
570 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800)))
572 /* Return joystick */
573 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
574 lpddi
->guidInstance
.Data3
= id
;
575 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
576 /* we only support traditional joysticks for now */
577 if (version
>= 0x0800)
578 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
580 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
581 sprintf(lpddi
->tszInstanceName
, "Joystick %d", id
);
583 /* get the device name */
584 get_osx_device_name(id
, lpddi
->tszProductName
, MAX_PATH
);
586 lpddi
->guidFFDriver
= GUID_NULL
;
593 static BOOL
joydev_enum_deviceW(DWORD dwDevType
, DWORD dwFlags
, LPDIDEVICEINSTANCEW lpddi
, DWORD version
, int id
)
598 if (id
>= find_joystick_devices()) return FALSE
;
600 if (dwFlags
& DIEDFL_FORCEFEEDBACK
) {
601 WARN("force feedback not supported\n");
605 if ((dwDevType
== 0) ||
606 ((dwDevType
== DIDEVTYPE_JOYSTICK
) && (version
> 0x0300 && version
< 0x0800)) ||
607 (((dwDevType
== DI8DEVCLASS_GAMECTRL
) || (dwDevType
== DI8DEVTYPE_JOYSTICK
)) && (version
>= 0x0800))) {
608 /* Return joystick */
609 lpddi
->guidInstance
= DInput_Wine_OsX_Joystick_GUID
;
610 lpddi
->guidInstance
.Data3
= id
;
611 lpddi
->guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
612 /* we only support traditional joysticks for now */
613 if (version
>= 0x0800)
614 lpddi
->dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
616 lpddi
->dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
617 sprintf(friendly
, "Joystick %d", id
);
618 MultiByteToWideChar(CP_ACP
, 0, friendly
, -1, lpddi
->tszInstanceName
, MAX_PATH
);
619 /* get the device name */
620 get_osx_device_name(id
, name
, MAX_PATH
);
622 MultiByteToWideChar(CP_ACP
, 0, name
, -1, lpddi
->tszProductName
, MAX_PATH
);
623 lpddi
->guidFFDriver
= GUID_NULL
;
630 static HRESULT
alloc_device(REFGUID rguid
, const void *jvt
, IDirectInputImpl
*dinput
,
631 LPDIRECTINPUTDEVICEA
* pdev
, unsigned short index
)
634 JoystickImpl
* newDevice
;
637 LPDIDATAFORMAT df
= NULL
;
639 int axis_map
[8]; /* max axes */
640 int slider_count
= 0;
642 TRACE("%s %p %p %p %hu\n", debugstr_guid(rguid
), jvt
, dinput
, pdev
, index
);
644 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(JoystickImpl
));
645 if (newDevice
== 0) {
646 WARN("out of memory\n");
648 return DIERR_OUTOFMEMORY
;
651 newDevice
->id
= index
;
653 newDevice
->generic
.guidProduct
= DInput_Wine_OsX_Joystick_GUID
;
654 newDevice
->generic
.joy_polldev
= poll_osx_device_state
;
656 /* get the device name */
657 get_osx_device_name(index
, name
, MAX_PATH
);
658 TRACE("Name %s\n",name
);
660 /* copy the device name */
661 newDevice
->generic
.name
= HeapAlloc(GetProcessHeap(),0,strlen(name
) + 1);
662 strcpy(newDevice
->generic
.name
, name
);
664 memset(axis_map
, 0, sizeof(axis_map
));
665 get_osx_device_elements(newDevice
, axis_map
);
667 TRACE("%i axes %i buttons %i povs\n",newDevice
->generic
.devcaps
.dwAxes
,newDevice
->generic
.devcaps
.dwButtons
,newDevice
->generic
.devcaps
.dwPOVs
);
669 if (newDevice
->generic
.devcaps
.dwButtons
> 128)
671 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice
->generic
.devcaps
.dwButtons
);
672 newDevice
->generic
.devcaps
.dwButtons
= 128;
675 newDevice
->generic
.base
.lpVtbl
= jvt
;
676 newDevice
->generic
.base
.ref
= 1;
677 newDevice
->generic
.base
.dinput
= dinput
;
678 newDevice
->generic
.base
.guid
= *rguid
;
679 InitializeCriticalSection(&newDevice
->generic
.base
.crit
);
680 newDevice
->generic
.base
.crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": JoystickImpl*->generic.base.crit");
682 /* Create copy of default data format */
683 if (!(df
= HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2
.dwSize
))) goto FAILED
;
684 memcpy(df
, &c_dfDIJoystick2
, c_dfDIJoystick2
.dwSize
);
686 df
->dwNumObjs
= newDevice
->generic
.devcaps
.dwAxes
+ newDevice
->generic
.devcaps
.dwPOVs
+ newDevice
->generic
.devcaps
.dwButtons
;
687 if (!(df
->rgodf
= HeapAlloc(GetProcessHeap(), 0, df
->dwNumObjs
* df
->dwObjSize
))) goto FAILED
;
689 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwAxes
; i
++)
694 case kHIDUsage_GD_X
: wine_obj
= 0; break;
695 case kHIDUsage_GD_Y
: wine_obj
= 1; break;
696 case kHIDUsage_GD_Z
: wine_obj
= 2; break;
697 case kHIDUsage_GD_Rx
: wine_obj
= 3; break;
698 case kHIDUsage_GD_Ry
: wine_obj
= 4; break;
699 case kHIDUsage_GD_Rz
: wine_obj
= 5; break;
700 case kHIDUsage_GD_Slider
:
701 wine_obj
= 6 + slider_count
;
705 if (wine_obj
< 0 ) continue;
707 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[wine_obj
], df
->dwObjSize
);
708 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(wine_obj
) | DIDFT_ABSAXIS
;
711 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwPOVs
; i
++)
713 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 8], df
->dwObjSize
);
714 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_POV
;
717 for (i
= 0; i
< newDevice
->generic
.devcaps
.dwButtons
; i
++)
719 memcpy(&df
->rgodf
[idx
], &c_dfDIJoystick2
.rgodf
[i
+ 12], df
->dwObjSize
);
720 df
->rgodf
[idx
].pguid
= &GUID_Button
;
721 df
->rgodf
[idx
++].dwType
= DIDFT_MAKEINSTANCE(i
) | DIDFT_PSHBUTTON
;
723 newDevice
->generic
.base
.data_format
.wine_df
= df
;
725 /* create default properties */
726 newDevice
->generic
.props
= HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2
.dwNumObjs
*sizeof(ObjProps
));
727 if (newDevice
->generic
.props
== 0)
730 /* initialize default properties */
731 get_osx_device_elements_props(newDevice
);
733 IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A
)newDevice
->generic
.base
.dinput
);
735 newDevice
->generic
.devcaps
.dwSize
= sizeof(newDevice
->generic
.devcaps
);
736 newDevice
->generic
.devcaps
.dwFlags
= DIDC_ATTACHED
;
737 if (newDevice
->generic
.base
.dinput
->dwVersion
>= 0x0800)
738 newDevice
->generic
.devcaps
.dwDevType
= DI8DEVTYPE_JOYSTICK
| (DI8DEVTYPEJOYSTICK_STANDARD
<< 8);
740 newDevice
->generic
.devcaps
.dwDevType
= DIDEVTYPE_JOYSTICK
| (DIDEVTYPEJOYSTICK_TRADITIONAL
<< 8);
741 newDevice
->generic
.devcaps
.dwFFSamplePeriod
= 0;
742 newDevice
->generic
.devcaps
.dwFFMinTimeResolution
= 0;
743 newDevice
->generic
.devcaps
.dwFirmwareRevision
= 0;
744 newDevice
->generic
.devcaps
.dwHardwareRevision
= 0;
745 newDevice
->generic
.devcaps
.dwFFDriverVersion
= 0;
747 if (TRACE_ON(dinput
)) {
748 _dump_DIDATAFORMAT(newDevice
->generic
.base
.data_format
.wine_df
);
749 _dump_DIDEVCAPS(&newDevice
->generic
.devcaps
);
752 *pdev
= (LPDIRECTINPUTDEVICEA
)newDevice
;
757 hr
= DIERR_OUTOFMEMORY
;
758 if (df
) HeapFree(GetProcessHeap(), 0, df
->rgodf
);
759 HeapFree(GetProcessHeap(), 0, df
);
760 release_DataFormat(&newDevice
->generic
.base
.data_format
);
761 HeapFree(GetProcessHeap(),0,newDevice
->generic
.name
);
762 HeapFree(GetProcessHeap(),0,newDevice
->generic
.props
);
763 HeapFree(GetProcessHeap(),0,newDevice
);
769 /******************************************************************************
770 * get_joystick_index : Get the joystick index from a given GUID
772 static unsigned short get_joystick_index(REFGUID guid
)
774 GUID wine_joystick
= DInput_Wine_OsX_Joystick_GUID
;
775 GUID dev_guid
= *guid
;
777 wine_joystick
.Data3
= 0;
780 /* for the standard joystick GUID use index 0 */
781 if(IsEqualGUID(&GUID_Joystick
,guid
)) return 0;
783 /* for the wine joystick GUIDs use the index stored in Data3 */
784 if(IsEqualGUID(&wine_joystick
, &dev_guid
)) return guid
->Data3
;
789 static HRESULT
joydev_create_deviceA(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEA
* pdev
)
791 unsigned short index
;
792 int joystick_devices_count
;
794 TRACE("%p %s %p %p\n",dinput
, debugstr_guid(rguid
), riid
, pdev
);
797 if ((joystick_devices_count
= find_joystick_devices()) == 0)
798 return DIERR_DEVICENOTREG
;
800 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
801 joystick_devices_count
&& index
< joystick_devices_count
)
803 if ((riid
== NULL
) ||
804 IsEqualGUID(&IID_IDirectInputDeviceA
, riid
) ||
805 IsEqualGUID(&IID_IDirectInputDevice2A
, riid
) ||
806 IsEqualGUID(&IID_IDirectInputDevice7A
, riid
) ||
807 IsEqualGUID(&IID_IDirectInputDevice8A
, riid
))
809 return alloc_device(rguid
, &JoystickAvt
, dinput
, pdev
, index
);
812 WARN("no interface\n");
813 return DIERR_NOINTERFACE
;
816 return DIERR_DEVICENOTREG
;
819 static HRESULT
joydev_create_deviceW(IDirectInputImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEW
* pdev
)
821 unsigned short index
;
822 int joystick_devices_count
;
824 TRACE("%p %s %p %p\n",dinput
, debugstr_guid(rguid
), riid
, pdev
);
827 if ((joystick_devices_count
= find_joystick_devices()) == 0)
828 return DIERR_DEVICENOTREG
;
830 if ((index
= get_joystick_index(rguid
)) < 0xffff &&
831 joystick_devices_count
&& index
< joystick_devices_count
)
833 if ((riid
== NULL
) ||
834 IsEqualGUID(&IID_IDirectInputDeviceW
, riid
) ||
835 IsEqualGUID(&IID_IDirectInputDevice2W
, riid
) ||
836 IsEqualGUID(&IID_IDirectInputDevice7W
, riid
) ||
837 IsEqualGUID(&IID_IDirectInputDevice8W
, riid
))
839 return alloc_device(rguid
, &JoystickWvt
, dinput
, (LPDIRECTINPUTDEVICEA
*)pdev
, index
);
841 WARN("no interface\n");
842 return DIERR_NOINTERFACE
;
845 WARN("invalid device GUID %s\n",debugstr_guid(rguid
));
846 return DIERR_DEVICENOTREG
;
849 const struct dinput_device joystick_osx_device
= {
850 "Wine OS X joystick driver",
853 joydev_create_deviceA
,
854 joydev_create_deviceW
857 static const IDirectInputDevice8AVtbl JoystickAvt
=
859 IDirectInputDevice2AImpl_QueryInterface
,
860 IDirectInputDevice2AImpl_AddRef
,
861 IDirectInputDevice2AImpl_Release
,
862 JoystickAGenericImpl_GetCapabilities
,
863 IDirectInputDevice2AImpl_EnumObjects
,
864 JoystickAGenericImpl_GetProperty
,
865 JoystickAGenericImpl_SetProperty
,
866 JoystickAGenericImpl_Acquire
,
867 JoystickAGenericImpl_Unacquire
,
868 JoystickAGenericImpl_GetDeviceState
,
869 IDirectInputDevice2AImpl_GetDeviceData
,
870 IDirectInputDevice2AImpl_SetDataFormat
,
871 IDirectInputDevice2AImpl_SetEventNotification
,
872 IDirectInputDevice2AImpl_SetCooperativeLevel
,
873 JoystickAGenericImpl_GetObjectInfo
,
874 JoystickAGenericImpl_GetDeviceInfo
,
875 IDirectInputDevice2AImpl_RunControlPanel
,
876 IDirectInputDevice2AImpl_Initialize
,
877 IDirectInputDevice2AImpl_CreateEffect
,
878 IDirectInputDevice2AImpl_EnumEffects
,
879 IDirectInputDevice2AImpl_GetEffectInfo
,
880 IDirectInputDevice2AImpl_GetForceFeedbackState
,
881 IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
882 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
883 IDirectInputDevice2AImpl_Escape
,
884 JoystickAGenericImpl_Poll
,
885 IDirectInputDevice2AImpl_SendDeviceData
,
886 IDirectInputDevice7AImpl_EnumEffectsInFile
,
887 IDirectInputDevice7AImpl_WriteEffectToFile
,
888 IDirectInputDevice8AImpl_BuildActionMap
,
889 IDirectInputDevice8AImpl_SetActionMap
,
890 IDirectInputDevice8AImpl_GetImageInfo
893 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
894 # define XCAST(fun) (typeof(JoystickWvt.fun))
896 # define XCAST(fun) (void*)
899 static const IDirectInputDevice8WVtbl JoystickWvt
=
901 IDirectInputDevice2WImpl_QueryInterface
,
902 XCAST(AddRef
)IDirectInputDevice2AImpl_AddRef
,
903 XCAST(Release
)IDirectInputDevice2AImpl_Release
,
904 XCAST(GetCapabilities
)JoystickAGenericImpl_GetCapabilities
,
905 IDirectInputDevice2WImpl_EnumObjects
,
906 XCAST(GetProperty
)JoystickAGenericImpl_GetProperty
,
907 XCAST(SetProperty
)JoystickAGenericImpl_SetProperty
,
908 XCAST(Acquire
)JoystickAGenericImpl_Acquire
,
909 XCAST(Unacquire
)JoystickAGenericImpl_Unacquire
,
910 XCAST(GetDeviceState
)JoystickAGenericImpl_GetDeviceState
,
911 XCAST(GetDeviceData
)IDirectInputDevice2AImpl_GetDeviceData
,
912 XCAST(SetDataFormat
)IDirectInputDevice2AImpl_SetDataFormat
,
913 XCAST(SetEventNotification
)IDirectInputDevice2AImpl_SetEventNotification
,
914 XCAST(SetCooperativeLevel
)IDirectInputDevice2AImpl_SetCooperativeLevel
,
915 JoystickWGenericImpl_GetObjectInfo
,
916 JoystickWGenericImpl_GetDeviceInfo
,
917 XCAST(RunControlPanel
)IDirectInputDevice2AImpl_RunControlPanel
,
918 XCAST(Initialize
)IDirectInputDevice2AImpl_Initialize
,
919 XCAST(CreateEffect
)IDirectInputDevice2AImpl_CreateEffect
,
920 IDirectInputDevice2WImpl_EnumEffects
,
921 IDirectInputDevice2WImpl_GetEffectInfo
,
922 XCAST(GetForceFeedbackState
)IDirectInputDevice2AImpl_GetForceFeedbackState
,
923 XCAST(SendForceFeedbackCommand
)IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
924 XCAST(EnumCreatedEffectObjects
)IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
925 XCAST(Escape
)IDirectInputDevice2AImpl_Escape
,
926 XCAST(Poll
)JoystickAGenericImpl_Poll
,
927 XCAST(SendDeviceData
)IDirectInputDevice2AImpl_SendDeviceData
,
928 IDirectInputDevice7WImpl_EnumEffectsInFile
,
929 IDirectInputDevice7WImpl_WriteEffectToFile
,
930 IDirectInputDevice8WImpl_BuildActionMap
,
931 IDirectInputDevice8WImpl_SetActionMap
,
932 IDirectInputDevice8WImpl_GetImageInfo
936 #else /* HAVE_IOHIDMANAGERCREATE */
938 const struct dinput_device joystick_osx_device
= {
939 "Wine OS X joystick driver",
946 #endif /* HAVE_IOHIDMANAGERCREATE */