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