diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index 46f6e8cd9..abfb1c62b 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -105,10 +105,11 @@ FreeDevice(recDevice *removeDevice) return pDeviceNext; } -static SInt32 -GetHIDElementState(recDevice *pDevice, recElement *pElement) +static SDL_bool +GetHIDElementState(recDevice *pDevice, recElement *pElement, SInt32 *pValue) { SInt32 value = 0; + int returnValue = SDL_FALSE; if (pDevice && pElement) { IOHIDValueRef valueRef; @@ -122,25 +123,34 @@ GetHIDElementState(recDevice *pDevice, recElement *pElement) if (value > pElement->maxReport) { pElement->maxReport = value; } + *pValue = value; + + returnValue = SDL_TRUE; } } - - return value; + return returnValue; } -static SInt32 -GetHIDScaledCalibratedState(recDevice * pDevice, recElement * pElement, SInt32 min, SInt32 max) +static SDL_bool +GetHIDScaledCalibratedState(recDevice * pDevice, recElement * pElement, SInt32 min, SInt32 max, SInt32 *pValue) { const float deviceScale = max - min; const float readScale = pElement->maxReport - pElement->minReport; - const SInt32 value = GetHIDElementState(pDevice, pElement); - if (readScale == 0) { - return value; /* no scaling at all */ - } - return ((value - pElement->minReport) * deviceScale / readScale) + min; + int returnValue = SDL_FALSE; + if (GetHIDElementState(pDevice, pElement, pValue)) + { + if (readScale == 0) { + returnValue = SDL_TRUE; /* no scaling at all */ + } + else + { + *pValue = ((*pValue - pElement->minReport) * deviceScale / readScale) + min; + returnValue = SDL_TRUE; + } + } + return returnValue; } - static void JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender) { @@ -698,9 +708,14 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) element = device->firstAxis; i = 0; + + int goodRead = SDL_FALSE; while (element) { - value = GetHIDScaledCalibratedState(device, element, -32768, 32767); - SDL_PrivateJoystickAxis(joystick, i, value); + goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value); + if (goodRead) { + SDL_PrivateJoystickAxis(joystick, i, value); + } + element = element->pNext; ++i; } @@ -708,63 +723,70 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) element = device->firstButton; i = 0; while (element) { - value = GetHIDElementState(device, element); - if (value > 1) { /* handle pressure-sensitive buttons */ - value = 1; + goodRead = GetHIDElementState(device, element, &value); + if (goodRead) { + if (value > 1) { /* handle pressure-sensitive buttons */ + value = 1; + } + SDL_PrivateJoystickButton(joystick, i, value); } - SDL_PrivateJoystickButton(joystick, i, value); + element = element->pNext; ++i; } element = device->firstHat; i = 0; + while (element) { Uint8 pos = 0; range = (element->max - element->min + 1); - value = GetHIDElementState(device, element) - element->min; - if (range == 4) { /* 4 position hatswitch - scale up value */ - value *= 2; - } else if (range != 8) { /* Neither a 4 nor 8 positions - fall back to default position (centered) */ - value = -1; - } - switch (value) { - case 0: - pos = SDL_HAT_UP; - break; - case 1: - pos = SDL_HAT_RIGHTUP; - break; - case 2: - pos = SDL_HAT_RIGHT; - break; - case 3: - pos = SDL_HAT_RIGHTDOWN; - break; - case 4: - pos = SDL_HAT_DOWN; - break; - case 5: - pos = SDL_HAT_LEFTDOWN; - break; - case 6: - pos = SDL_HAT_LEFT; - break; - case 7: - pos = SDL_HAT_LEFTUP; - break; - default: - /* Every other value is mapped to center. We do that because some - * joysticks use 8 and some 15 for this value, and apparently - * there are even more variants out there - so we try to be generous. - */ - pos = SDL_HAT_CENTERED; - break; - } - - SDL_PrivateJoystickHat(joystick, i, pos); + goodRead = GetHIDElementState(device, element, &value); + if (goodRead) { + value -= element->min; + if (range == 4) { /* 4 position hatswitch - scale up value */ + value *= 2; + } else if (range != 8) { /* Neither a 4 nor 8 positions - fall back to default position (centered) */ + value = -1; + } + switch (value) { + case 0: + pos = SDL_HAT_UP; + break; + case 1: + pos = SDL_HAT_RIGHTUP; + break; + case 2: + pos = SDL_HAT_RIGHT; + break; + case 3: + pos = SDL_HAT_RIGHTDOWN; + break; + case 4: + pos = SDL_HAT_DOWN; + break; + case 5: + pos = SDL_HAT_LEFTDOWN; + break; + case 6: + pos = SDL_HAT_LEFT; + break; + case 7: + pos = SDL_HAT_LEFTUP; + break; + default: + /* Every other value is mapped to center. We do that because some + * joysticks use 8 and some 15 for this value, and apparently + * there are even more variants out there - so we try to be generous. + */ + pos = SDL_HAT_CENTERED; + break; + } + SDL_PrivateJoystickHat(joystick, i, pos); + } + element = element->pNext; ++i; }