Imported Upstream version 2.0.4
[platform/upstream/SDL.git] / src / joystick / haiku / SDL_haikujoystick.cc
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 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 <os/support/String.h>
28 #include <os/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 SDL_SYS_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  */
59     int SDL_SYS_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           SDL_SYS_numjoysticks = 0;
69           SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport));
70           SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname));
71         for (i = 0; (SDL_SYS_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[SDL_SYS_numjoysticks] = strdup(name);
78                       SDL_joyname[SDL_SYS_numjoysticks] = strdup(stick_name.String());
79                       SDL_SYS_numjoysticks++;
80                       joystick.Close();
81                 }
82             }
83         }
84         return (SDL_SYS_numjoysticks);
85     }
86
87     int SDL_SYS_NumJoysticks()
88     {
89         return SDL_SYS_numjoysticks;
90     }
91
92     void SDL_SYS_JoystickDetect()
93     {
94     }
95
96 /* Function to get the device-dependent name of a joystick */
97     const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index)
98     {
99         return SDL_joyname[device_index];
100     }
101
102 /* Function to perform the mapping from device index to the instance id for this index */
103     SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
104     {
105         return device_index;
106     }
107
108 /* Function to open a joystick for use.
109    The joystick to open is specified by the device index.
110    This should fill the nbuttons and naxes fields of the joystick structure.
111    It returns 0, or -1 if there is an error.
112  */
113     int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
114     {
115         BJoystick *stick;
116
117         /* Create the joystick data structure */
118         joystick->instance_id = device_index;
119         joystick->hwdata = (struct joystick_hwdata *)
120             SDL_malloc(sizeof(*joystick->hwdata));
121         if (joystick->hwdata == NULL) {
122             return SDL_OutOfMemory();
123         }
124         SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
125         stick = new BJoystick;
126         joystick->hwdata->stick = stick;
127
128         /* Open the requested joystick for use */
129         if (stick->Open(SDL_joyport[device_index]) == B_ERROR) {
130             SDL_SYS_JoystickClose(joystick);
131             return SDL_SetError("Unable to open joystick");
132         }
133
134         /* Set the joystick to calibrated mode */
135         stick->EnableCalibration();
136
137         /* Get the number of buttons, hats, and axes on the joystick */
138         joystick->nbuttons = stick->CountButtons();
139         joystick->naxes = stick->CountAxes();
140         joystick->nhats = stick->CountHats();
141
142         joystick->hwdata->new_axes = (int16 *)
143             SDL_malloc(joystick->naxes * sizeof(int16));
144         joystick->hwdata->new_hats = (uint8 *)
145             SDL_malloc(joystick->nhats * sizeof(uint8));
146         if (!joystick->hwdata->new_hats || !joystick->hwdata->new_axes) {
147             SDL_SYS_JoystickClose(joystick);
148             return SDL_OutOfMemory();
149         }
150
151         /* We're done! */
152         return (0);
153     }
154
155 /* Function to determine if this joystick is attached to the system right now */
156     SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
157     {
158         return SDL_TRUE;
159     }
160
161 /* Function to update the state of a joystick - called as a device poll.
162  * This function shouldn't update the joystick structure directly,
163  * but instead should call SDL_PrivateJoystick*() to deliver events
164  * and update joystick device state.
165  */
166     void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
167     {
168         static const Uint8 hat_map[9] = {
169             SDL_HAT_CENTERED,
170             SDL_HAT_UP,
171             SDL_HAT_RIGHTUP,
172             SDL_HAT_RIGHT,
173             SDL_HAT_RIGHTDOWN,
174             SDL_HAT_DOWN,
175             SDL_HAT_LEFTDOWN,
176             SDL_HAT_LEFT,
177             SDL_HAT_LEFTUP
178         };
179         const int JITTER = (32768 / 10);        /* 10% jitter threshold (ok?) */
180
181         BJoystick *stick;
182         int i, change;
183         int16 *axes;
184         uint8 *hats;
185         uint32 buttons;
186
187         /* Set up data pointers */
188         stick = joystick->hwdata->stick;
189         axes = joystick->hwdata->new_axes;
190         hats = joystick->hwdata->new_hats;
191
192         /* Get the new joystick state */
193         stick->Update();
194         stick->GetAxisValues(axes);
195         stick->GetHatValues(hats);
196         buttons = stick->ButtonValues();
197
198         /* Generate axis motion events */
199         for (i = 0; i < joystick->naxes; ++i) {
200             change = ((int32) axes[i] - joystick->axes[i]);
201             if ((change > JITTER) || (change < -JITTER)) {
202                 SDL_PrivateJoystickAxis(joystick, i, axes[i]);
203             }
204         }
205
206         /* Generate hat change events */
207         for (i = 0; i < joystick->nhats; ++i) {
208             if (hats[i] != joystick->hats[i]) {
209                 SDL_PrivateJoystickHat(joystick, i, hat_map[hats[i]]);
210             }
211         }
212
213         /* Generate button events */
214         for (i = 0; i < joystick->nbuttons; ++i) {
215             if ((buttons & 0x01) != joystick->buttons[i]) {
216                 SDL_PrivateJoystickButton(joystick, i, (buttons & 0x01));
217             }
218             buttons >>= 1;
219         }
220     }
221
222 /* Function to close a joystick after use */
223     void SDL_SYS_JoystickClose(SDL_Joystick * joystick)
224     {
225         if (joystick->hwdata) {
226             joystick->hwdata->stick->Close();
227             delete joystick->hwdata->stick;
228             SDL_free(joystick->hwdata->new_hats);
229             SDL_free(joystick->hwdata->new_axes);
230             SDL_free(joystick->hwdata);
231         }
232     }
233
234 /* Function to perform any system-specific joystick related cleanup */
235     void SDL_SYS_JoystickQuit(void)
236     {
237         int i;
238
239         for (i = 0; SDL_joyport[i]; ++i) {
240             SDL_free(SDL_joyport[i]);
241         }
242         SDL_joyport[0] = NULL;
243
244         for (i = 0; SDL_joyname[i]; ++i) {
245             SDL_free(SDL_joyname[i]);
246         }
247         SDL_joyname[0] = NULL;
248     }
249
250     SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
251     {
252         SDL_JoystickGUID guid;
253         /* the GUID is just the first 16 chars of the name for now */
254         const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
255         SDL_zero( guid );
256         SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
257         return guid;
258     }
259
260     SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
261     {
262         SDL_JoystickGUID guid;
263         /* the GUID is just the first 16 chars of the name for now */
264         const char *name = joystick->name;
265         SDL_zero( guid );
266         SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
267         return guid;
268     }
269
270 };                              // extern "C"
271
272 #endif /* SDL_JOYSTICK_HAIKU */
273
274 /* vi: set ts=4 sw=4 expandtab: */