~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/Documentation/joystick-api.txt

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1                       Joystick API Documentation                -*-Text-*-
  2 
  3                         Ragnar Hojland Espinosa
  4                           <ragnar@macula.net>
  5 
  6                               7 Aug 1998
  7 
  8 
  9 1. Initialization
 10 ~~~~~~~~~~~~~~~~~
 11 
 12 Open the joystick device following the usual semantics (that is, with open).
 13 Since the driver now reports events instead of polling for changes,
 14 immediately after the open it will issue a series of synthetic events
 15 (JS_EVENT_INIT) that you can read to check the initial state of the
 16 joystick.
 17 
 18 By default, the device is opened in blocking mode.
 19 
 20         int fd = open ("/dev/js0", O_RDONLY);
 21 
 22 
 23 2. Event Reading
 24 ~~~~~~~~~~~~~~~~
 25 
 26         struct js_event e;
 27         read (fd, &e, sizeof(struct js_event));
 28 
 29 where js_event is defined as
 30 
 31         struct js_event {
 32                 __u32 time;     /* event timestamp in milliseconds */
 33                 __s16 value;    /* value */
 34                 __u8 type;      /* event type */
 35                 __u8 number;    /* axis/button number */
 36         };
 37 
 38 If the read is successful, it will return sizeof(struct js_event), unless
 39 you wanted to read more than one event per read as described in section 3.1.
 40 
 41 
 42 2.1 js_event.type
 43 ~~~~~~~~~~~~~~~~~
 44 
 45 The possible values of ``type'' are
 46 
 47         #define JS_EVENT_BUTTON         0x01    /* button pressed/released */
 48         #define JS_EVENT_AXIS           0x02    /* joystick moved */
 49         #define JS_EVENT_INIT           0x80    /* initial state of device */
 50 
 51 As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed
 52 events on open. That is, if it's issuing a INIT BUTTON event, the
 53 current type value will be
 54 
 55         int type = JS_EVENT_BUTTON | JS_EVENT_INIT;     /* 0x81 */
 56 
 57 If you choose not to differentiate between synthetic or real events
 58 you can turn off the JS_EVENT_INIT bits
 59 
 60         type &= ~JS_EVENT_INIT;                         /* 0x01 */
 61 
 62 
 63 2.2 js_event.number
 64 ~~~~~~~~~~~~~~~~~~~
 65 
 66 The values of ``number'' correspond to the axis or button that
 67 generated the event. Note that they carry separate numeration (that
 68 is, you have both an axis 0 and a button 0). Generally,
 69 
 70                         number
 71         1st Axis X      0
 72         1st Axis Y      1
 73         2nd Axis X      2
 74         2nd Axis Y      3
 75         ...and so on
 76 
 77 Hats vary from one joystick type to another. Some can be moved in 8
 78 directions, some only in 4, The driver, however, always reports a hat as two
 79 independent axis, even if the hardware doesn't allow independent movement.
 80 
 81 
 82 2.3 js_event.value
 83 ~~~~~~~~~~~~~~~~~~
 84 
 85 For an axis, ``value'' is a signed integer between -32767 and +32767
 86 representing the position of the joystick along that axis. If you
 87 don't read a 0 when the joystick is `dead', or if it doesn't span the
 88 full range, you should recalibrate it (with, for example, jscal).
 89 
 90 For a button, ``value'' for a press button event is 1 and for a release
 91 button event is 0.
 92 
 93 Though this
 94 
 95         if (js_event.type == JS_EVENT_BUTTON) {
 96                 buttons_state ^= (1 << js_event.number);
 97         }
 98 
 99 may work well if you handle JS_EVENT_INIT events separately,
