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