src/joystick/haiku/SDL_haikujoystick.cc
author Sam Lantinga <slouken@libsdl.org>
Tue, 03 Jan 2017 23:39:28 -0800
changeset 10745 7461fcef6ae2
parent 10737 3406a0f8b041
child 10753 220a81177cfb
permissions -rw-r--r--
Fixed binding the D-pad on some Super NES style controllers
Fixed a case where partial trigger pull could be bound to another button

There is a fundamental problem not resolved by this commit:

Some controllers have axes (triggers, pedals, etc.) that don't start at zero, but we're guaranteed that if we get a value that it's correct. For these controllers, the current code works, where we take the first value we get and use that as the zero point and generate axis motion starting from that point on.

Other controllers have digital axes (D-pad) that assume a zero starting point, and the first value we get is the min or max axis value when the D-pad is moved. For these controllers, the current code thinks that the zero point is the axis value after the D-pad motion and this doesn't work.

My hypothesis is that the first class of devices is more common and that we should solve for that, and add an exception to SDL_JoystickAxesCenteredAtZero() as needed for the second class of devices.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@0
    22
icculus@7981
    23
#ifdef SDL_JOYSTICK_HAIKU
slouken@1635
    24
philipp@8138
    25
/* This is the Haiku implementation of the SDL joystick API */
slouken@0
    26
icculus@7981
    27
#include <os/support/String.h>
icculus@7981
    28
#include <os/device/Joystick.h>
slouken@0
    29
slouken@1895
    30
extern "C"
slouken@1895
    31
{
slouken@0
    32
slouken@0
    33
#include "SDL_joystick.h"
slouken@1361
    34
#include "../SDL_sysjoystick.h"
slouken@1361
    35
#include "../SDL_joystick_c.h"
slouken@0
    36
slouken@0
    37
slouken@0
    38
/* The maximum number of joysticks we'll detect */
slouken@1895
    39
#define MAX_JOYSTICKS	16
slouken@0
    40
slouken@0
    41
/* A list of available joysticks */
slouken@1895
    42
    static char *SDL_joyport[MAX_JOYSTICKS];
slouken@1895
    43
    static char *SDL_joyname[MAX_JOYSTICKS];
slouken@0
    44
slouken@0
    45
/* The private structure used to keep track of a joystick */
slouken@1895
    46
    struct joystick_hwdata
slouken@1895
    47
    {
slouken@1895
    48
        BJoystick *stick;
slouken@1895
    49
        uint8 *new_hats;
slouken@1895
    50
        int16 *new_axes;
slouken@1895
    51
    };
slouken@0
    52
slouken@6698
    53
    static int SDL_SYS_numjoysticks = 0;
slouken@6698
    54
slouken@0
    55
/* Function to scan the system for joysticks.
philipp@9311
    56
 * Joystick 0 should be the system default joystick.
slouken@0
    57
 * It should return 0, or -1 on an unrecoverable fatal error.
slouken@0
    58
 */
slouken@1895
    59
    int SDL_SYS_JoystickInit(void)
slouken@1895
    60
    {
slouken@1895
    61
        BJoystick joystick;
slouken@1895
    62
        int i;
slouken@1895
    63
        int32 nports;
slouken@1895
    64
        char name[B_OS_NAME_LENGTH];
slouken@1895
    65
slouken@1895
    66
        /* Search for attached joysticks */
slouken@1895
    67
          nports = joystick.CountDevices();
slouken@6698
    68
          SDL_SYS_numjoysticks = 0;
slouken@1895
    69
          SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport));
slouken@1895
    70
          SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname));
slouken@6698
    71
        for (i = 0; (SDL_SYS_numjoysticks < MAX_JOYSTICKS) && (i < nports); ++i)
slouken@1895
    72
        {
slouken@1895
    73
            if (joystick.GetDeviceName(i, name) == B_OK) {
slouken@1895
    74
                if (joystick.Open(name) != B_ERROR) {
slouken@1895
    75
                    BString stick_name;
slouken@1895
    76
                      joystick.GetControllerName(&stick_name);
philipp@10187
    77
                      SDL_joyport[SDL_SYS_numjoysticks] = SDL_strdup(name);
philipp@10187
    78
                      SDL_joyname[SDL_SYS_numjoysticks] = SDL_strdup(stick_name.String());
slouken@6698
    79
                      SDL_SYS_numjoysticks++;
slouken@1895
    80
                      joystick.Close();
slouken@1895
    81
                }
slouken@1895
    82
            }
slouken@1895
    83
        }
slouken@6698
    84
        return (SDL_SYS_numjoysticks);
slouken@1895
    85
    }
slouken@0
    86
philipp@10617
    87
    int SDL_SYS_NumJoysticks(void)
