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.1.1.1 2007/08/03 18:51:31 Exp $ 9 101. Initialization 11~~~~~~~~~~~~~~~~~ 12 13Open the joystick device following the usual semantics (that is, with open). 14Since the driver now reports events instead of polling for changes, 15immediately 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 17joystick. 18 19By default, the device is opened in blocking mode. 20 21 int fd = open ("/dev/js0", O_RDONLY); 22 23 242. Event Reading 25~~~~~~~~~~~~~~~~ 26 27 struct js_event e; 28 read (fd, &e, sizeof(struct js_event)); 29 30where 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 39If the read is successful, it will return sizeof(struct js_event), unless 40you wanted to read more than one event per read as described in section 3.1. 41 42 432.1 js_event.type 44~~~~~~~~~~~~~~~~~ 45 46The 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 52As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed 53events on open. That is, if it's issuing a INIT BUTTON event, the 54current type value will be 55 56 int type = JS_EVENT_BUTTON | JS_EVENT_INIT; /* 0x81 */ 57 58If you choose not to differentiate between synthetic or real events 59you can turn off the JS_EVENT_INIT bits 60 61 type &= ~JS_EVENT_INIT; /* 0x01 */ 62 63 642.2 js_event.number 65~~~~~~~~~~~~~~~~~~~ 66 67The values of ``number'' correspond to the axis or button that 68generated the event. Note that they carry separate numeration (that 69is, 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 78Hats vary from one joystick type to another. Some can be moved in 8 79directions, some only in 4, The driver, however, always reports a hat as two 80independent axis, even if the hardware doesn't allow independent movement. 81 82 832.3 js_event.value 84~~~~~~~~~~~~~~~~~~ 85 86For an axis, ``value'' is a signed integer between -32767 and +32767 87representing the position of the joystick along that axis. If you 88don't read a 0 when the joystick is `dead', or if it doesn't span the 89full range, you should recalibrate it (with, for example, jscal). 90 91For a button, ``value'' for a press button event is 1 and for a release 92button event is 0. 93 94Though this 95 96 if (js_event.type == JS_EVENT_BUTTON) { 97 buttons_state ^= (1 << js_event.number); 98 } 99 100may 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 109is much safer since it can't lose sync with the driver. As you would 110have to write a separate handler for JS_EVENT_INIT events in the first 111snippet, this ends up being shorter. 112 113 1142.4 js_event.time 115~~~~~~~~~~~~~~~~~ 116 117The time an event was generated is stored in ``js_event.time''. It's a time 118in milliseconds since ... well, since sometime in the past. This eases the 119task of detecting double clicks, figuring out if movement of axis and button 120presses happened at the same time, and similar. 121 122 1233. Reading 124~~~~~~~~~~ 125 126If you open the device in blocking mode, a read will block (that is, 127wait) forever until an event is generated and effectively read. There 128are two alternatives if you can't afford to wait forever (which is, 129admittedly, 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 1383.1 O_NONBLOCK 139~~~~~~~~~~~~~~ 140 141If read returns -1 when reading in O_NONBLOCK mode, this isn't 142necessarily a "real" error (check errno(3)); it can just mean there 143are no events pending to be read on the driver queue. You should read 144all events on the queue (that is, until you get a -1). 145 146For 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 159One reason for emptying the queue is that if it gets full you'll start 160missing events since the queue is finite, and older events will get 161overwritten. 162 163The other reason is that you want to know all what happened, and not 164delay the processing till later. 165 166Why can get the queue full? Because you don't empty the queue as 167mentioned, or because too much time elapses from one read to another 168and too many events to store in the queue get generated. Note that 169high system load may contribute to space those reads even more. 170 171If time between reads is enough to fill the queue and lose an event, 172the driver will switch to startup mode and next time you read it, 173synthetic events (JS_EVENT_INIT) will be generated to inform you of 174the 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 181In the above code, you might as well want to read more than one event 182at a time using the typical read(2) functionality. For that, you would 183replace the read above with something like 184 185 struct js_event mybuffer[0xff]; 186 int i = read (fd, mybuffer, sizeof(struct mybuffer)); 187 188In this case, read would return -1 if the queue was empty, or some 189other value in which the number of events read would be i / 190sizeof(js_event) Again, if the buffer was full, it's a good idea to 191process the events and keep reading it until you empty the driver queue. 192 193 1944. IOCTLs 195~~~~~~~~~ 196 197The 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 207For example, to read the number of axes 208 209 char number_of_axes; 210 ioctl (fd, JSIOCGAXES, &number_of_axes); 211 212 2134.1 JSIOGCVERSION 214~~~~~~~~~~~~~~~~~ 215 216JSIOGCVERSION is a good way to check in run-time whether the running 217driver is 1.0+ and supports the event interface. If it is not, the 218IOCTL will fail. For a compile-time decision, you can test the 219JS_VERSION symbol 220 221 #ifdef JS_VERSION 222 #if JS_VERSION > 0xsomething 223 224 2254.2 JSIOCGNAME 226~~~~~~~~~~~~~~ 227 228JSIOCGNAME(len) allows you to get the name string of the joystick - the same 229as is being printed at boot time. The 'len' argument is the length of the 230buffer provided by the application asking for the name. It is used to avoid 231possible 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 2394.3 JSIOC[SG]CORR 240~~~~~~~~~~~~~~~~~ 241 242For usage on JSIOC[SG]CORR I suggest you to look into jscal.c They are 243not needed in a normal program, only in joystick calibration software 244such as jscal or kcmjoy. These IOCTLs and data types aren't considered 245to be in the stable part of the API, and therefore may change without 246warning in following releases of the driver. 247 248Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold 249information for all axis. That is, struct js_corr corr[MAX_AXIS]; 250 251struct js_corr is defined as 252 253 struct js_corr { 254 __s32 coef[8]; 255 __u16 prec; 256 __u16 type; 257 }; 258 259and ``type'' 260 261 #define JS_CORR_NONE 0x00 /* returns raw values */ 262 #define JS_CORR_BROKEN 0x01 /* broken line */ 263 264 2655. Backward compatibility 266~~~~~~~~~~~~~~~~~~~~~~~~~ 267 268The 0.x joystick driver API is quite limited and its usage is deprecated. 269The 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 279As you can figure out from the example, the read returns immediately, 280with 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 288and JS_RETURN is defined as 289 290 #define JS_RETURN sizeof(struct JS_DATA_TYPE) 291 292To test the state of the buttons, 293 294 first_button_state = js.buttons & 1; 295 second_button_state = js.buttons & 2; 296 297The axis values do not have a defined range in the original 0.x driver, 298except for that the values are non-negative. The 1.2.8+ drivers use a 299fixed range for reporting the values, 1 being the minimum, 128 the 300center, and 255 maximum value. 301 302The v0.8.0.2 driver also had an interface for 'digital joysticks', (now 303called Multisystem joysticks in this driver), under /dev/djsX. This driver 304doesn't try to be compatible with that interface. 305 306 3076. 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 316EOF 317