100 
101         if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) {
102                 if (js_event.value)
103                         buttons_state |= (1 << js_event.number);
104                 else
105                         buttons_state &= ~(1 << js_event.number);
106         }
107 
108 is much safer since it can't lose sync with the driver. As you would
109 have to write a separate handler for JS_EVENT_INIT events in the first
110 snippet, this ends up being shorter.
111 
112 
113 2.4 js_event.time
114 ~~~~~~~~~~~~~~~~~
115 
116 The time an event was generated is stored in ``js_event.time''. It's a time
117 in miliseconds since ... well, since sometime in the past.  This eases the
118 task of detecting double clicks, figuring out if movement of axis and button
119 presses happened at the same time, and similar.
120 
121 
122 3. Reading
123 ~~~~~~~~~~
124 
125 If you open the device in blocking mode, a read will block (that is,
126 wait) forever until an event is generated and effectively read. There
127 are two alternatives if you can't afford to wait forever (which is,
128 admittedly, a long time;)
129 
130         a) use select to wait until there's data to be read on fd, or
131            until it timeouts. There's a good example on the select(2)
132            man page.
133 
134         b) open the device in non-blocking mode (O_NONBLOCK)
135 
136 
137 3.1 O_NONBLOCK
138 ~~~~~~~~~~~~~~
139 
140 If read returns -1 when reading in O_NONBLOCK mode, this isn't
141 necessarily a "real" error (check errno(3)); it can just mean there
142 are no events pending to be read on the driver queue. You should read
143 all events on the queue (that is, until you get a -1).
144 
145 For example,
146 
147         while (1) {
148                 while (read (fd, &e, sizeof(struct js_event)) > 0) {
149                         process_event (e);
150                 }
151                 /* EAGAIN is returned when the queue is empty */
152                 if (errno != EAGAIN) {
153                         /* error */
154                 }
155                 /* do something interesting with processed events */
156         }
157 
158 One reason for emptying the queue is that if it gets full you'll start
159 missing events since the queue is finite, and older events will get
160 overwritten.
161 
162 The other reason is that you want to know all what happened, and not
163 delay the processing till later.
164 
165 Why can get the queue full? Because you don't empty the queue as
166 mentioned, or because too much time elapses from one read to another
167 and too many events to store in the queue get generated. Note that
168 high system load may contribute to space those reads even more.
169 
170 If time between reads is enough to fill the queue and loose an event,
171 the driver will switch to startup mode and next time you read it,
172 synthetic events (JS_EVENT_INIT) will be generated to inform you of
173 the actual state of the joystick.
174 
175 [As for version 1.2.8, the queue is circular and able to hold 64
176  events. You can increment this size bumping up JS_BUFF_SIZE in
177  joystick.h and recompiling the driver.]
178 
179 
180 In the above code, you might as well want to read more than one event
181 at a time using the typical read(2) functionality. For that, you would
182 replace the read above with something like
183 
184         struct js_event mybuffer[0xff];
185         int i = read (fd, mybuffer, sizeof(struct mybuffer));
186 
187 In this case, read would return -1 if the queue was empty, or some
188 other value in which the number of events read would be i /
189 sizeof(js_event)  Again, if the buffer was full, it's a good idea to
190 process the events and keep reading it until you empty the driver queue.
191 
192 
193 4. IOCTLs
194 ~~~~~~~~~
195 
196 The joystick driver defines the following ioctl(2) operations.
197 
198                                 /* function                     3rd arg  */
199         #define JSIOCGAXES      /* get number of axes           char     */
200         #define JSIOCGBUTTONS   /* get number of buttons        char     */
201         #define JSIOCGVERSION   /* get driver version           int      */
202         #define JSIOCGNAME(len) /* get identifier string        char     */
203         #define JSIOCSCORR      /* set correction values        &js_corr */
204         #define JSIOCGCORR      /* get correction values        &js_corr */
205 
206 For example, to read the number of axes
207 
208         char number_of_axes;
209         ioctl (fd, JSIOCGAXES, &number_of_axes);
210 
211 
212 4.1 JSIOGCVERSION
213 ~~~~~~~~~~~~~~~~~
214 
215 JSIOGCVERSION is a good way to check in run-time whether the running
216 driver is 1.0+ and supports the event interface. If it is not, the
217 IOCTL will fail. For a compile-time decision, you can test the
218 JS_VERSION symbol
219 
220         #ifdef JS_VERSION
221         #if JS_VERSION > 0xsomething
222 
223 
224 4.2 JSIOCGNAME
225 ~~~~~~~~~~~~~~
226 
227 JSIOCGNAME(len) allows you to get the name string of the joystick - the same
228 as is being printed at boot time. The 'len' argument is the length of the
229 buffer provided by the application asking for the name. It is used to avoid
230 possible overrun should the name be too long.
231 
232         char name[128];
233         if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
234                 strncpy(name, "Unknown", sizeof(name));
235         printf("Name: %s\n", name);
236 
237 
238 4.3 JSIOC[SG]CORR
239 ~~~~~~~~~~~~~~~~~
240 
241 For usage on JSIOC[SG]CORR I suggest you to look into jscal.c  They are
242 not needed in a normal program, only in joystick calibration software
243 such as jscal or kcmjoy. These IOCTLs and data types aren't considered
244 to be in the stable part of the API, and therefore may change without
245 warning in following releases of the driver.
246 
247 Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold
248 information for all axis. That is, struct js_corr corr[MAX_AXIS];
249 
250 struct js_corr is defined as
251 
252         struct js_corr {
253                 __s32 coef[8];
254                 __u16 prec;
255                 __u16 type;
256         };
257 
258 and ``type''
259 
260         #define JS_CORR_NONE            0x00    /* returns raw values */
261         #define JS_CORR_BROKEN          0x01    /* broken line */
262 
263 
264 5. Backward compatibility
265 ~~~~~~~~~~~~~~~~~~~~~~~~~
266 
267 The 0.x joystick driver API is quite limited and its usage is deprecated.
268 The driver offers backward compatibility, though. Here's a quick summary:
269 
270         struct JS_DATA_TYPE js;
271         while (1) {
272                 if (read (fd, &js, JS_RETURN) != JS_RETURN) {
273                         /* error */
274                 }
275                 usleep (1000);
276         }
277 
278 As you can figure out from the example, the read returns immediately,
279 with the actual state of the joystick.
280 
281         struct JS_DATA_TYPE {
282                 int buttons;    /* immediate button state */
283                 int x;          /* immediate x axis value */
284                 int y;          /* immediate y axis value */
285         };
286 
287 and JS_RETURN is defined as
288 
289         #define JS_RETURN       sizeof(struct JS_DATA_TYPE)
290 
291 To test the state of the buttons,
292 
293         first_button_state  = js.buttons & 1;
294         second_button_state = js.buttons & 2;
295 
296 The axis values do not have a defined range in the original 0.x driver,
297 except for that the values are non-negative. The 1.2.8+ drivers use a
298 fixed range for reporting the values, 1 being the minimum, 128 the
299 center, and 255 maximum value.
300 
301 The v0.8.0.2 driver also had an interface for 'digital joysticks', (now
302 called Multisystem joysticks in this driver), under /dev/djsX. This driver
303 doesn't try to be compatible with that interface.
304 
305 
306 6. Final Notes
307 ~~~~~~~~~~~~~~
308 
309 ____/|  Comments, additions, and specially corrections are welcome.
310 \ o.O|  Documentation valid for at least version 1.2.8 of the joystick
311  =(_)=  driver and as usual, the ultimate source for documentation is
312    U    to "Use The Source Luke" or, at your convenience, Vojtech ;)
313 
314                                         - Ragnar
315 EOF

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.