slouken@6707
    88
    {
slouken@6707
    89
        return SDL_SYS_numjoysticks;
slouken@6707
    90
    }
slouken@6707
    91
philipp@10617
    92
    void SDL_SYS_JoystickDetect(void)
slouken@6707
    93
    {
slouken@6707
    94
    }
slouken@6707
    95
slouken@0
    96
/* Function to get the device-dependent name of a joystick */
slouken@6707
    97
    const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index)
slouken@1895
    98
    {
slouken@6707
    99
        return SDL_joyname[device_index];
slouken@6707
   100
    }
slouken@6707
   101
slouken@6707
   102
/* Function to perform the mapping from device index to the instance id for this index */
slouken@6707
   103
    SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
slouken@6707
   104
    {
slouken@6707
   105
        return device_index;
slouken@1895
   106
    }
slouken@0
   107
slouken@0
   108
/* Function to open a joystick for use.
philipp@9380
   109
   The joystick to open is specified by the device index.
slouken@0
   110
   This should fill the nbuttons and naxes fields of the joystick structure.
slouken@0
   111
   It returns 0, or -1 if there is an error.
slouken@0
   112
 */
slouken@6698
   113
    int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
slouken@1895
   114
    {
slouken@1895
   115
        BJoystick *stick;
slouken@0
   116
slouken@1895
   117
        /* Create the joystick data structure */
slouken@6698
   118
        joystick->instance_id = device_index;
slouken@1895
   119
        joystick->hwdata = (struct joystick_hwdata *)
slouken@1895
   120
            SDL_malloc(sizeof(*joystick->hwdata));
slouken@1895
   121
        if (joystick->hwdata == NULL) {
icculus@7037
   122
            return SDL_OutOfMemory();
slouken@1895
   123
        }
slouken@1895
   124
        SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
slouken@1895
   125
        stick = new BJoystick;
slouken@1895
   126
        joystick->hwdata->stick = stick;
slouken@0
   127
slouken@1895
   128
        /* Open the requested joystick for use */
slouken@6698
   129
        if (stick->Open(SDL_joyport[device_index]) == B_ERROR) {
slouken@1895
   130
            SDL_SYS_JoystickClose(joystick);
icculus@7037
   131
            return SDL_SetError("Unable to open joystick");
slouken@1895
   132
        }
slouken@0
   133
slouken@1895
   134
        /* Set the joystick to calibrated mode */
slouken@1895
   135
        stick->EnableCalibration();
slouken@0
   136
slouken@1895
   137
        /* Get the number of buttons, hats, and axes on the joystick */
slouken@1895
   138
        joystick->nbuttons = stick->CountButtons();
slouken@1895
   139
        joystick->naxes = stick->CountAxes();
slouken@1895
   140
        joystick->nhats = stick->CountHats();
slouken@0
   141
slouken@1895
   142
        joystick->hwdata->new_axes = (int16 *)
slouken@1895
   143
            SDL_malloc(joystick->naxes * sizeof(int16));
slouken@1895
   144
        joystick->hwdata->new_hats = (uint8 *)
slouken@1895
   145
            SDL_malloc(joystick->nhats * sizeof(uint8));
slouken@1895
   146
        if (!joystick->hwdata->new_hats || !joystick->hwdata->new_axes) {
slouken@1895
   147
            SDL_SYS_JoystickClose(joystick);
icculus@7037
   148
            return SDL_OutOfMemory();
slouken@1895
   149
        }
slouken@0
   150
slouken@1895
   151
        /* We're done! */
slouken@1895
   152
        return (0);
slouken@1895
   153
    }
slouken@0
   154
philipp@9561
   155
/* Function to determine if this joystick is attached to the system right now */
slouken@6707
   156
    SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
slouken@6707
   157
    {
slouken@6707
   158
        return SDL_TRUE;
slouken@6707
   159
    }
slouken@6707
   160
slouken@0
   161
/* Function to update the state of a joystick - called as a device poll.
slouken@0
   162
 * This function shouldn't update the joystick structure directly,
slouken@0
   163
 * but instead should call SDL_PrivateJoystick*() to deliver events
slouken@0
   164
 * and update joystick device state.
slouken@0
   165
 */
slouken@1895
   166
    void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
