WinRT: merged with SDL 2.0.1 codebase

This commit is contained in:
David Ludwig 2013-10-27 21:26:46 -04:00
commit 59df93166d
344 changed files with 12745 additions and 7248 deletions

View file

@ -52,7 +52,7 @@ struct _SDL_HatMapping
*/
#define k_nMaxHatEntries 0x3f + 1
/* our in memory mapping db between joystick objects and controller mappings*/
/* our in memory mapping db between joystick objects and controller mappings */
struct _SDL_ControllerMapping
{
SDL_JoystickGUID guid;
@ -758,7 +758,7 @@ SDL_GameControllerLoadHints()
{
const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERCONFIG);
if ( hint && hint[0] ) {
int nchHints = SDL_strlen( hint );
size_t nchHints = SDL_strlen( hint );
char *pUserMappings = SDL_malloc( nchHints + 1 );
char *pTempMappings = pUserMappings;
SDL_memcpy( pUserMappings, hint, nchHints );

View file

@ -437,22 +437,13 @@ SDL_JoystickClose(SDL_Joystick * joystick)
joysticklist = joysticklist->next;
}
if (joystick->name)
SDL_free(joystick->name);
SDL_free(joystick->name);
/* Free the data associated with this joystick */
if (joystick->axes) {
SDL_free(joystick->axes);
}
if (joystick->hats) {
SDL_free(joystick->hats);
}
if (joystick->balls) {
SDL_free(joystick->balls);
}
if (joystick->buttons) {
SDL_free(joystick->buttons);
}
SDL_free(joystick->axes);
SDL_free(joystick->hats);
SDL_free(joystick->balls);
SDL_free(joystick->buttons);
SDL_free(joystick);
}
@ -488,14 +479,14 @@ SDL_PrivateJoystickShouldIgnoreEvent()
if (SDL_WasInit(SDL_INIT_VIDEO)) {
if (SDL_GetKeyboardFocus() == NULL) {
// Video is initialized and we don't have focus, ignore the event.
/* Video is initialized and we don't have focus, ignore the event. */
return SDL_TRUE;
} else {
return SDL_FALSE;
}
}
// Video subsystem wasn't initialized, always allow the event
/* Video subsystem wasn't initialized, always allow the event */
return SDL_FALSE;
}
@ -772,6 +763,11 @@ SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
/* return the guid for this opened device */
SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
{
if (!SDL_PrivateJoystickValid(joystick)) {
SDL_JoystickGUID emptyGUID;
SDL_zero( emptyGUID );
return emptyGUID;
}
return SDL_SYS_JoystickGetGUID( joystick );
}
@ -785,7 +781,7 @@ void SDL_JoystickGetGUIDString( SDL_JoystickGUID guid, char *pszGUID, int cbGUID
return;
}
for ( i = 0; i < sizeof(guid.data) && i < (cbGUID-1); i++ )
for ( i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++ )
{
/* each input byte writes 2 ascii chars, and might write a null byte. */
/* If we don't have room for next input byte, stop */
@ -834,7 +830,7 @@ SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
{
SDL_JoystickGUID guid;
int maxoutputbytes= sizeof(guid);
int len = SDL_strlen( pchGUID );
size_t len = SDL_strlen( pchGUID );
Uint8 *p;
int i;

View file

@ -111,6 +111,7 @@ extern SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick);
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
/* Function to get the current instance id of the joystick located at device_index */
extern SDL_bool SDL_SYS_IsXInputDeviceIndex( int device_index );
extern SDL_bool SDL_SYS_IsXInputJoystick(SDL_Joystick * joystick);
#endif
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -231,12 +231,8 @@ extern "C"
if (joystick->hwdata) {
joystick->hwdata->stick->Close();
delete joystick->hwdata->stick;
if (joystick->hwdata->new_hats) {
SDL_free(joystick->hwdata->new_hats);
}
if (joystick->hwdata->new_axes) {
SDL_free(joystick->hwdata->new_axes);
}
SDL_free(joystick->hwdata->new_hats);
SDL_free(joystick->hwdata->new_axes);
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
}

View file

@ -446,48 +446,47 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joy)
static int x, y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
if (joy->hwdata->type == BSDJOY_JOY) {
if (read(joy->hwdata->fd, &gameport, sizeof gameport) !=
sizeof gameport)
return;
if (abs(x - gameport.x) > 8) {
x = gameport.x;
if (x < xmin) {
xmin = x;
while (read(joy->hwdata->fd, &gameport, sizeof gameport) == sizeof gameport) {
if (abs(x - gameport.x) > 8) {
x = gameport.x;
if (x < xmin) {
xmin = x;
}
if (x > xmax) {
xmax = x;
}
if (xmin == xmax) {
xmin--;
xmax++;
}
v = (Sint32) x;
v -= (xmax + xmin + 1) / 2;
v *= 32768 / ((xmax - xmin + 1) / 2);
SDL_PrivateJoystickAxis(joy, 0, v);
}
if (x > xmax) {
xmax = x;
if (abs(y - gameport.y) > 8) {
y = gameport.y;
if (y < ymin) {
ymin = y;
}
if (y > ymax) {
ymax = y;
}
if (ymin == ymax) {
ymin--;
ymax++;
}
v = (Sint32) y;
v -= (ymax + ymin + 1) / 2;
v *= 32768 / ((ymax - ymin + 1) / 2);
SDL_PrivateJoystickAxis(joy, 1, v);
}
if (xmin == xmax) {
xmin--;
xmax++;
if (gameport.b1 != joy->buttons[0]) {
SDL_PrivateJoystickButton(joy, 0, gameport.b1);
}
v = (Sint32) x;
v -= (xmax + xmin + 1) / 2;
v *= 32768 / ((xmax - xmin + 1) / 2);
SDL_PrivateJoystickAxis(joy, 0, v);
}
if (abs(y - gameport.y) > 8) {
y = gameport.y;
if (y < ymin) {
ymin = y;
if (gameport.b2 != joy->buttons[1]) {
SDL_PrivateJoystickButton(joy, 1, gameport.b2);
}
if (y > ymax) {
ymax = y;
}
if (ymin == ymax) {
ymin--;
ymax++;
}
v = (Sint32) y;
v -= (ymax + ymin + 1) / 2;
v *= 32768 / ((ymax - ymin + 1) / 2);
SDL_PrivateJoystickAxis(joy, 1, v);
}
if (gameport.b1 != joy->buttons[0]) {
SDL_PrivateJoystickButton(joy, 0, gameport.b1);
}
if (gameport.b2 != joy->buttons[1]) {
SDL_PrivateJoystickButton(joy, 1, gameport.b2);
}
return;
}
@ -495,65 +494,62 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joy)
rep = &joy->hwdata->inreport;
if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) {
return;
}
while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
#else
hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
#endif
if (hdata == NULL) {
fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);
return;
}
if (hdata == NULL) {
/*fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);*/
continue;
}
for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
switch (hitem.kind) {
case hid_input:
switch (HID_PAGE(hitem.usage)) {
case HUP_GENERIC_DESKTOP:
{
unsigned usage = HID_USAGE(hitem.usage);
int joyaxe = usage_to_joyaxe(usage);
if (joyaxe >= 0) {
naxe = joy->hwdata->axis_map[joyaxe];
/* scaleaxe */
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
v -= (hitem.logical_maximum +
hitem.logical_minimum + 1) / 2;
v *= 32768 /
((hitem.logical_maximum -
hitem.logical_minimum + 1) / 2);
if (v != joy->axes[naxe]) {
SDL_PrivateJoystickAxis(joy, naxe, v);
for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
switch (hitem.kind) {
case hid_input:
switch (HID_PAGE(hitem.usage)) {
case HUP_GENERIC_DESKTOP:
{
unsigned usage = HID_USAGE(hitem.usage);
int joyaxe = usage_to_joyaxe(usage);
if (joyaxe >= 0) {
naxe = joy->hwdata->axis_map[joyaxe];
/* scaleaxe */
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
v -= (hitem.logical_maximum +
hitem.logical_minimum + 1) / 2;
v *= 32768 /
((hitem.logical_maximum -
hitem.logical_minimum + 1) / 2);
if (v != joy->axes[naxe]) {
SDL_PrivateJoystickAxis(joy, naxe, v);
}
} else if (usage == HUG_HAT_SWITCH) {
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
SDL_PrivateJoystickHat(joy, 0,
hatval_to_sdl(v) -
hitem.logical_minimum);
}
} else if (usage == HUG_HAT_SWITCH) {
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
SDL_PrivateJoystickHat(joy, 0,
hatval_to_sdl(v) -
hitem.logical_minimum);
break;
}
case HUP_BUTTON:
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
if (joy->buttons[nbutton] != v) {
SDL_PrivateJoystickButton(joy, nbutton, v);
}
nbutton++;
break;
default:
continue;
}
case HUP_BUTTON:
v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
if (joy->buttons[nbutton] != v) {
SDL_PrivateJoystickButton(joy, nbutton, v);
}
nbutton++;
break;
default:
continue;
break;
}
break;
default:
break;
}
hid_end_parse(hdata);
}
hid_end_parse(hdata);
return;
}
/* Function to close a joystick after use */
@ -577,10 +573,8 @@ SDL_SYS_JoystickQuit(void)
int i;
for (i = 0; i < MAX_JOYS; i++) {
if (joynames[i] != NULL)
SDL_free(joynames[i]);
if (joydevnames[i] != NULL)
SDL_free(joydevnames[i]);
SDL_free(joynames[i]);
SDL_free(joydevnames[i]);
}
return;
@ -657,9 +651,7 @@ report_alloc(struct report *r, struct report_desc *rd, int repind)
static void
report_free(struct report *r)
{
if (r->buf != NULL) {
SDL_free(r->buf);
}
SDL_free(r->buf);
r->status = SREPORT_UNINIT;
}

View file

@ -589,7 +589,6 @@ HIDBuildDevice(io_object_t hidDevice)
if (kIOReturnSuccess == result) {
HIDGetDeviceInfo(hidDevice, hidProperties, pDevice); /* hidDevice used to find parents in registry tree */
HIDGetCollectionElements(hidProperties, pDevice);
pDevice->instance_id = ++s_joystick_instance_id;
} else {
DisposePtr((Ptr) pDevice);
pDevice = NULL;
@ -678,6 +677,9 @@ AddDeviceHelper( io_object_t ioHIDDeviceObject )
return 0;
}
/* Allocate an instance ID for this device */
device->instance_id = ++s_joystick_instance_id;
/* We have to do some storage of the io_service_t for
* SDL_HapticOpenFromJoystick */
if (FFIsForceFeedback(ioHIDDeviceObject) == FF_OK) {
@ -771,7 +773,7 @@ SDL_SYS_JoystickInit(void)
("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching.");
}
/*/ Now search I/O Registry for matching devices. */
/* Now search I/O Registry for matching devices. */
result =
IOServiceGetMatchingServices(masterPort, hidMatchDictionary,
&hidObjectIterator);

View file

@ -106,7 +106,7 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
[[SDLUIAccelerationDelegate sharedDelegate] setHasNewData: NO];
SDL_PrivateJoystickAxis(joystick, 0, orientation[0]);
SDL_PrivateJoystickAxis(joystick, 1, orientation[1]);
SDL_PrivateJoystickAxis(joystick, 1, -orientation[1]);
SDL_PrivateJoystickAxis(joystick, 2, orientation[2]);
}

View file

@ -52,124 +52,13 @@
#define SYN_DROPPED 3
#endif
/*
* !!! FIXME: move all the udev stuff to src/core/linux, so I can reuse it
* !!! FIXME: for audio hardware disconnects.
*/
#ifdef HAVE_LIBUDEV_H
#define SDL_USE_LIBUDEV 1
#include "SDL_loadso.h"
#include <libudev.h>
#include <sys/time.h>
#include <sys/types.h>
#include "../../core/linux/SDL_udev.h"
/* we never link directly to libudev. */
/* !!! FIXME: can we generalize this? ALSA, etc, do the same things. */
static const char *udev_library = "libudev.so.0";
static void *udev_handle = NULL;
/* !!! FIXME: this is kinda ugly. */
static SDL_bool
load_udev_sym(const char *fn, void **addr)
{
*addr = SDL_LoadFunction(udev_handle, fn);
if (*addr == NULL) {
/* Don't call SDL_SetError(): SDL_LoadFunction already did. */
return SDL_FALSE;
}
return SDL_TRUE;
}
/* libudev entry points... */
static const char *(*UDEV_udev_device_get_action)(struct udev_device *) = NULL;
static const char *(*UDEV_udev_device_get_devnode)(struct udev_device *) = NULL;
static const char *(*UDEV_udev_device_get_property_value)(struct udev_device *, const char *) = NULL;
static struct udev_device *(*UDEV_udev_device_new_from_syspath)(struct udev *, const char *) = NULL;
static void (*UDEV_udev_device_unref)(struct udev_device *) = NULL;
static int (*UDEV_udev_enumerate_add_match_property)(struct udev_enumerate *, const char *, const char *) = NULL;
static int (*UDEV_udev_enumerate_add_match_subsystem)(struct udev_enumerate *, const char *) = NULL;
static struct udev_list_entry *(*UDEV_udev_enumerate_get_list_entry)(struct udev_enumerate *) = NULL;
static struct udev_enumerate *(*UDEV_udev_enumerate_new)(struct udev *) = NULL;
static int (*UDEV_udev_enumerate_scan_devices)(struct udev_enumerate *) = NULL;
static void (*UDEV_udev_enumerate_unref)(struct udev_enumerate *) = NULL;
static const char *(*UDEV_udev_list_entry_get_name)(struct udev_list_entry *) = NULL;
static struct udev_list_entry *(*UDEV_udev_list_entry_get_next)(struct udev_list_entry *) = NULL;
static int (*UDEV_udev_monitor_enable_receiving)(struct udev_monitor *) = NULL;
static int (*UDEV_udev_monitor_filter_add_match_subsystem_devtype)(struct udev_monitor *, const char *, const char *) = NULL;
static int (*UDEV_udev_monitor_get_fd)(struct udev_monitor *) = NULL;
static struct udev_monitor *(*UDEV_udev_monitor_new_from_netlink)(struct udev *, const char *) = NULL;
static struct udev_device *(*UDEV_udev_monitor_receive_device)(struct udev_monitor *) = NULL;
static void (*UDEV_udev_monitor_unref)(struct udev_monitor *) = NULL;
static struct udev *(*UDEV_udev_new)(void) = NULL;
static void (*UDEV_udev_unref)(struct udev *) = NULL;
static int
load_udev_syms(void)
{
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
#define SDL_UDEV_SYM(x) \
if (!load_udev_sym(#x, (void **) (char *) &UDEV_##x)) return -1
SDL_UDEV_SYM(udev_device_get_action);
SDL_UDEV_SYM(udev_device_get_devnode);
SDL_UDEV_SYM(udev_device_get_property_value);
SDL_UDEV_SYM(udev_device_new_from_syspath);
SDL_UDEV_SYM(udev_device_unref);
SDL_UDEV_SYM(udev_enumerate_add_match_property);
SDL_UDEV_SYM(udev_enumerate_add_match_subsystem);
SDL_UDEV_SYM(udev_enumerate_get_list_entry);
SDL_UDEV_SYM(udev_enumerate_new);
SDL_UDEV_SYM(udev_enumerate_scan_devices);
SDL_UDEV_SYM(udev_enumerate_unref);
SDL_UDEV_SYM(udev_list_entry_get_name);
SDL_UDEV_SYM(udev_list_entry_get_next);
SDL_UDEV_SYM(udev_monitor_enable_receiving);
SDL_UDEV_SYM(udev_monitor_filter_add_match_subsystem_devtype);
SDL_UDEV_SYM(udev_monitor_get_fd);
SDL_UDEV_SYM(udev_monitor_new_from_netlink);
SDL_UDEV_SYM(udev_monitor_receive_device);
SDL_UDEV_SYM(udev_monitor_unref);
SDL_UDEV_SYM(udev_new);
SDL_UDEV_SYM(udev_unref);
#undef SDL_UDEV_SYM
return 0;
}
static void
UnloadUDEVLibrary(void)
{
if (udev_handle != NULL) {
SDL_UnloadObject(udev_handle);
udev_handle = NULL;
}
}
static int
LoadUDEVLibrary(void)
{
int retval = 0;
if (udev_handle == NULL) {
udev_handle = SDL_LoadObject(udev_library);
if (udev_handle == NULL) {
retval = -1;
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
} else {
retval = load_udev_syms();
if (retval < 0) {
UnloadUDEVLibrary();
}
}
}
return retval;
}
static struct udev *udev = NULL;
static struct udev_monitor *udev_mon = NULL;
#endif
static int MaybeAddDevice(const char *path);
#if SDL_USE_LIBUDEV
static int MaybeRemoveDevice(const char *path);
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
#endif /* SDL_USE_LIBUDEV */
/* A linked list of available joysticks */
@ -246,6 +135,30 @@ IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *gui
return 1;
}
#if SDL_USE_LIBUDEV
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
{
if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
return;
}
switch( udev_type )
{
case SDL_UDEV_DEVICEADDED:
MaybeAddDevice(devpath);
break;
case SDL_UDEV_DEVICEREMOVED:
MaybeRemoveDevice(devpath);
break;
default:
break;
}
}
#endif /* SDL_USE_LIBUDEV */
/* !!! FIXME: I would love to dump this code and use libudev instead. */
static int
@ -257,6 +170,9 @@ MaybeAddDevice(const char *path)
char namebuf[128];
SDL_JoystickGUID guid;
SDL_joylist_item *item;
#if !SDL_EVENTS_DISABLED
SDL_Event event;
#endif
if (path == NULL) {
return -1;
@ -314,6 +230,19 @@ MaybeAddDevice(const char *path)
SDL_joylist_tail = item;
}
/* !!! FIXME: Move this to an SDL_PrivateJoyDeviceAdded() function? */
#if !SDL_EVENTS_DISABLED
event.type = SDL_JOYDEVICEADDED;
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
event.jdevice.which = numjoysticks;
if ( (SDL_EventOK == NULL) ||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
SDL_PushEvent(&event);
}
}
#endif /* !SDL_EVENTS_DISABLED */
return numjoysticks++;
}
@ -324,6 +253,9 @@ MaybeRemoveDevice(const char *path)
{
SDL_joylist_item *item;
SDL_joylist_item *prev = NULL;
#if !SDL_EVENTS_DISABLED
SDL_Event event;
#endif
if (path == NULL) {
return -1;
@ -345,6 +277,20 @@ MaybeRemoveDevice(const char *path)
if (item == SDL_joylist_tail) {
SDL_joylist_tail = prev;
}
/* !!! FIXME: Move this to an SDL_PrivateJoyDeviceRemoved() function? */
#if !SDL_EVENTS_DISABLED
event.type = SDL_JOYDEVICEREMOVED;
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
event.jdevice.which = item->device_instance;
if ( (SDL_EventOK == NULL) ||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
SDL_PushEvent(&event);
}
}
#endif /* !SDL_EVENTS_DISABLED */
SDL_free(item->path);
SDL_free(item->name);
SDL_free(item);
@ -380,40 +326,19 @@ JoystickInitWithoutUdev(void)
static int
JoystickInitWithUdev(void)
{
struct udev_enumerate *enumerate = NULL;
struct udev_list_entry *devs = NULL;
struct udev_list_entry *item = NULL;
SDL_assert(udev == NULL);
udev = UDEV_udev_new();
if (udev == NULL) {
return SDL_SetError("udev_new() failed");
if (SDL_UDEV_Init() < 0) {
return SDL_SetError("Could not initialize UDEV");
}
udev_mon = UDEV_udev_monitor_new_from_netlink(udev, "udev");
if (udev_mon != NULL) { /* okay if it's NULL, we just lose hotplugging. */
UDEV_udev_monitor_filter_add_match_subsystem_devtype(udev_mon,
"input", NULL);
UDEV_udev_monitor_enable_receiving(udev_mon);
/* Set up the udev callback */
if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
SDL_UDEV_Quit();
return SDL_SetError("Could not set up joystick <-> udev callback");
}
enumerate = UDEV_udev_enumerate_new(udev);
if (enumerate == NULL) {
return SDL_SetError("udev_enumerate_new() failed");
}
UDEV_udev_enumerate_add_match_subsystem(enumerate, "input");
UDEV_udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYSTICK", "1");
UDEV_udev_enumerate_scan_devices(enumerate);
devs = UDEV_udev_enumerate_get_list_entry(enumerate);
for (item = devs; item; item = UDEV_udev_list_entry_get_next(item)) {
const char *path = UDEV_udev_list_entry_get_name(item);
struct udev_device *dev = UDEV_udev_device_new_from_syspath(udev, path);
MaybeAddDevice(UDEV_udev_device_get_devnode(dev));
UDEV_udev_device_unref(dev);
}
UDEV_udev_enumerate_unref(enumerate);
/* Force a scan to build the initial device list */
SDL_UDEV_Scan();
return numjoysticks;
}
@ -439,9 +364,7 @@ SDL_SYS_JoystickInit(void)
}
#if SDL_USE_LIBUDEV
if (LoadUDEVLibrary() == 0) { /* okay if this fails, FOR NOW. */
return JoystickInitWithUdev();
}
return JoystickInitWithUdev();
#endif
return JoystickInitWithoutUdev();
@ -452,99 +375,21 @@ int SDL_SYS_NumJoysticks()
return numjoysticks;
}
static SDL_bool
HotplugUpdateAvailable(void)
{
#if SDL_USE_LIBUDEV
if (udev_mon != NULL) {
const int fd = UDEV_udev_monitor_get_fd(udev_mon);
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = 0;
tv.tv_usec = 0;
if ((select(fd+1, &fds, NULL, NULL, &tv) > 0) && (FD_ISSET(fd, &fds))) {
return SDL_TRUE;
}
}
#endif
return SDL_FALSE;
}
void SDL_SYS_JoystickDetect()
{
#if SDL_USE_LIBUDEV
struct udev_device *dev = NULL;
const char *devnode = NULL;
const char *action = NULL;
const char *val = NULL;
while (HotplugUpdateAvailable()) {
dev = UDEV_udev_monitor_receive_device(udev_mon);
if (dev == NULL) {
break;
}
val = UDEV_udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
if ((!val) || (SDL_strcmp(val, "1") != 0)) {
continue;
}
action = UDEV_udev_device_get_action(dev);
devnode = UDEV_udev_device_get_devnode(dev);
if (SDL_strcmp(action, "add") == 0) {
const int device_index = MaybeAddDevice(devnode);
if (device_index != -1) {
/* !!! FIXME: Move this to an SDL_PrivateJoyDeviceAdded() function? */
#if !SDL_EVENTS_DISABLED
SDL_Event event;
event.type = SDL_JOYDEVICEADDED;
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
event.jdevice.which = device_index;
if ( (SDL_EventOK == NULL) ||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
SDL_PushEvent(&event);
}
}
#endif /* !SDL_EVENTS_DISABLED */
}
} else if (SDL_strcmp(action, "remove") == 0) {
const int inst = MaybeRemoveDevice(devnode);
if (inst != -1) {
/* !!! FIXME: Move this to an SDL_PrivateJoyDeviceRemoved() function? */
#if !SDL_EVENTS_DISABLED
SDL_Event event;
event.type = SDL_JOYDEVICEREMOVED;
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
event.jdevice.which = inst;
if ( (SDL_EventOK == NULL) ||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
SDL_PushEvent(&event);
}
}
#endif /* !SDL_EVENTS_DISABLED */
}
}
UDEV_udev_device_unref(dev);
}
SDL_UDEV_Poll();
#endif
}
SDL_bool SDL_SYS_JoystickNeedsPolling()
{
/*
* This results in a select() call, so technically we're polling to
* decide if we should poll, but I think this function is here because
* Windows has to do an enormous amount of work to detect new sticks,
* whereas libudev just needs to see if there's more data available on
* a socket...so this should be acceptable, I hope.
*/
return HotplugUpdateAvailable();
#if SDL_USE_LIBUDEV
return SDL_TRUE;
#endif
return SDL_FALSE;
}
static SDL_joylist_item *
@ -772,7 +617,7 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
return !joystick->closed && (joystick->hwdata->item != NULL);
}
static __inline__ void
static SDL_INLINE void
HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
{
struct hwdata_hat *the_hat;
@ -798,14 +643,14 @@ HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
}
}
static __inline__ void
static SDL_INLINE void
HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value)
{
stick->hwdata->balls[ball].axis[axis] += value;
}
static __inline__ int
static SDL_INLINE int
AxisCorrect(SDL_Joystick * joystick, int which, int value)
{
struct axis_correct *correct;
@ -834,7 +679,7 @@ AxisCorrect(SDL_Joystick * joystick, int which, int value)
return value;
}
static __inline__ void
static SDL_INLINE void
PollAllValues(SDL_Joystick * joystick)
{
struct input_absinfo absinfo;
@ -872,7 +717,7 @@ PollAllValues(SDL_Joystick * joystick)
}
}
static __inline__ void
static SDL_INLINE void
HandleInputEvents(SDL_Joystick * joystick)
{
struct input_event events[32];
@ -1011,15 +856,8 @@ SDL_SYS_JoystickQuit(void)
instance_counter = 0;
#if SDL_USE_LIBUDEV
if (udev_mon != NULL) {
UDEV_udev_monitor_unref(udev_mon);
udev_mon = NULL;
}
if (udev != NULL) {
UDEV_udev_unref(udev);
udev = NULL;
}
UnloadUDEVLibrary();
SDL_UDEV_DelCallback(joystick_udev_callback);
SDL_UDEV_Quit();
#endif
}

