joystick-api.rst 10.2 KB
Newer Older
1 2 3
=====================
Programming Interface
=====================
L
Linus Torvalds 已提交
4

5
:Author: Ragnar Hojland Espinosa <ragnar@macula.net> - 7 Aug 1998
L
Linus Torvalds 已提交
6

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Introduction
============

.. important::
   This document describes legacy ``js`` interface. Newer clients are
   encouraged to switch to the generic event (``evdev``) interface.

The 1.0 driver uses a new, event based approach to the joystick driver.
Instead of the user program polling for the joystick values, the joystick
driver now reports only any changes of its state. See joystick-api.txt,
joystick.h and jstest.c included in the joystick package for more
information. The joystick device can be used in either blocking or
nonblocking mode, and supports select() calls.

For backward compatibility the old (v0.x) interface is still included.
Any call to the joystick driver using the old interface will return values
that are compatible to the old interface. This interface is still limited
to 2 axes, and applications using it usually decode only 2 buttons, although
the driver provides up to 32.

27 28
Initialization
==============
L
Linus Torvalds 已提交
29 30 31 32

Open the joystick device following the usual semantics (that is, with open).
Since the driver now reports events instead of polling for changes,
immediately after the open it will issue a series of synthetic events
33
(JS_EVENT_INIT) that you can read to obtain the initial state of the
L
Linus Torvalds 已提交
34 35
joystick.

36
By default, the device is opened in blocking mode::
L
Linus Torvalds 已提交
37

38
	int fd = open ("/dev/input/js0", O_RDONLY);
L
Linus Torvalds 已提交
39 40


41 42 43 44
Event Reading
=============

::
L
Linus Torvalds 已提交
45 46

	struct js_event e;
47
	read (fd, &e, sizeof(e));
L
Linus Torvalds 已提交
48

49
where js_event is defined as::
L
Linus Torvalds 已提交
50 51 52 53 54 55 56 57

	struct js_event {
		__u32 time;     /* event timestamp in milliseconds */
		__s16 value;    /* value */
		__u8 type;      /* event type */
		__u8 number;    /* axis/button number */
	};

58 59
If the read is successful, it will return sizeof(e), unless you wanted to read
more than one event per read as described in section 3.1.
L
Linus Torvalds 已提交
60 61


62 63
js_event.type
-------------
L
Linus Torvalds 已提交
64

65
The possible values of ``type`` are::
L
Linus Torvalds 已提交
66 67 68 69 70 71 72

	#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
	#define JS_EVENT_AXIS           0x02    /* joystick moved */
	#define JS_EVENT_INIT           0x80    /* initial state of device */

As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed
events on open. That is, if it's issuing a INIT BUTTON event, the
73
current type value will be::
L
Linus Torvalds 已提交
74 75 76 77

	int type = JS_EVENT_BUTTON | JS_EVENT_INIT;	/* 0x81 */

If you choose not to differentiate between synthetic or real events
78
you can turn off the JS_EVENT_INIT bits::
L
Linus Torvalds 已提交
79 80 81 82

	type &= ~JS_EVENT_INIT;				/* 0x01 */


83 84
js_event.number
---------------
L
Linus Torvalds 已提交
85

86
The values of ``number`` correspond to the axis or button that
L
Linus Torvalds 已提交
87 88 89
generated the event. Note that they carry separate numeration (that
is, you have both an axis 0 and a button 0). Generally,

90 91 92
        =============== =======
	Axis		number
        =============== =======
L
Linus Torvalds 已提交
93 94 95 96 97
	1st Axis X	0
	1st Axis Y	1
	2nd Axis X	2
	2nd Axis Y	3
	...and so on
98
        =============== =======
L
Linus Torvalds 已提交
99 100 101 102 103 104

Hats vary from one joystick type to another. Some can be moved in 8
directions, some only in 4, The driver, however, always reports a hat as two
independent axis, even if the hardware doesn't allow independent movement.


105 106
js_event.value
--------------
L
Linus Torvalds 已提交
107

108
For an axis, ``value`` is a signed integer between -32767 and +32767
L
Linus Torvalds 已提交
109
representing the position of the joystick along that axis. If you
110
don't read a 0 when the joystick is ``dead``, or if it doesn't span the
L
Linus Torvalds 已提交
111 112
full range, you should recalibrate it (with, for example, jscal).

