blob: 40268ad22398e25e078eec6f1e0d4f7f11900a72 [file] [log] [blame]
Aric Stewart225a4942009-03-10 14:59:20 -05001/* DirectInput Joystick device for Mac OS/X
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2009 CodeWeavers, Aric Stewart
7 *
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.
12 *
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.
17 *
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
21 */
22
23#include "config.h"
24#include "wine/port.h"
25
Charles Davisa2e11b42011-01-24 11:32:15 -070026#if defined(HAVE_IOKIT_HID_IOHIDLIB_H)
Aric Stewart225a4942009-03-10 14:59:20 -050027#define ULONG __carbon_ULONG
28#define E_INVALIDARG __carbon_E_INVALIDARG
29#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
30#define E_HANDLE __carbon_E_HANDLE
31#define E_ACCESSDENIED __carbon_E_ACCESSDENIED
32#define E_UNEXPECTED __carbon_E_UNEXPECTED
33#define E_FAIL __carbon_E_FAIL
34#define E_ABORT __carbon_E_ABORT
35#define E_POINTER __carbon_E_POINTER
36#define E_NOINTERFACE __carbon_E_NOINTERFACE
37#define E_NOTIMPL __carbon_E_NOTIMPL
38#define S_FALSE __carbon_S_FALSE
39#define S_OK __carbon_S_OK
40#define HRESULT_FACILITY __carbon_HRESULT_FACILITY
41#define IS_ERROR __carbon_IS_ERROR
42#define FAILED __carbon_FAILED
43#define SUCCEEDED __carbon_SUCCEEDED
44#define MAKE_HRESULT __carbon_MAKE_HRESULT
45#define HRESULT __carbon_HRESULT
46#define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE
Aric Stewart225a4942009-03-10 14:59:20 -050047#include <IOKit/hid/IOHIDLib.h>
Aric Stewart225a4942009-03-10 14:59:20 -050048#undef ULONG
49#undef E_INVALIDARG
50#undef E_OUTOFMEMORY
51#undef E_HANDLE
52#undef E_ACCESSDENIED
53#undef E_UNEXPECTED
54#undef E_FAIL
55#undef E_ABORT
56#undef E_POINTER
57#undef E_NOINTERFACE
58#undef E_NOTIMPL
59#undef S_FALSE
60#undef S_OK
61#undef HRESULT_FACILITY
62#undef IS_ERROR
63#undef FAILED
64#undef SUCCEEDED
65#undef MAKE_HRESULT
66#undef HRESULT
67#undef STDMETHODCALLTYPE
Charles Davisa2e11b42011-01-24 11:32:15 -070068#endif /* HAVE_IOKIT_HID_IOHIDLIB_H */
Aric Stewart225a4942009-03-10 14:59:20 -050069
70#include "wine/debug.h"
71#include "wine/unicode.h"
72#include "windef.h"
73#include "winbase.h"
74#include "winerror.h"
75#include "winreg.h"
76#include "dinput.h"
77
78#include "dinput_private.h"
79#include "device_private.h"
80#include "joystick_private.h"
81
Alexandre Julliard81f8c032009-03-11 16:49:55 +010082#ifdef HAVE_IOHIDMANAGERCREATE
Aric Stewart225a4942009-03-10 14:59:20 -050083
Andrew Talbotbf3d67c2011-11-12 22:49:26 +000084WINE_DEFAULT_DEBUG_CHANNEL(dinput);
85
Aric Stewart225a4942009-03-10 14:59:20 -050086static IOHIDManagerRef gIOHIDManagerRef = NULL;
Zach Smithfa5f61f2010-09-20 22:25:27 -040087static CFArrayRef gCollections = NULL;
Aric Stewart225a4942009-03-10 14:59:20 -050088
89typedef struct JoystickImpl JoystickImpl;
90static const IDirectInputDevice8AVtbl JoystickAvt;
91static const IDirectInputDevice8WVtbl JoystickWvt;
92
93struct JoystickImpl
94{
95 struct JoystickGenericImpl generic;
96
97 /* osx private */
98 int id;
99 CFMutableArrayRef elementCFArrayRef;
100 ObjProps **propmap;
101};
102
Vitaliy Margolen399be342011-01-09 15:43:48 -0700103static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
104{
Vitaliy Margolen6b304802011-01-09 15:44:19 -0700105 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface),
106 JoystickGenericImpl, base), JoystickImpl, generic);
Vitaliy Margolen399be342011-01-09 15:43:48 -0700107}
108static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
109{
Vitaliy Margolen6b304802011-01-09 15:44:19 -0700110 return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
111 JoystickGenericImpl, base), JoystickImpl, generic);
Vitaliy Margolen399be342011-01-09 15:43:48 -0700112}
113
Aric Stewart225a4942009-03-10 14:59:20 -0500114static const GUID DInput_Wine_OsX_Joystick_GUID = { /* 59CAD8F6-E617-41E2-8EB7-47B23EEEDC5A */
115 0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A}
116};
117
118static void CFSetApplierFunctionCopyToCFArray(const void *value, void *context)
119{
120 CFArrayAppendValue( ( CFMutableArrayRef ) context, value );
121}
122
123static CFMutableDictionaryRef creates_osx_device_match(int usage)
124{
125 CFMutableDictionaryRef result;
126
127 result = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
128 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
129
130 if ( result )
131 {
132 int number = kHIDPage_GenericDesktop;
133 CFNumberRef pageCFNumberRef = CFNumberCreate( kCFAllocatorDefault,
134 kCFNumberIntType, &number);
135
136 if ( pageCFNumberRef )
137 {
138 CFNumberRef usageCFNumberRef;
139
140 CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsagePageKey ),
141 pageCFNumberRef );
142 CFRelease( pageCFNumberRef );
143
144 usageCFNumberRef = CFNumberCreate( kCFAllocatorDefault,
145 kCFNumberIntType, &usage);
146 if ( usageCFNumberRef )
147 {
148 CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsageKey ),
149 usageCFNumberRef );
150 CFRelease( usageCFNumberRef );
151 }
152 else
153 {
Francois Gouget40363a22009-03-12 10:10:44 +0100154 ERR("CFNumberCreate() failed.\n");
Aric Stewart225a4942009-03-10 14:59:20 -0500155 return NULL;
156 }
157 }
158 else
159 {
Francois Gouget40363a22009-03-12 10:10:44 +0100160 ERR("CFNumberCreate failed.\n");
Aric Stewart225a4942009-03-10 14:59:20 -0500161 return NULL;
162 }
163 }
164 else
165 {
Francois Gouget40363a22009-03-12 10:10:44 +0100166 ERR("CFDictionaryCreateMutable failed.\n");
Aric Stewart225a4942009-03-10 14:59:20 -0500167 return NULL;
168 }
169
170 return result;
171}
172
Zach Smithfa5f61f2010-09-20 22:25:27 -0400173static CFIndex find_top_level(IOHIDDeviceRef tIOHIDDeviceRef, CFArrayRef topLevels)
174{
175 CFArrayRef gElementCFArrayRef;
176 CFIndex numTops = 0;
177
178 if (!tIOHIDDeviceRef)
179 return 0;
180
181 gElementCFArrayRef = IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRef, NULL, 0);
182
183 if (gElementCFArrayRef)
184 {
185 CFIndex idx, cnt = CFArrayGetCount(gElementCFArrayRef);
186 for (idx=0; idx<cnt; idx++)
187 {
188 IOHIDElementRef tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gElementCFArrayRef, idx);
189 int eleType = IOHIDElementGetType(tIOHIDElementRef);
190
191 /* Check for top-level gaming device collections */
192 if (eleType == kIOHIDElementTypeCollection && IOHIDElementGetParent(tIOHIDElementRef) == 0)
193 {
194 int tUsagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
195 int tUsage = IOHIDElementGetUsage(tIOHIDElementRef);
196
197 if (tUsagePage == kHIDPage_GenericDesktop &&
198 (tUsage == kHIDUsage_GD_Joystick || tUsage == kHIDUsage_GD_GamePad))
199 {
200 CFArrayAppendValue((CFMutableArrayRef)topLevels, tIOHIDElementRef);
201 numTops++;
202 }
203 }
204 }
205 }
206 return numTops;
207}
208
209static void get_element_children(IOHIDElementRef tElement, CFArrayRef childElements)
210{
211 CFIndex idx, cnt;
212 CFArrayRef tElementChildrenArray = IOHIDElementGetChildren(tElement);
213
214 cnt = CFArrayGetCount(tElementChildrenArray);
215 if (cnt < 1)
216 return;
217
218 /* Either add the element to the array or grab its children */
219 for (idx=0; idx<cnt; idx++)
220 {
221 IOHIDElementRef tChildElementRef;
222
223 tChildElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(tElementChildrenArray, idx);
224 if (IOHIDElementGetType(tChildElementRef) == kIOHIDElementTypeCollection)
225 get_element_children(tChildElementRef, childElements);
226 else
227 CFArrayAppendValue((CFMutableArrayRef)childElements, tChildElementRef);
228 }
229}
230
Aric Stewart225a4942009-03-10 14:59:20 -0500231static int find_osx_devices(void)
232{
233 IOReturn tIOReturn;
234 CFMutableDictionaryRef result;
235 CFSetRef devset;
236 CFArrayRef matching;
237
238 gIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, 0L );
239 tIOReturn = IOHIDManagerOpen( gIOHIDManagerRef, 0L);
240 if ( kIOReturnSuccess != tIOReturn )
241 {
Francois Gouget14e03d72009-04-20 15:10:22 +0200242 ERR("Couldn't open IOHIDManager.\n");
Aric Stewart225a4942009-03-10 14:59:20 -0500243 return 0;
244 }
245
246 matching = CFArrayCreateMutable( kCFAllocatorDefault, 0,
247 &kCFTypeArrayCallBacks );
248
249 /* build matching dictionary */
Zach Smithfa5f61f2010-09-20 22:25:27 -0400250 result = creates_osx_device_match(kHIDUsage_GD_Joystick);
Aric Stewart225a4942009-03-10 14:59:20 -0500251 if (!result)
252 {
253 CFRelease(matching);
254 return 0;
255 }
256 CFArrayAppendValue( ( CFMutableArrayRef )matching, result );
Zach Smithfa5f61f2010-09-20 22:25:27 -0400257 result = creates_osx_device_match(kHIDUsage_GD_GamePad);
Aric Stewart225a4942009-03-10 14:59:20 -0500258 if (!result)
259 {
260 CFRelease(matching);
261 return 0;
262 }
263 CFArrayAppendValue( ( CFMutableArrayRef )matching, result );
264
265 IOHIDManagerSetDeviceMatchingMultiple( gIOHIDManagerRef, matching);
266 devset = IOHIDManagerCopyDevices( gIOHIDManagerRef );
267 if (devset)
268 {
Zach Smithfa5f61f2010-09-20 22:25:27 -0400269 CFIndex countDevices, countCollections, idx;
270 CFArrayRef gDevices = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
Aric Stewart225a4942009-03-10 14:59:20 -0500271 CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, (void*)gDevices);
Aric Stewart225a4942009-03-10 14:59:20 -0500272 CFRelease( devset);
Zach Smithfa5f61f2010-09-20 22:25:27 -0400273 countDevices = CFArrayGetCount(gDevices);
Aric Stewart225a4942009-03-10 14:59:20 -0500274
Zach Smithfa5f61f2010-09-20 22:25:27 -0400275 gCollections = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
276 if (!gCollections)
277 return 0;
Aric Stewart225a4942009-03-10 14:59:20 -0500278
Zach Smithfa5f61f2010-09-20 22:25:27 -0400279 countCollections = 0;
280 for (idx = 0; idx < countDevices; idx++)
281 {
282 CFIndex tTop;
283 IOHIDDeviceRef tDevice;
284
285 tDevice = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDevices, idx);
286 tTop = find_top_level(tDevice, gCollections);
287 countCollections += tTop;
288 }
289
290 CFRelease(gDevices);
291
292 TRACE("found %i device(s), %i collection(s)\n",(int)countDevices,(int)countCollections);
293 return (int)countCollections;
Aric Stewart225a4942009-03-10 14:59:20 -0500294 }
295 return 0;
296}
297
298static int get_osx_device_name(int id, char *name, int length)
299{
300 CFStringRef str;
Zach Smithfa5f61f2010-09-20 22:25:27 -0400301 IOHIDElementRef tIOHIDElementRef;
Aric Stewart225a4942009-03-10 14:59:20 -0500302 IOHIDDeviceRef tIOHIDDeviceRef;
303
Zach Smithfa5f61f2010-09-20 22:25:27 -0400304 if (!gCollections)
Aric Stewart225a4942009-03-10 14:59:20 -0500305 return 0;
306
Zach Smithfa5f61f2010-09-20 22:25:27 -0400307 tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, id);
308
309 if (!tIOHIDElementRef)
310 {
311 ERR("Invalid Element requested %i\n",id);
312 return 0;
313 }
314
315 tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDElementRef);
Aric Stewart225a4942009-03-10 14:59:20 -0500316
Aric Stewart225a4942009-03-10 14:59:20 -0500317 if (name)
318 name[0] = 0;
319
320 if (!tIOHIDDeviceRef)
321 {
322 ERR("Invalid Device requested %i\n",id);
323 return 0;
324 }
325
326 str = IOHIDDeviceGetProperty(tIOHIDDeviceRef, CFSTR( kIOHIDProductKey ));
327 if (str)
328 {
329 CFIndex len = CFStringGetLength(str);
330 if (length >= len)
331 {
332 CFStringGetCString(str,name,length,kCFStringEncodingASCII);
333 return len;
334 }
335 else
336 return (len+1);
337 }
338 return 0;
339}
340
Aric Stewart79859cb2009-03-12 08:03:04 -0500341static void insert_sort_button(int header, IOHIDElementRef tIOHIDElementRef,
342 CFMutableArrayRef elementCFArrayRef, int index,
343 int target)
344{
345 IOHIDElementRef targetElement;
346 int usage;
347
348 CFArraySetValueAtIndex(elementCFArrayRef, header+index, NULL);
349 targetElement = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, header+target);
350 if (targetElement == NULL)
351 {
352 CFArraySetValueAtIndex(elementCFArrayRef, header+target,tIOHIDElementRef);
353 return;
354 }
355 usage = IOHIDElementGetUsage( targetElement );
356 usage --; /* usage 1 based index */
357
358 insert_sort_button(header, targetElement, elementCFArrayRef, target, usage);
359 CFArraySetValueAtIndex(elementCFArrayRef, header+target,tIOHIDElementRef);
360}
361
Aric Stewart08388a32009-03-10 14:59:56 -0500362static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
Aric Stewart225a4942009-03-10 14:59:20 -0500363{
Zach Smithfa5f61f2010-09-20 22:25:27 -0400364 IOHIDElementRef tIOHIDElementRef;
Aric Stewart225a4942009-03-10 14:59:20 -0500365 CFArrayRef gElementCFArrayRef;
366 DWORD axes = 0;
Aric Stewartae16df62009-03-10 15:00:03 -0500367 DWORD sliders = 0;
Aric Stewart225a4942009-03-10 14:59:20 -0500368 DWORD buttons = 0;
369 DWORD povs = 0;
370
371 device->elementCFArrayRef = NULL;
372
Zach Smithfa5f61f2010-09-20 22:25:27 -0400373 if (!gCollections)
Aric Stewart225a4942009-03-10 14:59:20 -0500374 return;
375
Zach Smithfa5f61f2010-09-20 22:25:27 -0400376 tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(gCollections, device->id);
Aric Stewart225a4942009-03-10 14:59:20 -0500377
Zach Smithfa5f61f2010-09-20 22:25:27 -0400378 if (!tIOHIDElementRef)
Aric Stewart225a4942009-03-10 14:59:20 -0500379 return;
380
Zach Smithfa5f61f2010-09-20 22:25:27 -0400381 gElementCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
382 get_element_children(tIOHIDElementRef, gElementCFArrayRef);
Aric Stewart225a4942009-03-10 14:59:20 -0500383
384 if (gElementCFArrayRef)
385 {
386 CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
387 /* build our element array in the order that dinput expects */
388 device->elementCFArrayRef = CFArrayCreateMutable(NULL,0,NULL);
389
390 for ( idx = 0; idx < cnt; idx++ )
391 {
392 IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
393 int eleType = IOHIDElementGetType( tIOHIDElementRef );
394 switch(eleType)
395 {
396 case kIOHIDElementTypeInput_Button:
397 {
Aric Stewart6bbec8e2009-03-11 15:06:31 -0500398 int usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef );
399 if (usagePage != kHIDPage_Button)
400 {
Frédéric Delanoyf932abf2011-07-30 12:03:08 +0200401 /* avoid strange elements found on the 360 controller */
Aric Stewart6bbec8e2009-03-11 15:06:31 -0500402 continue;
403 }
404
Aric Stewart225a4942009-03-10 14:59:20 -0500405 if (buttons < 128)
406 {
407 CFArrayInsertValueAtIndex(device->elementCFArrayRef, (axes+povs+buttons), tIOHIDElementRef);
408 buttons++;
409 }
410 break;
411 }
Aric Stewart0e7eba12009-03-10 14:59:28 -0500412 case kIOHIDElementTypeInput_Axis:
413 {
414 CFArrayInsertValueAtIndex(device->elementCFArrayRef, axes, tIOHIDElementRef);
415 axes++;
416 break;
417 }
Aric Stewart87d61ab2009-03-10 14:59:35 -0500418 case kIOHIDElementTypeInput_Misc:
419 {
420 uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
421 switch(usage)
422 {
423 case kHIDUsage_GD_Hatswitch:
424 {
425 CFArrayInsertValueAtIndex(device->elementCFArrayRef, (axes+povs), tIOHIDElementRef);
426 povs++;
427 break;
428 }
Aric Stewartae16df62009-03-10 15:00:03 -0500429 case kHIDUsage_GD_Slider:
430 sliders ++;
431 if (sliders > 2)
432 break;
433 /* fallthrough, sliders are axis */
Aric Stewartffbd6a72009-03-10 14:59:41 -0500434 case kHIDUsage_GD_X:
435 case kHIDUsage_GD_Y:
436 case kHIDUsage_GD_Z:
Aric Stewart17daca72009-03-10 14:59:49 -0500437 case kHIDUsage_GD_Rx:
438 case kHIDUsage_GD_Ry:
439 case kHIDUsage_GD_Rz:
Aric Stewartffbd6a72009-03-10 14:59:41 -0500440 {
441 CFArrayInsertValueAtIndex(device->elementCFArrayRef, axes, tIOHIDElementRef);
Aric Stewart08388a32009-03-10 14:59:56 -0500442 axis_map[axes]=usage;
Aric Stewartffbd6a72009-03-10 14:59:41 -0500443 axes++;
444 break;
445 }
Aric Stewart87d61ab2009-03-10 14:59:35 -0500446 default:
447 FIXME("Unhandled usage %i\n",usage);
448 }
449 break;
450 }
Aric Stewart225a4942009-03-10 14:59:20 -0500451 default:
452 FIXME("Unhandled type %i\n",eleType);
453 }
454 }
455 }
456
457 device->generic.devcaps.dwAxes = axes;
458 device->generic.devcaps.dwButtons = buttons;
459 device->generic.devcaps.dwPOVs = povs;
Aric Stewart79859cb2009-03-12 08:03:04 -0500460
461 /* Sort buttons into correct order */
462 for (buttons = 0; buttons < device->generic.devcaps.dwButtons; buttons++)
463 {
464 IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( device->elementCFArrayRef, axes+povs+buttons);
465 uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
466 usage --; /* usage is 1 indexed we need 0 indexed */
467 if (usage == buttons)
468 continue;
469
470 insert_sort_button(axes+povs, tIOHIDElementRef, device->elementCFArrayRef,buttons,usage);
471 }
Aric Stewart225a4942009-03-10 14:59:20 -0500472}
473
474static void get_osx_device_elements_props(JoystickImpl *device)
475{
476 CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;
477
478 if (gElementCFArrayRef)
479 {
480 CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
481
482 for ( idx = 0; idx < cnt; idx++ )
483 {
484 IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
485
486 device->generic.props[idx].lDevMin = IOHIDElementGetLogicalMin(tIOHIDElementRef);
487 device->generic.props[idx].lDevMax = IOHIDElementGetLogicalMax(tIOHIDElementRef);
488 device->generic.props[idx].lMin = 0;
489 device->generic.props[idx].lMax = 0xffff;
490 device->generic.props[idx].lDeadZone = 0;
491 device->generic.props[idx].lSaturation = 0;
492 }
493 }
494}
495
Vitaliy Margolen7d650d02011-01-03 07:25:11 -0700496static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
Aric Stewart225a4942009-03-10 14:59:20 -0500497{
Vitaliy Margolen399be342011-01-09 15:43:48 -0700498 JoystickImpl *device = impl_from_IDirectInputDevice8A(iface);
Zach Smithfa5f61f2010-09-20 22:25:27 -0400499 IOHIDElementRef tIOHIDTopElementRef;
Aric Stewart225a4942009-03-10 14:59:20 -0500500 IOHIDDeviceRef tIOHIDDeviceRef;
501 CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;
502
503 TRACE("polling device %i\n",device->id);
504
Zach Smithfa5f61f2010-09-20 22:25:27 -0400505 if (!gCollections)
Aric Stewart225a4942009-03-10 14:59:20 -0500506 return;
507
Zach Smithfa5f61f2010-09-20 22:25:27 -0400508 tIOHIDTopElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gCollections, device->id);
509 tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDTopElementRef);
Aric Stewart225a4942009-03-10 14:59:20 -0500510
511 if (!tIOHIDDeviceRef)
512 return;
513
514 if (gElementCFArrayRef)
515 {
516 int button_idx = 0;
Aric Stewart87d61ab2009-03-10 14:59:35 -0500517 int pov_idx = 0;
Aric Stewartae16df62009-03-10 15:00:03 -0500518 int slider_idx = 0;
Jonas Maebe90d86082011-06-16 21:11:46 +0200519 int inst_id;
Aric Stewart225a4942009-03-10 14:59:20 -0500520 CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
521
522 for ( idx = 0; idx < cnt; idx++ )
523 {
524 IOHIDValueRef valueRef;
Jonas Maebe90d86082011-06-16 21:11:46 +0200525 int val, oldVal, newVal;
Aric Stewart225a4942009-03-10 14:59:20 -0500526 IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
527 int eleType = IOHIDElementGetType( tIOHIDElementRef );
528
529 switch(eleType)
530 {
531 case kIOHIDElementTypeInput_Button:
532 if(button_idx < 128)
533 {
534 IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
535 val = IOHIDValueGetIntegerValue(valueRef);
Jonas Maebe90d86082011-06-16 21:11:46 +0200536 newVal = val ? 0x80 : 0x0;
537 oldVal = device->generic.js.rgbButtons[button_idx];
538 device->generic.js.rgbButtons[button_idx] = newVal;
539 if (oldVal != newVal)
540 {
541 inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON;
542 queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
543 }
Aric Stewart225a4942009-03-10 14:59:20 -0500544 button_idx ++;
545 }
546 break;
Aric Stewart87d61ab2009-03-10 14:59:35 -0500547 case kIOHIDElementTypeInput_Misc:
548 {
549 uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
550 switch(usage)
551 {
552 case kHIDUsage_GD_Hatswitch:
553 {
554 IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
555 val = IOHIDValueGetIntegerValue(valueRef);
Jonas Maebe90d86082011-06-16 21:11:46 +0200556 oldVal = device->generic.js.rgdwPOV[pov_idx];
Aric Stewart87d61ab2009-03-10 14:59:35 -0500557 if (val >= 8)
Jonas Maebe90d86082011-06-16 21:11:46 +0200558 newVal = -1;
Aric Stewart87d61ab2009-03-10 14:59:35 -0500559 else
Jonas Maebe90d86082011-06-16 21:11:46 +0200560 newVal = val * 4500;
561 device->generic.js.rgdwPOV[pov_idx] = newVal;
562 if (oldVal != newVal)
563 {
564 inst_id = DIDFT_MAKEINSTANCE(pov_idx) | DIDFT_POV;
565 queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
566 }
Aric Stewart87d61ab2009-03-10 14:59:35 -0500567 pov_idx ++;
568 break;
569 }
Aric Stewartffbd6a72009-03-10 14:59:41 -0500570 case kHIDUsage_GD_X:
571 case kHIDUsage_GD_Y:
572 case kHIDUsage_GD_Z:
Aric Stewart17daca72009-03-10 14:59:49 -0500573 case kHIDUsage_GD_Rx:
574 case kHIDUsage_GD_Ry:
575 case kHIDUsage_GD_Rz:
Aric Stewartae16df62009-03-10 15:00:03 -0500576 case kHIDUsage_GD_Slider:
Aric Stewartffbd6a72009-03-10 14:59:41 -0500577 {
Jonas Maebe90d86082011-06-16 21:11:46 +0200578 int wine_obj = -1;
579
Aric Stewartffbd6a72009-03-10 14:59:41 -0500580 IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
581 val = IOHIDValueGetIntegerValue(valueRef);
Jonas Maebe90d86082011-06-16 21:11:46 +0200582 newVal = joystick_map_axis(&device->generic.props[idx], val);
Aric Stewartffbd6a72009-03-10 14:59:41 -0500583 switch (usage)
584 {
585 case kHIDUsage_GD_X:
Jonas Maebe90d86082011-06-16 21:11:46 +0200586 wine_obj = 0;
587 oldVal = device->generic.js.lX;
588 device->generic.js.lX = newVal;
Aric Stewartffbd6a72009-03-10 14:59:41 -0500589 break;
590 case kHIDUsage_GD_Y:
Jonas Maebe90d86082011-06-16 21:11:46 +0200591 wine_obj = 1;
592 oldVal = device->generic.js.lY;
593 device->generic.js.lY = newVal;
Aric Stewartffbd6a72009-03-10 14:59:41 -0500594 break;
595 case kHIDUsage_GD_Z:
Jonas Maebe90d86082011-06-16 21:11:46 +0200596 wine_obj = 2;
597 oldVal = device->generic.js.lZ;
598 device->generic.js.lZ = newVal;
Aric Stewartffbd6a72009-03-10 14:59:41 -0500599 break;
Aric Stewart17daca72009-03-10 14:59:49 -0500600 case kHIDUsage_GD_Rx:
Jonas Maebe90d86082011-06-16 21:11:46 +0200601 wine_obj = 3;
602 oldVal = device->generic.js.lRx;
603 device->generic.js.lRx = newVal;
Aric Stewart17daca72009-03-10 14:59:49 -0500604 break;
605 case kHIDUsage_GD_Ry:
Jonas Maebe90d86082011-06-16 21:11:46 +0200606 wine_obj = 4;
607 oldVal = device->generic.js.lRy;
608 device->generic.js.lRy = newVal;
Aric Stewart17daca72009-03-10 14:59:49 -0500609 break;
610 case kHIDUsage_GD_Rz:
Jonas Maebe90d86082011-06-16 21:11:46 +0200611 wine_obj = 5;
612 oldVal = device->generic.js.lRz;
613 device->generic.js.lRz = newVal;
Aric Stewart17daca72009-03-10 14:59:49 -0500614 break;
Aric Stewartae16df62009-03-10 15:00:03 -0500615 case kHIDUsage_GD_Slider:
Jonas Maebe90d86082011-06-16 21:11:46 +0200616 wine_obj = 6 + slider_idx;
617 oldVal = device->generic.js.rglSlider[slider_idx];
618 device->generic.js.rglSlider[slider_idx] = newVal;
Aric Stewartae16df62009-03-10 15:00:03 -0500619 slider_idx ++;
620 break;
Aric Stewartffbd6a72009-03-10 14:59:41 -0500621 }
Jonas Maebe90d86082011-06-16 21:11:46 +0200622 if ((wine_obj != -1) &&
623 (oldVal != newVal))
624 {
625 inst_id = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
626 queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
627 }
628
Aric Stewartffbd6a72009-03-10 14:59:41 -0500629 break;
630 }
Aric Stewart87d61ab2009-03-10 14:59:35 -0500631 default:
632 FIXME("unhandled usage %i\n",usage);
633 }
634 break;
635 }
Aric Stewart225a4942009-03-10 14:59:20 -0500636 default:
637 FIXME("Unhandled type %i\n",eleType);
638 }
639 }
640 }
641}
642
643static INT find_joystick_devices(void)
644{
645 static INT joystick_devices_count = -1;
646
647 if (joystick_devices_count != -1) return joystick_devices_count;
648
649 joystick_devices_count = find_osx_devices();
650
651 return joystick_devices_count;
652}
653
654static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
655{
656 if (id >= find_joystick_devices()) return FALSE;
657
658 if (dwFlags & DIEDFL_FORCEFEEDBACK) {
659 WARN("force feedback not supported\n");
660 return FALSE;
661 }
662
663 if ((dwDevType == 0) ||
664 ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
665 (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800)))
666 {
667 /* Return joystick */
668 lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
669 lpddi->guidInstance.Data3 = id;
670 lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID;
671 /* we only support traditional joysticks for now */
672 if (version >= 0x0800)
673 lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
674 else
675 lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
676 sprintf(lpddi->tszInstanceName, "Joystick %d", id);
677
678 /* get the device name */
679 get_osx_device_name(id, lpddi->tszProductName, MAX_PATH);
680
681 lpddi->guidFFDriver = GUID_NULL;
682 return TRUE;
683 }
684
685 return FALSE;
686}
687
688static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
689{
690 char name[MAX_PATH];
691 char friendly[32];
692
693 if (id >= find_joystick_devices()) return FALSE;
694
695 if (dwFlags & DIEDFL_FORCEFEEDBACK) {
696 WARN("force feedback not supported\n");
697 return FALSE;
698 }
699
700 if ((dwDevType == 0) ||
701 ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
702 (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
703 /* Return joystick */
704 lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
705 lpddi->guidInstance.Data3 = id;
706 lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID;
707 /* we only support traditional joysticks for now */
708 if (version >= 0x0800)
709 lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
710 else
711 lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
712 sprintf(friendly, "Joystick %d", id);
713 MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH);
714 /* get the device name */
715 get_osx_device_name(id, name, MAX_PATH);
716
717 MultiByteToWideChar(CP_ACP, 0, name, -1, lpddi->tszProductName, MAX_PATH);
718 lpddi->guidFFDriver = GUID_NULL;
719 return TRUE;
720 }
721
722 return FALSE;
723}
724
Vitaliy Margolen6b304802011-01-09 15:44:19 -0700725static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
726 JoystickImpl **pdev, unsigned short index)
Aric Stewart225a4942009-03-10 14:59:20 -0500727{
728 DWORD i;
729 JoystickImpl* newDevice;
730 char name[MAX_PATH];
731 HRESULT hr;
732 LPDIDATAFORMAT df = NULL;
733 int idx = 0;
Aric Stewart08388a32009-03-10 14:59:56 -0500734 int axis_map[8]; /* max axes */
Aric Stewartae16df62009-03-10 15:00:03 -0500735 int slider_count = 0;
Aric Stewart225a4942009-03-10 14:59:20 -0500736
Vitaliy Margolen6b304802011-01-09 15:44:19 -0700737 TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
Aric Stewart225a4942009-03-10 14:59:20 -0500738
739 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
740 if (newDevice == 0) {
741 WARN("out of memory\n");
742 *pdev = 0;
743 return DIERR_OUTOFMEMORY;
744 }
745
746 newDevice->id = index;
747
Vitaliy Margolenfc4f1602009-04-19 20:33:22 -0600748 newDevice->generic.guidInstance = DInput_Wine_OsX_Joystick_GUID;
749 newDevice->generic.guidInstance.Data3 = index;
Aric Stewart225a4942009-03-10 14:59:20 -0500750 newDevice->generic.guidProduct = DInput_Wine_OsX_Joystick_GUID;
751 newDevice->generic.joy_polldev = poll_osx_device_state;
752
753 /* get the device name */
754 get_osx_device_name(index, name, MAX_PATH);
755 TRACE("Name %s\n",name);
756
757 /* copy the device name */
758 newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
759 strcpy(newDevice->generic.name, name);
760
Aric Stewart08388a32009-03-10 14:59:56 -0500761 memset(axis_map, 0, sizeof(axis_map));
762 get_osx_device_elements(newDevice, axis_map);
Aric Stewart225a4942009-03-10 14:59:20 -0500763
764 TRACE("%i axes %i buttons %i povs\n",newDevice->generic.devcaps.dwAxes,newDevice->generic.devcaps.dwButtons,newDevice->generic.devcaps.dwPOVs);
765
766 if (newDevice->generic.devcaps.dwButtons > 128)
767 {
768 WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons);
769 newDevice->generic.devcaps.dwButtons = 128;
770 }
771
Vitaliy Margolen6b304802011-01-09 15:44:19 -0700772 newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
773 newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
Aric Stewart225a4942009-03-10 14:59:20 -0500774 newDevice->generic.base.ref = 1;
775 newDevice->generic.base.dinput = dinput;
776 newDevice->generic.base.guid = *rguid;
777 InitializeCriticalSection(&newDevice->generic.base.crit);
778 newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
779
780 /* Create copy of default data format */
781 if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
782 memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
783
784 df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
785 if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
786
787 for (i = 0; i < newDevice->generic.devcaps.dwAxes; i++)
788 {
Aric Stewart08388a32009-03-10 14:59:56 -0500789 int wine_obj = -1;
790 switch (axis_map[i])
791 {
792 case kHIDUsage_GD_X: wine_obj = 0; break;
793 case kHIDUsage_GD_Y: wine_obj = 1; break;
794 case kHIDUsage_GD_Z: wine_obj = 2; break;
795 case kHIDUsage_GD_Rx: wine_obj = 3; break;
796 case kHIDUsage_GD_Ry: wine_obj = 4; break;
797 case kHIDUsage_GD_Rz: wine_obj = 5; break;
Aric Stewartae16df62009-03-10 15:00:03 -0500798 case kHIDUsage_GD_Slider:
799 wine_obj = 6 + slider_count;
800 slider_count++;
801 break;
Aric Stewart08388a32009-03-10 14:59:56 -0500802 }
803 if (wine_obj < 0 ) continue;
804
805 memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
806 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
Aric Stewart225a4942009-03-10 14:59:20 -0500807 }
808
809 for (i = 0; i < newDevice->generic.devcaps.dwPOVs; i++)
810 {
811 memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 8], df->dwObjSize);
812 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_POV;
813 }
814
815 for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++)
816 {
817 memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
818 df->rgodf[idx ].pguid = &GUID_Button;
819 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
820 }
821 newDevice->generic.base.data_format.wine_df = df;
822
Aric Stewart225a4942009-03-10 14:59:20 -0500823 /* initialize default properties */
824 get_osx_device_elements_props(newDevice);
825
Vitaliy Margolen15216092011-01-09 15:43:09 -0700826 IDirectInput_AddRef(&newDevice->generic.base.dinput->IDirectInput7A_iface);
Aric Stewart225a4942009-03-10 14:59:20 -0500827
Vitaliy Margolen9441d892011-01-18 21:06:37 -0700828 EnterCriticalSection(&dinput->crit);
829 list_add_tail(&dinput->devices_list, &newDevice->generic.base.entry);
830 LeaveCriticalSection(&dinput->crit);
831
Aric Stewart225a4942009-03-10 14:59:20 -0500832 newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
833 newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
834 if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
835 newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
836 else
837 newDevice->generic.devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
838 newDevice->generic.devcaps.dwFFSamplePeriod = 0;
839 newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
840 newDevice->generic.devcaps.dwFirmwareRevision = 0;
841 newDevice->generic.devcaps.dwHardwareRevision = 0;
842 newDevice->generic.devcaps.dwFFDriverVersion = 0;
843
844 if (TRACE_ON(dinput)) {
845 _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df);
846 _dump_DIDEVCAPS(&newDevice->generic.devcaps);
847 }
848
Vitaliy Margolen6b304802011-01-09 15:44:19 -0700849 *pdev = newDevice;
Aric Stewart225a4942009-03-10 14:59:20 -0500850
851 return DI_OK;
852
853FAILED:
854 hr = DIERR_OUTOFMEMORY;
855 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
856 HeapFree(GetProcessHeap(), 0, df);
857 release_DataFormat(&newDevice->generic.base.data_format);
858 HeapFree(GetProcessHeap(),0,newDevice->generic.name);
Aric Stewart225a4942009-03-10 14:59:20 -0500859 HeapFree(GetProcessHeap(),0,newDevice);
860 *pdev = 0;
861
862 return hr;
863}
864
865/******************************************************************************
866 * get_joystick_index : Get the joystick index from a given GUID
867 */
868static unsigned short get_joystick_index(REFGUID guid)
869{
870 GUID wine_joystick = DInput_Wine_OsX_Joystick_GUID;
871 GUID dev_guid = *guid;
872
873 wine_joystick.Data3 = 0;
874 dev_guid.Data3 = 0;
875
876 /* for the standard joystick GUID use index 0 */
877 if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
878
879 /* for the wine joystick GUIDs use the index stored in Data3 */
880 if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
881
882 return 0xffff;
883}
884
Vitaliy Margolen0ac5c602011-01-23 12:44:20 -0700885static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
Aric Stewart225a4942009-03-10 14:59:20 -0500886{
887 unsigned short index;
888 int joystick_devices_count;
889
Vitaliy Margolen0ac5c602011-01-23 12:44:20 -0700890 TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
Aric Stewart225a4942009-03-10 14:59:20 -0500891 *pdev = NULL;
892
893 if ((joystick_devices_count = find_joystick_devices()) == 0)
894 return DIERR_DEVICENOTREG;
895
896 if ((index = get_joystick_index(rguid)) < 0xffff &&
897 joystick_devices_count && index < joystick_devices_count)
898 {
Vitaliy Margolen0ac5c602011-01-23 12:44:20 -0700899 JoystickImpl *This;
900 HRESULT hr;
Vitaliy Margolen6b304802011-01-09 15:44:19 -0700901
Vitaliy Margolen0ac5c602011-01-23 12:44:20 -0700902 if (riid == NULL)
903 ;/* nothing */
904 else if (IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
905 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
906 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
907 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
908 {
909 unicode = 0;
910 }
911 else if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) ||
912 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
913 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
914 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
915 {
916 unicode = 1;
917 }
918 else
919 {
920 WARN("no interface\n");
921 return DIERR_NOINTERFACE;
Aric Stewart225a4942009-03-10 14:59:20 -0500922 }
923
Vitaliy Margolen0ac5c602011-01-23 12:44:20 -0700924 hr = alloc_device(rguid, dinput, &This, index);
925 if (!This) return hr;
926
927 if (unicode)
928 *pdev = &This->generic.base.IDirectInputDevice8W_iface;
929 else
930 *pdev = &This->generic.base.IDirectInputDevice8A_iface;
931 return hr;
Aric Stewart225a4942009-03-10 14:59:20 -0500932 }
933
934 return DIERR_DEVICENOTREG;
935}
936
Aric Stewart225a4942009-03-10 14:59:20 -0500937const struct dinput_device joystick_osx_device = {
938 "Wine OS X joystick driver",
939 joydev_enum_deviceA,
940 joydev_enum_deviceW,
Vitaliy Margolen0ac5c602011-01-23 12:44:20 -0700941 joydev_create_device
Aric Stewart225a4942009-03-10 14:59:20 -0500942};
943
944static const IDirectInputDevice8AVtbl JoystickAvt =
945{
946 IDirectInputDevice2AImpl_QueryInterface,
947 IDirectInputDevice2AImpl_AddRef,
948 IDirectInputDevice2AImpl_Release,
949 JoystickAGenericImpl_GetCapabilities,
950 IDirectInputDevice2AImpl_EnumObjects,
951 JoystickAGenericImpl_GetProperty,
952 JoystickAGenericImpl_SetProperty,
Vitaliy Margolenaee42372009-04-19 20:33:25 -0600953 IDirectInputDevice2AImpl_Acquire,
954 IDirectInputDevice2AImpl_Unacquire,
Aric Stewart225a4942009-03-10 14:59:20 -0500955 JoystickAGenericImpl_GetDeviceState,
956 IDirectInputDevice2AImpl_GetDeviceData,
957 IDirectInputDevice2AImpl_SetDataFormat,
958 IDirectInputDevice2AImpl_SetEventNotification,
959 IDirectInputDevice2AImpl_SetCooperativeLevel,
960 JoystickAGenericImpl_GetObjectInfo,
961 JoystickAGenericImpl_GetDeviceInfo,
962 IDirectInputDevice2AImpl_RunControlPanel,
963 IDirectInputDevice2AImpl_Initialize,
964 IDirectInputDevice2AImpl_CreateEffect,
965 IDirectInputDevice2AImpl_EnumEffects,
966 IDirectInputDevice2AImpl_GetEffectInfo,
967 IDirectInputDevice2AImpl_GetForceFeedbackState,
968 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
969 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
970 IDirectInputDevice2AImpl_Escape,
971 JoystickAGenericImpl_Poll,
972 IDirectInputDevice2AImpl_SendDeviceData,
973 IDirectInputDevice7AImpl_EnumEffectsInFile,
974 IDirectInputDevice7AImpl_WriteEffectToFile,
Lucas Fialho Zawackidc044e12011-07-11 22:36:56 -0300975 JoystickAGenericImpl_BuildActionMap,
976 JoystickAGenericImpl_SetActionMap,
Aric Stewart225a4942009-03-10 14:59:20 -0500977 IDirectInputDevice8AImpl_GetImageInfo
978};
979
Aric Stewart225a4942009-03-10 14:59:20 -0500980static const IDirectInputDevice8WVtbl JoystickWvt =
981{
982 IDirectInputDevice2WImpl_QueryInterface,
Vitaliy Margolen0f24b9e2011-01-09 15:43:55 -0700983 IDirectInputDevice2WImpl_AddRef,
984 IDirectInputDevice2WImpl_Release,
Vitaliy Margolen6a078852011-01-09 15:44:05 -0700985 JoystickWGenericImpl_GetCapabilities,
Aric Stewart225a4942009-03-10 14:59:20 -0500986 IDirectInputDevice2WImpl_EnumObjects,
Vitaliy Margolen6a078852011-01-09 15:44:05 -0700987 JoystickWGenericImpl_GetProperty,
988 JoystickWGenericImpl_SetProperty,
Vitaliy Margolen0f24b9e2011-01-09 15:43:55 -0700989 IDirectInputDevice2WImpl_Acquire,
990 IDirectInputDevice2WImpl_Unacquire,
Vitaliy Margolen6a078852011-01-09 15:44:05 -0700991 JoystickWGenericImpl_GetDeviceState,
Vitaliy Margolen0f24b9e2011-01-09 15:43:55 -0700992 IDirectInputDevice2WImpl_GetDeviceData,
993 IDirectInputDevice2WImpl_SetDataFormat,
994 IDirectInputDevice2WImpl_SetEventNotification,
995 IDirectInputDevice2WImpl_SetCooperativeLevel,
Aric Stewart225a4942009-03-10 14:59:20 -0500996 JoystickWGenericImpl_GetObjectInfo,
997 JoystickWGenericImpl_GetDeviceInfo,
Vitaliy Margolen0f24b9e2011-01-09 15:43:55 -0700998 IDirectInputDevice2WImpl_RunControlPanel,
999 IDirectInputDevice2WImpl_Initialize,
1000 IDirectInputDevice2WImpl_CreateEffect,
Aric Stewart225a4942009-03-10 14:59:20 -05001001 IDirectInputDevice2WImpl_EnumEffects,
1002 IDirectInputDevice2WImpl_GetEffectInfo,
Vitaliy Margolen0f24b9e2011-01-09 15:43:55 -07001003 IDirectInputDevice2WImpl_GetForceFeedbackState,
1004 IDirectInputDevice2WImpl_SendForceFeedbackCommand,
1005 IDirectInputDevice2WImpl_EnumCreatedEffectObjects,
1006 IDirectInputDevice2WImpl_Escape,
Vitaliy Margolen6a078852011-01-09 15:44:05 -07001007 JoystickWGenericImpl_Poll,
Vitaliy Margolen0f24b9e2011-01-09 15:43:55 -07001008 IDirectInputDevice2WImpl_SendDeviceData,
Aric Stewart225a4942009-03-10 14:59:20 -05001009 IDirectInputDevice7WImpl_EnumEffectsInFile,
1010 IDirectInputDevice7WImpl_WriteEffectToFile,
Lucas Fialho Zawackidc044e12011-07-11 22:36:56 -03001011 JoystickWGenericImpl_BuildActionMap,
1012 JoystickWGenericImpl_SetActionMap,
Aric Stewart225a4942009-03-10 14:59:20 -05001013 IDirectInputDevice8WImpl_GetImageInfo
1014};
Aric Stewart225a4942009-03-10 14:59:20 -05001015
Alexandre Julliard81f8c032009-03-11 16:49:55 +01001016#else /* HAVE_IOHIDMANAGERCREATE */
Aric Stewart225a4942009-03-10 14:59:20 -05001017
1018const struct dinput_device joystick_osx_device = {
1019 "Wine OS X joystick driver",
1020 NULL,
1021 NULL,
Aric Stewart225a4942009-03-10 14:59:20 -05001022 NULL
1023};
1024
Alexandre Julliard81f8c032009-03-11 16:49:55 +01001025#endif /* HAVE_IOHIDMANAGERCREATE */