~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/dinput/joystick_osx.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*  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 
 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>
 65 #undef LoadResource
 66 #undef CompareString
 67 #undef GetCurrentThread
 68 #undef _CDECL
 69 #undef DPRINTF
 70 #undef GetCurrentProcess
 71 #undef AnimatePalette
 72 #undef EqualRgn
 73 #undef FillRgn
 74 #undef FrameRgn
 75 #undef GetPixel
 76 #undef InvertRgn
 77 #undef LineTo
 78 #undef OffsetRgn
 79 #undef PaintRgn
 80 #undef Polygon
 81 #undef ResizePalette
 82 #undef SetRectRgn
 83 #undef ULONG
 84 #undef E_INVALIDARG
 85 #undef E_OUTOFMEMORY
 86 #undef E_HANDLE
 87 #undef E_ACCESSDENIED
 88 #undef E_UNEXPECTED
 89 #undef E_FAIL
 90 #undef E_ABORT
 91 #undef E_POINTER
 92 #undef E_NOINTERFACE
 93 #undef E_NOTIMPL
 94 #undef S_FALSE
 95 #undef S_OK
 96 #undef HRESULT_FACILITY
 97 #undef IS_ERROR
 98 #undef FAILED
 99 #undef SUCCEEDED
100 #undef MAKE_HRESULT
101 #undef HRESULT
102 #undef STDMETHODCALLTYPE
103 #endif /* HAVE_CARBON_CARBON_H */
104 
105 #include "wine/debug.h"
106 #include "wine/unicode.h"
107 #include "windef.h"
108 #include "winbase.h"
109 #include "winerror.h"
110 #include "winreg.h"
111 #include "dinput.h"
112 
113 #include "dinput_private.h"
114 #include "device_private.h"
115 #include "joystick_private.h"
116 
117 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
118 
119 #ifdef HAVE_IOHIDMANAGERCREATE
120 
121 static IOHIDManagerRef gIOHIDManagerRef = NULL;
122 static CFArrayRef gDevices = NULL;
123 
124 typedef struct JoystickImpl JoystickImpl;
125 static const IDirectInputDevice8AVtbl JoystickAvt;
126 static const IDirectInputDevice8WVtbl JoystickWvt;
127 
128 struct JoystickImpl
129 {
130     struct JoystickGenericImpl generic;
131 
132     /* osx private */
133     int                    id;
134     CFMutableArrayRef      elementCFArrayRef;
135     ObjProps               **propmap;
136 };
137 
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}
140 };
141 
142 static void CFSetApplierFunctionCopyToCFArray(const void *value, void *context)
143 {
144     CFArrayAppendValue( ( CFMutableArrayRef ) context, value );
145 }
146 
147 static CFMutableDictionaryRef creates_osx_device_match(int usage)
148 {
149     CFMutableDictionaryRef result;
150 
151     result = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
152             &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
153 
154     if ( result )
155     {
156         int number = kHIDPage_GenericDesktop;
157         CFNumberRef pageCFNumberRef = CFNumberCreate( kCFAllocatorDefault,
158                           kCFNumberIntType, &number);
159 
160         if ( pageCFNumberRef )
161         {
162             CFNumberRef usageCFNumberRef;
163 
164             CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsagePageKey ),
165                 pageCFNumberRef );
166             CFRelease( pageCFNumberRef );
167 
168             usageCFNumberRef = CFNumberCreate( kCFAllocatorDefault,
169                         kCFNumberIntType, &usage);
170             if ( usageCFNumberRef )
171             {
172                 CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsageKey ),
173                     usageCFNumberRef );
174                 CFRelease( usageCFNumberRef );
175             }
176             else
177             {
178                 ERR("CFNumberCreate() failed.\n");
179                 return NULL;
180             }
181         }
182         else
183         {
184             ERR("CFNumberCreate failed.\n");
185             return NULL;
186         }
187     }
188     else
189     {
190         ERR("CFDictionaryCreateMutable failed.\n");
191         return NULL;
192     }
193 
194     return result;
195 }
196 
197 static int find_osx_devices(void)
198 {
199     IOReturn tIOReturn;
200     CFMutableDictionaryRef result;
201     CFSetRef devset;
202     CFArrayRef matching;
203 
204     gIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, 0L );
205     tIOReturn = IOHIDManagerOpen( gIOHIDManagerRef, 0L);
206     if ( kIOReturnSuccess != tIOReturn )
207     {
208         ERR("Couldn't open IOHIDManager.\n");
209         return 0;
210     }
211 
212      matching = CFArrayCreateMutable( kCFAllocatorDefault, 0,
213                         &kCFTypeArrayCallBacks );
214 
215     /* build matching dictionary */
216     result = creates_osx_device_match(kHIDPage_Sport);
217     if (!result)
218     {
219         CFRelease(matching);
220         return 0;
221     }
222     CFArrayAppendValue( ( CFMutableArrayRef )matching, result );
223     result = creates_osx_device_match(kHIDPage_Game);
224     if (!result)
225     {
226         CFRelease(matching);
227         return 0;
228     }
229     CFArrayAppendValue( ( CFMutableArrayRef )matching, result );
230 
231     IOHIDManagerSetDeviceMatchingMultiple( gIOHIDManagerRef, matching);
232     devset = IOHIDManagerCopyDevices( gIOHIDManagerRef );
233     if (devset)
234     {
235         CFIndex count;
236         gDevices = CFArrayCreateMutable( kCFAllocatorDefault, 0,
237                         &kCFTypeArrayCallBacks );
238         CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, (void*)gDevices);
239         count = CFArrayGetCount( gDevices);
240         CFRelease( devset);
241         count = CFArrayGetCount( gDevices);
242 
243         TRACE("found %i device(s)\n",(int)count);
244         return count;
245 
246     }
247     return 0;
248 }
249 
250 static int get_osx_device_name(int id, char *name, int length)
251 {
252     CFStringRef str;
253     IOHIDDeviceRef tIOHIDDeviceRef;
254 
255     if (!gDevices)
256         return 0;
257 
258     tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, id );
259 
260     if (!tIOHIDDeviceRef)
261         return 0;
262 
263     if (name)
264         name[0] = 0;
265 
266     if (!tIOHIDDeviceRef)
267     {
268         ERR("Invalid Device requested %i\n",id);
269         return 0;
270     }
271 
272     str = IOHIDDeviceGetProperty(tIOHIDDeviceRef, CFSTR( kIOHIDProductKey ));
273     if (str)
274     {
275         CFIndex len = CFStringGetLength(str);
276         if (length >= len)
277         {
278             CFStringGetCString(str,name,length,kCFStringEncodingASCII);
279             return len;
280         }
281         else
282             return (len+1);
283     }
284     return 0;
285 }
286 
287 static void insert_sort_button(int header, IOHIDElementRef tIOHIDElementRef,
288                                 CFMutableArrayRef elementCFArrayRef, int index,
289                                 int target)
290 {
291     IOHIDElementRef targetElement;
292     int usage;
293 
294     CFArraySetValueAtIndex(elementCFArrayRef, header+index, NULL);
295     targetElement = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, header+target);
296     if (targetElement == NULL)
297     {
298         CFArraySetValueAtIndex(elementCFArrayRef, header+target,tIOHIDElementRef);
299         return;
300     }
301     usage = IOHIDElementGetUsage( targetElement );
302     usage --; /* usage 1 based index */
303 
304     insert_sort_button(header, targetElement, elementCFArrayRef, target, usage);
305     CFArraySetValueAtIndex(elementCFArrayRef, header+target,tIOHIDElementRef);
306 }
307 
308 static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
309 {
310     IOHIDDeviceRef  tIOHIDDeviceRef;
311     CFArrayRef      gElementCFArrayRef;
312     DWORD           axes = 0;
313     DWORD           sliders = 0;
314     DWORD           buttons = 0;
315     DWORD           povs = 0;
316 
317     device->elementCFArrayRef = NULL;
318 
319     if (!gDevices)
320         return;
321 
322     tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, device->id );
323 
324     if (!tIOHIDDeviceRef)
325         return;
326 
327     gElementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef,
328                                 NULL, 0 );
329 
330     if (gElementCFArrayRef)
331     {
332         CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
333         /* build our element array in the order that dinput expects */
334         device->elementCFArrayRef = CFArrayCreateMutable(NULL,0,NULL);
335 
336         for ( idx = 0; idx < cnt; idx++ )
337         {
338             IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
339             int eleType = IOHIDElementGetType( tIOHIDElementRef );
340             switch(eleType)
341             {
342                 case kIOHIDElementTypeInput_Button:
343                 {
344                     int usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef );
345                     if (usagePage != kHIDPage_Button)
346                     {
347                         /* avoid strange elements found on the 360 controler */
348                         continue;
349                     }
350 
351                     if (buttons < 128)
352                     {
353                         CFArrayInsertValueAtIndex(device->elementCFArrayRef, (axes+povs+buttons), tIOHIDElementRef);
354                         buttons++;
355                     }
356                     break;
357                 }
358                 case kIOHIDElementTypeInput_Axis:
359                 {
360                     CFArrayInsertValueAtIndex(device->elementCFArrayRef, axes, tIOHIDElementRef);
361                     axes++;
362                     break;
363                 }
364                 case kIOHIDElementTypeInput_Misc:
365                 {
366                     uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
367                     switch(usage)
368                     {
369                         case kHIDUsage_GD_Hatswitch:
370                         {
371                             CFArrayInsertValueAtIndex(device->elementCFArrayRef, (axes+povs), tIOHIDElementRef);
372                             povs++;
373                             break;
374                         }
375                         case kHIDUsage_GD_Slider:
376                             sliders ++;
377                             if (sliders > 2)
378                                 break;
379                             /* fallthrough, sliders are axis */
380                         case kHIDUsage_GD_X:
381                         case kHIDUsage_GD_Y:
382                         case kHIDUsage_GD_Z:
383                         case kHIDUsage_GD_Rx:
384                         case kHIDUsage_GD_Ry:
385                         case kHIDUsage_GD_Rz:
386                         {
387                             CFArrayInsertValueAtIndex(device->elementCFArrayRef, axes, tIOHIDElementRef);
388                             axis_map[axes]=usage;
389                             axes++;
390                             break;
391                         }
392                         default:
393                             FIXME("Unhandled usage %i\n",usage);
394                     }
395                     break;
396                 }
397                 default:
398                     FIXME("Unhandled type %i\n",eleType);
399             }
400         }
401     }
402 
403     device->generic.devcaps.dwAxes = axes;
404     device->generic.devcaps.dwButtons = buttons;
405     device->generic.devcaps.dwPOVs = povs;
406 
407     /* Sort buttons into correct order */
408     for (buttons = 0; buttons < device->generic.devcaps.dwButtons; buttons++)
409     {
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)
414             continue;
415 
416         insert_sort_button(axes+povs, tIOHIDElementRef, device->elementCFArrayRef,buttons,usage);
417     }
418 }
419 
420 static void get_osx_device_elements_props(JoystickImpl *device)
421 {
422     CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;
423 
424     if (gElementCFArrayRef)
425     {
426         CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
427 
428         for ( idx = 0; idx < cnt; idx++ )
429         {
430             IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
431 
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;
438         }
439     }
440 }
441 
442 static void poll_osx_device_state(JoystickGenericImpl *device_in)
443 {
444     JoystickImpl *device = (JoystickImpl*)device_in;
445     IOHIDDeviceRef tIOHIDDeviceRef;
446     CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;
447 
448     TRACE("polling device %i\n",device->id);
449 
450     if (!gDevices)
451         return;
452 
453     tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDevices, device->id );
454 
455     if (!tIOHIDDeviceRef)
456         return;
457 
458     if (gElementCFArrayRef)
459     {
460         int button_idx = 0;
461         int pov_idx = 0;
462         int slider_idx = 0;
463         CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
464 
465         for ( idx = 0; idx < cnt; idx++ )
466         {
467             IOHIDValueRef valueRef;
468             int val;
469             IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
470             int eleType = IOHIDElementGetType( tIOHIDElementRef );
471 
472             switch(eleType)
473             {
474                 case kIOHIDElementTypeInput_Button:
475                     if(button_idx < 128)
476                     {
477                         IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
478                         val = IOHIDValueGetIntegerValue(valueRef);
479                         device->generic.js.rgbButtons[button_idx] = val ? 0x80 : 0x00;
480                         button_idx ++;
481                     }
482                     break;
483                 case kIOHIDElementTypeInput_Misc:
484                 {
485                     uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
486                     switch(usage)
487                     {
488                         case kHIDUsage_GD_Hatswitch:
489                         {
490                             IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
491                             val = IOHIDValueGetIntegerValue(valueRef);
492                             if (val >= 8)
493                                 device->generic.js.rgdwPOV[pov_idx] = -1;
494                             else
495                                 device->generic.js.rgdwPOV[pov_idx] = val * 4500;
496                             pov_idx ++;
497                             break;
498                         }
499                         case kHIDUsage_GD_X:
500                         case kHIDUsage_GD_Y:
501                         case kHIDUsage_GD_Z:
502                         case kHIDUsage_GD_Rx:
503                         case kHIDUsage_GD_Ry:
504                         case kHIDUsage_GD_Rz:
505                         case kHIDUsage_GD_Slider:
506                         {
507                             IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
508                             val = IOHIDValueGetIntegerValue(valueRef);
509                             switch (usage)
510                             {
511                             case kHIDUsage_GD_X:
512                                 device->generic.js.lX = joystick_map_axis(&device->generic.props[idx], val);
513                                 break;
514                             case kHIDUsage_GD_Y:
515                                 device->generic.js.lY = joystick_map_axis(&device->generic.props[idx], val);
516                                 break;
517                             case kHIDUsage_GD_Z:
518                                 device->generic.js.lZ = joystick_map_axis(&device->generic.props[idx], val);
519                                 break;
520                             case kHIDUsage_GD_Rx:
521                                 device->generic.js.lRx = joystick_map_axis(&device->generic.props[idx], val);
522                                 break;
523                             case kHIDUsage_GD_Ry:
524                                 device->generic.js.lRy = joystick_map_axis(&device->generic.props[idx], val);
525                                 break;
526                             case kHIDUsage_GD_Rz:
527                                 device->generic.js.lRz = joystick_map_axis(&device->generic.props[idx], val);
528                                 break;
529                             case kHIDUsage_GD_Slider:
530                                 device->generic.js.rglSlider[slider_idx] = joystick_map_axis(&device->generic.props[idx], val);
531                                 slider_idx ++;
532                                 break;
533                             }
534                             break;
535                         }
536                         default:
537                             FIXME("unhandled usage %i\n",usage);
538                     }
539                     break;
540                 }
541                 default:
542                     FIXME("Unhandled type %i\n",eleType);
543             }
544         }
545     }
546 }
547 
548 static INT find_joystick_devices(void)
549 {
550     static INT joystick_devices_count = -1;
551 
552     if (joystick_devices_count != -1) return joystick_devices_count;
553 
554     joystick_devices_count = find_osx_devices();
555 
556     return  joystick_devices_count;
557 }
558 
559 static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
560 {
561     if (id >= find_joystick_devices()) return FALSE;
562 
563     if (dwFlags & DIEDFL_FORCEFEEDBACK) {
564         WARN("force feedback not supported\n");
565         return FALSE;
566     }
567 
568     if ((dwDevType == 0) ||
569     ((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
570     (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800)))
571     {
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);
579         else
580             lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
581         sprintf(lpddi->tszInstanceName, "Joystick %d", id);
582 
583         /* get the device name */
584         get_osx_device_name(id, lpddi->tszProductName, MAX_PATH);
585 
586         lpddi->guidFFDriver = GUID_NULL;
587         return TRUE;
588     }
589 
590     return FALSE;
591 }
592 
593 static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
594 {
595     char name[MAX_PATH];
596     char friendly[32];
597 
598     if (id >= find_joystick_devices()) return FALSE;
599 
600     if (dwFlags & DIEDFL_FORCEFEEDBACK) {
601         WARN("force feedback not supported\n");
602         return FALSE;
603     }
604 
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);
615         else
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);
621 
622         MultiByteToWideChar(CP_ACP, 0, name, -1, lpddi->tszProductName, MAX_PATH);
623         lpddi->guidFFDriver = GUID_NULL;
624         return TRUE;
625     }
626 
627     return FALSE;
628 }
629 
630 static HRESULT alloc_device(REFGUID rguid, const void *jvt, IDirectInputImpl *dinput,
631     LPDIRECTINPUTDEVICEA* pdev, unsigned short index)
632 {
633     DWORD i;
634     JoystickImpl* newDevice;
635     char name[MAX_PATH];
636     HRESULT hr;
637     LPDIDATAFORMAT df = NULL;
638     int idx = 0;
639     int axis_map[8]; /* max axes */
640     int slider_count = 0;
641 
642     TRACE("%s %p %p %p %hu\n", debugstr_guid(rguid), jvt, dinput, pdev, index);
643 
644     newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
645     if (newDevice == 0) {
646         WARN("out of memory\n");
647         *pdev = 0;
648         return DIERR_OUTOFMEMORY;
649     }
650 
651     newDevice->id = index;
652 
653     newDevice->generic.guidInstance = DInput_Wine_OsX_Joystick_GUID;
654     newDevice->generic.guidInstance.Data3 = index;
655     newDevice->generic.guidProduct = DInput_Wine_OsX_Joystick_GUID;
656     newDevice->generic.joy_polldev = poll_osx_device_state;
657 
658     /* get the device name */
659     get_osx_device_name(index, name, MAX_PATH);
660     TRACE("Name %s\n",name);
661 
662     /* copy the device name */
663     newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
664     strcpy(newDevice->generic.name, name);
665 
666     memset(axis_map, 0, sizeof(axis_map));
667     get_osx_device_elements(newDevice, axis_map);
668 
669     TRACE("%i axes %i buttons %i povs\n",newDevice->generic.devcaps.dwAxes,newDevice->generic.devcaps.dwButtons,newDevice->generic.devcaps.dwPOVs);
670 
671     if (newDevice->generic.devcaps.dwButtons > 128)
672     {
673         WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons);
674         newDevice->generic.devcaps.dwButtons = 128;
675     }
676 
677     newDevice->generic.base.lpVtbl = jvt;
678     newDevice->generic.base.ref = 1;
679     newDevice->generic.base.dinput = dinput;
680     newDevice->generic.base.guid = *rguid;
681     InitializeCriticalSection(&newDevice->generic.base.crit);
682     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
683 
684     /* Create copy of default data format */
685     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
686     memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
687 
688     df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
689     if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
690 
691     for (i = 0; i < newDevice->generic.devcaps.dwAxes; i++)
692     {
693         int wine_obj = -1;
694         switch (axis_map[i])
695         {
696             case kHIDUsage_GD_X: wine_obj = 0; break;
697             case kHIDUsage_GD_Y: wine_obj = 1; break;
698             case kHIDUsage_GD_Z: wine_obj = 2; break;
699             case kHIDUsage_GD_Rx: wine_obj = 3; break;
700             case kHIDUsage_GD_Ry: wine_obj = 4; break;
701             case kHIDUsage_GD_Rz: wine_obj = 5; break;
702             case kHIDUsage_GD_Slider:
703                 wine_obj = 6 + slider_count;
704                 slider_count++;
705                 break;
706         }
707         if (wine_obj < 0 ) continue;
708 
709         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
710         df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
711     }
712 
713     for (i = 0; i < newDevice->generic.devcaps.dwPOVs; i++)
714     {
715         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 8], df->dwObjSize);
716         df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_POV;
717     }
718 
719     for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++)
720     {
721         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
722         df->rgodf[idx  ].pguid = &GUID_Button;
723         df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
724     }
725     newDevice->generic.base.data_format.wine_df = df;
726 
727     /* initialize default properties */
728     get_osx_device_elements_props(newDevice);
729 
730     IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->generic.base.dinput);
731 
732     newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
733     newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
734     if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
735         newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
736     else
737         newDevice->generic.devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
738     newDevice->generic.devcaps.dwFFSamplePeriod = 0;
739     newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
740     newDevice->generic.devcaps.dwFirmwareRevision = 0;
741     newDevice->generic.devcaps.dwHardwareRevision = 0;
742     newDevice->generic.devcaps.dwFFDriverVersion = 0;
743 
744     if (TRACE_ON(dinput)) {
745         _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df);
746         _dump_DIDEVCAPS(&newDevice->generic.devcaps);
747     }
748 
749     *pdev = (LPDIRECTINPUTDEVICEA)newDevice;
750 
751     return DI_OK;
752 
753 FAILED:
754     hr = DIERR_OUTOFMEMORY;
755     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
756     HeapFree(GetProcessHeap(), 0, df);
757     release_DataFormat(&newDevice->generic.base.data_format);
758     HeapFree(GetProcessHeap(),0,newDevice->generic.name);
759     HeapFree(GetProcessHeap(),0,newDevice);
760     *pdev = 0;
761 
762     return hr;
763 }
764 
765 /******************************************************************************
766   *     get_joystick_index : Get the joystick index from a given GUID
767   */
768 static unsigned short get_joystick_index(REFGUID guid)
769 {
770     GUID wine_joystick = DInput_Wine_OsX_Joystick_GUID;
771     GUID dev_guid = *guid;
772 
773     wine_joystick.Data3 = 0;
774     dev_guid.Data3 = 0;
775 
776     /* for the standard joystick GUID use index 0 */
777     if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
778 
779     /* for the wine joystick GUIDs use the index stored in Data3 */
780     if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
781 
782     return 0xffff;
783 }
784 
785 static HRESULT joydev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
786 {
787     unsigned short index;
788     int joystick_devices_count;
789 
790     TRACE("%p %s %p %p\n",dinput, debugstr_guid(rguid), riid, pdev);
791     *pdev = NULL;
792 
793     if ((joystick_devices_count = find_joystick_devices()) == 0)
794         return DIERR_DEVICENOTREG;
795 
796     if ((index = get_joystick_index(rguid)) < 0xffff &&
797         joystick_devices_count && index < joystick_devices_count)
798     {
799         if ((riid == NULL) ||
800         IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
801         IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
802         IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
803         IsEqualGUID(&IID_IDirectInputDevice8A, riid))
804         {
805             return alloc_device(rguid, &JoystickAvt, dinput, pdev, index);
806         }
807 
808         WARN("no interface\n");
809         return DIERR_NOINTERFACE;
810     }
811 
812     return DIERR_DEVICENOTREG;
813 }
814 
815 static HRESULT joydev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
816 {
817     unsigned short index;
818     int joystick_devices_count;
819 
820     TRACE("%p %s %p %p\n",dinput, debugstr_guid(rguid), riid, pdev);
821     *pdev = NULL;
822 
823     if ((joystick_devices_count = find_joystick_devices()) == 0)
824         return DIERR_DEVICENOTREG;
825 
826     if ((index = get_joystick_index(rguid)) < 0xffff &&
827         joystick_devices_count && index < joystick_devices_count)
828     {
829         if ((riid == NULL) ||
830         IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
831         IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
832         IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
833         IsEqualGUID(&IID_IDirectInputDevice8W, riid))
834         {
835             return alloc_device(rguid, &JoystickWvt, dinput, (LPDIRECTINPUTDEVICEA *)pdev, index);
836         }
837         WARN("no interface\n");
838         return DIERR_NOINTERFACE;
839     }
840 
841     WARN("invalid device GUID %s\n",debugstr_guid(rguid));
842     return DIERR_DEVICENOTREG;
843 }
844 
845 const struct dinput_device joystick_osx_device = {
846   "Wine OS X joystick driver",
847   joydev_enum_deviceA,
848   joydev_enum_deviceW,
849   joydev_create_deviceA,
850   joydev_create_deviceW
851 };
852 
853 static const IDirectInputDevice8AVtbl JoystickAvt =
854 {
855     IDirectInputDevice2AImpl_QueryInterface,
856     IDirectInputDevice2AImpl_AddRef,
857     IDirectInputDevice2AImpl_Release,
858     JoystickAGenericImpl_GetCapabilities,
859     IDirectInputDevice2AImpl_EnumObjects,
860     JoystickAGenericImpl_GetProperty,
861     JoystickAGenericImpl_SetProperty,
862     IDirectInputDevice2AImpl_Acquire,
863     IDirectInputDevice2AImpl_Unacquire,
864     JoystickAGenericImpl_GetDeviceState,
865     IDirectInputDevice2AImpl_GetDeviceData,
866     IDirectInputDevice2AImpl_SetDataFormat,
867     IDirectInputDevice2AImpl_SetEventNotification,
868     IDirectInputDevice2AImpl_SetCooperativeLevel,
869     JoystickAGenericImpl_GetObjectInfo,
870     JoystickAGenericImpl_GetDeviceInfo,
871     IDirectInputDevice2AImpl_RunControlPanel,
872     IDirectInputDevice2AImpl_Initialize,
873     IDirectInputDevice2AImpl_CreateEffect,
874     IDirectInputDevice2AImpl_EnumEffects,
875     IDirectInputDevice2AImpl_GetEffectInfo,
876     IDirectInputDevice2AImpl_GetForceFeedbackState,
877     IDirectInputDevice2AImpl_SendForceFeedbackCommand,
878     IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
879     IDirectInputDevice2AImpl_Escape,
880     JoystickAGenericImpl_Poll,
881     IDirectInputDevice2AImpl_SendDeviceData,
882     IDirectInputDevice7AImpl_EnumEffectsInFile,
883     IDirectInputDevice7AImpl_WriteEffectToFile,
884     IDirectInputDevice8AImpl_BuildActionMap,
885     IDirectInputDevice8AImpl_SetActionMap,
886     IDirectInputDevice8AImpl_GetImageInfo
887 };
888 
889 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
890 # define XCAST(fun) (typeof(JoystickWvt.fun))
891 #else
892 # define XCAST(fun) (void*)
893 #endif
894 
895 static const IDirectInputDevice8WVtbl JoystickWvt =
896 {
897     IDirectInputDevice2WImpl_QueryInterface,
898     XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
899     XCAST(Release)IDirectInputDevice2AImpl_Release,
900     XCAST(GetCapabilities)JoystickAGenericImpl_GetCapabilities,
901     IDirectInputDevice2WImpl_EnumObjects,
902     XCAST(GetProperty)JoystickAGenericImpl_GetProperty,
903     XCAST(SetProperty)JoystickAGenericImpl_SetProperty,
904     XCAST(Acquire)IDirectInputDevice2AImpl_Acquire,
905     XCAST(Unacquire)IDirectInputDevice2AImpl_Unacquire,
906     XCAST(GetDeviceState)JoystickAGenericImpl_GetDeviceState,
907     XCAST(GetDeviceData)IDirectInputDevice2AImpl_GetDeviceData,
908     XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
909     XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
910     XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
911     JoystickWGenericImpl_GetObjectInfo,
912     JoystickWGenericImpl_GetDeviceInfo,
913     XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
914     XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
915     XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
916     IDirectInputDevice2WImpl_EnumEffects,
917     IDirectInputDevice2WImpl_GetEffectInfo,
918     XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
919     XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
920     XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
921     XCAST(Escape)IDirectInputDevice2AImpl_Escape,
922     XCAST(Poll)JoystickAGenericImpl_Poll,
923     XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
924     IDirectInputDevice7WImpl_EnumEffectsInFile,
925     IDirectInputDevice7WImpl_WriteEffectToFile,
926     IDirectInputDevice8WImpl_BuildActionMap,
927     IDirectInputDevice8WImpl_SetActionMap,
928     IDirectInputDevice8WImpl_GetImageInfo
929 };
930 #undef XCAST
931 
932 #else /* HAVE_IOHIDMANAGERCREATE */
933 
934 const struct dinput_device joystick_osx_device = {
935   "Wine OS X joystick driver",
936   NULL,
937   NULL,
938   NULL,
939   NULL
940 };
941 
942 #endif /* HAVE_IOHIDMANAGERCREATE */
943 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.