SDL  2.0
SDL_virtualjoystick.c
Go to the documentation of this file.
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 
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 */
139 
140  /* Add virtual joystick to SDL-global lists */
141  hwdata->next = g_VJoys;
142  g_VJoys = hwdata;
144 
145  /* Return the new virtual-device's index */
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 
172 
173  if (!joystick || !joystick->hwdata) {
175  return SDL_SetError("Invalid joystick");
176  }
177 
178  hwdata = (joystick_hwdata *)joystick->hwdata;
179  if (axis < 0 || axis >= hwdata->nbuttons) {
181  return SDL_SetError("Invalid axis index");
182  }
183 
184  hwdata->axes[axis] = value;
185 
187  return 0;
188 }
189 
190 
191 int
192 SDL_JoystickSetVirtualButtonInner(SDL_Joystick * joystick, int button, Uint8 value)
193 {
194  joystick_hwdata *hwdata;
195 
197 
198  if (!joystick || !joystick->hwdata) {
200  return SDL_SetError("Invalid joystick");
201  }
202 
203  hwdata = (joystick_hwdata *)joystick->hwdata;
204  if (button < 0 || button >= hwdata->nbuttons) {
206  return SDL_SetError("Invalid button index");
207  }
208 
209  hwdata->buttons[button] = value;
210 
212  return 0;
213 }
214 
215 
216 int
217 SDL_JoystickSetVirtualHatInner(SDL_Joystick * joystick, int hat, Uint8 value)
218 {
219  joystick_hwdata *hwdata;
220 
222 
223  if (!joystick || !joystick->hwdata) {
225  return SDL_SetError("Invalid joystick");
226  }
227 
228  hwdata = (joystick_hwdata *)joystick->hwdata;
229  if (hat < 0 || hat >= hwdata->nbuttons) {
231  return SDL_SetError("Invalid hat index");
232  }
233 
234  hwdata->hats[hat] = value;
235 
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) {
385  }
386  for (i = 0; i < hwdata->nbuttons; ++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 
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: */
#define SDL_SetError
#define SDL_LockJoysticks
#define SDL_free
#define SDL_UnlockJoysticks
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_Unsupported()
Definition: SDL_error.h:89
const GLubyte GLuint red
Definition: SDL_glfuncs.h:80
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
SDL_JoystickID SDL_GetNextJoystickInstanceID()
Definition: SDL_joystick.c:262
int SDL_JoystickGetDeviceIndexFromInstanceID(SDL_JoystickID instance_id)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
SDL_JoystickType
Definition: SDL_joystick.h:84
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLbyte GLbyte blue
GLbyte green
GLsizei const GLfloat * value
uint16_t Uint16
Definition: SDL_stdinc.h:197
int16_t Sint16
Definition: SDL_stdinc.h:191
#define SDL_zero(x)
Definition: SDL_stdinc.h:426
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:163
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
Uint8 data[16]
Definition: SDL_joystick.h:71
struct joystick_hwdata * next
SDL_JoystickGUID guid
SDL_Texture * button
SDL_Texture * axis
static SDL_Joystick * joystick
Definition: testjoystick.c:37