Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
65711634
Commit
65711634
authored
Mar 16, 2015
by
Ken Thomases
Committed by
Alexandre Julliard
Mar 18, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winejoystick: Add WinMM joystick support for OS X.
parent
01227ab2
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
759 additions
and
3 deletions
+759
-3
configure
configure
+1
-1
configure.ac
configure.ac
+1
-1
Makefile.in
dlls/winejoystick.drv/Makefile.in
+3
-1
joystick_osx.c
dlls/winejoystick.drv/joystick_osx.c
+754
-0
No files found.
configure
View file @
65711634
...
...
@@ -13684,7 +13684,7 @@ fi
test
-n
"
$ALSA_LIBS
"
||
enable_winealsa_drv
=
${
enable_winealsa_drv
:-
no
}
test
-n
"
$COREAUDIO_LIBS
"
||
enable_winecoreaudio_drv
=
${
enable_winecoreaudio_drv
:-
no
}
test
"x
$ac_cv_member_oss_sysinfo_numaudioengines
"
=
xyes
||
enable_wineoss_drv
=
${
enable_wineoss_drv
:-
no
}
test
"
$ac_cv_header_linux_joystick_h
"
=
"yes"
||
enable_winejoystick_drv
=
${
enable_winejoystick_drv
:-
no
}
test
"
$ac_cv_header_linux_joystick_h
"
=
"yes"
-o
"
$ac_cv_header_IOKit_hid_IOHIDLib_h
"
=
"yes"
||
enable_winejoystick_drv
=
${
enable_winejoystick_drv
:-
no
}
if
test
"x
$ALSA_LIBS$COREAUDIO_LIBS
"
=
"x"
-a
\
"x
$ac_cv_member_oss_sysinfo_numaudioengines
"
!=
xyes
-a
\
...
...
configure.ac
View file @
65711634
...
...
@@ -1767,7 +1767,7 @@ dnl **** Disable unsupported winmm drivers ****
test -n "$ALSA_LIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no}
test -n "$COREAUDIO_LIBS" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no}
test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no}
test "$ac_cv_header_linux_joystick_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no}
test "$ac_cv_header_linux_joystick_h" = "yes"
-o "$ac_cv_header_IOKit_hid_IOHIDLib_h" = "yes"
|| enable_winejoystick_drv=${enable_winejoystick_drv:-no}
dnl **** Check for any sound system ****
if test "x$ALSA_LIBS$COREAUDIO_LIBS" = "x" -a \
...
...
dlls/winejoystick.drv/Makefile.in
View file @
65711634
MODULE
=
winejoystick.drv
IMPORTS
=
winmm user32
EXTRALIBS
=
$(IOKIT_LIBS)
C_SRCS
=
\
joystick.c
\
joystick_linux.c
joystick_linux.c
\
joystick_osx.c
dlls/winejoystick.drv/joystick_osx.c
0 → 100644
View file @
65711634
/*
* WinMM joystick driver OS X implementation
*
* Copyright 1997 Andreas Mohr
* Copyright 1998 Marcus Meissner
* Copyright 1998,1999 Lionel Ulmer
* Copyright 2000 Wolfgang Schwotzer
* Copyright 2000-2001 TransGaming Technologies Inc.
* Copyright 2002 David Hagood
* Copyright 2009 CodeWeavers, Aric Stewart
* Copyright 2015 Ken Thomases for CodeWeavers Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#if defined(HAVE_IOKIT_HID_IOHIDLIB_H)
#define DWORD UInt32
#define LPDWORD UInt32*
#define LONG SInt32
#define LPLONG SInt32*
#define E_PENDING __carbon_E_PENDING
#define ULONG __carbon_ULONG
#define E_INVALIDARG __carbon_E_INVALIDARG
#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
#define E_HANDLE __carbon_E_HANDLE
#define E_ACCESSDENIED __carbon_E_ACCESSDENIED
#define E_UNEXPECTED __carbon_E_UNEXPECTED
#define E_FAIL __carbon_E_FAIL
#define E_ABORT __carbon_E_ABORT
#define E_POINTER __carbon_E_POINTER
#define E_NOINTERFACE __carbon_E_NOINTERFACE
#define E_NOTIMPL __carbon_E_NOTIMPL
#define S_FALSE __carbon_S_FALSE
#define S_OK __carbon_S_OK
#define HRESULT_FACILITY __carbon_HRESULT_FACILITY
#define IS_ERROR __carbon_IS_ERROR
#define FAILED __carbon_FAILED
#define SUCCEEDED __carbon_SUCCEEDED
#define MAKE_HRESULT __carbon_MAKE_HRESULT
#define HRESULT __carbon_HRESULT
#define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
#undef ULONG
#undef E_INVALIDARG
#undef E_OUTOFMEMORY
#undef E_HANDLE
#undef E_ACCESSDENIED
#undef E_UNEXPECTED
#undef E_FAIL
#undef E_ABORT
#undef E_POINTER
#undef E_NOINTERFACE
#undef E_NOTIMPL
#undef S_FALSE
#undef S_OK
#undef HRESULT_FACILITY
#undef IS_ERROR
#undef FAILED
#undef SUCCEEDED
#undef MAKE_HRESULT
#undef HRESULT
#undef STDMETHODCALLTYPE
#undef DWORD
#undef LPDWORD
#undef LONG
#undef LPLONG
#undef E_PENDING
#include "joystick.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
joystick
);
#define MAXJOYSTICK (JOYSTICKID2 + 30)
enum
{
AXIS_X
,
AXIS_Y
,
AXIS_Z
,
AXIS_RX
,
AXIS_RY
,
AXIS_RZ
,
NUM_AXES
};
struct
axis
{
IOHIDElementRef
element
;
CFIndex
min_value
,
max_value
;
};
typedef
struct
{
BOOL
in_use
;
IOHIDElementRef
element
;
struct
axis
axes
[
NUM_AXES
];
CFMutableArrayRef
buttons
;
IOHIDElementRef
hatswitch
;
}
joystick_t
;
static
joystick_t
joysticks
[
MAXJOYSTICK
];
static
CFMutableArrayRef
device_main_elements
=
NULL
;
static
const
char
*
debugstr_cf
(
CFTypeRef
t
)
{
CFStringRef
s
;
const
char
*
ret
;
if
(
!
t
)
return
"(null)"
;
if
(
CFGetTypeID
(
t
)
==
CFStringGetTypeID
())
s
=
t
;
else
s
=
CFCopyDescription
(
t
);
ret
=
CFStringGetCStringPtr
(
s
,
kCFStringEncodingUTF8
);
if
(
ret
)
ret
=
debugstr_a
(
ret
);
if
(
!
ret
)
{
const
UniChar
*
u
=
CFStringGetCharactersPtr
(
s
);
if
(
u
)
ret
=
debugstr_wn
((
const
WCHAR
*
)
u
,
CFStringGetLength
(
s
));
}
if
(
!
ret
)
{
UniChar
buf
[
200
];
int
len
=
min
(
CFStringGetLength
(
s
),
sizeof
(
buf
)
/
sizeof
(
buf
[
0
]));
CFStringGetCharacters
(
s
,
CFRangeMake
(
0
,
len
),
buf
);
ret
=
debugstr_wn
(
buf
,
len
);
}
if
(
s
!=
t
)
CFRelease
(
s
);
return
ret
;
}
static
const
char
*
debugstr_device
(
IOHIDDeviceRef
device
)
{
return
wine_dbg_sprintf
(
"<IOHIDDevice %p product %s>"
,
device
,
debugstr_cf
(
IOHIDDeviceGetProperty
(
device
,
CFSTR
(
kIOHIDProductKey
))));
}
static
const
char
*
debugstr_element
(
IOHIDElementRef
element
)
{
return
wine_dbg_sprintf
(
"<IOHIDElement %p type %d usage %u/%u device %p>"
,
element
,
IOHIDElementGetType
(
element
),
IOHIDElementGetUsagePage
(
element
),
IOHIDElementGetUsage
(
element
),
IOHIDElementGetDevice
(
element
));
}
static
int
axis_for_usage
(
int
usage
)
{
switch
(
usage
)
{
case
kHIDUsage_GD_X
:
return
AXIS_X
;
case
kHIDUsage_GD_Y
:
return
AXIS_Y
;
case
kHIDUsage_GD_Z
:
return
AXIS_Z
;
case
kHIDUsage_GD_Rx
:
return
AXIS_RX
;
case
kHIDUsage_GD_Ry
:
return
AXIS_RY
;
case
kHIDUsage_GD_Rz
:
return
AXIS_RZ
;
}
return
-
1
;
}
/**************************************************************************
* joystick_from_id
*/
static
joystick_t
*
joystick_from_id
(
DWORD_PTR
device_id
)
{
int
index
;
if
((
device_id
-
(
DWORD_PTR
)
joysticks
)
%
sizeof
(
joysticks
[
0
])
!=
0
)
return
NULL
;
index
=
(
device_id
-
(
DWORD_PTR
)
joysticks
)
/
sizeof
(
joysticks
[
0
]);
if
(
index
<
0
||
index
>=
MAXJOYSTICK
||
!
((
joystick_t
*
)
device_id
)
->
in_use
)
return
NULL
;
return
(
joystick_t
*
)
device_id
;
}
/**************************************************************************
* create_osx_device_match
*/
static
CFDictionaryRef
create_osx_device_match
(
int
usage
)
{
CFDictionaryRef
result
=
NULL
;
int
number
;
CFStringRef
keys
[]
=
{
CFSTR
(
kIOHIDDeviceUsagePageKey
),
CFSTR
(
kIOHIDDeviceUsageKey
)
};
CFNumberRef
values
[
2
];
int
i
;
TRACE
(
"usage %d
\n
"
,
usage
);
number
=
kHIDPage_GenericDesktop
;
values
[
0
]
=
CFNumberCreate
(
kCFAllocatorDefault
,
kCFNumberIntType
,
&
number
);
values
[
1
]
=
CFNumberCreate
(
kCFAllocatorDefault
,
kCFNumberIntType
,
&
usage
);
if
(
values
[
0
]
&&
values
[
1
])
{
result
=
CFDictionaryCreate
(
NULL
,
(
const
void
**
)
keys
,
(
const
void
**
)
values
,
sizeof
(
values
)
/
sizeof
(
values
[
0
]),
&
kCFCopyStringDictionaryKeyCallBacks
,
&
kCFTypeDictionaryValueCallBacks
);
if
(
!
result
)
ERR
(
"CFDictionaryCreate failed.
\n
"
);
}
else
ERR
(
"CFNumberCreate failed.
\n
"
);
for
(
i
=
0
;
i
<
sizeof
(
values
)
/
sizeof
(
values
[
0
]);
i
++
)
if
(
values
[
i
])
CFRelease
(
values
[
i
]);
return
result
;
}
/**************************************************************************
* find_top_level
*/
static
CFIndex
find_top_level
(
IOHIDDeviceRef
hid_device
,
CFMutableArrayRef
main_elements
)
{
CFArrayRef
elements
;
CFIndex
total
=
0
;
TRACE
(
"hid_device %s
\n
"
,
debugstr_device
(
hid_device
));
if
(
!
hid_device
)
return
0
;
elements
=
IOHIDDeviceCopyMatchingElements
(
hid_device
,
NULL
,
0
);
if
(
elements
)
{
CFIndex
i
,
count
=
CFArrayGetCount
(
elements
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
IOHIDElementRef
element
=
(
IOHIDElementRef
)
CFArrayGetValueAtIndex
(
elements
,
i
);
int
type
=
IOHIDElementGetType
(
element
);
TRACE
(
"element %s
\n
"
,
debugstr_element
(
element
));
/* Check for top-level gaming device collections */
if
(
type
==
kIOHIDElementTypeCollection
&&
IOHIDElementGetParent
(
element
)
==
0
)
{
int
usage_page
=
IOHIDElementGetUsagePage
(
element
);
int
usage
=
IOHIDElementGetUsage
(
element
);
if
(
usage_page
==
kHIDPage_GenericDesktop
&&
(
usage
==
kHIDUsage_GD_Joystick
||
usage
==
kHIDUsage_GD_GamePad
))
{
CFArrayAppendValue
(
main_elements
,
element
);
total
++
;
}
}
}
CFRelease
(
elements
);
}
TRACE
(
"-> total %d
\n
"
,
(
int
)
total
);
return
total
;
}
/**************************************************************************
* find_osx_devices
*/
static
int
find_osx_devices
(
void
)
{
IOHIDManagerRef
hid_manager
;
int
usages
[]
=
{
kHIDUsage_GD_Joystick
,
kHIDUsage_GD_GamePad
};
int
i
;
CFDictionaryRef
matching_dicts
[
sizeof
(
usages
)
/
sizeof
(
usages
[
0
])];
CFArrayRef
matching
;
CFSetRef
devset
;
TRACE
(
"()
\n
"
);
hid_manager
=
IOHIDManagerCreate
(
kCFAllocatorDefault
,
0L
);
if
(
IOHIDManagerOpen
(
hid_manager
,
0
)
!=
kIOReturnSuccess
)
{
ERR
(
"Couldn't open IOHIDManager.
\n
"
);
CFRelease
(
hid_manager
);
return
0
;
}
for
(
i
=
0
;
i
<
sizeof
(
matching_dicts
)
/
sizeof
(
matching_dicts
[
0
]);
i
++
)
{
matching_dicts
[
i
]
=
create_osx_device_match
(
usages
[
i
]);
if
(
!
matching_dicts
[
i
])
{
while
(
i
>
0
)
CFRelease
(
matching_dicts
[
--
i
]);
goto
fail
;
}
}
matching
=
CFArrayCreate
(
NULL
,
(
const
void
**
)
matching_dicts
,
sizeof
(
matching_dicts
)
/
sizeof
(
matching_dicts
[
0
]),
&
kCFTypeArrayCallBacks
);
for
(
i
=
0
;
i
<
sizeof
(
matching_dicts
)
/
sizeof
(
matching_dicts
[
0
]);
i
++
)
CFRelease
(
matching_dicts
[
i
]);
IOHIDManagerSetDeviceMatchingMultiple
(
hid_manager
,
matching
);
CFRelease
(
matching
);
devset
=
IOHIDManagerCopyDevices
(
hid_manager
);
if
(
devset
)
{
CFIndex
num_devices
,
num_main_elements
;
const
void
**
refs
;
CFArrayRef
devices
;
num_devices
=
CFSetGetCount
(
devset
);
refs
=
HeapAlloc
(
GetProcessHeap
(),
0
,
num_devices
*
sizeof
(
*
refs
));
if
(
!
refs
)
{
CFRelease
(
devset
);
goto
fail
;
}
CFSetGetValues
(
devset
,
refs
);
devices
=
CFArrayCreate
(
NULL
,
refs
,
num_devices
,
&
kCFTypeArrayCallBacks
);
HeapFree
(
GetProcessHeap
(),
0
,
refs
);
CFRelease
(
devset
);
if
(
!
devices
)
goto
fail
;
device_main_elements
=
CFArrayCreateMutable
(
kCFAllocatorDefault
,
0
,
&
kCFTypeArrayCallBacks
);
if
(
!
device_main_elements
)
{
CFRelease
(
devices
);
goto
fail
;
}
num_main_elements
=
0
;
for
(
i
=
0
;
i
<
num_devices
;
i
++
)
{
IOHIDDeviceRef
hid_device
=
(
IOHIDDeviceRef
)
CFArrayGetValueAtIndex
(
devices
,
i
);
TRACE
(
"hid_device %s
\n
"
,
debugstr_device
(
hid_device
));
num_main_elements
+=
find_top_level
(
hid_device
,
device_main_elements
);
}
CFRelease
(
devices
);
TRACE
(
"found %i device(s), %i collection(s)
\n
"
,(
int
)
num_devices
,(
int
)
num_main_elements
);
return
(
int
)
num_main_elements
;
}
fail:
IOHIDManagerClose
(
hid_manager
,
0
);
CFRelease
(
hid_manager
);
return
0
;
}
/**************************************************************************
* collect_joystick_elements
*/
static
void
collect_joystick_elements
(
joystick_t
*
joystick
,
IOHIDElementRef
collection
)
{
CFIndex
i
,
count
;
CFArrayRef
children
=
IOHIDElementGetChildren
(
collection
);
TRACE
(
"collection %s
\n
"
,
debugstr_element
(
collection
));
count
=
CFArrayGetCount
(
children
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
IOHIDElementRef
child
;
int
type
;
child
=
(
IOHIDElementRef
)
CFArrayGetValueAtIndex
(
children
,
i
);
TRACE
(
"child %s
\n
"
,
debugstr_element
(
child
));
type
=
IOHIDElementGetType
(
child
);
switch
(
type
)
{
case
kIOHIDElementTypeCollection
:
collect_joystick_elements
(
joystick
,
child
);
break
;
case
kIOHIDElementTypeInput_Button
:
{
int
usage_page
=
IOHIDElementGetUsagePage
(
child
);
TRACE
(
"kIOHIDElementTypeInput_Button usage_page %d
\n
"
,
usage_page
);
/* avoid strange elements found on the 360 controller */
if
(
usage_page
==
kHIDPage_Button
)
CFArrayAppendValue
(
joystick
->
buttons
,
child
);
break
;
}
case
kIOHIDElementTypeInput_Axis
:
{
TRACE
(
"kIOHIDElementTypeInput_Axis; ignoring
\n
"
);
break
;
}
case
kIOHIDElementTypeInput_Misc
:
{
uint32_t
usage
=
IOHIDElementGetUsage
(
child
);
switch
(
usage
)
{
case
kHIDUsage_GD_Hatswitch
:
{
TRACE
(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch
\n
"
);
if
(
joystick
->
hatswitch
)
TRACE
(
" ignoring additional hatswitch
\n
"
);
else
joystick
->
hatswitch
=
(
IOHIDElementRef
)
CFRetain
(
child
);
break
;
}
case
kHIDUsage_GD_X
:
case
kHIDUsage_GD_Y
:
case
kHIDUsage_GD_Z
:
case
kHIDUsage_GD_Rx
:
case
kHIDUsage_GD_Ry
:
case
kHIDUsage_GD_Rz
:
{
int
axis
=
axis_for_usage
(
usage
);
TRACE
(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_<axis> (%d) axis %d
\n
"
,
usage
,
axis
);
if
(
axis
<
0
||
joystick
->
axes
[
axis
].
element
)
TRACE
(
" ignoring
\n
"
);
else
{
joystick
->
axes
[
axis
].
element
=
(
IOHIDElementRef
)
CFRetain
(
child
);
joystick
->
axes
[
axis
].
min_value
=
IOHIDElementGetLogicalMin
(
child
);
joystick
->
axes
[
axis
].
max_value
=
IOHIDElementGetLogicalMax
(
child
);
}
break
;
}
case
kHIDUsage_GD_Slider
:
TRACE
(
"kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Slider; ignoring
\n
"
);
break
;
default:
FIXME
(
"kIOHIDElementTypeInput_Misc / Unhandled usage %d
\n
"
,
usage
);
break
;
}
break
;
}
default:
FIXME
(
"Unhandled type %i
\n
"
,
type
);
break
;
}
}
}
/**************************************************************************
* button_usage_comparator
*/
static
CFComparisonResult
button_usage_comparator
(
const
void
*
val1
,
const
void
*
val2
,
void
*
context
)
{
IOHIDElementRef
element1
=
(
IOHIDElementRef
)
val1
,
element2
=
(
IOHIDElementRef
)
val2
;
int
usage1
=
IOHIDElementGetUsage
(
element1
),
usage2
=
IOHIDElementGetUsage
(
element2
);
if
(
usage1
<
usage2
)
return
kCFCompareLessThan
;
if
(
usage1
>
usage2
)
return
kCFCompareGreaterThan
;
return
kCFCompareEqualTo
;
}
/**************************************************************************
* driver_open
*/
LRESULT
driver_open
(
LPSTR
str
,
DWORD
index
)
{
if
(
index
>=
MAXJOYSTICK
||
joysticks
[
index
].
in_use
)
return
0
;
joysticks
[
index
].
in_use
=
TRUE
;
return
(
LRESULT
)
&
joysticks
[
index
];
}
/**************************************************************************
* driver_close
*/
LRESULT
driver_close
(
DWORD_PTR
device_id
)
{
joystick_t
*
joystick
=
joystick_from_id
(
device_id
);
int
i
;
if
(
joystick
==
NULL
)
return
0
;
CFRelease
(
joystick
->
element
);
for
(
i
=
0
;
i
<
NUM_AXES
;
i
++
)
{
if
(
joystick
->
axes
[
i
].
element
)
CFRelease
(
joystick
->
axes
[
i
].
element
);
}
if
(
joystick
->
buttons
)
CFRelease
(
joystick
->
buttons
);
if
(
joystick
->
hatswitch
)
CFRelease
(
joystick
->
hatswitch
);
memset
(
joystick
,
0
,
sizeof
(
*
joystick
));
return
1
;
}
/**************************************************************************
* open_joystick
*/
static
BOOL
open_joystick
(
joystick_t
*
joystick
)
{
CFIndex
index
;
CFRange
range
;
if
(
joystick
->
element
)
return
TRUE
;
if
(
!
device_main_elements
)
{
find_osx_devices
();
if
(
!
device_main_elements
)
return
FALSE
;
}
index
=
joystick
-
joysticks
;
if
(
index
>
CFArrayGetCount
(
device_main_elements
))
return
FALSE
;
joystick
->
element
=
(
IOHIDElementRef
)
CFArrayGetValueAtIndex
(
device_main_elements
,
index
);
joystick
->
buttons
=
CFArrayCreateMutable
(
kCFAllocatorDefault
,
0
,
&
kCFTypeArrayCallBacks
);
collect_joystick_elements
(
joystick
,
joystick
->
element
);
/* Sort buttons into correct order */
range
.
location
=
0
;
range
.
length
=
CFArrayGetCount
(
joystick
->
buttons
);
CFArraySortValues
(
joystick
->
buttons
,
range
,
button_usage_comparator
,
NULL
);
if
(
range
.
length
>
32
)
{
/* Delete any buttons beyond the first 32 */
range
.
location
=
32
;
range
.
length
-=
32
;
CFArrayReplaceValues
(
joystick
->
buttons
,
range
,
NULL
,
0
);
}
return
TRUE
;
}
/**************************************************************************
* driver_joyGetDevCaps
*/
LRESULT
driver_joyGetDevCaps
(
DWORD_PTR
device_id
,
JOYCAPSW
*
caps
,
DWORD
size
)
{
joystick_t
*
joystick
;
IOHIDDeviceRef
device
;
if
((
joystick
=
joystick_from_id
(
device_id
))
==
NULL
)
return
MMSYSERR_NODRIVER
;
if
(
!
open_joystick
(
joystick
))
return
JOYERR_PARMS
;
caps
->
szPname
[
0
]
=
0
;
device
=
IOHIDElementGetDevice
(
joystick
->
element
);
if
(
device
)
{
CFStringRef
product_name
=
IOHIDDeviceGetProperty
(
device
,
CFSTR
(
kIOHIDProductKey
));
if
(
product_name
)
{
CFRange
range
;
range
.
location
=
0
;
range
.
length
=
min
(
MAXPNAMELEN
-
1
,
CFStringGetLength
(
product_name
));
CFStringGetCharacters
(
product_name
,
range
,
(
UniChar
*
)
caps
->
szPname
);
caps
->
szPname
[
range
.
length
]
=
0
;
}
}
caps
->
wMid
=
MM_MICROSOFT
;
caps
->
wPid
=
MM_PC_JOYSTICK
;
caps
->
wXmin
=
0
;
caps
->
wXmax
=
0xFFFF
;
caps
->
wYmin
=
0
;
caps
->
wYmax
=
0xFFFF
;
caps
->
wZmin
=
0
;
caps
->
wZmax
=
joystick
->
axes
[
AXIS_Z
].
element
?
0xFFFF
:
0
;
caps
->
wNumButtons
=
CFArrayGetCount
(
joystick
->
buttons
);
if
(
size
==
sizeof
(
JOYCAPSW
))
{
int
i
;
/* complete 95 structure */
caps
->
wRmin
=
0
;
caps
->
wRmax
=
0xFFFF
;
caps
->
wUmin
=
0
;
caps
->
wUmax
=
0xFFFF
;
caps
->
wVmin
=
0
;
caps
->
wVmax
=
0xFFFF
;
caps
->
wMaxAxes
=
6
;
/* same as MS Joystick Driver */
caps
->
wNumAxes
=
0
;
caps
->
wMaxButtons
=
32
;
/* same as MS Joystick Driver */
caps
->
szRegKey
[
0
]
=
0
;
caps
->
szOEMVxD
[
0
]
=
0
;
caps
->
wCaps
=
0
;
for
(
i
=
0
;
i
<
NUM_AXES
;
i
++
)
{
if
(
joystick
->
axes
[
i
].
element
)
{
caps
->
wNumAxes
++
;
switch
(
i
)
{
case
AXIS_Z
:
caps
->
wCaps
|=
JOYCAPS_HASZ
;
break
;
case
AXIS_RX
:
caps
->
wCaps
|=
JOYCAPS_HASU
;
break
;
case
AXIS_RY
:
caps
->
wCaps
|=
JOYCAPS_HASV
;
break
;
case
AXIS_RZ
:
caps
->
wCaps
|=
JOYCAPS_HASR
;
break
;
}
}
}
if
(
joystick
->
hatswitch
)
caps
->
wCaps
|=
JOYCAPS_HASPOV
|
JOYCAPS_POV4DIR
;
}
TRACE
(
"name %s buttons %u axes %d caps 0x%08x
\n
"
,
debugstr_w
(
caps
->
szPname
),
caps
->
wNumButtons
,
caps
->
wNumAxes
,
caps
->
wCaps
);
return
JOYERR_NOERROR
;
}
/**************************************************************************
* driver_joyGetPosEx
*/
LRESULT
driver_joyGetPosEx
(
DWORD_PTR
device_id
,
JOYINFOEX
*
info
)
{
static
const
struct
{
DWORD
flag
;
off_t
offset
;
}
axis_map
[
NUM_AXES
]
=
{
{
JOY_RETURNX
,
FIELD_OFFSET
(
JOYINFOEX
,
dwXpos
)
},
{
JOY_RETURNY
,
FIELD_OFFSET
(
JOYINFOEX
,
dwYpos
)
},
{
JOY_RETURNZ
,
FIELD_OFFSET
(
JOYINFOEX
,
dwZpos
)
},
{
JOY_RETURNU
,
FIELD_OFFSET
(
JOYINFOEX
,
dwUpos
)
},
{
JOY_RETURNV
,
FIELD_OFFSET
(
JOYINFOEX
,
dwVpos
)
},
{
JOY_RETURNR
,
FIELD_OFFSET
(
JOYINFOEX
,
dwRpos
)
},
};
joystick_t
*
joystick
;
IOHIDDeviceRef
device
;
CFIndex
i
,
count
;
IOHIDValueRef
valueRef
;
long
value
;
if
((
joystick
=
joystick_from_id
(
device_id
))
==
NULL
)
return
MMSYSERR_NODRIVER
;
if
(
!
open_joystick
(
joystick
))
return
JOYERR_PARMS
;
device
=
IOHIDElementGetDevice
(
joystick
->
element
);
if
(
info
->
dwFlags
&
JOY_RETURNBUTTONS
)
{
info
->
dwButtons
=
0
;
info
->
dwButtonNumber
=
0
;
count
=
CFArrayGetCount
(
joystick
->
buttons
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
IOHIDElementRef
button
=
(
IOHIDElementRef
)
CFArrayGetValueAtIndex
(
joystick
->
buttons
,
i
);
IOHIDDeviceGetValue
(
device
,
button
,
&
valueRef
);
value
=
IOHIDValueGetIntegerValue
(
valueRef
);
if
(
value
)
{
info
->
dwButtons
|=
1
<<
i
;
if
(
!
info
->
dwButtonNumber
)
info
->
dwButtonNumber
=
i
+
1
;
}
}
}
for
(
i
=
0
;
i
<
NUM_AXES
;
i
++
)
{
if
(
info
->
dwFlags
&
axis_map
[
i
].
flag
)
{
DWORD
*
field
=
(
DWORD
*
)((
char
*
)
info
+
axis_map
[
i
].
offset
);
if
(
joystick
->
axes
[
i
].
element
)
{
IOHIDDeviceGetValue
(
device
,
joystick
->
axes
[
i
].
element
,
&
valueRef
);
value
=
IOHIDValueGetIntegerValue
(
valueRef
)
-
joystick
->
axes
[
i
].
min_value
;
*
field
=
MulDiv
(
value
,
0xFFFF
,
joystick
->
axes
[
i
].
max_value
-
joystick
->
axes
[
i
].
min_value
);
}
else
{
*
field
=
0
;
info
->
dwFlags
&=
~
axis_map
[
i
].
flag
;
}
}
}
if
(
info
->
dwFlags
&
JOY_RETURNPOV
)
{
if
(
joystick
->
hatswitch
)
{
IOHIDDeviceGetValue
(
device
,
joystick
->
hatswitch
,
&
valueRef
);
value
=
IOHIDValueGetIntegerValue
(
valueRef
);
if
(
value
>=
8
)
info
->
dwPOV
=
JOY_POVCENTERED
;
else
info
->
dwPOV
=
value
*
4500
;
}
else
{
info
->
dwPOV
=
0
;
info
->
dwFlags
&=
~
JOY_RETURNPOV
;
}
}
TRACE
(
"x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, pov %d, flags: 0x%04x
\n
"
,
info
->
dwXpos
,
info
->
dwYpos
,
info
->
dwZpos
,
info
->
dwRpos
,
info
->
dwUpos
,
info
->
dwVpos
,
info
->
dwButtons
,
info
->
dwPOV
,
info
->
dwFlags
);
return
JOYERR_NOERROR
;
}
/**************************************************************************
* driver_joyGetPos
*/
LRESULT
driver_joyGetPos
(
DWORD_PTR
device_id
,
JOYINFO
*
info
)
{
JOYINFOEX
ji
;
LONG
ret
;
memset
(
&
ji
,
0
,
sizeof
(
ji
));
ji
.
dwSize
=
sizeof
(
ji
);
ji
.
dwFlags
=
JOY_RETURNX
|
JOY_RETURNY
|
JOY_RETURNZ
|
JOY_RETURNBUTTONS
;
ret
=
driver_joyGetPosEx
(
device_id
,
&
ji
);
if
(
ret
==
JOYERR_NOERROR
)
{
info
->
wXpos
=
ji
.
dwXpos
;
info
->
wYpos
=
ji
.
dwYpos
;
info
->
wZpos
=
ji
.
dwZpos
;
info
->
wButtons
=
ji
.
dwButtons
;
}
return
ret
;
}
#endif
/* HAVE_IOKIT_HID_IOHIDLIB_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment