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