SDL_virtualjoystick.c (10310B)
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 #if defined(SDL_JOYSTICK_VIRTUAL) 24 25 /* This is the virtual implementation of the SDL joystick API */ 26 27 #include "SDL_virtualjoystick_c.h" 28 #include "../SDL_sysjoystick.h" 29 #include "../SDL_joystick_c.h" 30 31 extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver; 32 33 static joystick_hwdata * g_VJoys = NULL; 34 35 36 static joystick_hwdata * 37 VIRTUAL_HWDataForIndex(int device_index) 38 { 39 joystick_hwdata *vjoy = g_VJoys; 40 while (vjoy) { 41 if (device_index == 0) 42 break; 43 --device_index; 44 vjoy = vjoy->next; 45 } 46 return vjoy; 47 } 48 49 50 static void 51 VIRTUAL_FreeHWData(joystick_hwdata *hwdata) 52 { 53 joystick_hwdata * cur = g_VJoys; 54 joystick_hwdata * prev = NULL; 55 56 if (!hwdata) { 57 return; 58 } 59 if (hwdata->axes) { 60 SDL_free((void *)hwdata->axes); 61 hwdata->axes = NULL; 62 } 63 if (hwdata->buttons) { 64 SDL_free((void *)hwdata->buttons); 65 hwdata->buttons = NULL; 66 } 67 if (hwdata->hats) { 68 SDL_free(hwdata->hats); 69 hwdata->hats = NULL; 70 } 71 72 /* Remove hwdata from SDL-global list */ 73 while (cur) { 74 if (hwdata == cur) { 75 if (prev) { 76 prev->next = cur->next; 77 } else { 78 g_VJoys = cur->next; 79 } 80 break; 81 } 82 prev = cur; 83 cur = cur->next; 84 } 85 86 SDL_free(hwdata); 87 } 88 89 90 int 91 SDL_JoystickAttachVirtualInner(SDL_JoystickType type, 92 int naxes, 93 int nbuttons, 94 int nhats) 95 { 96 joystick_hwdata *hwdata = NULL; 97 int device_index = -1; 98 99 hwdata = SDL_calloc(1, sizeof(joystick_hwdata)); 100 if (!hwdata) { 101 VIRTUAL_FreeHWData(hwdata); 102 return SDL_OutOfMemory(); 103 } 104 105 hwdata->naxes = naxes; 106 hwdata->nbuttons = nbuttons; 107 hwdata->nhats = nhats; 108 hwdata->name = "Virtual Joystick"; 109 110 /* Note that this is a Virtual device and what subtype it is */ 111 hwdata->guid.data[14] = 'v'; 112 hwdata->guid.data[15] = (Uint8)type; 113 114 /* Allocate fields for different control-types */ 115 if (naxes > 0) { 116 hwdata->axes = SDL_calloc(naxes, sizeof(Sint16)); 117 if (!hwdata->axes) { 118 VIRTUAL_FreeHWData(hwdata); 119 return SDL_OutOfMemory(); 120 } 121 } 122 if (nbuttons > 0) { 123 hwdata->buttons = SDL_calloc(nbuttons, sizeof(Uint8)); 124 if (!hwdata->buttons) { 125 VIRTUAL_FreeHWData(hwdata); 126 return SDL_OutOfMemory(); 127 } 128 } 129 if (nhats > 0) { 130 hwdata->hats = SDL_calloc(nhats, sizeof(Uint8)); 131 if (!hwdata->hats) { 132 VIRTUAL_FreeHWData(hwdata); 133 return SDL_OutOfMemory(); 134 } 135 } 136 137 /* Allocate an instance ID for this device */ 138 hwdata->instance_id = SDL_GetNextJoystickInstanceID(); 139 140 /* Add virtual joystick to SDL-global lists */ 141 hwdata->next = g_VJoys; 142 g_VJoys = hwdata; 143 SDL_PrivateJoystickAdded(hwdata->instance_id); 144 145 /* Return the new virtual-device's index */ 146 device_index = SDL_JoystickGetDeviceIndexFromInstanceID(hwdata->instance_id); 147 return device_index; 148 } 149 150 151 int 152 SDL_JoystickDetachVirtualInner(int device_index) 153 { 154 SDL_JoystickID instance_id; 155 joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); 156 if (!hwdata) { 157 return SDL_SetError("Virtual joystick data not found"); 158 } 159 instance_id = hwdata->instance_id; 160 VIRTUAL_FreeHWData(hwdata); 161 SDL_PrivateJoystickRemoved(instance_id); 162 return 0; 163 } 164 165 166 int 167 SDL_JoystickSetVirtualAxisInner(SDL_Joystick * joystick, int axis, Sint16 value) 168 { 169 joystick_hwdata *hwdata; 170 171 SDL_LockJoysticks(); 172 173 if (!joystick || !joystick->hwdata) { 174 SDL_UnlockJoysticks(); 175 return SDL_SetError("Invalid joystick"); 176 } 177 178 hwdata = (joystick_hwdata *)joystick->hwdata; 179 if (axis < 0 || axis >= hwdata->nbuttons) { 180 SDL_UnlockJoysticks(); 181 return SDL_SetError("Invalid axis index"); 182 } 183 184 hwdata->axes[axis] = value; 185 186 SDL_UnlockJoysticks(); 187 return 0; 188 } 189 190 191 int 192 SDL_JoystickSetVirtualButtonInner(SDL_Joystick * joystick, int button, Uint8 value) 193 { 194 joystick_hwdata *hwdata; 195 196 SDL_LockJoysticks(); 197 198 if (!joystick || !joystick->hwdata) { 199 SDL_UnlockJoysticks(); 200 return SDL_SetError("Invalid joystick"); 201 } 202 203 hwdata = (joystick_hwdata *)joystick->hwdata; 204 if (button < 0 || button >= hwdata->nbuttons) { 205 SDL_UnlockJoysticks(); 206 return SDL_SetError("Invalid button index"); 207 } 208 209 hwdata->buttons[button] = value; 210 211 SDL_UnlockJoysticks(); 212 return 0; 213 } 214 215 216 int 217 SDL_JoystickSetVirtualHatInner(SDL_Joystick * joystick, int hat, Uint8 value) 218 { 219 joystick_hwdata *hwdata; 220 221 SDL_LockJoysticks(); 222 223 if (!joystick || !joystick->hwdata) { 224 SDL_UnlockJoysticks(); 225 return SDL_SetError("Invalid joystick"); 226 } 227 228 hwdata = (joystick_hwdata *)joystick->hwdata; 229 if (hat < 0 || hat >= hwdata->nbuttons) { 230 SDL_UnlockJoysticks(); 231 return SDL_SetError("Invalid hat index"); 232 } 233 234 hwdata->hats[hat] = value; 235 236 SDL_UnlockJoysticks(); 237 return 0; 238 } 239 240 241 static int 242 VIRTUAL_JoystickInit(void) 243 { 244 return 0; 245 } 246 247 248 static int 249 VIRTUAL_JoystickGetCount(void) 250 { 251 int count = 0; 252 joystick_hwdata *cur = g_VJoys; 253 while (cur) { 254 ++count; 255 cur = cur->next; 256 } 257 return count; 258 } 259 260 261 static void 262 VIRTUAL_JoystickDetect(void) 263 { 264 } 265 266 267 static const char * 268 VIRTUAL_JoystickGetDeviceName(int device_index) 269 { 270 joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); 271 if (!hwdata) { 272 return NULL; 273 } 274 return hwdata->name ? hwdata->name : ""; 275 } 276 277 278 static int 279 VIRTUAL_JoystickGetDevicePlayerIndex(int device_index) 280 { 281 return -1; 282 } 283 284 285 static void 286 VIRTUAL_JoystickSetDevicePlayerIndex(int device_index, int player_index) 287 { 288 } 289 290 291 static SDL_JoystickGUID 292 VIRTUAL_JoystickGetDeviceGUID(int device_index) 293 { 294 joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); 295 if (!hwdata) { 296 SDL_JoystickGUID guid; 297 SDL_zero(guid); 298 return guid; 299 } 300 return hwdata->guid; 301 } 302 303 304 static SDL_JoystickID 305 VIRTUAL_JoystickGetDeviceInstanceID(int device_index) 306 { 307 joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); 308 if (!hwdata) { 309 return -1; 310 } 311 return hwdata->instance_id; 312 } 313 314 315 static int 316 VIRTUAL_JoystickOpen(SDL_Joystick * joystick, int device_index) 317 { 318 joystick_hwdata *hwdata = VIRTUAL_HWDataForIndex(device_index); 319 if (!hwdata) { 320 return SDL_SetError("No such device"); 321 } 322 if (hwdata->opened) { 323 return SDL_SetError("Joystick already opened"); 324 } 325 joystick->instance_id = hwdata->instance_id; 326 joystick->hwdata = hwdata; 327 joystick->naxes = hwdata->naxes; 328 joystick->nbuttons = hwdata->nbuttons; 329 joystick->nhats = hwdata->nhats; 330 hwdata->opened = SDL_TRUE; 331 return 0; 332 } 333 334 335 static int 336 VIRTUAL_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) 337 { 338 return SDL_Unsupported(); 339 } 340 341 static int 342 VIRTUAL_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) 343 { 344 return SDL_Unsupported(); 345 } 346 347 348 static SDL_bool 349 VIRTUAL_JoystickHasLED(SDL_Joystick * joystick) 350 { 351 return SDL_FALSE; 352 } 353 354 355 static int 356 VIRTUAL_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) 357 { 358 return SDL_Unsupported(); 359 } 360 361 static int 362 VIRTUAL_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) 363 { 364 return SDL_Unsupported(); 365 } 366 367 368 static void 369 VIRTUAL_JoystickUpdate(SDL_Joystick * joystick) 370 { 371 joystick_hwdata *hwdata; 372 int i; 373 374 if (!joystick) { 375 return; 376 } 377 if (!joystick->hwdata) { 378 return; 379 } 380 381 hwdata = (joystick_hwdata *)joystick->hwdata; 382 383 for (i = 0; i < hwdata->naxes; ++i) { 384 SDL_PrivateJoystickAxis(joystick, i, hwdata->axes[i]); 385 } 386 for (i = 0; i < hwdata->nbuttons; ++i) { 387 SDL_PrivateJoystickButton(joystick, i, hwdata->buttons[i]); 388 } 389 for (i = 0; i < hwdata->nhats; ++i) { 390 SDL_PrivateJoystickHat(joystick, i, hwdata->hats[i]); 391 } 392 } 393 394 395 static void 396 VIRTUAL_JoystickClose(SDL_Joystick * joystick) 397 { 398 joystick_hwdata *hwdata; 399 400 if (!joystick) { 401 return; 402 } 403 if (!joystick->hwdata) { 404 return; 405 } 406 407 hwdata = (joystick_hwdata *)joystick->hwdata; 408 hwdata->opened = SDL_FALSE; 409 } 410 411 412 static void 413 VIRTUAL_JoystickQuit(void) 414 { 415 while (g_VJoys) { 416 VIRTUAL_FreeHWData(g_VJoys); 417 } 418 } 419 420 static SDL_bool 421 VIRTUAL_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) 422 { 423 return SDL_FALSE; 424 } 425 426 SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver = 427 { 428 VIRTUAL_JoystickInit, 429 VIRTUAL_JoystickGetCount, 430 VIRTUAL_JoystickDetect, 431 VIRTUAL_JoystickGetDeviceName, 432 VIRTUAL_JoystickGetDevicePlayerIndex, 433 VIRTUAL_JoystickSetDevicePlayerIndex, 434 VIRTUAL_JoystickGetDeviceGUID, 435 VIRTUAL_JoystickGetDeviceInstanceID, 436 VIRTUAL_JoystickOpen, 437 VIRTUAL_JoystickRumble, 438 VIRTUAL_JoystickRumbleTriggers, 439 VIRTUAL_JoystickHasLED, 440 VIRTUAL_JoystickSetLED, 441 VIRTUAL_JoystickSetSensorsEnabled, 442 VIRTUAL_JoystickUpdate, 443 VIRTUAL_JoystickClose, 444 VIRTUAL_JoystickQuit, 445 VIRTUAL_JoystickGetGamepadMapping 446 }; 447 448 #endif /* SDL_JOYSTICK_VIRTUAL || SDL_JOYSTICK_DISABLED */ 449 450 /* vi: set ts=4 sw=4 expandtab: */