View file

@ -60,7 +60,7 @@ static point c = { 78, 32767 };
static point d = { 128, 32767 };
/* simple linear interpolation between two points */
static __inline__ void lerp (point *dest, point *a, point *b, float t)
static SDL_INLINE void lerp (point *dest, point *a, point *b, float t)
{
dest->x = a->x + (b->x - a->x)*t;
dest->y = a->y + (b->y - a->y)*t;

View file

@ -46,40 +46,17 @@
#include "../../events/SDL_events_c.h"
#endif
/* The latest version of mingw-w64 defines IID_IWbemLocator in wbemcli.h
instead of declaring it like Visual Studio and other mingw32 compilers.
So, we need to take care of this here before we define INITGUID.
*/
#ifdef __MINGW32__
#define __IWbemLocator_INTERFACE_DEFINED__
#endif /* __MINGW32__ */
#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
#include "SDL_dxjoystick_c.h"
#ifdef __MINGW32__
/* And now that we've included wbemcli.h we need to declare these interfaces */
typedef struct IWbemLocatorVtbl {
BEGIN_INTERFACE
HRESULT (WINAPI *QueryInterface)(IWbemLocator *This,REFIID riid,void **ppvObject);
ULONG (WINAPI *AddRef)(IWbemLocator *This);
ULONG (WINAPI *Release)(IWbemLocator *This);
HRESULT (WINAPI *ConnectServer)(IWbemLocator *This,const BSTR strNetworkResource,const BSTR strUser,const BSTR strPassword,const BSTR strLocale,LONG lSecurityFlags,const BSTR strAuthority,IWbemContext *pCtx,IWbemServices **ppNamespace);
END_INTERFACE
} IWbemLocatorVtbl;
struct IWbemLocator {
CONST_VTBL struct IWbemLocatorVtbl *lpVtbl;
};
#define IWbemLocator_ConnectServer(This,strNetworkResource,strUser,strPassword,strLocale,lSecurityFlags,strAuthority,pCtx,ppNamespace) (This)->lpVtbl->ConnectServer(This,strNetworkResource,strUser,strPassword,strLocale,lSecurityFlags,strAuthority,pCtx,ppNamespace)
#endif /* __MINGW32__ */
#ifndef DIDFT_OPTIONAL
#define DIDFT_OPTIONAL 0x80000000
#endif
DEFINE_GUID(GUID_DEVINTERFACE_HID, 0x4D1E55B2L, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */
#define MAX_JOYSTICKS 8
#define AXIS_MIN -32768 /* minimum value for axis coordinate */
#define AXIS_MAX 32767 /* maximum value for axis coordinate */
#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
@ -94,7 +71,6 @@ static LPDIRECTINPUT8 dinput = NULL;
static SDL_bool s_bDeviceAdded = SDL_FALSE;
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
static SDL_JoystickID s_nInstanceID = -1;
static GUID *s_pKnownJoystickGUIDs = NULL;
static SDL_cond *s_condJoystickThread = NULL;
static SDL_mutex *s_mutexJoyStickEnum = NULL;
static SDL_Thread *s_threadJoystick = NULL;
@ -396,156 +372,74 @@ SetDIerror(const char *function, HRESULT code)
} \
}
DEFINE_GUID(CLSID_WbemLocator, 0x4590f811,0x1d3a,0x11d0,0x89,0x1F,0x00,0xaa,0x00,0x4b,0x2e,0x24);
DEFINE_GUID(IID_IWbemLocator, 0xdc12a687,0x737f,0x11cf,0x88,0x4d,0x00,0xaa,0x00,0x4b,0x2e,0x24);
DEFINE_GUID(IID_ValveStreamingGamepad, MAKELONG( 0x28DE, 0x11FF ),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
DEFINE_GUID(IID_X360WiredGamepad, MAKELONG( 0x045E, 0x02A1 ),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
DEFINE_GUID(IID_X360WirelessGamepad, MAKELONG( 0x045E, 0x028E ),0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
/*-----------------------------------------------------------------------------
*
* code from MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ee417014(v=vs.85).aspx
*
* Enum each PNP device using WMI and check each device ID to see if it contains
* "IG_" (ex. "VID_045E&PID_028E&IG_00"). If it does, then it's an XInput device
* Unfortunately this information can not be found by just using DirectInput
*-----------------------------------------------------------------------------*/
BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput )
static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
static UINT SDL_RawDevListCount = 0;
static SDL_bool
SDL_IsXInputDevice( const GUID* pGuidProductFromDirectInput )
{
static const GUID *s_XInputProductGUID[] = {
&IID_ValveStreamingGamepad
&IID_ValveStreamingGamepad,
&IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
&IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
};
IWbemLocator* pIWbemLocator = NULL;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemClassObject* pDevices[20];
IWbemServices* pIWbemServices = NULL;
DWORD uReturned = 0;
BSTR bstrNamespace = NULL;
BSTR bstrDeviceID = NULL;
BSTR bstrClassName = NULL;
SDL_bool bIsXinputDevice= SDL_FALSE;
UINT iDevice = 0;
VARIANT var;
HRESULT hr;
DWORD bCleanupCOM;
if (!s_bXInputEnabled)
{
size_t iDevice;
UINT i;
if (!s_bXInputEnabled) {
return SDL_FALSE;
}
// Check for well known XInput device GUIDs
// We need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list.
/* Check for well known XInput device GUIDs */
/* This lets us skip RAWINPUT for popular devices. Also, we need to do this for the Valve Streaming Gamepad because it's virtualized and doesn't show up in the device list. */
for ( iDevice = 0; iDevice < SDL_arraysize(s_XInputProductGUID); ++iDevice ) {
if (SDL_memcmp(pGuidProductFromDirectInput, s_XInputProductGUID[iDevice], sizeof(GUID)) == 0) {
return SDL_TRUE;
}
}
SDL_memset( pDevices, 0x0, sizeof(pDevices) );
/* Go through RAWINPUT (WinXP and later) to find HID devices. */
/* Cache this if we end up using it. */
if (SDL_RawDevList == NULL) {
if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
return SDL_FALSE; /* oh well. */
}
/* CoInit if needed */
hr = CoInitialize(NULL);
bCleanupCOM = SUCCEEDED(hr);
SDL_RawDevList = (PRAWINPUTDEVICELIST) SDL_malloc(sizeof (RAWINPUTDEVICELIST) * SDL_RawDevListCount);
if (SDL_RawDevList == NULL) {
SDL_OutOfMemory();
return SDL_FALSE;
}
/* Create WMI */
hr = CoCreateInstance( &CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IWbemLocator,
(LPVOID*) &pIWbemLocator);
if( FAILED(hr) || pIWbemLocator == NULL )
goto LCleanup;
bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );if( bstrNamespace == NULL ) goto LCleanup;
bstrClassName = SysAllocString( L"Win32_PNPEntity" ); if( bstrClassName == NULL ) goto LCleanup;
bstrDeviceID = SysAllocString( L"DeviceID" ); if( bstrDeviceID == NULL ) goto LCleanup;
/* Connect to WMI */
hr = IWbemLocator_ConnectServer( pIWbemLocator, bstrNamespace, NULL, NULL, 0L,
0L, NULL, NULL, &pIWbemServices );
if( FAILED(hr) || pIWbemServices == NULL )
goto LCleanup;
/* Switch security level to IMPERSONATE. */
CoSetProxyBlanket( (IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
hr = IWbemServices_CreateInstanceEnum( pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices );
if( FAILED(hr) || pEnumDevices == NULL )
goto LCleanup;
/* Loop over all devices */
for( ;; )
{
/* Get 20 at a time */
hr = IEnumWbemClassObject_Next( pEnumDevices, 10000, 20, pDevices, &uReturned );
if( FAILED(hr) )
goto LCleanup;
if( uReturned == 0 )
break;
for( iDevice=0; iDevice<uReturned; iDevice++ )
{
/* For each device, get its device ID */
hr = IWbemClassObject_Get( pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL );
if( SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != NULL )
{
/* Check if the device ID contains "IG_". If it does, then it's an XInput device */
/* This information can not be found from DirectInput */
char *pDeviceString = WIN_StringToUTF8( var.bstrVal );
if( SDL_strstr( pDeviceString, "IG_" ) )
{
/* If it does, then get the VID/PID from var.bstrVal */
long dwPid = 0, dwVid = 0;
char * strPid = NULL;
DWORD dwVidPid = 0;
char * strVid = SDL_strstr( pDeviceString, "VID_" );
if( strVid )
{
dwVid = SDL_strtol( strVid + 4, NULL, 16 );
}
strPid = SDL_strstr( pDeviceString, "PID_" );
if( strPid )
{
dwPid = SDL_strtol( strPid + 4, NULL, 16 );
}
/* Compare the VID/PID to the DInput device */
dwVidPid = MAKELONG( dwVid, dwPid );
if( dwVidPid == pGuidProductFromDirectInput->Data1 )
{
bIsXinputDevice = SDL_TRUE;
}
}
if ( pDeviceString )
SDL_free( pDeviceString );
if ( bIsXinputDevice )
break;
}
SAFE_RELEASE( pDevices[iDevice] );
if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof (RAWINPUTDEVICELIST)) == -1) {
SDL_free(SDL_RawDevList);
SDL_RawDevList = NULL;
return SDL_FALSE; /* oh well. */
}
}
LCleanup:
for (i = 0; i < SDL_RawDevListCount; i++) {
RID_DEVICE_INFO rdi;
char devName[128];
UINT rdiSize = sizeof (rdi);
UINT nameSize = SDL_arraysize(devName);
for( iDevice=0; iDevice<20; iDevice++ )
SAFE_RELEASE( pDevices[iDevice] );
SAFE_RELEASE( pEnumDevices );
SAFE_RELEASE( pIWbemLocator );
SAFE_RELEASE( pIWbemServices );
rdi.cbSize = sizeof (rdi);
if ( (SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
(SDL_strstr(devName, "IG_") != NULL) ) {
return SDL_TRUE;
}
}
if ( bstrNamespace )
SysFreeString( bstrNamespace );
if ( bstrClassName )
SysFreeString( bstrClassName );
if ( bstrDeviceID )
SysFreeString( bstrDeviceID );
if( bCleanupCOM )
CoUninitialize();
return bIsXinputDevice;
return SDL_FALSE;
}
@ -586,10 +480,10 @@ SDL_JoystickThread(void *_data)
HWND messageWindow = 0;
HDEVNOTIFY hNotify = 0;
DEV_BROADCAST_DEVICEINTERFACE dbh;
SDL_bool bOpenedXInputDevices[4];
SDL_bool bOpenedXInputDevices[SDL_XINPUT_MAX_DEVICES];
WNDCLASSEX wincl;
SDL_memset( bOpenedXInputDevices, 0x0, sizeof(bOpenedXInputDevices) );
SDL_zero(bOpenedXInputDevices);
WIN_CoInitialize();
@ -610,11 +504,11 @@ SDL_JoystickThread(void *_data)
return SDL_SetError("Failed to create message window for joystick autodetect.", GetLastError());
}
SDL_memset(&dbh, 0x0, sizeof(dbh));
SDL_zero(dbh);
dbh.dbcc_size = sizeof(dbh);
dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
dbh.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
hNotify = RegisterDeviceNotification( messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE );
if ( !hNotify )
@ -626,9 +520,8 @@ SDL_JoystickThread(void *_data)
while ( s_bJoystickThreadQuit == SDL_FALSE )
{
MSG messages;
Uint8 userId;
int nCurrentOpenedXInputDevices = 0;
int nNewOpenedXInputDevices = 0;
SDL_bool bXInputChanged = SDL_FALSE;
SDL_CondWaitTimeout( s_condJoystickThread, s_mutexJoyStickEnum, 300 );
while ( s_bJoystickThreadQuit == SDL_FALSE && PeekMessage(&messages, messageWindow, 0, 0, PM_NOREMOVE) )
@ -639,33 +532,24 @@ SDL_JoystickThread(void *_data)
}
}
if ( s_bXInputEnabled && XINPUTGETCAPABILITIES )
{
if ( s_bXInputEnabled && XINPUTGETCAPABILITIES ) {
/* scan for any change in XInput devices */
for ( userId = 0; userId < 4; userId++ )
{
Uint8 userId;
for (userId = 0; userId < SDL_XINPUT_MAX_DEVICES; userId++) {
XINPUT_CAPABILITIES capabilities;
DWORD result;
if ( bOpenedXInputDevices[userId] == SDL_TRUE )
nCurrentOpenedXInputDevices++;
result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
if ( result == ERROR_SUCCESS )
{
bOpenedXInputDevices[userId] = SDL_TRUE;
nNewOpenedXInputDevices++;
}
else
{
bOpenedXInputDevices[userId] = SDL_FALSE;
const DWORD result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
const SDL_bool available = (result == ERROR_SUCCESS);
if (bOpenedXInputDevices[userId] != available) {
bXInputChanged = SDL_TRUE;
bOpenedXInputDevices[userId] = available;
}
}
}
if ( s_pKnownJoystickGUIDs && ( s_bWindowsDeviceChanged || nNewOpenedXInputDevices != nCurrentOpenedXInputDevices ) )
{
if (s_bWindowsDeviceChanged || bXInputChanged) {
SDL_UnlockMutex( s_mutexJoyStickEnum ); /* let main thread go while we SDL_Delay(). */
SDL_Delay( 300 ); /* wait for direct input to find out about this device */
SDL_LockMutex( s_mutexJoyStickEnum );
s_bDeviceRemoved = SDL_TRUE;
s_bDeviceAdded = SDL_TRUE;
@ -730,15 +614,16 @@ SDL_SYS_JoystickInit(void)
return SetDIerror("IDirectInput::Initialize", result);
}
s_mutexJoyStickEnum = SDL_CreateMutex();
s_condJoystickThread = SDL_CreateCond();
s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
SDL_SYS_JoystickDetect();
if ((s_bXInputEnabled) && (WIN_LoadXInputDLL() == -1)) {
s_bXInputEnabled = SDL_FALSE; /* oh well. */
}
s_mutexJoyStickEnum = SDL_CreateMutex();
s_condJoystickThread = SDL_CreateCond();
s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
SDL_SYS_JoystickDetect();
if ( !s_threadJoystick )
{
s_bJoystickThreadQuit = SDL_FALSE;
@ -767,15 +652,17 @@ int SDL_SYS_NumJoysticks()
return nJoysticks;
}
static int s_iNewGUID = 0;
/* helper function for direct input, gets called for each connected joystick */
static BOOL CALLBACK
EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
{
JoyStick_DeviceData *pNewJoystick;
JoyStick_DeviceData *pPrevJoystick = NULL;
SDL_bool bXInputDevice;
if (SDL_IsXInputDevice( &pdidInstance->guidProduct )) {
return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
}
pNewJoystick = *(JoyStick_DeviceData **)pContext;
while ( pNewJoystick )
{
@ -794,58 +681,109 @@ static BOOL CALLBACK
pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
s_iNewGUID++;
if ( s_iNewGUID < MAX_JOYSTICKS )
return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
else
return DIENUM_STOP;
return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
}
pPrevJoystick = pNewJoystick;
pNewJoystick = pNewJoystick->pNext;
}
s_bDeviceAdded = SDL_TRUE;
bXInputDevice = IsXInputDevice( &pdidInstance->guidProduct );
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc( sizeof(JoyStick_DeviceData) );
if ( bXInputDevice )
{
pNewJoystick->bXInputDevice = SDL_TRUE;
pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
if (!pNewJoystick) {
return DIENUM_CONTINUE; /* better luck next time? */
}
else
{
pNewJoystick->bXInputDevice = SDL_FALSE;
SDL_zerop(pNewJoystick);
pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
if (!pNewJoystick->joystickname) {
SDL_free(pNewJoystick);
return DIENUM_CONTINUE; /* better luck next time? */
}
SDL_memcpy(&(pNewJoystick->dxdevice), pdidInstance,
sizeof(DIDEVICEINSTANCE));
pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
pNewJoystick->XInputUserId = INVALID_XINPUT_USERID;
pNewJoystick->send_add_event = 1;
pNewJoystick->nInstanceID = ++s_nInstanceID;
SDL_memcpy( &pNewJoystick->guid, &pdidInstance->guidProduct, sizeof(pNewJoystick->guid) );
pNewJoystick->pNext = NULL;
if ( SYS_Joystick )
{
pNewJoystick->pNext = SYS_Joystick;
}
pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
s_pKnownJoystickGUIDs[ s_iNewGUID ] = pdidInstance->guidInstance;
s_iNewGUID++;
s_bDeviceAdded = SDL_TRUE;
if ( s_iNewGUID < MAX_JOYSTICKS )
return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
else
return DIENUM_STOP;
return DIENUM_CONTINUE; /* get next device, please */
}
static void
AddXInputDevice(const Uint8 userid, JoyStick_DeviceData **pContext)
{
char name[32];
JoyStick_DeviceData *pPrevJoystick = NULL;
JoyStick_DeviceData *pNewJoystick = *pContext;
while (pNewJoystick) {
if ((pNewJoystick->bXInputDevice) && (pNewJoystick->XInputUserId == userid)) {
/* if we are replacing the front of the list then update it */
if (pNewJoystick == *pContext) {
*pContext = pNewJoystick->pNext;
} else if (pPrevJoystick) {
pPrevJoystick->pNext = pNewJoystick->pNext;
}
pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
return; /* already in the list. */
}
pPrevJoystick = pNewJoystick;
pNewJoystick = pNewJoystick->pNext;
}
pNewJoystick = (JoyStick_DeviceData *) SDL_malloc(sizeof (JoyStick_DeviceData));
if (!pNewJoystick) {
return; /* better luck next time? */
}
SDL_zerop(pNewJoystick);
SDL_snprintf(name, sizeof (name), "XInput Controller #%u", ((unsigned int) userid) + 1);
pNewJoystick->joystickname = SDL_strdup(name);
if (!pNewJoystick->joystickname) {
SDL_free(pNewJoystick);
return; /* better luck next time? */
}
pNewJoystick->bXInputDevice = SDL_TRUE;
pNewJoystick->XInputUserId = userid;
pNewJoystick->send_add_event = 1;
pNewJoystick->nInstanceID = ++s_nInstanceID;
pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
s_bDeviceAdded = SDL_TRUE;
}
static void
EnumXInputDevices(JoyStick_DeviceData **pContext)
{
if (s_bXInputEnabled) {
int iuserid;
/* iterate in reverse, so these are in the final list in ascending numeric order. */
for (iuserid = SDL_XINPUT_MAX_DEVICES-1; iuserid >= 0; iuserid--) {
const Uint8 userid = (Uint8) iuserid;
XINPUT_CAPABILITIES capabilities;
if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
/* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
/* !!! FIXME: we might want to support steering wheels or guitars or whatever laster. */
if (capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD) {
AddXInputDevice(userid, pContext);
}
}
}
}
}
/* detect any new joysticks being inserted into the system */
void SDL_SYS_JoystickDetect()
{
@ -853,25 +791,27 @@ void SDL_SYS_JoystickDetect()
/* only enum the devices if the joystick thread told us something changed */
if ( s_bDeviceAdded || s_bDeviceRemoved )
{
SDL_LockMutex( s_mutexJoyStickEnum );
s_bDeviceAdded = SDL_FALSE;
s_bDeviceRemoved = SDL_FALSE;
pCurList = SYS_Joystick;
SYS_Joystick = NULL;
s_iNewGUID = 0;
SDL_LockMutex( s_mutexJoyStickEnum );
if ( !s_pKnownJoystickGUIDs )
s_pKnownJoystickGUIDs = SDL_malloc( sizeof(GUID)*MAX_JOYSTICKS );
SDL_memset( s_pKnownJoystickGUIDs, 0x0, sizeof(GUID)*MAX_JOYSTICKS );
/* Look for joysticks, wheels, head trackers, gamepads, etc.. */
/* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
IDirectInput8_EnumDevices(dinput,
DI8DEVCLASS_GAMECTRL,
EnumJoysticksCallback,
&pCurList, DIEDFL_ATTACHEDONLY);
SDL_free(SDL_RawDevList); /* in case we used this in DirectInput enumerator. */
SDL_RawDevList = NULL;
SDL_RawDevListCount = 0;
/* Look for XInput devices. Do this last, so they're first in the final list. */
EnumXInputDevices(&pCurList);
SDL_UnlockMutex( s_mutexJoyStickEnum );
}
@ -895,7 +835,7 @@ void SDL_SYS_JoystickDetect()
pListNext = pCurList->pNext;
SDL_free(pCurList->joystickname);
SDL_free( pCurList );
SDL_free(pCurList);
pCurList = pListNext;
}
@ -974,17 +914,11 @@ int
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
{
HRESULT result;
LPDIRECTINPUTDEVICE8 device;
DIPROPDWORD dipdw;
JoyStick_DeviceData *joystickdevice = SYS_Joystick;
for (; device_index > 0; device_index--)
joystickdevice = joystickdevice->pNext;
SDL_memset(&dipdw, 0, sizeof(DIPROPDWORD));
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
/* allocate memory for system specific hardware data */
joystick->instance_id = joystickdevice->nInstanceID;
joystick->closed = 0;
@ -993,71 +927,50 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
if (joystick->hwdata == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(joystick->hwdata, 0, sizeof(struct joystick_hwdata));
joystick->hwdata->buffered = 1;
joystick->hwdata->removed = 0;
joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
joystick->hwdata->guid = joystickdevice->guid;
SDL_zerop(joystick->hwdata);
if ( joystickdevice->bXInputDevice )
{
if (joystickdevice->bXInputDevice) {
const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
const Uint8 userId = joystickdevice->XInputUserId;
XINPUT_CAPABILITIES capabilities;
Uint8 userId = 0;
DWORD result;
JoyStick_DeviceData *joysticklist = SYS_Joystick;
/* scan the opened joysticks and pick the next free xinput userid for this one */
for( ; joysticklist; joysticklist = joysticklist->pNext)
{
if ( joysticklist->bXInputDevice && joysticklist->XInputUserId == userId )
userId++;
}
if ( s_bXInputEnabled && XINPUTGETCAPABILITIES )
{
result = XINPUTGETCAPABILITIES( userId, XINPUT_FLAG_GAMEPAD, &capabilities );
if ( result == ERROR_SUCCESS )
{
const SDL_bool bIs14OrLater = (SDL_XInputVersion >= ((1<<16)|4));
SDL_bool bIsSupported = SDL_FALSE;
/* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
bIsSupported = ( capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD );
SDL_assert(s_bXInputEnabled);
SDL_assert(XINPUTGETCAPABILITIES);
SDL_assert(userId >= 0);
SDL_assert(userId < SDL_XINPUT_MAX_DEVICES);
if ( !bIsSupported )
{
joystickdevice->bXInputDevice = SDL_FALSE;
}
else
{
/* valid */
joystick->hwdata->bXInputDevice = SDL_TRUE;
if ((!bIs14OrLater) || (capabilities.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
joystick->hwdata->bXInputHaptic = SDL_TRUE;
}
SDL_memset( joystick->hwdata->XInputState, 0x0, sizeof(joystick->hwdata->XInputState) );
joystickdevice->XInputUserId = userId;
joystick->hwdata->userid = userId;
joystick->hwdata->currentXInputSlot = 0;
/* The XInput API has a hard coded button/axis mapping, so we just match it */
joystick->naxes = 6;
joystick->nbuttons = 15;
joystick->nballs = 0;
joystick->nhats = 0;
}
joystick->hwdata->bXInputDevice = SDL_TRUE;
if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
} else {
/* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */
SDL_assert(capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
if ((!bIs14OrLater) || (capabilities.Flags & XINPUT_CAPS_FFB_SUPPORTED)) {
joystick->hwdata->bXInputHaptic = SDL_TRUE;
}
else
{
joystickdevice->bXInputDevice = SDL_FALSE;
}
}
else
{
joystickdevice->bXInputDevice = SDL_FALSE;
}
}
joystick->hwdata->userid = userId;
if ( joystickdevice->bXInputDevice == SDL_FALSE )
{
joystick->hwdata->bXInputDevice = SDL_FALSE;
/* The XInput API has a hard coded button/axis mapping, so we just match it */
joystick->naxes = 6;
joystick->nbuttons = 15;
joystick->nballs = 0;
joystick->nhats = 0;
}
} else { /* use DirectInput, not XInput. */
LPDIRECTINPUTDEVICE8 device;
DIPROPDWORD dipdw;
joystick->hwdata->buffered = 1;
joystick->hwdata->removed = 0;
joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
joystick->hwdata->guid = joystickdevice->guid;
SDL_zero(dipdw);
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
result =
IDirectInput8_CreateDevice(dinput,
@ -1642,29 +1555,13 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
if ( joystick->hwdata->bXInputDevice )
{
JoyStick_DeviceData *joysticklist = SYS_Joystick;
/* scan the opened joysticks and clear the userid for this instance */
for( ; joysticklist; joysticklist = joysticklist->pNext)
{
if ( joysticklist->bXInputDevice && joysticklist->nInstanceID == joystick->instance_id )
{
joysticklist->XInputUserId = INVALID_XINPUT_USERID;
}
}
}
else
{
if (!joystick->hwdata->bXInputDevice) {
IDirectInputDevice8_Unacquire(joystick->hwdata->InputDevice);
IDirectInputDevice8_Release(joystick->hwdata->InputDevice);
}
if (joystick->hwdata != NULL) {
/* free system specific hardware data */
SDL_free(joystick->hwdata);
}
/* free system specific hardware data */
SDL_free(joystick->hwdata);
joystick->closed = 1;
}
@ -1709,18 +1606,11 @@ SDL_SYS_JoystickQuit(void)
coinitialized = SDL_FALSE;
}
if ( s_pKnownJoystickGUIDs )
{
SDL_free( s_pKnownJoystickGUIDs );
s_pKnownJoystickGUIDs = NULL;
}
if (s_bXInputEnabled) {
WIN_UnloadXInputDLL();
}
}
/* return the stable device guid for this device index */
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
{
@ -1750,6 +1640,12 @@ SDL_bool SDL_SYS_IsXInputDeviceIndex(int device_index)
return device->bXInputDevice;
}
/* return SDL_TRUE if this device was opened with XInput */
SDL_bool SDL_SYS_IsXInputJoystick(SDL_Joystick * joystick)
{
return joystick->hwdata->bXInputDevice;
}
#endif /* SDL_JOYSTICK_DINPUT */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -42,7 +42,18 @@
#include <xinput.h>
#include <devguid.h>
#include <dbt.h>
#include <xinput.h>
#ifndef XUSER_MAX_COUNT
#define XUSER_MAX_COUNT 4
#endif
#ifndef XUSER_INDEX_ANY
#define XUSER_INDEX_ANY 0x000000FF
#endif
#ifndef XINPUT_CAPS_FFB_SUPPORTED
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
#endif
/* typedef's for XInput structs we use */
typedef struct
@ -94,13 +105,8 @@ extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */
#define XINPUTGETSTATE SDL_XInputGetState
#define XINPUTSETSTATE SDL_XInputSetState
#define XINPUTGETCAPABILITIES SDL_XInputGetCapabilities
#define INVALID_XINPUT_USERID 255
#define SDL_XINPUT_MAX_DEVICES 4
#ifndef XINPUT_CAPS_FFB_SUPPORTED
#define XINPUT_CAPS_FFB_SUPPORTED 0x0001
#endif
#define INVALID_XINPUT_USERID XUSER_INDEX_ANY
#define SDL_XINPUT_MAX_DEVICES XUSER_MAX_COUNT
#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */

View file

@ -33,6 +33,11 @@
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
#ifdef REGSTR_VAL_JOYOEMNAME
#undef REGSTR_VAL_JOYOEMNAME
#endif
#define REGSTR_VAL_JOYOEMNAME "OEMName"
#define MAX_JOYSTICKS 16
#define MAX_AXES 6 /* each joystick can have up to 6 axes */
#define MAX_BUTTONS 32 /* and 32 buttons */
@ -45,7 +50,7 @@
/* array to hold joystick ID values */
static UINT SYS_JoystickID[MAX_JOYSTICKS];
static JOYCAPS SYS_Joystick[MAX_JOYSTICKS];
static JOYCAPSA SYS_Joystick[MAX_JOYSTICKS];
static char *SYS_JoystickName[MAX_JOYSTICKS];
/* The private structure used to keep track of a joystick */
@ -148,7 +153,7 @@ SDL_SYS_JoystickInit(void)
int i;
int maxdevs;
JOYINFOEX joyinfo;
JOYCAPS joycaps;
JOYCAPSA joycaps;
MMRESULT result;
/* Reset the joystick ID & name mapping tables */
@ -166,7 +171,7 @@ SDL_SYS_JoystickInit(void)
joyinfo.dwFlags = JOY_RETURNALL;
result = joyGetPosEx(i, &joyinfo);
if (result == JOYERR_NOERROR) {
result = joyGetDevCaps(i, &joycaps, sizeof(joycaps));
result = joyGetDevCapsA(i, &joycaps, sizeof(joycaps));
if (result == JOYERR_NOERROR) {
SYS_JoystickID[SDL_SYS_numjoysticks] = i;
SYS_Joystick[SDL_SYS_numjoysticks] = joycaps;
@ -384,11 +389,9 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
if (joystick->hwdata != NULL) {
/* free system specific hardware data */
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
}
/* free system specific hardware data */
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
}
/* Function to perform any system-specific joystick related cleanup */
@ -397,10 +400,8 @@ SDL_SYS_JoystickQuit(void)
{
int i;
for (i = 0; i < MAX_JOYSTICKS; i++) {
if (SYS_JoystickName[i] != NULL) {
SDL_free(SYS_JoystickName[i]);
SYS_JoystickName[i] = NULL;
}
SDL_free(SYS_JoystickName[i]);
SYS_JoystickName[i] = NULL;
}
}