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

