1/* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2006 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken@libsdl.org 21*/ 22#include "SDL_config.h" 23 24#ifdef SDL_JOYSTICK_BEOS 25 26/* This is the system specific header for the SDL joystick API */ 27 28#include <be/support/String.h> 29#include <be/device/Joystick.h> 30 31extern "C" { 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 */ 42static char *SDL_joyport[MAX_JOYSTICKS]; 43static char *SDL_joyname[MAX_JOYSTICKS]; 44 45/* The private structure used to keep track of a joystick */ 46struct joystick_hwdata { 47 BJoystick *stick; 48 uint8 *new_hats; 49 int16 *new_axes; 50}; 51 52/* Function to scan the system for joysticks. 53 * This function should set SDL_numjoysticks to the number of available 54 * joysticks. Joystick 0 should be the system default joystick. 55 * It should return 0, or -1 on an unrecoverable fatal error. 56 */ 57int SDL_SYS_JoystickInit(void) 58{ 59 BJoystick joystick; 60 int numjoysticks; 61 int i; 62 int32 nports; 63 char name[B_OS_NAME_LENGTH]; 64 65 /* Search for attached joysticks */ 66 nports = joystick.CountDevices(); 67 numjoysticks = 0; 68 SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport)); 69 SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname)); 70 for ( i=0; (SDL_numjoysticks < MAX_JOYSTICKS) && (i < nports); ++i ) { 71 if ( joystick.GetDeviceName(i, name) == B_OK ) { 72 if ( joystick.Open(name) != B_ERROR ) { 73 BString stick_name; 74 joystick.GetControllerName(&stick_name); 75 SDL_joyport[numjoysticks] = strdup(name); 76 SDL_joyname[numjoysticks] = 77 strdup(stick_name.String()); 78 numjoysticks++; 79 joystick.Close(); 80 } 81 } 82 } 83 return(numjoysticks); 84} 85 86/* Function to get the device-dependent name of a joystick */ 87const char *SDL_SYS_JoystickName(int index) 88{ 89 return SDL_joyname[index]; 90} 91 92/* Function to open a joystick for use. 93 The joystick to open is specified by the index field of the joystick. 94 This should fill the nbuttons and naxes fields of the joystick structure. 95 It returns 0, or -1 if there is an error. 96 */ 97int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) 98{ 99 BJoystick *stick; 100 101 /* Create the joystick data structure */ 102 joystick->hwdata = (struct joystick_hwdata *) 103 SDL_malloc(sizeof(*joystick->hwdata)); 104 if ( joystick->hwdata == NULL ) { 105 SDL_OutOfMemory(); 106 return(-1); 107 } 108 SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); 109 stick = new BJoystick; 110 joystick->hwdata->stick = stick; 111 112 /* Open the requested joystick for use */ 113 if ( stick->Open(SDL_joyport[joystick->index]) == B_ERROR ) { 114 SDL_SetError("Unable to open joystick"); 115 SDL_SYS_JoystickClose(joystick); 116 return(-1); 117 } 118 119 /* Set the joystick to calibrated mode */ 120 stick->EnableCalibration(); 121 122 /* Get the number of buttons, hats, and axes on the joystick */ 123 joystick->nbuttons = stick->CountButtons(); 124 joystick->naxes = stick->CountAxes(); 125 joystick->nhats = stick->CountHats(); 126 127 joystick->hwdata->new_axes = (int16 *) 128 SDL_malloc(joystick->naxes*sizeof(int16)); 129 joystick->hwdata->new_hats = (uint8 *) 130 SDL_malloc(joystick->nhats*sizeof(uint8)); 131 if ( ! joystick->hwdata->new_hats || ! joystick->hwdata->new_axes ) { 132 SDL_OutOfMemory(); 133 SDL_SYS_JoystickClose(joystick); 134 return(-1); 135 } 136 137 /* We're done! */ 138 return(0); 139} 140 141/* Function to update the state of a joystick - called as a device poll. 142 * This function shouldn't update the joystick structure directly, 143 * but instead should call SDL_PrivateJoystick*() to deliver events 144 * and update joystick device state. 145 */ 146void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) 147{ 148 static const Uint8 hat_map[9] = { 149 SDL_HAT_CENTERED, 150 SDL_HAT_UP, 151 SDL_HAT_RIGHTUP, 152 SDL_HAT_RIGHT, 153 SDL_HAT_RIGHTDOWN, 154 SDL_HAT_DOWN, 155 SDL_HAT_LEFTDOWN, 156 SDL_HAT_LEFT, 157 SDL_HAT_LEFTUP 158 }; 159 const int JITTER = (32768/10); /* 10% jitter threshold (ok?) */ 160 161 BJoystick *stick; 162 int i, change; 163 int16 *axes; 164 uint8 *hats; 165 uint32 buttons; 166 167 /* Set up data pointers */ 168 stick = joystick->hwdata->stick; 169 axes = joystick->hwdata->new_axes; 170 hats = joystick->hwdata->new_hats; 171 172 /* Get the new joystick state */ 173 stick->Update(); 174 stick->GetAxisValues(axes); 175 stick->GetHatValues(hats); 176 buttons = stick->ButtonValues(); 177 178 /* Generate axis motion events */ 179 for ( i=0; i<joystick->naxes; ++i ) { 180 change = ((int32)axes[i] - joystick->axes[i]); 181 if ( (change > JITTER) || (change < -JITTER) ) { 182 SDL_PrivateJoystickAxis(joystick, i, axes[i]); 183 } 184 } 185 186 /* Generate hat change events */ 187 for ( i=0; i<joystick->nhats; ++i ) { 188 if ( hats[i] != joystick->hats[i] ) { 189 SDL_PrivateJoystickHat(joystick, i, hat_map[hats[i]]); 190 } 191 } 192 193 /* Generate button events */ 194 for ( i=0; i<joystick->nbuttons; ++i ) { 195 if ( (buttons&0x01) != joystick->buttons[i] ) { 196 SDL_PrivateJoystickButton(joystick, i, (buttons&0x01)); 197 } 198 buttons >>= 1; 199 } 200} 201 202/* Function to close a joystick after use */ 203void SDL_SYS_JoystickClose(SDL_Joystick *joystick) 204{ 205 if ( joystick->hwdata ) { 206 joystick->hwdata->stick->Close(); 207 delete joystick->hwdata->stick; 208 if ( joystick->hwdata->new_hats ) { 209 SDL_free(joystick->hwdata->new_hats); 210 } 211 if ( joystick->hwdata->new_axes ) { 212 SDL_free(joystick->hwdata->new_axes); 213 } 214 SDL_free(joystick->hwdata); 215 joystick->hwdata = NULL; 216 } 217} 218 219/* Function to perform any system-specific joystick related cleanup */ 220void SDL_SYS_JoystickQuit(void) 221{ 222 int i; 223 224 for ( i=0; SDL_joyport[i]; ++i ) { 225 SDL_free(SDL_joyport[i]); 226 } 227 SDL_joyport[0] = NULL; 228 229 for ( i=0; SDL_joyname[i]; ++i ) { 230 SDL_free(SDL_joyname[i]); 231 } 232 SDL_joyname[0] = NULL; 233} 234 235}; // extern "C" 236 237#endif /* SDL_JOYSTICK_BEOS */ 238