slouken@1895
   167
    {
slouken@1895
   168
        static const Uint8 hat_map[9] = {
slouken@1895
   169
            SDL_HAT_CENTERED,
slouken@1895
   170
            SDL_HAT_UP,
slouken@1895
   171
            SDL_HAT_RIGHTUP,
slouken@1895
   172
            SDL_HAT_RIGHT,
slouken@1895
   173
            SDL_HAT_RIGHTDOWN,
slouken@1895
   174
            SDL_HAT_DOWN,
slouken@1895
   175
            SDL_HAT_LEFTDOWN,
slouken@1895
   176
            SDL_HAT_LEFT,
slouken@1895
   177
            SDL_HAT_LEFTUP
slouken@1895
   178
        };
slouken@0
   179
slouken@1895
   180
        BJoystick *stick;
slouken@1895
   181
        int i, change;
slouken@1895
   182
        int16 *axes;
slouken@1895
   183
        uint8 *hats;
slouken@1895
   184
        uint32 buttons;
slouken@0
   185
slouken@1895
   186
        /* Set up data pointers */
slouken@1895
   187
        stick = joystick->hwdata->stick;
slouken@1895
   188
        axes = joystick->hwdata->new_axes;
slouken@1895
   189
        hats = joystick->hwdata->new_hats;
slouken@0
   190
slouken@1895
   191
        /* Get the new joystick state */
slouken@1895
   192
        stick->Update();
slouken@1895
   193
        stick->GetAxisValues(axes);
slouken@1895
   194
        stick->GetHatValues(hats);
slouken@1895
   195
        buttons = stick->ButtonValues();
slouken@0
   196
slouken@1895
   197
        /* Generate axis motion events */
slouken@1895
   198
        for (i = 0; i < joystick->naxes; ++i) {
slouken@10745
   199
            SDL_PrivateJoystickAxis(joystick, i, axes[i]);
slouken@1895
   200
        }
slouken@0
   201
slouken@1895
   202
        /* Generate hat change events */
slouken@1895
   203
        for (i = 0; i < joystick->nhats; ++i) {
slouken@10745
   204
            SDL_PrivateJoystickHat(joystick, i, hat_map[hats[i]]);
slouken@1895
   205
        }
slouken@0
   206
slouken@1895
   207
        /* Generate button events */
slouken@1895
   208
        for (i = 0; i < joystick->nbuttons; ++i) {
slouken@10745
   209
            SDL_PrivateJoystickButton(joystick, i, (buttons & 0x01));
slouken@1895
   210
            buttons >>= 1;
slouken@1895
   211
        }
slouken@1895
   212
    }
slouken@0
   213
slouken@0
   214
/* Function to close a joystick after use */
slouken@1895
   215
    void SDL_SYS_JoystickClose(SDL_Joystick * joystick)
slouken@1895
   216
    {
slouken@1895
   217
        if (joystick->hwdata) {
slouken@1895
   218
            joystick->hwdata->stick->Close();
slouken@1895
   219
            delete joystick->hwdata->stick;
slouken@7719
   220
            SDL_free(joystick->hwdata->new_hats);
slouken@7719
   221
            SDL_free(joystick->hwdata->new_axes);
slouken@1895
   222
            SDL_free(joystick->hwdata);
slouken@1895
   223
        }
slouken@1895
   224
    }
slouken@0
   225
slouken@0
   226
/* Function to perform any system-specific joystick related cleanup */
slouken@1895
   227
    void SDL_SYS_JoystickQuit(void)
slouken@1895
   228
    {
slouken@1895
   229
        int i;
slouken@0
   230
slouken@1895
   231
        for (i = 0; SDL_joyport[i]; ++i) {
slouken@1895
   232
            SDL_free(SDL_joyport[i]);
slouken@1895
   233
        }
slouken@1895
   234
        SDL_joyport[0] = NULL;
slouken@0
   235
slouken@1895
   236
        for (i = 0; SDL_joyname[i]; ++i) {
slouken@1895
   237
            SDL_free(SDL_joyname[i]);
slouken@1895
   238
        }
slouken@1895
   239
        SDL_joyname[0] = NULL;
slouken@1895
   240
    }
slouken@0
   241
slouken@6744
   242
    SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
slouken@6698
   243
    {
slouken@6744
   244
        SDL_JoystickGUID guid;
slouken@7191
   245
        /* the GUID is just the first 16 chars of the name for now */
slouken@6707
   246
        const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
slouken@6698
   247
        SDL_zero( guid );
slouken@6698
   248
        SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
slouken@6698
   249
        return guid;
slouken@6698
   250
    }
slouken@6698
   251
slouken@6744
   252
    SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
slouken@6698
   253
    {
slouken@6744
   254
        SDL_JoystickGUID guid;
slouken@7191
   255
        /* the GUID is just the first 16 chars of the name for now */
slouken@6698
   256
        const char *name = joystick->name;
slouken@6698
   257
        SDL_zero( guid );
slouken@6698
   258
        SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
slouken@6698
   259
        return guid;
slouken@6698
   260
    }
slouken@6698
   261
slouken@1895
   262
};                              // extern "C"
slouken@1635
   263
icculus@7981
   264
#endif /* SDL_JOYSTICK_HAIKU */
icculus@7981
   265
slouken@1895
   266
/* vi: set ts=4 sw=4 expandtab: */