113
For a button, ``value`` for a press button event is 1 and for a release
L
Linus Torvalds 已提交
114 115
button event is 0.

116
Though this::
L
Linus Torvalds 已提交
117 118 119 120 121 122 123

	if (js_event.type == JS_EVENT_BUTTON) {
		buttons_state ^= (1 << js_event.number);
	}

may work well if you handle JS_EVENT_INIT events separately,

124 125
::

L
Linus Torvalds 已提交
126 127
	if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) {
		if (js_event.value)
128 129 130
			buttons_state |= (1 << js_event.number);
		else
			buttons_state &= ~(1 << js_event.number);
L
Linus Torvalds 已提交
131 132 133 134 135 136 137
	}

is much safer since it can't lose sync with the driver. As you would
have to write a separate handler for JS_EVENT_INIT events in the first
snippet, this ends up being shorter.


138 139
js_event.time
-------------
L
Linus Torvalds 已提交
140

141
The time an event was generated is stored in ``js_event.time``. It's a time
L
Linus Torvalds 已提交
142 143 144 145 146
in milliseconds since ... well, since sometime in the past.  This eases the
task of detecting double clicks, figuring out if movement of axis and button
presses happened at the same time, and similar.


147 148
Reading
=======
L
Linus Torvalds 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161

If you open the device in blocking mode, a read will block (that is,
wait) forever until an event is generated and effectively read. There
are two alternatives if you can't afford to wait forever (which is,
admittedly, a long time;)

	a) use select to wait until there's data to be read on fd, or
	   until it timeouts. There's a good example on the select(2)
	   man page.

	b) open the device in non-blocking mode (O_NONBLOCK)


162 163
O_NONBLOCK
----------
L
Linus Torvalds 已提交
164 165 166 167 168 169 170 171

If read returns -1 when reading in O_NONBLOCK mode, this isn't
necessarily a "real" error (check errno(3)); it can just mean there
are no events pending to be read on the driver queue. You should read
all events on the queue (that is, until you get a -1).

For example,

172 173
::

L
Linus Torvalds 已提交
174
	while (1) {
175 176 177 178 179 180 181 182
		while (read (fd, &e, sizeof(e)) > 0) {
			process_event (e);
		}
		/* EAGAIN is returned when the queue is empty */
		if (errno != EAGAIN) {
			/* error */
		}
		/* do something interesting with processed events */
L
Linus Torvalds 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	}

One reason for emptying the queue is that if it gets full you'll start
missing events since the queue is finite, and older events will get
overwritten.

The other reason is that you want to know all what happened, and not
delay the processing till later.

Why can get the queue full? Because you don't empty the queue as
mentioned, or because too much time elapses from one read to another
and too many events to store in the queue get generated. Note that
high system load may contribute to space those reads even more.

If time between reads is enough to fill the queue and lose an event,
the driver will switch to startup mode and next time you read it,
synthetic events (JS_EVENT_INIT) will be generated to inform you of
the actual state of the joystick.

202 203 204

.. note::

205
 As of version 1.2.8, the queue is circular and able to hold 64
L
Linus Torvalds 已提交
206
 events. You can increment this size bumping up JS_BUFF_SIZE in
207
 joystick.h and recompiling the driver.
L
Linus Torvalds 已提交
208 209 210 211


In the above code, you might as well want to read more than one event
at a time using the typical read(2) functionality. For that, you would
212
replace the read above with something like::
L
Linus Torvalds 已提交
213 214

	struct js_event mybuffer[0xff];
215
	int i = read (fd, mybuffer, sizeof(mybuffer));
L
Linus Torvalds 已提交
216 217 218 219 220 221 222

In this case, read would return -1 if the queue was empty, or some
other value in which the number of events read would be i /
sizeof(js_event)  Again, if the buffer was full, it's a good idea to
process the events and keep reading it until you empty the driver queue.


223 224
IOCTLs
======
L
Linus Torvalds 已提交
225

226
The joystick driver defines the following ioctl(2) operations::
L
Linus Torvalds 已提交
227 228 229 230 231 232 233 234 235

				/* function			3rd arg  */
	#define JSIOCGAXES	/* get number of axes		char	 */
	#define JSIOCGBUTTONS	/* get number of buttons	char	 */
	#define JSIOCGVERSION	/* get driver version		int	 */
	#define JSIOCGNAME(len) /* get identifier string	char	 */
	#define JSIOCSCORR	/* set correction values	&js_corr */
	#define JSIOCGCORR	/* get correction values	&js_corr */

