2626 */
2727
2828/* Author: Ian.Piumarta@INRIA.Fr
29+ /* Author: davidf@afeka.ac.il
2930 */
3031
31- #include "sq.h"
32+ #include <assert.h>
33+ #include <limits.h>
34+ #include <stdio.h>
35+ #include <string.h>
36+ #include <stdint.h>
37+ #include <unistd.h>
38+ #include <stdlib.h>
39+ #include <sys/ioctl.h>
40+ #include <sys/types.h>
41+ #include <fcntl.h>
42+ #include <dirent.h>
43+ #include <errno.h>
44+ #include <poll.h>
45+ #include <linux/input-event-codes.h>
46+ #include <linux/input.h>
3247#include "JoystickTabletPlugin.h"
3348
34- /* we don't have any joysticks */
49+ #define DEVICE_DIR "/dev/input/by-id/"
50+ #define JOYSTICK_TOKEN "-event-joystick"
51+ #define MAX_JOYSTICK 2
52+ #define BITS_IN_WORD 32
3553
36- void * joySticks = 0 ;
54+ #define EVENT_BUF_SIZE 10
3755
38- int joystickRead (int index ) { return 0 ; }
39- int joystickInit (void ) { return 0 ; }
56+ typedef struct _input_event {
57+ struct timeval time ;
58+ unsigned short type ;
59+ unsigned short code ;
60+ unsigned int value ;
61+ } input_event ;
4062
41- /* we don't have any tablets either */
63+ typedef struct {
64+ int fd ;
65+ int button_index [4 ]; // key code for each button
66+ int button_state [4 ];
67+ struct input_absinfo abs_x ;
68+ struct input_absinfo abs_y ;
69+ } joystick_state_t ;
70+
71+ joystick_state_t joystick_state [MAX_JOYSTICK ];
72+ int joystick_count ;
73+
74+ int
75+ testBit (int i , uint32_t * x ) {
76+ return x [i / BITS_IN_WORD ] & (1 << (i % BITS_IN_WORD ));
77+ }
78+
79+ int
80+ enumerateJoysticks ()
81+ {
82+
83+ char dev_path [PATH_MAX ];
84+ struct dirent * current_entry ;
85+ DIR * device_dir ;
86+ int result ;
87+
88+ result = 1 ;
89+ errno = 0 ;
90+ device_dir = opendir (DEVICE_DIR );
91+
92+ if (device_dir == NULL ) {
93+ perror ("opendir" );
94+ return 0 ;
95+ }
96+
97+ current_entry = readdir (device_dir );
98+
99+ if (current_entry == NULL ) {
100+ perror ("readdir" );
101+ result = 0 ;
102+ }
103+
104+ while (current_entry != NULL ) {
105+
106+ if (current_entry -> d_type == DT_LNK &&
107+ strstr (current_entry -> d_name , JOYSTICK_TOKEN ) != NULL &&
108+ strlen (current_entry -> d_name ) + strlen (DEVICE_DIR ) < PATH_MAX + 1 &&
109+ joystick_count < MAX_JOYSTICK ) {
110+
111+ dev_path [0 ] = '\0' ;
112+ strcat (dev_path , DEVICE_DIR );
113+ strcat (dev_path , current_entry -> d_name );
114+
115+ joystick_state [joystick_count ].fd = open (dev_path , O_RDONLY );
116+
117+ if (joystick_state [joystick_count ].fd != -1 ) {
118+ ++ joystick_count ;
119+ }
120+
121+ }
122+ current_entry = readdir (device_dir );
123+ }
124+
125+ closedir (device_dir );
126+
127+ return result ;
128+ }
129+
130+ int
131+ detectButtons (joystick_state_t * pj )
132+ {
133+
134+ int fd ;
135+
136+ uint32_t supported_keys [KEY_CNT / BITS_IN_WORD + 1 ] = { 0 };
137+
138+ fd = pj -> fd ;
139+
140+ if (ioctl (fd , EVIOCGBIT (EV_KEY , KEY_MAX ), & supported_keys ) == -1 ) {
141+ perror ("ioctl" );
142+ return -1 ;
143+ }
144+
145+ if (testBit (BTN_JOYSTICK , supported_keys ) == 0 && testBit (BTN_GAMEPAD , supported_keys ) == 0 ) {
146+
147+ // we did not find any buttons, something is wrong with this device.
148+ return -1 ;
149+ }
150+
151+ if (testBit (BTN_JOYSTICK , supported_keys ) == 1 ) {
152+
153+ // it's an old style joystick device
154+
155+ pj -> button_index [0 ] = BTN_JOYSTICK ;
156+ pj -> button_index [1 ] = BTN_THUMB ;
157+ pj -> button_index [2 ] = BTN_THUMB2 ;
158+ pj -> button_index [3 ] = BTN_TOP ;
159+
160+ }
161+ else {
162+ // it's a modern gamepad device
163+
164+ pj -> button_index [0 ] = BTN_NORTH ;
165+ pj -> button_index [1 ] = BTN_EAST ;
166+ pj -> button_index [2 ] = BTN_SOUTH ;
167+ pj -> button_index [3 ] = BTN_WEST ;
168+ }
169+
170+ return 1 ;
171+ }
172+
173+ int
174+ detectAxes (joystick_state_t * pj )
175+ {
176+
177+ int fd ;
178+
179+ uint32_t supported_axes [ABS_CNT / BITS_IN_WORD + 1 ] = { 0 };
180+
181+ fd = pj -> fd ;
182+
183+ if (ioctl (fd , EVIOCGBIT (EV_ABS , ABS_MAX ), & supported_axes ) == -1 ) {
184+ perror ("ioctl" );
185+ return -1 ;
186+ }
187+
188+ if (testBit (ABS_X , supported_axes ) == 0 || testBit (ABS_Y , supported_axes ) == 0 ) {
189+ // something is wrong, we could not find both required axes
190+ return -1 ;
191+ }
192+
193+ return 1 ;
194+ }
195+
196+ int
197+ readJoystickState (joystick_state_t * pj )
198+ {
199+
200+ if (ioctl (pj -> fd , EVIOCGABS (ABS_X ), & pj -> abs_x ) == -1 )
201+ return -1 ;
202+
203+ if (ioctl (pj -> fd , EVIOCGABS (ABS_Y ), & pj -> abs_y ) == -1 )
204+ return -1 ;
205+
206+ return 1 ;
207+ }
208+
209+ int
210+ initializeJoystickState (joystick_state_t * pj )
211+ {
212+ if (detectButtons (pj ) == -1 ) {
213+ return 0 ;
214+ }
215+
216+ if (detectAxes (pj ) == -1 ) {
217+ return 0 ;
218+ }
219+
220+ if (readJoystickState (pj ) == -1 ) {
221+ return 0 ;
222+ }
223+
224+ return 1 ;
225+ }
226+
227+ int
228+ joystickInit (void )
229+ {
230+
231+ if (enumerateJoysticks () == 0 ) {
232+ return 0 ;
233+ }
234+
235+ for (int i = 0 ; i < joystick_count ; ++ i ) {
236+ if (initializeJoystickState (& joystick_state [i ]) == 0 )
237+ return 0 ;
238+ }
239+
240+ return 1 ;
241+ }
242+
243+ double
244+ map (double x , double from_begin ,double from_end , double to_begin , double
245+ to_end )
246+ {
247+ return to_begin + (to_end - to_begin )* (x - from_begin )/(from_end - from_begin );
248+ }
249+
250+ int
251+ readNewEvents (joystick_state_t * pj )
252+ {
253+ input_event event [EVENT_BUF_SIZE ];
254+ int count ;
255+ int i , j ;
256+
257+ count = read (pj -> fd , & event , sizeof (input_event )* EVENT_BUF_SIZE );
258+
259+ for (i = 0 ; i < count / sizeof (input_event ) ; ++ i ) {
260+
261+ if (event [i ].type == EV_KEY ) {
262+ for (j = 0 ; j < 4 ; ++ j ) {
263+ if (pj -> button_index [j ] == event [i ].code ) {
264+ pj -> button_state [j ] = event [i ].value ;
265+ }
266+ }
267+ }
268+
269+ if (event [i ].type == EV_ABS ) {
270+ if (event [i ].code == ABS_X ) {
271+ pj -> abs_x .value = event [i ].value ;
272+ }
273+
274+ if (event [i ].code == ABS_Y ) {
275+ pj -> abs_y .value = event [i ].value ;
276+ }
277+ }
278+ }
279+ return 1 ;
280+ }
281+
282+ int
283+ joystickRead (int index )
284+ {
285+ uint32_t result ;
286+ joystick_state_t * pj ;
287+ struct pollfd poll_fds ;
288+ int ret ;
289+ int x , y ;
290+
291+ result = 0 ;
292+ -- index ;
293+
294+ if (index < 0 || index >= joystick_count )
295+ return 0 ;
296+
297+ pj = & joystick_state [index ];
298+
299+ poll_fds .fd = pj -> fd ;
300+ poll_fds .events = POLLIN ;
301+
302+ ret = poll (& poll_fds , 1 , 0 );
303+
304+ if (ret == -1 )
305+ return 0 ;
306+
307+ if (ret > 0 ) {
308+
309+ ret = readNewEvents (pj );
310+
311+ if (ret == -1 )
312+ return 0 ;
313+ }
314+
315+ x = (int )map (pj -> abs_x .value , pj -> abs_x .minimum , pj -> abs_x .maximum , 0 , 0x7FF );
316+ y = (int )map (pj -> abs_y .value , pj -> abs_y .minimum , pj -> abs_y .maximum , 0 , 0x7FF );
317+
318+ return (1 << 27 ) | (pj -> button_state [0 ] << 22 ) | (pj -> button_state [1 ] << 23 ) | (pj -> button_state [2 ] << 24 ) | (pj -> button_state [3 ] << 25 ) | (y << 11 ) | x ;
319+
320+ }
321+
322+ int
323+ joystickShutdown (void )
324+ {
325+ int i ;
326+
327+ for (i = 0 ; i < joystick_count ; ++ i ) {
328+ close (joystick_state [i ].fd );
329+ }
330+
331+ joystick_count = 0 ;
332+ }
333+
334+
335+ /* we don't have any tablets */
42336
43337int tabletInit (void )
44338{
@@ -60,7 +354,3 @@ int tabletResultSize(void)
60354 return 0 ;
61355}
62356
63- int joystickShutdown (void )
64- {
65- return 0 ;
66- }
0 commit comments