1ad649380SDmitry Torokhov.. _joystick-api: 2ad649380SDmitry Torokhov 34c79e98bSDmitry Torokhov===================== 44c79e98bSDmitry TorokhovProgramming Interface 54c79e98bSDmitry Torokhov===================== 64c79e98bSDmitry Torokhov 74c79e98bSDmitry Torokhov:Author: Ragnar Hojland Espinosa <ragnar@macula.net> - 7 Aug 1998 84c79e98bSDmitry Torokhov 94c79e98bSDmitry TorokhovIntroduction 104c79e98bSDmitry Torokhov============ 114c79e98bSDmitry Torokhov 124c79e98bSDmitry Torokhov.. important:: 134c79e98bSDmitry Torokhov This document describes legacy ``js`` interface. Newer clients are 144c79e98bSDmitry Torokhov encouraged to switch to the generic event (``evdev``) interface. 154c79e98bSDmitry Torokhov 164c79e98bSDmitry TorokhovThe 1.0 driver uses a new, event based approach to the joystick driver. 174c79e98bSDmitry TorokhovInstead of the user program polling for the joystick values, the joystick 184c79e98bSDmitry Torokhovdriver now reports only any changes of its state. See joystick-api.txt, 194c79e98bSDmitry Torokhovjoystick.h and jstest.c included in the joystick package for more 204c79e98bSDmitry Torokhovinformation. The joystick device can be used in either blocking or 214c79e98bSDmitry Torokhovnonblocking mode, and supports select() calls. 224c79e98bSDmitry Torokhov 234c79e98bSDmitry TorokhovFor backward compatibility the old (v0.x) interface is still included. 244c79e98bSDmitry TorokhovAny call to the joystick driver using the old interface will return values 254c79e98bSDmitry Torokhovthat are compatible to the old interface. This interface is still limited 264c79e98bSDmitry Torokhovto 2 axes, and applications using it usually decode only 2 buttons, although 274c79e98bSDmitry Torokhovthe driver provides up to 32. 284c79e98bSDmitry Torokhov 294c79e98bSDmitry TorokhovInitialization 304c79e98bSDmitry Torokhov============== 314c79e98bSDmitry Torokhov 324c79e98bSDmitry TorokhovOpen the joystick device following the usual semantics (that is, with open). 334c79e98bSDmitry TorokhovSince the driver now reports events instead of polling for changes, 344c79e98bSDmitry Torokhovimmediately after the open it will issue a series of synthetic events 354c79e98bSDmitry Torokhov(JS_EVENT_INIT) that you can read to obtain the initial state of the 364c79e98bSDmitry Torokhovjoystick. 374c79e98bSDmitry Torokhov 384c79e98bSDmitry TorokhovBy default, the device is opened in blocking mode:: 394c79e98bSDmitry Torokhov 404c79e98bSDmitry Torokhov int fd = open ("/dev/input/js0", O_RDONLY); 414c79e98bSDmitry Torokhov 424c79e98bSDmitry Torokhov 434c79e98bSDmitry TorokhovEvent Reading 444c79e98bSDmitry Torokhov============= 454c79e98bSDmitry Torokhov 464c79e98bSDmitry Torokhov:: 474c79e98bSDmitry Torokhov 484c79e98bSDmitry Torokhov struct js_event e; 494c79e98bSDmitry Torokhov read (fd, &e, sizeof(e)); 504c79e98bSDmitry Torokhov 514c79e98bSDmitry Torokhovwhere js_event is defined as:: 524c79e98bSDmitry Torokhov 534c79e98bSDmitry Torokhov struct js_event { 544c79e98bSDmitry Torokhov __u32 time; /* event timestamp in milliseconds */ 554c79e98bSDmitry Torokhov __s16 value; /* value */ 564c79e98bSDmitry Torokhov __u8 type; /* event type */ 574c79e98bSDmitry Torokhov __u8 number; /* axis/button number */ 584c79e98bSDmitry Torokhov }; 594c79e98bSDmitry Torokhov 604c79e98bSDmitry TorokhovIf the read is successful, it will return sizeof(e), unless you wanted to read 614c79e98bSDmitry Torokhovmore than one event per read as described in section 3.1. 624c79e98bSDmitry Torokhov 634c79e98bSDmitry Torokhov 644c79e98bSDmitry Torokhovjs_event.type 654c79e98bSDmitry Torokhov------------- 664c79e98bSDmitry Torokhov 674c79e98bSDmitry TorokhovThe possible values of ``type`` are:: 684c79e98bSDmitry Torokhov 694c79e98bSDmitry Torokhov #define JS_EVENT_BUTTON 0x01 /* button pressed/released */ 704c79e98bSDmitry Torokhov #define JS_EVENT_AXIS 0x02 /* joystick moved */ 714c79e98bSDmitry Torokhov #define JS_EVENT_INIT 0x80 /* initial state of device */ 724c79e98bSDmitry Torokhov 734c79e98bSDmitry TorokhovAs mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed 74eef8abdaSRandy Dunlapevents on open. That is, if it's issuing an INIT BUTTON event, the 754c79e98bSDmitry Torokhovcurrent type value will be:: 764c79e98bSDmitry Torokhov 774c79e98bSDmitry Torokhov int type = JS_EVENT_BUTTON | JS_EVENT_INIT; /* 0x81 */ 784c79e98bSDmitry Torokhov 794c79e98bSDmitry TorokhovIf you choose not to differentiate between synthetic or real events 804c79e98bSDmitry Torokhovyou can turn off the JS_EVENT_INIT bits:: 814c79e98bSDmitry Torokhov 824c79e98bSDmitry Torokhov type &= ~JS_EVENT_INIT; /* 0x01 */ 834c79e98bSDmitry Torokhov 844c79e98bSDmitry Torokhov 854c79e98bSDmitry Torokhovjs_event.number 864c79e98bSDmitry Torokhov--------------- 874c79e98bSDmitry Torokhov 884c79e98bSDmitry TorokhovThe values of ``number`` correspond to the axis or button that 894c79e98bSDmitry Torokhovgenerated the event. Note that they carry separate numeration (that 904c79e98bSDmitry Torokhovis, you have both an axis 0 and a button 0). Generally, 914c79e98bSDmitry Torokhov 924c79e98bSDmitry Torokhov =============== ======= 934c79e98bSDmitry Torokhov Axis number 944c79e98bSDmitry Torokhov =============== ======= 954c79e98bSDmitry Torokhov 1st Axis X 0 964c79e98bSDmitry Torokhov 1st Axis Y 1 974c79e98bSDmitry Torokhov 2nd Axis X 2 984c79e98bSDmitry Torokhov 2nd Axis Y 3 994c79e98bSDmitry Torokhov ...and so on 1004c79e98bSDmitry Torokhov =============== ======= 1014c79e98bSDmitry Torokhov 1024c79e98bSDmitry TorokhovHats vary from one joystick type to another. Some can be moved in 8 103eef8abdaSRandy Dunlapdirections, some only in 4. The driver, however, always reports a hat as two 104eef8abdaSRandy Dunlapindependent axes, even if the hardware doesn't allow independent movement. 1054c79e98bSDmitry Torokhov 1064c79e98bSDmitry Torokhov 1074c79e98bSDmitry Torokhovjs_event.value 1084c79e98bSDmitry Torokhov-------------- 1094c79e98bSDmitry Torokhov 1104c79e98bSDmitry TorokhovFor an axis, ``value`` is a signed integer between -32767 and +32767 1114c79e98bSDmitry Torokhovrepresenting the position of the joystick along that axis. If you 1124c79e98bSDmitry Torokhovdon't read a 0 when the joystick is ``dead``, or if it doesn't span the 1134c79e98bSDmitry Torokhovfull range, you should recalibrate it (with, for example, jscal). 1144c79e98bSDmitry Torokhov 1154c79e98bSDmitry TorokhovFor a button, ``value`` for a press button event is 1 and for a release 1164c79e98bSDmitry Torokhovbutton event is 0. 1174c79e98bSDmitry Torokhov 1184c79e98bSDmitry TorokhovThough this:: 1194c79e98bSDmitry Torokhov 1204c79e98bSDmitry Torokhov if (js_event.type == JS_EVENT_BUTTON) { 1214c79e98bSDmitry Torokhov buttons_state ^= (1 << js_event.number); 1224c79e98bSDmitry Torokhov } 1234c79e98bSDmitry Torokhov 1244c79e98bSDmitry Torokhovmay work well if you handle JS_EVENT_INIT events separately, 1254c79e98bSDmitry Torokhov 1264c79e98bSDmitry Torokhov:: 1274c79e98bSDmitry Torokhov 1284c79e98bSDmitry Torokhov if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) { 1294c79e98bSDmitry Torokhov if (js_event.value) 1304c79e98bSDmitry Torokhov buttons_state |= (1 << js_event.number); 1314c79e98bSDmitry Torokhov else 1324c79e98bSDmitry Torokhov buttons_state &= ~(1 << js_event.number); 1334c79e98bSDmitry Torokhov } 1344c79e98bSDmitry Torokhov 1354c79e98bSDmitry Torokhovis much safer since it can't lose sync with the driver. As you would 1364c79e98bSDmitry Torokhovhave to write a separate handler for JS_EVENT_INIT events in the first 1374c79e98bSDmitry Torokhovsnippet, this ends up being shorter. 1384c79e98bSDmitry Torokhov 1394c79e98bSDmitry Torokhov 1404c79e98bSDmitry Torokhovjs_event.time 1414c79e98bSDmitry Torokhov------------- 1424c79e98bSDmitry Torokhov 1434c79e98bSDmitry TorokhovThe time an event was generated is stored in ``js_event.time``. It's a time 1444c79e98bSDmitry Torokhovin milliseconds since ... well, since sometime in the past. This eases the 1454c79e98bSDmitry Torokhovtask of detecting double clicks, figuring out if movement of axis and button 1464c79e98bSDmitry Torokhovpresses happened at the same time, and similar. 1474c79e98bSDmitry Torokhov 1484c79e98bSDmitry Torokhov 1494c79e98bSDmitry TorokhovReading 1504c79e98bSDmitry Torokhov======= 1514c79e98bSDmitry Torokhov 1524c79e98bSDmitry TorokhovIf you open the device in blocking mode, a read will block (that is, 1534c79e98bSDmitry Torokhovwait) forever until an event is generated and effectively read. There 1544c79e98bSDmitry Torokhovare two alternatives if you can't afford to wait forever (which is, 1554c79e98bSDmitry Torokhovadmittedly, a long time;) 1564c79e98bSDmitry Torokhov 1574c79e98bSDmitry Torokhov a) use select to wait until there's data to be read on fd, or 1584c79e98bSDmitry Torokhov until it timeouts. There's a good example on the select(2) 1594c79e98bSDmitry Torokhov man page. 1604c79e98bSDmitry Torokhov 1614c79e98bSDmitry Torokhov b) open the device in non-blocking mode (O_NONBLOCK) 1624c79e98bSDmitry Torokhov 1634c79e98bSDmitry Torokhov 1644c79e98bSDmitry TorokhovO_NONBLOCK 1654c79e98bSDmitry Torokhov---------- 1664c79e98bSDmitry Torokhov 1674c79e98bSDmitry TorokhovIf read returns -1 when reading in O_NONBLOCK mode, this isn't 1684c79e98bSDmitry Torokhovnecessarily a "real" error (check errno(3)); it can just mean there 1694c79e98bSDmitry Torokhovare no events pending to be read on the driver queue. You should read 1704c79e98bSDmitry Torokhovall events on the queue (that is, until you get a -1). 1714c79e98bSDmitry Torokhov 1724c79e98bSDmitry TorokhovFor example, 1734c79e98bSDmitry Torokhov 1744c79e98bSDmitry Torokhov:: 1754c79e98bSDmitry Torokhov 1764c79e98bSDmitry Torokhov while (1) { 1774c79e98bSDmitry Torokhov while (read (fd, &e, sizeof(e)) > 0) { 1784c79e98bSDmitry Torokhov process_event (e); 1794c79e98bSDmitry Torokhov } 1804c79e98bSDmitry Torokhov /* EAGAIN is returned when the queue is empty */ 1814c79e98bSDmitry Torokhov if (errno != EAGAIN) { 1824c79e98bSDmitry Torokhov /* error */ 1834c79e98bSDmitry Torokhov } 1844c79e98bSDmitry Torokhov /* do something interesting with processed events */ 1854c79e98bSDmitry Torokhov } 1864c79e98bSDmitry Torokhov 1874c79e98bSDmitry TorokhovOne reason for emptying the queue is that if it gets full you'll start 1884c79e98bSDmitry Torokhovmissing events since the queue is finite, and older events will get 1894c79e98bSDmitry Torokhovoverwritten. 1904c79e98bSDmitry Torokhov 191eef8abdaSRandy DunlapThe other reason is that you want to know all that happened, and not 1924c79e98bSDmitry Torokhovdelay the processing till later. 1934c79e98bSDmitry Torokhov 194eef8abdaSRandy DunlapWhy can the queue get full? Because you don't empty the queue as 1954c79e98bSDmitry Torokhovmentioned, or because too much time elapses from one read to another 1964c79e98bSDmitry Torokhovand too many events to store in the queue get generated. Note that 1974c79e98bSDmitry Torokhovhigh system load may contribute to space those reads even more. 1984c79e98bSDmitry Torokhov 1994c79e98bSDmitry TorokhovIf time between reads is enough to fill the queue and lose an event, 2004c79e98bSDmitry Torokhovthe driver will switch to startup mode and next time you read it, 2014c79e98bSDmitry Torokhovsynthetic events (JS_EVENT_INIT) will be generated to inform you of 2024c79e98bSDmitry Torokhovthe actual state of the joystick. 2034c79e98bSDmitry Torokhov 2044c79e98bSDmitry Torokhov 2054c79e98bSDmitry Torokhov.. note:: 2064c79e98bSDmitry Torokhov 2074c79e98bSDmitry Torokhov As of version 1.2.8, the queue is circular and able to hold 64 2084c79e98bSDmitry Torokhov events. You can increment this size bumping up JS_BUFF_SIZE in 2094c79e98bSDmitry Torokhov joystick.h and recompiling the driver. 2104c79e98bSDmitry Torokhov 2114c79e98bSDmitry Torokhov 2124c79e98bSDmitry TorokhovIn the above code, you might as well want to read more than one event 2134c79e98bSDmitry Torokhovat a time using the typical read(2) functionality. For that, you would 2144c79e98bSDmitry Torokhovreplace the read above with something like:: 2154c79e98bSDmitry Torokhov 2164c79e98bSDmitry Torokhov struct js_event mybuffer[0xff]; 2174c79e98bSDmitry Torokhov int i = read (fd, mybuffer, sizeof(mybuffer)); 2184c79e98bSDmitry Torokhov 2194c79e98bSDmitry TorokhovIn this case, read would return -1 if the queue was empty, or some 2204c79e98bSDmitry Torokhovother value in which the number of events read would be i / 2214c79e98bSDmitry Torokhovsizeof(js_event) Again, if the buffer was full, it's a good idea to 2224c79e98bSDmitry Torokhovprocess the events and keep reading it until you empty the driver queue. 2234c79e98bSDmitry Torokhov 2244c79e98bSDmitry Torokhov 2254c79e98bSDmitry TorokhovIOCTLs 2264c79e98bSDmitry Torokhov====== 2274c79e98bSDmitry Torokhov 2284c79e98bSDmitry TorokhovThe joystick driver defines the following ioctl(2) operations:: 2294c79e98bSDmitry Torokhov 2304c79e98bSDmitry Torokhov /* function 3rd arg */ 2314c79e98bSDmitry Torokhov #define JSIOCGAXES /* get number of axes char */ 2324c79e98bSDmitry Torokhov #define JSIOCGBUTTONS /* get number of buttons char */ 2334c79e98bSDmitry Torokhov #define JSIOCGVERSION /* get driver version int */ 2344c79e98bSDmitry Torokhov #define JSIOCGNAME(len) /* get identifier string char */ 2354c79e98bSDmitry Torokhov #define JSIOCSCORR /* set correction values &js_corr */ 2364c79e98bSDmitry Torokhov #define JSIOCGCORR /* get correction values &js_corr */ 2374c79e98bSDmitry Torokhov 2384c79e98bSDmitry TorokhovFor example, to read the number of axes:: 2394c79e98bSDmitry Torokhov 2404c79e98bSDmitry Torokhov char number_of_axes; 2414c79e98bSDmitry Torokhov ioctl (fd, JSIOCGAXES, &number_of_axes); 2424c79e98bSDmitry Torokhov 2434c79e98bSDmitry Torokhov 2444c79e98bSDmitry TorokhovJSIOGCVERSION 2454c79e98bSDmitry Torokhov------------- 2464c79e98bSDmitry Torokhov 2474c79e98bSDmitry TorokhovJSIOGCVERSION is a good way to check in run-time whether the running 2484c79e98bSDmitry Torokhovdriver is 1.0+ and supports the event interface. If it is not, the 2494c79e98bSDmitry TorokhovIOCTL will fail. For a compile-time decision, you can test the 2504c79e98bSDmitry TorokhovJS_VERSION symbol:: 2514c79e98bSDmitry Torokhov 2524c79e98bSDmitry Torokhov #ifdef JS_VERSION 2534c79e98bSDmitry Torokhov #if JS_VERSION > 0xsomething 2544c79e98bSDmitry Torokhov 2554c79e98bSDmitry Torokhov 2564c79e98bSDmitry TorokhovJSIOCGNAME 2574c79e98bSDmitry Torokhov---------- 2584c79e98bSDmitry Torokhov 2594c79e98bSDmitry TorokhovJSIOCGNAME(len) allows you to get the name string of the joystick - the same 2604c79e98bSDmitry Torokhovas is being printed at boot time. The 'len' argument is the length of the 2614c79e98bSDmitry Torokhovbuffer provided by the application asking for the name. It is used to avoid 2624c79e98bSDmitry Torokhovpossible overrun should the name be too long:: 2634c79e98bSDmitry Torokhov 2644c79e98bSDmitry Torokhov char name[128]; 2654c79e98bSDmitry Torokhov if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0) 266*f9ce26c5SKees Cook strscpy(name, "Unknown", sizeof(name)); 2674c79e98bSDmitry Torokhov printf("Name: %s\n", name); 2684c79e98bSDmitry Torokhov 2694c79e98bSDmitry Torokhov 2704c79e98bSDmitry TorokhovJSIOC[SG]CORR 2714c79e98bSDmitry Torokhov------------- 2724c79e98bSDmitry Torokhov 2734c79e98bSDmitry TorokhovFor usage on JSIOC[SG]CORR I suggest you to look into jscal.c They are 2744c79e98bSDmitry Torokhovnot needed in a normal program, only in joystick calibration software 2754c79e98bSDmitry Torokhovsuch as jscal or kcmjoy. These IOCTLs and data types aren't considered 2764c79e98bSDmitry Torokhovto be in the stable part of the API, and therefore may change without 2774c79e98bSDmitry Torokhovwarning in following releases of the driver. 2784c79e98bSDmitry Torokhov 2794c79e98bSDmitry TorokhovBoth JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold 280eef8abdaSRandy Dunlapinformation for all axes. That is, struct js_corr corr[MAX_AXIS]; 2814c79e98bSDmitry Torokhov 2824c79e98bSDmitry Torokhovstruct js_corr is defined as:: 2834c79e98bSDmitry Torokhov 2844c79e98bSDmitry Torokhov struct js_corr { 2854c79e98bSDmitry Torokhov __s32 coef[8]; 2864c79e98bSDmitry Torokhov __u16 prec; 2874c79e98bSDmitry Torokhov __u16 type; 2884c79e98bSDmitry Torokhov }; 2894c79e98bSDmitry Torokhov 2904c79e98bSDmitry Torokhovand ``type``:: 2914c79e98bSDmitry Torokhov 2924c79e98bSDmitry Torokhov #define JS_CORR_NONE 0x00 /* returns raw values */ 2934c79e98bSDmitry Torokhov #define JS_CORR_BROKEN 0x01 /* broken line */ 2944c79e98bSDmitry Torokhov 2954c79e98bSDmitry Torokhov 2964c79e98bSDmitry TorokhovBackward compatibility 2974c79e98bSDmitry Torokhov====================== 2984c79e98bSDmitry Torokhov 2994c79e98bSDmitry TorokhovThe 0.x joystick driver API is quite limited and its usage is deprecated. 3004c79e98bSDmitry TorokhovThe driver offers backward compatibility, though. Here's a quick summary:: 3014c79e98bSDmitry Torokhov 3024c79e98bSDmitry Torokhov struct JS_DATA_TYPE js; 3034c79e98bSDmitry Torokhov while (1) { 3044c79e98bSDmitry Torokhov if (read (fd, &js, JS_RETURN) != JS_RETURN) { 3054c79e98bSDmitry Torokhov /* error */ 3064c79e98bSDmitry Torokhov } 3074c79e98bSDmitry Torokhov usleep (1000); 3084c79e98bSDmitry Torokhov } 3094c79e98bSDmitry Torokhov 3104c79e98bSDmitry TorokhovAs you can figure out from the example, the read returns immediately, 3114c79e98bSDmitry Torokhovwith the actual state of the joystick:: 3124c79e98bSDmitry Torokhov 3134c79e98bSDmitry Torokhov struct JS_DATA_TYPE { 3144c79e98bSDmitry Torokhov int buttons; /* immediate button state */ 3154c79e98bSDmitry Torokhov int x; /* immediate x axis value */ 3164c79e98bSDmitry Torokhov int y; /* immediate y axis value */ 3174c79e98bSDmitry Torokhov }; 3184c79e98bSDmitry Torokhov 3194c79e98bSDmitry Torokhovand JS_RETURN is defined as:: 3204c79e98bSDmitry Torokhov 3214c79e98bSDmitry Torokhov #define JS_RETURN sizeof(struct JS_DATA_TYPE) 3224c79e98bSDmitry Torokhov 3234c79e98bSDmitry TorokhovTo test the state of the buttons, 3244c79e98bSDmitry Torokhov 3254c79e98bSDmitry Torokhov:: 3264c79e98bSDmitry Torokhov 3274c79e98bSDmitry Torokhov first_button_state = js.buttons & 1; 3284c79e98bSDmitry Torokhov second_button_state = js.buttons & 2; 3294c79e98bSDmitry Torokhov 3304c79e98bSDmitry TorokhovThe axis values do not have a defined range in the original 0.x driver, 331eef8abdaSRandy Dunlapexcept that the values are non-negative. The 1.2.8+ drivers use a 3324c79e98bSDmitry Torokhovfixed range for reporting the values, 1 being the minimum, 128 the 3334c79e98bSDmitry Torokhovcenter, and 255 maximum value. 3344c79e98bSDmitry Torokhov 3354c79e98bSDmitry TorokhovThe v0.8.0.2 driver also had an interface for 'digital joysticks', (now 3364c79e98bSDmitry Torokhovcalled Multisystem joysticks in this driver), under /dev/djsX. This driver 3374c79e98bSDmitry Torokhovdoesn't try to be compatible with that interface. 3384c79e98bSDmitry Torokhov 3394c79e98bSDmitry Torokhov 3404c79e98bSDmitry TorokhovFinal Notes 3414c79e98bSDmitry Torokhov=========== 3424c79e98bSDmitry Torokhov 3434c79e98bSDmitry Torokhov:: 3444c79e98bSDmitry Torokhov 3454c79e98bSDmitry Torokhov ____/| Comments, additions, and specially corrections are welcome. 3464c79e98bSDmitry Torokhov \ o.O| Documentation valid for at least version 1.2.8 of the joystick 3474c79e98bSDmitry Torokhov =(_)= driver and as usual, the ultimate source for documentation is 3484c79e98bSDmitry Torokhov U to "Use The Source Luke" or, at your convenience, Vojtech ;) 349