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

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

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

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