You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
Amiga 4-joystick parport extension
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Parallel port pins:
|
||||
|
||||
(2) - Up1 (6) - Up2
|
||||
(3) - Down1 (7) - Down2
|
||||
(4) - Left1 (8) - Left2
|
||||
(5) - Right1 (9) - Right2
|
||||
(13) - Fire1 (11) - Fire2
|
||||
(18) - Gnd1 (18) - Gnd2
|
||||
|
||||
Amiga digital joystick pinout
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(1) - Up
|
||||
(2) - Down
|
||||
(3) - Left
|
||||
(4) - Right
|
||||
(5) - n/c
|
||||
(6) - Fire button
|
||||
(7) - +5V (50mA)
|
||||
(8) - Gnd
|
||||
(9) - Thumb button
|
||||
|
||||
Amiga mouse pinout
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
(1) - V-pulse
|
||||
(2) - H-pulse
|
||||
(3) - VQ-pulse
|
||||
(4) - HQ-pulse
|
||||
(5) - Middle button
|
||||
(6) - Left button
|
||||
(7) - +5V (50mA)
|
||||
(8) - Gnd
|
||||
(9) - Right button
|
||||
|
||||
Amiga analog joystick pinout
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
(1) - Top button
|
||||
(2) - Top2 button
|
||||
(3) - Trigger button
|
||||
(4) - Thumb button
|
||||
(5) - Analog X
|
||||
(6) - n/c
|
||||
(7) - +5V (50mA)
|
||||
(8) - Gnd
|
||||
(9) - Analog Y
|
||||
|
||||
Amiga lightpen pinout
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
(1) - n/c
|
||||
(2) - n/c
|
||||
(3) - n/c
|
||||
(4) - n/c
|
||||
(5) - Touch button
|
||||
(6) - /Beamtrigger
|
||||
(7) - +5V (50mA)
|
||||
(8) - Gnd
|
||||
(9) - Stylus button
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
NAME rev ADDR type chip Description
|
||||
JOY0DAT 00A R Denise Joystick-mouse 0 data (left vert, horiz)
|
||||
JOY1DAT 00C R Denise Joystick-mouse 1 data (right vert,horiz)
|
||||
|
||||
These addresses each read a 16 bit register. These in turn
|
||||
are loaded from the MDAT serial stream and are clocked in on
|
||||
the rising edge of SCLK. MLD output is used to parallel load
|
||||
the external parallel-to-serial converter.This in turn is
|
||||
loaded with the 4 quadrature inputs from each of two game
|
||||
controller ports (8 total) plus 8 miscellaneous control bits
|
||||
which are new for LISA and can be read in upper 8 bits of
|
||||
LISAID.
|
||||
Register bits are as follows:
|
||||
Mouse counter usage (pins 1,3 =Yclock, pins 2,4 =Xclock)
|
||||
|
||||
BIT# 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
JOY0DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
|
||||
JOY1DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
|
||||
|
||||
0=LEFT CONTROLLER PAIR, 1=RIGHT CONTROLLER PAIR.
|
||||
(4 counters total).The bit usage for both left and right
|
||||
addresses is shown below. Each 6 bit counter (Y7-Y2,X7-X2) is
|
||||
clocked by 2 of the signals input from the mouse serial
|
||||
stream. Starting with first bit recived:
|
||||
|
||||
+-------------------+-----------------------------------------+
|
||||
| Serial | Bit Name | Description |
|
||||
+--------+----------+-----------------------------------------+
|
||||
| 0 | M0H | JOY0DAT Horizontal Clock |
|
||||
| 1 | M0HQ | JOY0DAT Horizontal Clock (quadrature) |
|
||||
| 2 | M0V | JOY0DAT Vertical Clock |
|
||||
| 3 | M0VQ | JOY0DAT Vertical Clock (quadrature) |
|
||||
| 4 | M1V | JOY1DAT Horizontall Clock |
|
||||
| 5 | M1VQ | JOY1DAT Horizontall Clock (quadrature) |
|
||||
| 6 | M1V | JOY1DAT Vertical Clock |
|
||||
| 7 | M1VQ | JOY1DAT Vertical Clock (quadrature) |
|
||||
+--------+----------+-----------------------------------------+
|
||||
|
||||
Bits 1 and 0 of each counter (Y1-Y0,X1-X0) may be
|
||||
read to determine the state of the related input signal pair.
|
||||
This allows these pins to double as joystick switch inputs.
|
||||
Joystick switch closures can be deciphered as follows:
|
||||
|
||||
+------------+------+---------------------------------+
|
||||
| Directions | Pin# | Counter bits |
|
||||
+------------+------+---------------------------------+
|
||||
| Forward | 1 | Y1 xor Y0 (BIT#09 xor BIT#08) |
|
||||
| Left | 3 | Y1 |
|
||||
| Back | 2 | X1 xor X0 (BIT#01 xor BIT#00) |
|
||||
| Right | 4 | X1 |
|
||||
+------------+------+---------------------------------+
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
NAME rev ADDR type chip Description
|
||||
JOYTEST 036 W Denise Write to all 4 joystick-mouse counters at once.
|
||||
|
||||
Mouse counter write test data:
|
||||
BIT# 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
JOYxDAT Y7 Y6 Y5 Y4 Y3 Y2 xx xx X7 X6 X5 X4 X3 X2 xx xx
|
||||
JOYxDAT Y7 Y6 Y5 Y4 Y3 Y2 xx xx X7 X6 X5 X4 X3 X2 xx xx
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
NAME rev ADDR type chip Description
|
||||
POT0DAT h 012 R Paula Pot counter data left pair (vert, horiz)
|
||||
POT1DAT h 014 R Paula Pot counter data right pair (vert,horiz)
|
||||
|
||||
These addresses each read a pair of 8 bit pot counters.
|
||||
(4 counters total). The bit assignment for both
|
||||
addresses is shown below. The counters are stopped by signals
|
||||
from 2 controller connectors (left-right) with 2 pins each.
|
||||
|
||||
BIT# 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
RIGHT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
|
||||
LEFT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
|
||||
|
||||
+--------------------------+-------+
|
||||
| CONNECTORS | PAULA |
|
||||
+-------+------+-----+-----+-------+
|
||||
| Loc. | Dir. | Sym | pin | pin |
|
||||
+-------+------+-----+-----+-------+
|
||||
| RIGHT | Y | RX | 9 | 33 |
|
||||
| RIGHT | X | RX | 5 | 32 |
|
||||
| LEFT | Y | LY | 9 | 36 |
|
||||
| LEFT | X | LX | 5 | 35 |
|
||||
+-------+------+-----+-----+-------+
|
||||
|
||||
With normal (NTSC or PAL) horiz. line rate, the pots will
|
||||
give a full scale (FF) reading with about 500kohms in one
|
||||
frame time. With proportionally faster horiz line times,
|
||||
the counters will count proportionally faster.
|
||||
This should be noted when doing variable beam displays.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
NAME rev ADDR type chip Description
|
||||
POTGO 034 W Paula Pot port (4 bit) bi-direction and data, and pot counter start.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
NAME rev ADDR type chip Description
|
||||
POTINP 016 R Paula Pot pin data read
|
||||
|
||||
This register controls a 4 bit bi-direction I/O port
|
||||
that shares the same 4 pins as the 4 pot counters above.
|
||||
|
||||
+-------+----------+---------------------------------------------+
|
||||
| BIT# | FUNCTION | DESCRIPTION |
|
||||
+-------+----------+---------------------------------------------+
|
||||
| 15 | OUTRY | Output enable for Paula pin 33 |
|
||||
| 14 | DATRY | I/O data Paula pin 33 |
|
||||
| 13 | OUTRX | Output enable for Paula pin 32 |
|
||||
| 12 | DATRX | I/O data Paula pin 32 |
|
||||
| 11 | OUTLY | Out put enable for Paula pin 36 |
|
||||
| 10 | DATLY | I/O data Paula pin 36 |
|
||||
| 09 | OUTLX | Output enable for Paula pin 35 |
|
||||
| 08 | DATLX | I/O data Paula pin 35 |
|
||||
| 07-01 | X | Not used |
|
||||
| 00 | START | Start pots (dump capacitors,start counters) |
|
||||
+-------+----------+---------------------------------------------+
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
I have written a small patch that let's me use my Amiga CD32
|
||||
joypad connected to the parallel port. Thought I'd share it with you so
|
||||
you can add it to the list of supported joysticks (hopefully someone will
|
||||
find it useful).
|
||||
|
||||
It needs the following wiring:
|
||||
|
||||
CD32 pad | Parallel port
|
||||
----------------------------
|
||||
1 (Up) | 2 (D0)
|
||||
2 (Down) | 3 (D1)
|
||||
3 (Left) | 4 (D2)
|
||||
4 (Right) | 5 (D3)
|
||||
5 (Fire3) | 14 (AUTOFD)
|
||||
6 (Fire1) | 17 (SELIN)
|
||||
7 (+5V) | 1 (STROBE)
|
||||
8 (Gnd) | 18 (Gnd)
|
||||
9 (Fire2) | 7 (D5)
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
Preface.
|
||||
|
||||
This is a new low-level driver to support analog joystick attached to
|
||||
Crystal SoundFusion CS4610/CS4612/CS4615. This code is based upon
|
||||
Vortex/Solo drivers as an example of decoration style, and ALSA
|
||||
0.5.8a kernel drivers as an chipset documentation and samples.
|
||||
|
||||
This version does not have cooked mode support; the basic code
|
||||
is present here, but have not tested completely. The button analysis
|
||||
is completed in this mode, but the axis movement is not.
|
||||
|
||||
Raw mode works fine with analog joystick front-end driver and cs461x
|
||||
driver as a backend. I've tested this driver with CS4610, 4-axis and
|
||||
4-button joystick; I mean the jstest utility. Also I've tried to
|
||||
play in xracer game using joystick, and the result is better than
|
||||
keyboard only mode.
|
||||
|
||||
The sensitivity and calibrate quality have not been tested; the two
|
||||
reasons are performed: the same hardware cannot work under Win95 (blue
|
||||
screen in VJOYD); I have no documentation on my chip; and the existing
|
||||
behavior in my case was not raised the requirement of joystick calibration.
|
||||
So the driver have no code to perform hardware related calibration.
|
||||
|
||||
The patch contains minor changes of Config.in and Makefile files. All
|
||||
needed code have been moved to one separate file cs461x.c like ns558.c
|
||||
This driver have the basic support for PCI devices only; there is no
|
||||
ISA or PnP ISA cards supported. AFAIK the ns558 have support for Crystal
|
||||
ISA and PnP ISA series.
|
||||
|
||||
The driver works witn ALSA drivers simultaneously. For exmple, the xracer
|
||||
uses joystick as input device and PCM device as sound output in one time.
|
||||
There are no sound or input collisions detected. The source code have
|
||||
comments about them; but I've found the joystick can be initialized
|
||||
separately of ALSA modules. So, you canm use only one joystick driver
|
||||
without ALSA drivers. The ALSA drivers are not needed to compile or
|
||||
run this driver.
|
||||
|
||||
There are no debug information print have been placed in source, and no
|
||||
specific options required to work this driver. The found chipset parameters
|
||||
are printed via printk(KERN_INFO "..."), see the /var/log/messages to
|
||||
inspect cs461x: prefixed messages to determine possible card detection
|
||||
errors.
|
||||
|
||||
Regards,
|
||||
Viktor
|
||||
@@ -0,0 +1,227 @@
|
||||
Force feedback for Linux.
|
||||
By Johann Deneux <deneux@ifrance.com> on 2001/04/22.
|
||||
You may redistribute this file. Please remember to include shape.fig and
|
||||
interactive.fig as well.
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
0. Introduction
|
||||
~~~~~~~~~~~~~~~
|
||||
This document describes how to use force feedback devices under Linux. The
|
||||
goal is not to support these devices as if they were simple input-only devices
|
||||
(as it is already the case), but to really enable the rendering of force
|
||||
effects.
|
||||
At the moment, only I-Force devices are supported, and not officially. That
|
||||
means I had to find out how the protocol works on my own. Of course, the
|
||||
information I managed to grasp is far from being complete, and I can not
|
||||
guarranty that this driver will work for you.
|
||||
This document only describes the force feedback part of the driver for I-Force
|
||||
devices. Please read joystick.txt before reading further this document.
|
||||
|
||||
2. Instructions to the user
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Here are instructions on how to compile and use the driver. In fact, this
|
||||
driver is the normal iforce, input and evdev drivers written by Vojtech
|
||||
Pavlik, plus additions to support force feedback.
|
||||
|
||||
Before you start, let me WARN you that some devices shake violently during the
|
||||
initialisation phase. This happens for example with my "AVB Top Shot Pegasus".
|
||||
To stop this annoying behaviour, move you joystick to its limits. Anyway, you
|
||||
should keep a hand on your device, in order to avoid it to brake down if
|
||||
something goes wrong.
|
||||
|
||||
At the kernel's compilation:
|
||||
- Enable IForce/Serial
|
||||
- Enable Event interface
|
||||
|
||||
Compile the modules, install them.
|
||||
|
||||
You also need inputattach.
|
||||
|
||||
You then need to insert the modules into the following order:
|
||||
% modprobe joydev
|
||||
% modprobe serport # Only for serial
|
||||
% modprobe iforce
|
||||
% modprobe evdev
|
||||
% ./inputattach -ifor $2 & # Only for serial
|
||||
If you are using USB, you don't need the inputattach step.
|
||||
|
||||
Please check that you have all the /dev/input entries needed:
|
||||
cd /dev
|
||||
rm js*
|
||||
mkdir input
|
||||
mknod input/js0 c 13 0
|
||||
mknod input/js1 c 13 1
|
||||
mknod input/js2 c 13 2
|
||||
mknod input/js3 c 13 3
|
||||
ln -s input/js0 js0
|
||||
ln -s input/js1 js1
|
||||
ln -s input/js2 js2
|
||||
ln -s input/js3 js3
|
||||
|
||||
mknod input/event0 c 13 64
|
||||
mknod input/event1 c 13 65
|
||||
mknod input/event2 c 13 66
|
||||
mknod input/event3 c 13 67
|
||||
|
||||
2.1 Does it work ?
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
There is an utility called fftest that will allow you to test the driver.
|
||||
% fftest /dev/input/eventXX
|
||||
|
||||
3. Instructions to the developper
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
All interactions are done using the event API. That is, you can use ioctl()
|
||||
and write() on /dev/input/eventXX.
|
||||
This information is subject to change.
|
||||
|
||||
3.1 Querying device capabilities
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#include <linux/input.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
unsigned long features[1 + FF_MAX/sizeof(unsigned long)];
|
||||
int ioctl(int file_descriptor, int request, unsigned long *features);
|
||||
|
||||
"request" must be EVIOCGBIT(EV_FF, size of features array in bytes )
|
||||
|
||||
Returns the features supported by the device. features is a bitfield with the
|
||||
following bits:
|
||||
- FF_X has an X axis (usually joysticks)
|
||||
- FF_Y has an Y axis (usually joysticks)
|
||||
- FF_WHEEL has a wheel (usually sterring wheels)
|
||||
- FF_CONSTANT can render constant force effects
|
||||
- FF_PERIODIC can render periodic effects (sine, triangle, square...)
|
||||
- FF_RAMP can render ramp effects
|
||||
- FF_SPRING can simulate the presence of a spring
|
||||
- FF_FRICTION can simulate friction
|
||||
- FF_DAMPER can simulate damper effects
|
||||
- FF_RUMBLE rumble effects (normally the only effect supported by rumble
|
||||
pads)
|
||||
- FF_INERTIA can simulate inertia
|
||||
|
||||
|
||||
int ioctl(int fd, EVIOCGEFFECTS, int *n);
|
||||
|
||||
Returns the number of effects the device can keep in its memory.
|
||||
|
||||
3.2 Uploading effects to the device
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#include <linux/input.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
|
||||
|
||||
"request" must be EVIOCSFF.
|
||||
|
||||
"effect" points to a structure describing the effect to upload. The effect is
|
||||
uploaded, but not played.
|
||||
The content of effect may be modified. In particular, its field "id" is set
|
||||
to the unique id assigned by the driver. This data is required for performing
|
||||
some operations (removing an effect, controlling the playback).
|
||||
This if field must be set to -1 by the user in order to tell the driver to
|
||||
allocate a new effect.
|
||||
See <linux/input.h> for a description of the ff_effect stuct. You should also
|
||||
find help in a few sketches, contained in files shape.fig and interactive.fig.
|
||||
You need xfig to visualize these files.
|
||||
|
||||
3.3 Removing an effect from the device
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
int ioctl(int fd, EVIOCRMFF, effect.id);
|
||||
|
||||
This makes room for new effects in the device's memory. Please note this won't
|
||||
stop the effect if it was playing.
|
||||
|
||||
3.4 Controlling the playback of effects
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Control of playing is done with write(). Below is an example:
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct input_event play;
|
||||
struct input_event stop;
|
||||
struct ff_effect effect;
|
||||
int fd;
|
||||
...
|
||||
fd = open("/dev/input/eventXX", O_RDWR);
|
||||
...
|
||||
/* Play three times */
|
||||
play.type = EV_FF;
|
||||
play.code = effect.id;
|
||||
play.value = 3;
|
||||
|
||||
write(fd, (const void*) &play, sizeof(play));
|
||||
...
|
||||
/* Stop an effect */
|
||||
stop.type = EV_FF;
|
||||
stop.code = effect.id;
|
||||
stop.value = 0;
|
||||
|
||||
write(fd, (const void*) &play, sizeof(stop));
|
||||
|
||||
3.5 Setting the gain
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
Not all devices have the same strength. Therefore, users should set a gain
|
||||
factor depending on how strong they want effects to be. This setting is
|
||||
persistent across access to the driver, so you should not care about it if
|
||||
you are writing games, as another utility probably already set this for you.
|
||||
|
||||
/* Set the gain of the device
|
||||
int gain; /* between 0 and 100 */
|
||||
struct input_event ie; /* structure used to communicate with the driver */
|
||||
|
||||
ie.type = EV_FF;
|
||||
ie.code = FF_GAIN;
|
||||
ie.value = 0xFFFFUL * gain / 100;
|
||||
|
||||
if (write(fd, &ie, sizeof(ie)) == -1)
|
||||
perror("set gain");
|
||||
|
||||
3.6 Enabling/Disabling autocenter
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The autocenter feature quite disturbs the rendering of effects in my opinion,
|
||||
and I think it should be an effect, which computation depends on the game
|
||||
type. But you can enable it if you want.
|
||||
|
||||
int autocenter; /* between 0 and 100 */
|
||||
struct input_event ie;
|
||||
|
||||
ie.type = EV_FF;
|
||||
ie.code = FF_AUTOCENTER;
|
||||
ie.value = 0xFFFFUL * autocenter / 100;
|
||||
|
||||
if (write(fd, &ie, sizeof(ie)) == -1)
|
||||
perror("set auto-center");
|
||||
|
||||
A value of 0 means "no auto-center".
|
||||
|
||||
3.7 Dynamic update of an effect
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Proceed as if you wanted to upload a new effect, except that instead of
|
||||
setting the id field to -1, you set it to the wanted effect id.
|
||||
Normally, the effect is not stopped and restarted. However, depending on the
|
||||
type of device, not all parameters can be dynamically updated. For example,
|
||||
the direction of an effect cannot be updated with iforce devices. In this
|
||||
case, the driver stops the effect, up-load it, and restart it.
|
||||
|
||||
|
||||
3.8 Information about the status of effects
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Every time the status of an effect is changed, an event is sent. The values
|
||||
and meanings of the fields of the event are as follows:
|
||||
struct input_event {
|
||||
/* When the status of the effect changed */
|
||||
struct timeval time;
|
||||
|
||||
/* Set to EV_FF_STATUS */
|
||||
unsigned short type;
|
||||
|
||||
/* Contains the id of the effect */
|
||||
unsigned short code;
|
||||
|
||||
/* Indicates the status */
|
||||
unsigned int value;
|
||||
};
|
||||
|
||||
FF_STATUS_STOPPED The effect stopped playing
|
||||
FF_STATUS_PLAYING The effect started to play
|
||||
@@ -0,0 +1,189 @@
|
||||
$Id: gameport-programming.txt,v 1.3 2001/04/24 13:51:37 vojtech Exp $
|
||||
|
||||
Programming gameport drivers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1. A basic classic gameport
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If the gameport doesn't provide more than the inb()/outb() functionality,
|
||||
the code needed to register it with the joystick drivers is simple:
|
||||
|
||||
struct gameport gameport;
|
||||
|
||||
gameport.io = MY_IO_ADDRESS;
|
||||
gameport_register_port(&gameport);
|
||||
|
||||
Make sure struct gameport is initialized to 0 in all other fields. The
|
||||
gameport generic code will take care of the rest.
|
||||
|
||||
If your hardware supports more than one io address, and your driver can
|
||||
choose which one program the hardware to, starting from the more exotic
|
||||
addresses is preferred, because the likelyhood of clashing with the standard
|
||||
0x201 address is smaller.
|
||||
|
||||
Eg. if your driver supports addresses 0x200, 0x208, 0x210 and 0x218, then
|
||||
0x218 would be the address of first choice.
|
||||
|
||||
If your hardware supports a gameport address that is not mapped to ISA io
|
||||
space (is above 0x1000), use that one, and don't map the ISA mirror.
|
||||
|
||||
Also, always request_region() on the whole io space occupied by the
|
||||
gameport. Although only one ioport is really used, the gameport usually
|
||||
occupies from one to sixteen addresses in the io space.
|
||||
|
||||
Please also consider enabling the gameport on the card in the ->open()
|
||||
callback if the io is mapped to ISA space - this way it'll occupy the io
|
||||
space only when something really is using it. Disable it again in the
|
||||
->close() callback. You also can select the io address in the ->open()
|
||||
callback, so that it doesn't fail if some of the possible addresses are
|
||||
already occupied by other gameports.
|
||||
|
||||
2. Memory mapped gameport
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When a gameport can be accessed through MMIO, this way is preferred, because
|
||||
it is faster, allowing more reads per second. Registering such a gameport
|
||||
isn't as easy as a basic IO one, but not so much complex:
|
||||
|
||||
struct gameport gameport;
|
||||
|
||||
void my_trigger(struct gameport *gameport)
|
||||
{
|
||||
my_mmio = 0xff;
|
||||
}
|
||||
|
||||
unsigned char my_read(struct gameport *gameport)
|
||||
{
|
||||
return my_mmio;
|
||||
}
|
||||
|
||||
gameport.read = my_read;
|
||||
gameport.trigger = my_trigger;
|
||||
gameport_register_port(&gameport);
|
||||
|
||||
3. Cooked mode gameport
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are gameports that can report the axis values as numbers, that means
|
||||
the driver doesn't have to measure them the old way - an ADC is built into
|
||||
the gameport. To register a cooked gameport:
|
||||
|
||||
struct gameport gameport;
|
||||
|
||||
int my_cooked_read(struct gameport *gameport, int *axes, int *buttons)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
axes[i] = my_mmio[i];
|
||||
buttons[i] = my_mmio[4];
|
||||
}
|
||||
|
||||
int my_open(struct gameport *gameport, int mode)
|
||||
{
|
||||
return -(mode != GAMEPORT_MODE_COOKED);
|
||||
}
|
||||
|
||||
gameport.cooked_read = my_cooked_read;
|
||||
gameport.open = my_open;
|
||||
gameport.fuzz = 8;
|
||||
gameport_register_port(&gameport);
|
||||
|
||||
The only confusing thing here is the fuzz value. Best determined by
|
||||
experimentation, it is the amount of noise in the ADC data. Perfect
|
||||
gameports can set this to zero, most common have fuzz between 8 and 32.
|
||||
See analog.c and input.c for handling of fuzz - the fuzz value determines
|
||||
the size of a gaussian filter window that is used to eliminate the noise
|
||||
in the data.
|
||||
|
||||
4. More complex gameports
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Gameports can support both raw and cooked modes. In that case combine either
|
||||
examples 1+2 or 1+3. Gameports can support internal calibration - see below,
|
||||
and also lightning.c and analog.c on how that works. If your driver supports
|
||||
more than one gameport instance simultaneously, use the ->private member of
|
||||
the gameport struct to point to your data.
|
||||
|
||||
5. Unregistering a gameport
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Simple:
|
||||
|
||||
gameport_unregister_port(&gameport);
|
||||
|
||||
6. The gameport structure
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
struct gameport {
|
||||
|
||||
void *private;
|
||||
|
||||
A private pointer for free use in the gameport driver. (Not the joystick
|
||||
driver!)
|
||||
|
||||
int number;
|
||||
|
||||
Number assigned to the gameport when registered. Informational purpose only.
|
||||
|
||||
int io;
|
||||
|
||||
I/O address for use with raw mode. You have to either set this, or ->read()
|
||||
to some value if your gameport supports raw mode.
|
||||
|
||||
int speed;
|
||||
|
||||
Raw mode speed of the gameport reads in thousands of reads per second.
|
||||
|
||||
int fuzz;
|
||||
|
||||
If the gameport supports cooked mode, this should be set to a value that
|
||||
represents the amount of noise in the data. See section 3.
|
||||
|
||||
void (*trigger)(struct gameport *);
|
||||
|
||||
Trigger. This function should trigger the ns558 oneshots. If set to NULL,
|
||||
outb(0xff, io) will be used.
|
||||
|
||||
unsigned char (*read)(struct gameport *);
|
||||
|
||||
Read the buttons and ns558 oneshot bits. If set to NULL, inb(io) will be
|
||||
used instead.
|
||||
|
||||
int (*cooked_read)(struct gameport *, int *axes, int *buttons);
|
||||
|
||||
If the gameport supports cooked mode, it should point this to its cooked
|
||||
read function. It should fill axes[0..3] with four values of the joystick axes
|
||||
and buttons[0] with four bits representing the buttons.
|
||||
|
||||
int (*calibrate)(struct gameport *, int *axes, int *max);
|
||||
|
||||
Function for calibrating the ADC hardware. When called, axes[0..3] should be
|
||||
pre-filled by cooked data by the caller, max[0..3] should be pre-filled with
|
||||
expected maximums for each axis. The calibrate() function should set the
|
||||
sensitivity of the ADC hardware so that the maximums fit in its range and
|
||||
recompute the axes[] values to match the new sensitivity or re-read them from
|
||||
the hardware so that they give valid values.
|
||||
|
||||
int (*open)(struct gameport *, int mode);
|
||||
|
||||
Open() serves two purposes. First a driver either opens the port in raw or
|
||||
in cooked mode, the open() callback can decide which modes are supported.
|
||||
Second, resource allocation can happen here. The port can also be enabled
|
||||
here. Prior to this call, other fields of the gameport struct (namely the io
|
||||
member) need not to be valid.
|
||||
|
||||
void (*close)(struct gameport *);
|
||||
|
||||
Close() should free the resources allocated by open, possibly disabling the
|
||||
gameport.
|
||||
|
||||
struct gameport_dev *dev;
|
||||
struct gameport *next;
|
||||
|
||||
For internal use by the gameport layer.
|
||||
|
||||
};
|
||||
|
||||
Enjoy!
|
||||
@@ -0,0 +1,254 @@
|
||||
** Introduction
|
||||
This document describes what I managed to discover about the protocol used to
|
||||
specify force effects to I-Force 2.0 devices. None of this information comes
|
||||
from Immerse. That's why you should not trust what is written in this
|
||||
document. This document is intended to help understanding the protocol.
|
||||
This is not a reference. Comments and corrections are welcome. To contact me,
|
||||
send an email to: deneux@ifrance.com
|
||||
|
||||
** WARNING **
|
||||
I may not be held responsible for any dammage or harm caused if you try to
|
||||
send data to your I-Force device based on what you read in this document.
|
||||
|
||||
** Preliminary Notes:
|
||||
All values are hexadecimal with big-endian encoding (msb on the left). Beware,
|
||||
values inside packets are encoded using little-endian. Bytes whose roles are
|
||||
unknown are marked ??? Information that needs deeper inspection is marked (?)
|
||||
|
||||
** General form of a packet **
|
||||
This is how packets look when the device uses the rs232 to communicate.
|
||||
2B OP LEN DATA CS
|
||||
CS is the checksum. It is equal to the exclusive or of all bytes.
|
||||
|
||||
When using USB:
|
||||
OP DATA
|
||||
The 2B, LEN and CS fields have disappeared, probably because USB handles frames and
|
||||
data corruption is handled or unsignificant.
|
||||
|
||||
First, I describe effects that are sent by the device to the computer
|
||||
|
||||
** Device input state
|
||||
This packet is used to indicate the state of each button and the value of each
|
||||
axis
|
||||
OP= 01 for a joystick, 03 for a wheel
|
||||
LEN= Varies from device to device
|
||||
00 X-Axis lsb
|
||||
01 X-Axis msb
|
||||
02 Y-Axis lsb, or gas pedal for a wheel
|
||||
03 Y-Axis msb, or brake pedal for a wheel
|
||||
04 Throttle
|
||||
05 Buttons
|
||||
06 Lower 4 bits: Buttons
|
||||
Upper 4 bits: Hat
|
||||
07 Rudder
|
||||
|
||||
** Device effects states
|
||||
OP= 02
|
||||
LEN= Varies
|
||||
00 ? Bit 1 (Value 2) is the value of the deadman switch
|
||||
01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id.
|
||||
02 ??
|
||||
03 Address of parameter block changed (lsb)
|
||||
04 Address of parameter block changed (msb)
|
||||
05 Address of second parameter block changed (lsb)
|
||||
... depending on the number of parameter blocks updated
|
||||
|
||||
** Force effect **
|
||||
OP= 01
|
||||
LEN= 0e
|
||||
00 Channel (when playing several effects at the same time, each must be assigned a channel)
|
||||
01 Wave form
|
||||
Val 00 Constant
|
||||
Val 20 Square
|
||||
Val 21 Triangle
|
||||
Val 22 Sine
|
||||
Val 23 Sawtooth up
|
||||
Val 24 Sawtooth down
|
||||
Val 40 Spring (Force = f(pos))
|
||||
Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration))
|
||||
|
||||
|
||||
02 Axes affected and trigger
|
||||
Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction
|
||||
Val 4 = X axis only. Byte 05 must contain 5a
|
||||
Val 8 = Y axis only. Byte 05 must contain b4
|
||||
Val c = X and Y axes. Bytes 05 must contain 60
|
||||
Bits 0-3: Val 0 = No trigger
|
||||
Val x+1 = Button x triggers the effect
|
||||
When the whole byte is 0, cancel the previously set trigger
|
||||
|
||||
03-04 Duration of effect (little endian encoding, in ms)
|
||||
|
||||
05 Direction of effect, if applicable. Else, see 02 for value to assign.
|
||||
|
||||
06-07 Minimum time between triggering.
|
||||
|
||||
08-09 Address of periodicity or magnitude parameters
|
||||
0a-0b Address of attack and fade parameters, or ffff if none.
|
||||
*or*
|
||||
08-09 Address of interactive parameters for X-axis, or ffff if not applicable
|
||||
0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable
|
||||
|
||||
0c-0d Delay before execution of effect (little endian encoding, in ms)
|
||||
|
||||
|
||||
** Time based parameters **
|
||||
|
||||
*** Attack and fade ***
|
||||
OP= 02
|
||||
LEN= 08
|
||||
00-01 Address where to store the parameteres
|
||||
02-03 Duration of attack (little endian encoding, in ms)
|
||||
04 Level at end of attack. Signed byte.
|
||||
05-06 Duration of fade.
|
||||
07 Level at end of fade.
|
||||
|
||||
*** Magnitude ***
|
||||
OP= 03
|
||||
LEN= 03
|
||||
00-01 Address
|
||||
02 Level. Signed byte.
|
||||
|
||||
*** Periodicity ***
|
||||
OP= 04
|
||||
LEN= 07
|
||||
00-01 Address
|
||||
02 Magnitude. Signed byte.
|
||||
03 Offset. Signed byte.
|
||||
04 Phase. Val 00 = 0 deg, Val 40 = 90 degs.
|
||||
05-06 Period (little endian encoding, in ms)
|
||||
|
||||
** Interactive parameters **
|
||||
OP= 05
|
||||
LEN= 0a
|
||||
00-01 Address
|
||||
02 Positive Coeff
|
||||
03 Negative Coeff
|
||||
04+05 Offset (center)
|
||||
06+07 Dead band (Val 01F4 = 5000 (decimal))
|
||||
08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal))
|
||||
09 Negative saturation
|
||||
|
||||
The encoding is a bit funny here: For coeffs, these are signed values. The
|
||||
maximum value is 64 (100 decimal), the min is 9c.
|
||||
For the offset, the minimum value is FE0C, the maximum value is 01F4.
|
||||
For the deadband, the minimum value is 0, the max is 03E8.
|
||||
|
||||
** Controls **
|
||||
OP= 41
|
||||
LEN= 03
|
||||
00 Channel
|
||||
01 Start/Stop
|
||||
Val 00: Stop
|
||||
Val 01: Start and play once.
|
||||
Val 41: Start and play n times (See byte 02 below)
|
||||
02 Number of iterations n.
|
||||
|
||||
** Init **
|
||||
|
||||
*** Querying features ***
|
||||
OP= ff
|
||||
Query command. Length varies according to the query type.
|
||||
The general format of this packet is:
|
||||
ff 01 QUERY [INDEX] CHECKSUM
|
||||
reponses are of the same form:
|
||||
FF LEN QUERY VALUE_QUERIED CHECKSUM2
|
||||
where LEN = 1 + length(VALUE_QUERIED)
|
||||
|
||||
**** Query ram size ****
|
||||
QUERY = 42 ('B'uffer size)
|
||||
The device should reply with the same packet plus two additionnal bytes
|
||||
containing the size of the memory:
|
||||
ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available.
|
||||
|
||||
**** Query number of effects ****
|
||||
QUERY = 4e ('N'umber of effects)
|
||||
The device should respond by sending the number of effects that can be played
|
||||
at the same time (one byte)
|
||||
ff 02 4e 14 CS would stand for 20 effects.
|
||||
|
||||
**** Vendor's id ****
|
||||
QUERY = 4d ('M'anufacturer)
|
||||
Query the vendors'id (2 bytes)
|
||||
|
||||
**** Product id *****
|
||||
QUERY = 50 ('P'roduct)
|
||||
Query the product id (2 bytes)
|
||||
|
||||
**** Open device ****
|
||||
QUERY = 4f ('O'pen)
|
||||
No data returned.
|
||||
|
||||
**** Close device *****
|
||||
QUERY = 43 ('C')lose
|
||||
No data returned.
|
||||
|
||||
**** Query effect ****
|
||||
QUERY = 45 ('E')
|
||||
Send effect type.
|
||||
Returns nonzero if supported (2 bytes)
|
||||
|
||||
**** Firmware Version ****
|
||||
QUERY = 56 ('V'ersion)
|
||||
Sends back 3 bytes - major, minor, subminor
|
||||
|
||||
*** Initialisation of the device ***
|
||||
|
||||
**** Set Control ****
|
||||
!!! Device dependent, can be different on different models !!!
|
||||
OP= 40 <idx> <val> [<val>]
|
||||
LEN= 2 or 3
|
||||
00 Idx
|
||||
Idx 00 Set dead zone (0..2048)
|
||||
Idx 01 Ignore Deadman sensor (0..1)
|
||||
Idx 02 Enable comm watchdog (0..1)
|
||||
Idx 03 Set the strength of the spring (0..100)
|
||||
Idx 04 Enable or disable the spring (0/1)
|
||||
Idx 05 Set axis saturation threshold (0..2048)
|
||||
|
||||
**** Set Effect State ****
|
||||
OP= 42 <val>
|
||||
LEN= 1
|
||||
00 State
|
||||
Bit 3 Pause force feedback
|
||||
Bit 2 Enable force feedback
|
||||
Bit 0 Stop all effects
|
||||
|
||||
**** Set overall gain ****
|
||||
OP= 43 <val>
|
||||
LEN= 1
|
||||
00 Gain
|
||||
Val 00 = 0%
|
||||
Val 40 = 50%
|
||||
Val 80 = 100%
|
||||
|
||||
** Parameter memory **
|
||||
|
||||
Each device has a certain amount of memory to store parameters of effects.
|
||||
The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below
|
||||
is the amount of memory apparently needed for every set of parameters:
|
||||
- period : 0c
|
||||
- magnitude : 02
|
||||
- attack and fade : 0e
|
||||
- interactive : 08
|
||||
|
||||
** Appendix: How to study the protocol ? **
|
||||
|
||||
1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com)
|
||||
2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!)
|
||||
3. Play the effect, and watch what happens on the spy screen.
|
||||
|
||||
A few words about ComPortSpy:
|
||||
At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect.
|
||||
Remember it's free (as in free beer) and alpha!
|
||||
|
||||
** URLS **
|
||||
Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy.
|
||||
|
||||
** Author of this document **
|
||||
Johann Deneux <deneux@ifrance.com>
|
||||
Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/
|
||||
|
||||
Additions by Vojtech Pavlik.
|
||||
|
||||
I-Force is trademark of Immersion Corp.
|
||||
@@ -0,0 +1,281 @@
|
||||
$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $
|
||||
|
||||
Programming input drivers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1. Creating an input device driver
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1.0 The simplest example
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Here comes a very simple example of an input device driver. The device has
|
||||
just one button and the button is accessible at i/o port BUTTON_PORT. When
|
||||
pressed or released a BUTTON_IRQ happens. The driver could look like:
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
|
||||
{
|
||||
input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1);
|
||||
input_sync(&button_dev);
|
||||
}
|
||||
|
||||
static int __init button_init(void)
|
||||
{
|
||||
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
|
||||
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
button_dev.evbit[0] = BIT(EV_KEY);
|
||||
button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
|
||||
|
||||
input_register_device(&button_dev);
|
||||
}
|
||||
|
||||
static void __exit button_exit(void)
|
||||
{
|
||||
input_unregister_device(&button_dev);
|
||||
free_irq(BUTTON_IRQ, button_interrupt);
|
||||
}
|
||||
|
||||
module_init(button_init);
|
||||
module_exit(button_exit);
|
||||
|
||||
1.1 What the example does
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
First it has to include the <linux/input.h> file, which interfaces to the
|
||||
input subsystem. This provides all the definitions needed.
|
||||
|
||||
In the _init function, which is called either upon module load or when
|
||||
booting the kernel, it grabs the required resources (it should also check
|
||||
for the presence of the device).
|
||||
|
||||
Then it sets the input bitfields. This way the device driver tells the other
|
||||
parts of the input systems what it is - what events can be generated or
|
||||
accepted by this input device. Our example device can only generate EV_KEY type
|
||||
events, and from those only BTN_0 event code. Thus we only set these two
|
||||
bits. We could have used
|
||||
|
||||
set_bit(EV_KEY, button_dev.evbit);
|
||||
set_bit(BTN_0, button_dev.keybit);
|
||||
|
||||
as well, but with more than single bits the first approach tends to be
|
||||
shorter.
|
||||
|
||||
Then the example driver registers the input device structure by calling
|
||||
|
||||
input_register_device(&button_dev);
|
||||
|
||||
This adds the button_dev structure to linked lists of the input driver and
|
||||
calls device handler modules _connect functions to tell them a new input
|
||||
device has appeared. Because the _connect functions may call kmalloc(,
|
||||
GFP_KERNEL), which can sleep, input_register_device() must not be called
|
||||
from an interrupt or with a spinlock held.
|
||||
|
||||
While in use, the only used function of the driver is
|
||||
|
||||
button_interrupt()
|
||||
|
||||
which upon every interrupt from the button checks its state and reports it
|
||||
via the
|
||||
|
||||
input_report_key()
|
||||
|
||||
call to the input system. There is no need to check whether the interrupt
|
||||
routine isn't reporting two same value events (press, press for example) to
|
||||
the input system, because the input_report_* functions check that
|
||||
themselves.
|
||||
|
||||
Then there is the
|
||||
|
||||
input_sync()
|
||||
|
||||
call to tell those who receive the events that we've sent a complete report.
|
||||
This doesn't seem important in the one button case, but is quite important
|
||||
for for example mouse movement, where you don't want the X and Y values
|
||||
to be interpreted separately, because that'd result in a different movement.
|
||||
|
||||
1.2 dev->open() and dev->close()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In case the driver has to repeatedly poll the device, because it doesn't
|
||||
have an interrupt coming from it and the polling is too expensive to be done
|
||||
all the time, or if the device uses a valuable resource (eg. interrupt), it
|
||||
can use the open and close callback to know when it can stop polling or
|
||||
release the interrupt and when it must resume polling or grab the interrupt
|
||||
again. To do that, we would add this to our example driver:
|
||||
|
||||
int button_used = 0;
|
||||
|
||||
static int button_open(struct input_dev *dev)
|
||||
{
|
||||
if (button_used++)
|
||||
return 0;
|
||||
|
||||
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
|
||||
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
|
||||
button_used--;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void button_close(struct input_dev *dev)
|
||||
{
|
||||
if (!--button_used)
|
||||
free_irq(IRQ_AMIGA_VERTB, button_interrupt);
|
||||
}
|
||||
|
||||
static int __init button_init(void)
|
||||
{
|
||||
...
|
||||
button_dev.open = button_open;
|
||||
button_dev.close = button_close;
|
||||
...
|
||||
}
|
||||
|
||||
Note the button_used variable - we have to track how many times the open
|
||||
function was called to know when exactly our device stops being used.
|
||||
|
||||
The open() callback should return a 0 in case of success or any nonzero value
|
||||
in case of failure. The close() callback (which is void) must always succeed.
|
||||
|
||||
1.3 Basic event types
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The most simple event type is EV_KEY, which is used for keys and buttons.
|
||||
It's reported to the input system via:
|
||||
|
||||
input_report_key(struct input_dev *dev, int code, int value)
|
||||
|
||||
See linux/input.h for the allowable values of code (from 0 to KEY_MAX).
|
||||
Value is interpreted as a truth value, ie any nonzero value means key
|
||||
pressed, zero value means key released. The input code generates events only
|
||||
in case the value is different from before.
|
||||
|
||||
In addition to EV_KEY, there are two more basic event types: EV_REL and
|
||||
EV_ABS. They are used for relative and absolute values supplied by the
|
||||
device. A relative value may be for example a mouse movement in the X axis.
|
||||
The mouse reports it as a relative difference from the last position,
|
||||
because it doesn't have any absolute coordinate system to work in. Absolute
|
||||
events are namely for joysticks and digitizers - devices that do work in an
|
||||
absolute coordinate systems.
|
||||
|
||||
Having the device report EV_REL buttons is as simple as with EV_KEY, simply
|
||||
set the corresponding bits and call the
|
||||
|
||||
input_report_rel(struct input_dev *dev, int code, int value)
|
||||
|
||||
function. Events are generated only for nonzero value.
|
||||
|
||||
However EV_ABS requires a little special care. Before calling
|
||||
input_register_device, you have to fill additional fields in the input_dev
|
||||
struct for each absolute axis your device has. If our button device had also
|
||||
the ABS_X axis:
|
||||
|
||||
button_dev.absmin[ABS_X] = 0;
|
||||
button_dev.absmax[ABS_X] = 255;
|
||||
button_dev.absfuzz[ABS_X] = 4;
|
||||
button_dev.absflat[ABS_X] = 8;
|
||||
|
||||
This setting would be appropriate for a joystick X axis, with the minimum of
|
||||
0, maximum of 255 (which the joystick *must* be able to reach, no problem if
|
||||
it sometimes reports more, but it must be able to always reach the min and
|
||||
max values), with noise in the data up to +- 4, and with a center flat
|
||||
position of size 8.
|
||||
|
||||
If you don't need absfuzz and absflat, you can set them to zero, which mean
|
||||
that the thing is precise and always returns to exactly the center position
|
||||
(if it has any).
|
||||
|
||||
1.4 The void *private field
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This field in the input structure can be used to point to any private data
|
||||
structures in the input device driver, in case the driver handles more than
|
||||
one device. You'll need it in the open and close callbacks.
|
||||
|
||||
1.5 NBITS(), LONG(), BIT()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These three macros from input.h help some bitfield computations:
|
||||
|
||||
NBITS(x) - returns the length of a bitfield array in longs for x bits
|
||||
LONG(x) - returns the index in the array in longs for bit x
|
||||
BIT(x) - returns the index in a long for bit x
|
||||
|
||||
1.6 The number, id* and name fields
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The dev->number is assigned by the input system to the input device when it
|
||||
is registered. It has no use except for identifying the device to the user
|
||||
in system messages.
|
||||
|
||||
The dev->name should be set before registering the input device by the input
|
||||
device driver. It's a string like 'Generic button device' containing a
|
||||
user friendly name of the device.
|
||||
|
||||
The id* fields contain the bus ID (PCI, USB, ...), vendor ID and device ID
|
||||
of the device. The bus IDs are defined in input.h. The vendor and device ids
|
||||
are defined in pci_ids.h, usb_ids.h and similar include files. These fields
|
||||
should be set by the input device driver before registering it.
|
||||
|
||||
The idtype field can be used for specific information for the input device
|
||||
driver.
|
||||
|
||||
The id and name fields can be passed to userland via the evdev interface.
|
||||
|
||||
1.7 The keycode, keycodemax, keycodesize fields
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These two fields will be used for any input devices that report their data
|
||||
as scancodes. If not all scancodes can be known by autodetection, they may
|
||||
need to be set by userland utilities. The keycode array then is an array
|
||||
used to map from scancodes to input system keycodes. The keycode max will
|
||||
contain the size of the array and keycodesize the size of each entry in it
|
||||
(in bytes).
|
||||
|
||||
1.8 Key autorepeat
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
... is simple. It is handled by the input.c module. Hardware autorepeat is
|
||||
not used, because it's not present in many devices and even where it is
|
||||
present, it is broken sometimes (at keyboards: Toshiba notebooks). To enable
|
||||
autorepeat for your device, just set EV_REP in dev->evbit. All will be
|
||||
handled by the input system.
|
||||
|
||||
1.9 Other event types, handling output events
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The other event types up to now are:
|
||||
|
||||
EV_LED - used for the keyboard LEDs.
|
||||
EV_SND - used for keyboard beeps.
|
||||
|
||||
They are very similar to for example key events, but they go in the other
|
||||
direction - from the system to the input device driver. If your input device
|
||||
driver can handle these events, it has to set the respective bits in evbit,
|
||||
*and* also the callback routine:
|
||||
|
||||
button_dev.event = button_event;
|
||||
|
||||
int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
|
||||
{
|
||||
if (type == EV_SND && code == SND_BELL) {
|
||||
outb(value, BUTTON_BELL);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
This callback routine can be called from an interrupt or a BH (although that
|
||||
isn't a rule), and thus must not sleep, and must not take too long to finish.
|
||||
@@ -0,0 +1,312 @@
|
||||
Linux Input drivers v1.0
|
||||
(c) 1999-2001 Vojtech Pavlik <vojtech@ucw.cz>
|
||||
Sponsored by SuSE
|
||||
$Id: input.txt,v 1.8 2002/05/29 03:15:01 bradleym Exp $
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
0. Disclaimer
|
||||
~~~~~~~~~~~~~
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Should you need to contact me, the author, you can do so either by e-mail
|
||||
- mail your message to <vojtech@ucw.cz>, or by paper mail: Vojtech Pavlik,
|
||||
Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
|
||||
For your convenience, the GNU General Public License version 2 is included
|
||||
in the package: See the file COPYING.
|
||||
|
||||
1. Introduction
|
||||
~~~~~~~~~~~~~~~
|
||||
This is a collection of drivers that is designed to support all input
|
||||
devices under Linux. While it is currently used only on for USB input
|
||||
devices, future use (say 2.5/2.6) is expected to expand to replace
|
||||
most of the existing input system, which is why it lives in
|
||||
drivers/input/ instead of drivers/usb/.
|
||||
|
||||
The centre of the input drivers is the input module, which must be
|
||||
loaded before any other of the input modules - it serves as a way of
|
||||
communication between two groups of modules:
|
||||
|
||||
1.1 Device drivers
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
These modules talk to the hardware (for example via USB), and provide
|
||||
events (keystrokes, mouse movements) to the input module.
|
||||
|
||||
1.2 Event handlers
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
These modules get events from input and pass them where needed via
|
||||
various interfaces - keystrokes to the kernel, mouse movements via a
|
||||
simulated PS/2 interface to GPM and X and so on.
|
||||
|
||||
2. Simple Usage
|
||||
~~~~~~~~~~~~~~~
|
||||
For the most usual configuration, with one USB mouse and one USB keyboard,
|
||||
you'll have to load the following modules (or have them built in to the
|
||||
kernel):
|
||||
|
||||
input
|
||||
mousedev
|
||||
keybdev
|
||||
usbcore
|
||||
uhci_hcd or ohci_hcd or ehci_hcd
|
||||
usbhid
|
||||
|
||||
After this, the USB keyboard will work straight away, and the USB mouse
|
||||
will be available as a character device on major 13, minor 63:
|
||||
|
||||
crw-r--r-- 1 root root 13, 63 Mar 28 22:45 mice
|
||||
|
||||
This device has to be created, unless you use devfs, in which case it's
|
||||
created automatically. The commands to do create it by hand are:
|
||||
|
||||
cd /dev
|
||||
mkdir input
|
||||
mknod input/mice c 13 63
|
||||
|
||||
After that you have to point GPM (the textmode mouse cut&paste tool) and
|
||||
XFree to this device to use it - GPM should be called like:
|
||||
|
||||
gpm -t ps2 -m /dev/input/mice
|
||||
|
||||
And in X:
|
||||
|
||||
Section "Pointer"
|
||||
Protocol "ImPS/2"
|
||||
Device "/dev/input/mice"
|
||||
ZAxisMapping 4 5
|
||||
EndSection
|
||||
|
||||
When you do all of the above, you can use your USB mouse and keyboard.
|
||||
|
||||
3. Detailed Description
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
3.1 Device drivers
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Device drivers are the modules that generate events. The events are
|
||||
however not useful without being handled, so you also will need to use some
|
||||
of the modules from section 3.2.
|
||||
|
||||
3.1.1 usbhid
|
||||
~~~~~~~~~~~~
|
||||
usbhid is the largest and most complex driver of the whole suite. It
|
||||
handles all HID devices, and because there is a very wide variety of them,
|
||||
and because the USB HID specification isn't simple, it needs to be this big.
|
||||
|
||||
Currently, it handles USB mice, joysticks, gamepads, steering wheels
|
||||
keyboards, trackballs and digitizers.
|
||||
|
||||
However, USB uses HID also for monitor controls, speaker controls, UPSs,
|
||||
LCDs and many other purposes.
|
||||
|
||||
The monitor and speaker controls should be easy to add to the hid/input
|
||||
interface, but for the UPSs and LCDs it doesn't make much sense. For this,
|
||||
the hiddev interface was designed. See Documentation/usb/hiddev.txt
|
||||
for more information about it.
|
||||
|
||||
The usage of the usbhid module is very simple, it takes no parameters,
|
||||
detects everything automatically and when a HID device is inserted, it
|
||||
detects it appropriately.
|
||||
|
||||
However, because the devices vary wildly, you might happen to have a
|
||||
device that doesn't work well. In that case #define DEBUG at the beginning
|
||||
of hid-core.c and send me the syslog traces.
|
||||
|
||||
3.1.2 usbmouse
|
||||
~~~~~~~~~~~~~~
|
||||
For embedded systems, for mice with broken HID descriptors and just any
|
||||
other use when the big usbhid wouldn't be a good choice, there is the
|
||||
usbmouse driver. It handles USB mice only. It uses a simpler HIDBP
|
||||
protocol. This also means the mice must support this simpler protocol. Not
|
||||
all do. If you don't have any strong reason to use this module, use usbhid
|
||||
instead.
|
||||
|
||||
3.1.3 usbkbd
|
||||
~~~~~~~~~~~~
|
||||
Much like usbmouse, this module talks to keyboards with a simplified
|
||||
HIDBP protocol. It's smaller, but doesn't support any extra special keys.
|
||||
Use usbhid instead if there isn't any special reason to use this.
|
||||
|
||||
3.1.4 wacom
|
||||
~~~~~~~~~~~
|
||||
This is a driver for Wacom Graphire and Intuos tablets. Not for Wacom
|
||||
PenPartner, that one is handled by the HID driver. Although the Intuos and
|
||||
Graphire tablets claim that they are HID tablets as well, they are not and
|
||||
thus need this specific driver.
|
||||
|
||||
3.1.5 iforce
|
||||
~~~~~~~~~~~~
|
||||
A driver for I-Force joysticks and wheels, both over USB and RS232.
|
||||
It includes ForceFeedback support now, even though Immersion
|
||||
Corp. considers the protocol a trade secret and won't disclose a word
|
||||
about it.
|
||||
|
||||
3.2 Event handlers
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Event handlers distrubite the events from the devices to userland and
|
||||
kernel, as needed.
|
||||
|
||||
3.2.1 keybdev
|
||||
~~~~~~~~~~~~~
|
||||
keybdev is currently a rather ugly hack that translates the input
|
||||
events into architecture-specific keyboard raw mode (Xlated AT Set2 on
|
||||
x86), and passes them into the handle_scancode function of the
|
||||
keyboard.c module. This works well enough on all architectures that
|
||||
keybdev can generate rawmode on, other architectures can be added to
|
||||
it.
|
||||
|
||||
The right way would be to pass the events to keyboard.c directly,
|
||||
best if keyboard.c would itself be an event handler. This is done in
|
||||
the input patch, available on the webpage mentioned below.
|
||||
|
||||
3.2.2 mousedev
|
||||
~~~~~~~~~~~~~~
|
||||
mousedev is also a hack to make programs that use mouse input
|
||||
work. It takes events from either mice or digitizers/tablets and makes
|
||||
a PS/2-style (a la /dev/psaux) mouse device available to the
|
||||
userland. Ideally, the programs could use a more reasonable interface,
|
||||
for example evdev
|
||||
|
||||
Mousedev devices in /dev/input (as shown above) are:
|
||||
|
||||
crw-r--r-- 1 root root 13, 32 Mar 28 22:45 mouse0
|
||||
crw-r--r-- 1 root root 13, 33 Mar 29 00:41 mouse1
|
||||
crw-r--r-- 1 root root 13, 34 Mar 29 00:41 mouse2
|
||||
crw-r--r-- 1 root root 13, 35 Apr 1 10:50 mouse3
|
||||
...
|
||||
...
|
||||
crw-r--r-- 1 root root 13, 62 Apr 1 10:50 mouse30
|
||||
crw-r--r-- 1 root root 13, 63 Apr 1 10:50 mice
|
||||
|
||||
Each 'mouse' device is assigned to a single mouse or digitizer, except
|
||||
the last one - 'mice'. This single character device is shared by all
|
||||
mice and digitizers, and even if none are connected, the device is
|
||||
present. This is useful for hotplugging USB mice, so that programs
|
||||
can open the device even when no mice are present.
|
||||
|
||||
CONFIG_INPUT_MOUSEDEV_SCREEN_[XY] in the kernel configuration are
|
||||
the size of your screen (in pixels) in XFree86. This is needed if you
|
||||
want to use your digitizer in X, because its movement is sent to X
|
||||
via a virtual PS/2 mouse and thus needs to be scaled
|
||||
accordingly. These values won't be used if you use a mouse only.
|
||||
|
||||
Mousedev will generate either PS/2, ImPS/2 (Microsoft IntelliMouse) or
|
||||
ExplorerPS/2 (IntelliMouse Explorer) protocols, depending on what the
|
||||
program reading the data wishes. You can set GPM and X to any of
|
||||
these. You'll need ImPS/2 if you want to make use of a wheel on a USB
|
||||
mouse and ExplorerPS/2 if you want to use extra (up to 5) buttons.
|
||||
|
||||
3.2.3 joydev
|
||||
~~~~~~~~~~~~
|
||||
Joydev implements v0.x and v1.x Linux joystick api, much like
|
||||
drivers/char/joystick/joystick.c used to in earlier versions. See
|
||||
joystick-api.txt in the Documentation subdirectory for details. As
|
||||
soon as any joystick is connected, it can be accessed in /dev/input
|
||||
on:
|
||||
|
||||
crw-r--r-- 1 root root 13, 0 Apr 1 10:50 js0
|
||||
crw-r--r-- 1 root root 13, 1 Apr 1 10:50 js1
|
||||
crw-r--r-- 1 root root 13, 2 Apr 1 10:50 js2
|
||||
crw-r--r-- 1 root root 13, 3 Apr 1 10:50 js3
|
||||
...
|
||||
|
||||
And so on up to js31.
|
||||
|
||||
3.2.4 evdev
|
||||
~~~~~~~~~~~
|
||||
evdev is the generic input event interface. It passes the events
|
||||
generated in the kernel straight to the program, with timestamps. The
|
||||
API is still evolving, but should be useable now. It's described in
|
||||
section 5.
|
||||
|
||||
This should be the way for GPM and X to get keyboard and mouse mouse
|
||||
events. It allows for multihead in X without any specific multihead
|
||||
kernel support. The event codes are the same on all architectures and
|
||||
are hardware independent.
|
||||
|
||||
The devices are in /dev/input:
|
||||
|
||||
crw-r--r-- 1 root root 13, 64 Apr 1 10:49 event0
|
||||
crw-r--r-- 1 root root 13, 65 Apr 1 10:50 event1
|
||||
crw-r--r-- 1 root root 13, 66 Apr 1 10:50 event2
|
||||
crw-r--r-- 1 root root 13, 67 Apr 1 10:50 event3
|
||||
...
|
||||
|
||||
And so on up to event31.
|
||||
|
||||
4. Verifying if it works
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Typing a couple keys on the keyboard should be enough to check that
|
||||
a USB keyboard works and is correctly connected to the kernel keyboard
|
||||
driver.
|
||||
|
||||
Doing a cat /dev/input/mouse0 (c, 13, 32) will verify that a mouse
|
||||
is also emulated, characters should appear if you move it.
|
||||
|
||||
You can test the joystick emulation with the 'jstest' utility,
|
||||
available in the joystick package (see Documentation/input/joystick.txt).
|
||||
|
||||
You can test the event devices with the 'evtest' utility available
|
||||
in the LinuxConsole project CVS archive (see the URL below).
|
||||
|
||||
5. Event interface
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Should you want to add event device support into any application (X, gpm,
|
||||
svgalib ...) I <vojtech@ucw.cz> will be happy to provide you any help I
|
||||
can. Here goes a description of the current state of things, which is going
|
||||
to be extended, but not changed incompatibly as time goes:
|
||||
|
||||
You can use blocking and nonblocking reads, also select() on the
|
||||
/dev/input/eventX devices, and you'll always get a whole number of input
|
||||
events on a read. Their layout is:
|
||||
|
||||
struct input_event {
|
||||
struct timeval time;
|
||||
unsigned short type;
|
||||
unsigned short code;
|
||||
unsigned int value;
|
||||
};
|
||||
|
||||
'time' is the timestamp, it returns the time at which the event happened.
|
||||
Type is for example EV_REL for relative momement, REL_KEY for a keypress or
|
||||
release. More types are defined in include/linux/input.h.
|
||||
|
||||
'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
|
||||
list is in include/linux/input.h.
|
||||
|
||||
'value' is the value the event carries. Either a relative change for
|
||||
EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for
|
||||
release, 1 for keypress and 2 for autorepeat.
|
||||
|
||||
6. Contacts
|
||||
~~~~~~~~~~~
|
||||
This effort has its home page at:
|
||||
|
||||
http://www.suse.cz/development/input/
|
||||
|
||||
You'll find both the latest HID driver and the complete Input driver
|
||||
there as well as information how to access the CVS repository for
|
||||
latest revisions of the drivers.
|
||||
|
||||
There is also a mailing list for this:
|
||||
|
||||
majordomo@atrey.karlin.mff.cuni.cz
|
||||
|
||||
Send "subscribe linux-input" to subscribe to it.
|
||||
|
||||
The input changes are also being worked on as part of the LinuxConsole
|
||||
project, see:
|
||||
|
||||
http://sourceforge.net/projects/linuxconsole/
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#FIG 3.2
|
||||
Landscape
|
||||
Center
|
||||
Inches
|
||||
Letter
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
2 1 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 6
|
||||
1200 3600 1800 3600 2400 4800 3000 4800 4200 5700 4800 5700
|
||||
2 2 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 5
|
||||
1200 3150 4800 3150 4800 6300 1200 6300 1200 3150
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
1200 4800 4800 4800
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
|
||||
2400 4800 2400 6525 1950 7125 1950 7800
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
|
||||
3000 4800 3000 6525 3600 7125 3600 7800
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 1 3
|
||||
0 0 1.00 60.00 120.00
|
||||
3825 5400 4125 5100 5400 5100
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 1 3
|
||||
0 0 1.00 60.00 120.00
|
||||
2100 4200 2400 3900 5400 3900
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
4800 5700 5400 5700
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
1800 3600 5400 3600
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 1 3
|
||||
0 0 1.00 60.00 120.00
|
||||
2700 4800 2700 4425 5400 4425
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
|
||||
0 0 1.00 60.00 120.00
|
||||
0 0 1.00 60.00 120.00
|
||||
1950 7800 3600 7800
|
||||
4 1 0 50 0 0 12 0.0000 4 135 810 2775 7725 Dead band\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1155 5400 5700 right saturation\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 1065 5400 3600 left saturation\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 2505 5400 3900 left coeff ( positive in that case )\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 2640 5475 5100 right coeff ( negative in that case )\001
|
||||
4 0 0 50 0 0 12 0.0000 4 105 480 5400 4425 center\001
|
||||
@@ -0,0 +1,316 @@
|
||||
Joystick API Documentation -*-Text-*-
|
||||
|
||||
Ragnar Hojland Espinosa
|
||||
<ragnar@macula.net>
|
||||
|
||||
7 Aug 1998
|
||||
|
||||
$Id: joystick-api.txt,v 1.2 2001/05/08 21:21:23 vojtech Exp $
|
||||
|
||||
1. Initialization
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
(JS_EVENT_INIT) that you can read to check the initial state of the
|
||||
joystick.
|
||||
|
||||
By default, the device is opened in blocking mode.
|
||||
|
||||
int fd = open ("/dev/js0", O_RDONLY);
|
||||
|
||||
|
||||
2. Event Reading
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
struct js_event e;
|
||||
read (fd, &e, sizeof(struct js_event));
|
||||
|
||||
where js_event is defined as
|
||||
|
||||
struct js_event {
|
||||
__u32 time; /* event timestamp in milliseconds */
|
||||
__s16 value; /* value */
|
||||
__u8 type; /* event type */
|
||||
__u8 number; /* axis/button number */
|
||||
};
|
||||
|
||||
If the read is successful, it will return sizeof(struct js_event), unless
|
||||
you wanted to read more than one event per read as described in section 3.1.
|
||||
|
||||
|
||||
2.1 js_event.type
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The possible values of ``type'' are
|
||||
|
||||
#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
|
||||
current type value will be
|
||||
|
||||
int type = JS_EVENT_BUTTON | JS_EVENT_INIT; /* 0x81 */
|
||||
|
||||
If you choose not to differentiate between synthetic or real events
|
||||
you can turn off the JS_EVENT_INIT bits
|
||||
|
||||
type &= ~JS_EVENT_INIT; /* 0x01 */
|
||||
|
||||
|
||||
2.2 js_event.number
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The values of ``number'' correspond to the axis or button that
|
||||
generated the event. Note that they carry separate numeration (that
|
||||
is, you have both an axis 0 and a button 0). Generally,
|
||||
|
||||
number
|
||||
1st Axis X 0
|
||||
1st Axis Y 1
|
||||
2nd Axis X 2
|
||||
2nd Axis Y 3
|
||||
...and so on
|
||||
|
||||
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.
|
||||
|
||||
|
||||
2.3 js_event.value
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For an axis, ``value'' is a signed integer between -32767 and +32767
|
||||
representing the position of the joystick along that axis. If you
|
||||
don't read a 0 when the joystick is `dead', or if it doesn't span the
|
||||
full range, you should recalibrate it (with, for example, jscal).
|
||||
|
||||
For a button, ``value'' for a press button event is 1 and for a release
|
||||
button event is 0.
|
||||
|
||||
Though this
|
||||
|
||||
if (js_event.type == JS_EVENT_BUTTON) {
|
||||
buttons_state ^= (1 << js_event.number);
|
||||
}
|
||||
|
||||
may work well if you handle JS_EVENT_INIT events separately,
|
||||
|
||||
if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) {
|
||||
if (js_event.value)
|
||||
buttons_state |= (1 << js_event.number);
|
||||
else
|
||||
buttons_state &= ~(1 << js_event.number);
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
|
||||
2.4 js_event.time
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The time an event was generated is stored in ``js_event.time''. It's a time
|
||||
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.
|
||||
|
||||
|
||||
3. Reading
|
||||
~~~~~~~~~~
|
||||
|
||||
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)
|
||||
|
||||
|
||||
3.1 O_NONBLOCK
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
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,
|
||||
|
||||
while (1) {
|
||||
while (read (fd, &e, sizeof(struct js_event)) > 0) {
|
||||
process_event (e);
|
||||
}
|
||||
/* EAGAIN is returned when the queue is empty */
|
||||
if (errno != EAGAIN) {
|
||||
/* error */
|
||||
}
|
||||
/* do something interesting with processed events */
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
[As for version 1.2.8, the queue is circular and able to hold 64
|
||||
events. You can increment this size bumping up JS_BUFF_SIZE in
|
||||
joystick.h and recompiling the driver.]
|
||||
|
||||
|
||||
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
|
||||
replace the read above with something like
|
||||
|
||||
struct js_event mybuffer[0xff];
|
||||
int i = read (fd, mybuffer, sizeof(struct mybuffer));
|
||||
|
||||
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.
|
||||
|
||||
|
||||
4. IOCTLs
|
||||
~~~~~~~~~
|
||||
|
||||
The joystick driver defines the following ioctl(2) operations.
|
||||
|
||||
/* 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 */
|
||||
|
||||
For example, to read the number of axes
|
||||
|
||||
char number_of_axes;
|
||||
ioctl (fd, JSIOCGAXES, &number_of_axes);
|
||||
|
||||
|
||||
4.1 JSIOGCVERSION
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
JS_VERSION symbol
|
||||
|
||||
#ifdef JS_VERSION
|
||||
#if JS_VERSION > 0xsomething
|
||||
|
||||
|
||||
4.2 JSIOCGNAME
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
possible overrun should the name be too long.
|
||||
|
||||
char name[128];
|
||||
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
printf("Name: %s\n", name);
|
||||
|
||||
|
||||
4.3 JSIOC[SG]CORR
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
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];
|
||||
|
||||
struct js_corr is defined as
|
||||
|
||||
struct js_corr {
|
||||
__s32 coef[8];
|
||||
__u16 prec;
|
||||
__u16 type;
|
||||
};
|
||||
|
||||
and ``type''
|
||||
|
||||
#define JS_CORR_NONE 0x00 /* returns raw values */
|
||||
#define JS_CORR_BROKEN 0x01 /* broken line */
|
||||
|
||||
|
||||
5. Backward compatibility
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The 0.x joystick driver API is quite limited and its usage is deprecated.
|
||||
The driver offers backward compatibility, though. Here's a quick summary:
|
||||
|
||||
struct JS_DATA_TYPE js;
|
||||
while (1) {
|
||||
if (read (fd, &js, JS_RETURN) != JS_RETURN) {
|
||||
/* error */
|
||||
}
|
||||
usleep (1000);
|
||||
}
|
||||
|
||||
As you can figure out from the example, the read returns immediately,
|
||||
with the actual state of the joystick.
|
||||
|
||||
struct JS_DATA_TYPE {
|
||||
int buttons; /* immediate button state */
|
||||
int x; /* immediate x axis value */
|
||||
int y; /* immediate y axis value */
|
||||
};
|
||||
|
||||
and JS_RETURN is defined as
|
||||
|
||||
#define JS_RETURN sizeof(struct JS_DATA_TYPE)
|
||||
|
||||
To test the state of the buttons,
|
||||
|
||||
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.
|
||||
|
||||
|
||||
6. Final Notes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
____/| 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 ;)
|
||||
|
||||
- Ragnar
|
||||
EOF
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
#FIG 3.2
|
||||
Landscape
|
||||
Center
|
||||
Inches
|
||||
Letter
|
||||
100.00
|
||||
Single
|
||||
-2
|
||||
1200 2
|
||||
2 1 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 6
|
||||
4200 3600 4200 3075 4950 2325 7425 2325 8250 3150 8250 3600
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
4200 3675 4200 5400
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
8250 3675 8250 5400
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
3675 3600 8700 3600
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
8775 3600 10200 3600
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
8325 3150 9075 3150
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
7500 2325 10200 2325
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
3600 3600 3000 3600
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
4125 3075 3000 3075
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
|
||||
0 0 1.00 60.00 120.00
|
||||
0 0 1.00 60.00 120.00
|
||||
4200 5400 8175 5400
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
|
||||
0 0 1.00 60.00 120.00
|
||||
0 0 1.00 60.00 120.00
|
||||
10125 2325 10125 3600
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
|
||||
0 0 1.00 60.00 120.00
|
||||
0 0 1.00 60.00 120.00
|
||||
3000 3150 3000 3600
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
|
||||
0 0 1.00 60.00 120.00
|
||||
0 0 1.00 60.00 120.00
|
||||
9075 3150 9075 3600
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
4950 2325 4950 1200
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
|
||||
7425 2325 7425 1200
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
|
||||
4200 3075 4200 2400 3600 1800 3600 1200
|
||||
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 4
|
||||
8250 3150 8250 2475 8775 1950 8775 1200
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
|
||||
0 0 1.00 60.00 120.00
|
||||
0 0 1.00 60.00 120.00
|
||||
3600 1275 4950 1275
|
||||
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
|
||||
0 0 1.00 60.00 120.00
|
||||
0 0 1.00 60.00 120.00
|
||||
7425 1275 8700 1275
|
||||
4 1 0 50 0 0 12 0.0000 4 135 1140 6075 5325 Effect duration\001
|
||||
4 0 0 50 0 0 12 0.0000 4 180 1305 10200 3000 Effect magnitude\001
|
||||
4 0 0 50 0 0 12 0.0000 4 135 780 9150 3450 Fade level\001
|
||||
4 1 0 50 0 0 12 0.0000 4 180 1035 4275 1200 Attack length\001
|
||||
4 1 0 50 0 0 12 0.0000 4 180 885 8175 1200 Fade length\001
|
||||
4 2 0 50 0 0 12 0.0000 4 135 930 2925 3375 Attack level\001
|
||||
@@ -0,0 +1,116 @@
|
||||
xpad - Linux USB driver for X-Box gamepads
|
||||
|
||||
This is the very first release of a driver for X-Box gamepads.
|
||||
Basically, this was hacked away in just a few hours, so don't expect
|
||||
miracles.
|
||||
In particular, there is currently NO support for the rumble pack.
|
||||
You won't find many ff-aware linux applications anyway.
|
||||
|
||||
|
||||
0. Status
|
||||
---------
|
||||
|
||||
For now, this driver has only been tested on just one Linux-Box.
|
||||
This one is running a 2.4.18 kernel with usb-uhci on an amd athlon 600.
|
||||
|
||||
The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) reports
|
||||
8 axes and 10 buttons.
|
||||
|
||||
Alls 8 axes work, though they all have the same range (-32768..32767)
|
||||
and the zero-setting is not correct for the triggers (I don't know if that
|
||||
is some limitation of jstest, since the input device setup should be fine. I
|
||||
didn't have a look at jstest itself yet).
|
||||
|
||||
All of the 10 buttons work (in digital mode). The six buttons on the
|
||||
right side (A, B, X, Y, black, white) are said to be "analog" and
|
||||
report their values as 8 bit unsigned, not sure what this is good for.
|
||||
|
||||
I tested the controller with quake3, and configuration and
|
||||
in game functionality were OK. However, I find it rather difficult to
|
||||
play first person shooters with a pad. Your mileage may vary.
|
||||
|
||||
|
||||
1. USB adapter
|
||||
--------------
|
||||
|
||||
Before you can actually use the driver, you need to get yourself an
|
||||
adapter cable to connect the X-Box controller to your Linux-Box.
|
||||
|
||||
Such a cable is pretty easy to build. The Controller itself is a USB compound
|
||||
device (a hub with three ports for two expansion slots and the controller
|
||||
device) with the only difference in a nonstandard connector (5 pins vs. 4 on
|
||||
standard USB connector).
|
||||
|
||||
You just need to solder a USB connector onto the cable and keep the
|
||||
yellow wire unconnected. The other pins have the same order on both
|
||||
connectors so there is no magic to it. Detailed info on these matters
|
||||
can be found on the net ([1], [2], [3]).
|
||||
|
||||
Thanks to the trip splitter found on the cable you don't even need to cut the
|
||||
original one. You can buy an extension cable and cut that instead. That way,
|
||||
you can still use the controller with your X-Box, if you have one ;)
|
||||
|
||||
|
||||
2. driver installation
|
||||
----------------------
|
||||
|
||||
Once you have the adapter cable and the controller is connected, you need
|
||||
to load your USB subsystem and should cat /proc/bus/usb/devices.
|
||||
There should be an entry like the one at the end [4].
|
||||
|
||||
Currently (as of version 0.0.4), the following three devices are included:
|
||||
original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202
|
||||
original Microsoft XBOX controller (Japan), vendor=0x045e, product=0x0285
|
||||
InterAct PowerPad Pro (Germany), vendor=0x05fd, product=0x107a
|
||||
|
||||
If you have another controller that is not listed above and is not recognized
|
||||
by the driver, please drop me a line with the appropriate info (that is, include
|
||||
the name, vendor and product ID, as well as the country where you bought it;
|
||||
sending the whole dump out of /proc/bus/usb/devices along would be even better).
|
||||
|
||||
In theory, the driver should work with other controllers than mine
|
||||
(InterAct PowerPad pro, bought in Germany) just fine, but I cannot test this
|
||||
for I only have this one controller.
|
||||
|
||||
If you compiled and installed the driver, test the functionality:
|
||||
> modprobe xpad
|
||||
> modprobe joydev
|
||||
> jstest /dev/js0
|
||||
|
||||
There should be a single line showing 18 inputs (8 axes, 10 buttons), and
|
||||
it's values should change if you move the sticks and push the buttons.
|
||||
|
||||
It works? Voila, your done ;)
|
||||
|
||||
|
||||
3. Thanks
|
||||
---------
|
||||
|
||||
I have to thank ITO Takayuki for the detailed info on his site
|
||||
http://euc.jp/periphs/xbox-controller.ja.html.
|
||||
|
||||
His useful info and both the usb-skeleton as well as the iforce input driver
|
||||
(Greg Kroah-Hartmann; Vojtech Pavlik) helped a lot in rapid prototyping
|
||||
the basic functionality.
|
||||
|
||||
|
||||
4. References
|
||||
-------------
|
||||
|
||||
1. http://euc.jp/periphs/xbox-controller.ja.html (ITO Takayuki)
|
||||
2. http://xpad.xbox-scene.com/
|
||||
3. http://www.xboxhackz.com/Hackz-Reference.htm
|
||||
|
||||
4. /proc/bus/usb/devices - dump from InterAct PowerPad Pro (Germany):
|
||||
|
||||
T: Bus=01 Lev=03 Prnt=04 Port=00 Cnt=01 Dev#= 5 Spd=12 MxCh= 0
|
||||
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=32 #Cfgs= 1
|
||||
P: Vendor=05fd ProdID=107a Rev= 1.00
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
|
||||
I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=(none)
|
||||
E: Ad=81(I) Atr=03(Int.) MxPS= 32 Ivl= 10ms
|
||||
E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl= 10ms
|
||||
|
||||
--
|
||||
Marko Friedemann <mfr@bmx-chemnitz.de>
|
||||
2002-07-16
|
||||
Reference in New Issue
Block a user