236
For example, to read the number of axes::
L
Linus Torvalds 已提交
237 238 239 240 241

	char number_of_axes;
	ioctl (fd, JSIOCGAXES, &number_of_axes);


242 243
JSIOGCVERSION
-------------
L
Linus Torvalds 已提交
244 245 246 247

JSIOGCVERSION is a good way to check in run-time whether the running
driver is 1.0+ and supports the event interface. If it is not, the
IOCTL will fail. For a compile-time decision, you can test the
248
JS_VERSION symbol::
L
Linus Torvalds 已提交
249 250 251 252 253

	#ifdef JS_VERSION
	#if JS_VERSION > 0xsomething


254 255
JSIOCGNAME
----------
L
Linus Torvalds 已提交
256 257 258 259

JSIOCGNAME(len) allows you to get the name string of the joystick - the same
as is being printed at boot time. The 'len' argument is the length of the
buffer provided by the application asking for the name. It is used to avoid
260
possible overrun should the name be too long::
L
Linus Torvalds 已提交
261 262 263 264 265 266 267

	char name[128];
	if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
		strncpy(name, "Unknown", sizeof(name));
	printf("Name: %s\n", name);


268 269
JSIOC[SG]CORR
-------------
L
Linus Torvalds 已提交
270 271 272 273 274 275 276 277 278 279

For usage on JSIOC[SG]CORR I suggest you to look into jscal.c  They are
not needed in a normal program, only in joystick calibration software
such as jscal or kcmjoy. These IOCTLs and data types aren't considered
to be in the stable part of the API, and therefore may change without
warning in following releases of the driver.

Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold
information for all axis. That is, struct js_corr corr[MAX_AXIS];

280
struct js_corr is defined as::
L
Linus Torvalds 已提交
281 282 283 284 285 286 287

	struct js_corr {
		__s32 coef[8];
		__u16 prec;
		__u16 type;
	};

288
and ``type``::
L
Linus Torvalds 已提交
289 290 291 292 293

	#define JS_CORR_NONE            0x00    /* returns raw values */
	#define JS_CORR_BROKEN          0x01    /* broken line */


294 295
Backward compatibility
======================
L
Linus Torvalds 已提交
296 297

The 0.x joystick driver API is quite limited and its usage is deprecated.
298
The driver offers backward compatibility, though. Here's a quick summary::
L
Linus Torvalds 已提交
299 300 301 302

	struct JS_DATA_TYPE js;
	while (1) {
		if (read (fd, &js, JS_RETURN) != JS_RETURN) {
303 304 305
			/* error */
		}
		usleep (1000);
L
Linus Torvalds 已提交
306 307 308
	}

As you can figure out from the example, the read returns immediately,
309
with the actual state of the joystick::
L
Linus Torvalds 已提交
310 311 312 313 314 315 316

	struct JS_DATA_TYPE {
		int buttons;    /* immediate button state */
		int x;          /* immediate x axis value */
		int y;          /* immediate y axis value */
	};

317
and JS_RETURN is defined as::
L
Linus Torvalds 已提交
318 319 320 321 322

	#define JS_RETURN       sizeof(struct JS_DATA_TYPE)

To test the state of the buttons,

323 324
::

L
Linus Torvalds 已提交
325 326 327 328 329 330 331 332 333 334 335 336 337
	first_button_state  = js.buttons & 1;
	second_button_state = js.buttons & 2;

The axis values do not have a defined range in the original 0.x driver,
except for that the values are non-negative. The 1.2.8+ drivers use a
fixed range for reporting the values, 1 being the minimum, 128 the
center, and 255 maximum value.

The v0.8.0.2 driver also had an interface for 'digital joysticks', (now
called Multisystem joysticks in this driver), under /dev/djsX. This driver
doesn't try to be compatible with that interface.


338 339
Final Notes
===========
L
Linus Torvalds 已提交
340

341
::
L
Linus Torvalds 已提交
342

343 344 345 346
  ____/|	Comments, additions, and specially corrections are welcome.
  \ o.O|	Documentation valid for at least version 1.2.8 of the joystick
   =(_)=	driver and as usual, the ultimate source for documentation is
     U		to "Use The Source Luke" or, at your convenience, Vojtech ;)