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