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