Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input subsystem updates from Dmitry Torokhov:

 - a big update from Mauro converting input documentation to ReST format

 - Synaptics PS/2 is now aware of SMBus companion devices, which means
   that we can now use native RMI4 protocol to handle touchpads, instead
   of relying on legacy PS/2 mode.

 - we removed support from BMA180 accelerometer from input devices as it
   is now handled properly by IIO

 - update to TSC2007 to corretcly report pressure

 - other miscellaneous driver fixes.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (152 commits)
  Input: ar1021_i2c - use BIT to check for a bit
  Input: twl4030-pwrbutton - use input_set_capability() helper
  Input: twl4030-pwrbutton - use correct device for irq request
  Input: ar1021_i2c - enable touch mode during open
  Input: add uinput documentation
  dt-bindings: input: add bindings document for ar1021_i2c driver
  dt-bindings: input: rotary-encoder: fix typo
  Input: xen-kbdfront - add module parameter for setting resolution
  ARM: pxa/raumfeld: fix compile error in rotary controller resources
  Input: xpad - do not suggest writing to Dominic
  Input: xpad - don't use literal blocks inside footnotes
  Input: xpad - note that usb/devices is now at /sys/kernel/debug/
  Input: docs - freshen up introduction
  Input: docs - split input docs into kernel- and user-facing
  Input: docs - note that MT-A protocol is obsolete
  Input: docs - update joystick documentation a bit
  Input: docs - remove disclaimer/GPL notice
  Input: fix "Game console" heading level in joystick documentation
  Input: rotary-encoder - remove references to platform data from docs
  Input: move documentation for Amiga CD32
  ...
This commit is contained in:
Linus Torvalds 2017-05-03 12:38:20 -07:00
commit 16a12fa9ae
129 changed files with 7664 additions and 5446 deletions

View File

@ -348,6 +348,8 @@ latex_documents = [
'The kernel development community', 'manual'), 'The kernel development community', 'manual'),
('driver-api/index', 'driver-api.tex', 'The kernel driver API manual', ('driver-api/index', 'driver-api.tex', 'The kernel driver API manual',
'The kernel development community', 'manual'), 'The kernel development community', 'manual'),
('input/index', 'linux-input.tex', 'The Linux input driver subsystem',
'The kernel development community', 'manual'),
('kernel-documentation', 'kernel-documentation.tex', 'The Linux Kernel Documentation', ('kernel-documentation', 'kernel-documentation.tex', 'The Linux Kernel Documentation',
'The kernel development community', 'manual'), 'The kernel development community', 'manual'),
('process/index', 'development-process.tex', 'Linux Kernel Development Documentation', ('process/index', 'development-process.tex', 'Linux Kernel Development Documentation',

View File

@ -24,6 +24,8 @@ Optional Properties:
- debounce-delay-ms: debounce interval in milliseconds - debounce-delay-ms: debounce interval in milliseconds
- col-scan-delay-us: delay, measured in microseconds, that is needed - col-scan-delay-us: delay, measured in microseconds, that is needed
before we can scan keypad after activating column gpio before we can scan keypad after activating column gpio
- drive-inactive-cols: drive inactive columns during scan,
default is to turn inactive columns into inputs.
Example: Example:
matrix-keypad { matrix-keypad {

View File

@ -8,6 +8,7 @@ Required properties:
Optional properties: Optional properties:
- amp-supply: phandle to a regulator that acts as an amplifier for the beeper - amp-supply: phandle to a regulator that acts as an amplifier for the beeper
- beeper-hz: bell frequency in Hz
Example: Example:

View File

@ -7,6 +7,7 @@ PROPERTIES
Value type: <string> Value type: <string>
Definition: must be one of: Definition: must be one of:
"qcom,pm8058-vib" "qcom,pm8058-vib"
"qcom,pm8916-vib"
"qcom,pm8921-vib" "qcom,pm8921-vib"
- reg: - reg:

View File

@ -12,7 +12,7 @@ Optional properties:
- rotary-encoder,relative-axis: register a relative axis rather than an - rotary-encoder,relative-axis: register a relative axis rather than an
absolute one. Relative axis will only generate +1/-1 events on the input absolute one. Relative axis will only generate +1/-1 events on the input
device, hence no steps need to be passed. device, hence no steps need to be passed.
- rotary-encoder,rollover: Automatic rollove when the rotary value becomes - rotary-encoder,rollover: Automatic rollover when the rotary value becomes
greater than the specified steps or smaller than 0. For absolute axis only. greater than the specified steps or smaller than 0. For absolute axis only.
- rotary-encoder,steps-per-period: Number of steps (stable states) per period. - rotary-encoder,steps-per-period: Number of steps (stable states) per period.
The values have the following meaning: The values have the following meaning:

View File

@ -35,6 +35,7 @@ Optional properties:
- adi,conversion-interval: : 0 : convert one time only - adi,conversion-interval: : 0 : convert one time only
1-255: 515us + val * 35us (up to 9.440ms) 1-255: 515us + val * 35us (up to 9.440ms)
This property has to be a '/bits/ 8' value This property has to be a '/bits/ 8' value
- gpio-controller : Switch AUX/VBAT/GPIO pin to GPIO mode
Example: Example:
@ -51,3 +52,21 @@ Example:
adi,averaging = /bits/ 8 <1>; adi,averaging = /bits/ 8 <1>;
adi,conversion-interval = /bits/ 8 <255>; adi,conversion-interval = /bits/ 8 <255>;
}; };
ad7879@1 {
compatible = "adi,ad7879";
spi-max-frequency = <5000000>;
reg = <1>;
spi-cpol;
spi-cpha;
gpio-controller;
interrupt-parent = <&gpio1>;
interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
touchscreen-max-pressure = <4096>;
adi,resistance-plate-x = <120>;
adi,first-conversion-delay = /bits/ 8 <3>;
adi,acquisition-time = /bits/ 8 <1>;
adi,median-filter-size = /bits/ 8 <2>;
adi,averaging = /bits/ 8 <1>;
adi,conversion-interval = /bits/ 8 <255>;
};

View File

@ -0,0 +1,16 @@
* Microchip AR1020 and AR1021 touchscreen interface (I2C)
Required properties:
- compatible : "microchip,ar1021-i2c"
- reg : I2C slave address
- interrupt-parent : the phandle for the interrupt controller
- interrupts : touch controller interrupt
Example:
touchscreen@4d {
compatible = "microchip,ar1021-i2c";
reg = <0x4d>;
interrupt-parent = <&gpio3>;
interrupts = <11 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@ -0,0 +1,18 @@
* MAXI MAX11801 Resistive touch screen controller with i2c interface
Required properties:
- compatible: must be "maxim,max11801"
- reg: i2c slave address
- interrupt-parent: the phandle for the interrupt controller
- interrupts: touch controller interrupt
Example:
&i2c1 {
max11801: touchscreen@48 {
compatible = "maxim,max11801";
reg = <0x48>;
interrupt-parent = <&gpio3>;
interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
};
};

View File

@ -1,7 +1,12 @@
* GSL 1680 touchscreen controller * GSL 1680 touchscreen controller
Required properties: Required properties:
- compatible : "silead,gsl1680" - compatible : Must be one of the following, depending on the model:
"silead,gsl1680"
"silead,gsl1688"
"silead,gsl3670"
"silead,gsl3675"
"silead,gsl3692"
- reg : I2C slave address of the chip (0x40) - reg : I2C slave address of the chip (0x40)
- interrupt-parent : a phandle pointing to the interrupt controller - interrupt-parent : a phandle pointing to the interrupt controller
serving the interrupt for this chip serving the interrupt for this chip

View File

@ -1,19 +0,0 @@
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)

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8; mode: python -*-
project = "The Linux input driver subsystem"
tags.add("subproject")
latex_documents = [
('index', 'linux-input.tex', project,
'The kernel development community', 'manual'),
]

View File

@ -1,10 +1,11 @@
----------------------
ALPS Touchpad Protocol ALPS Touchpad Protocol
---------------------- ----------------------
Introduction Introduction
------------ ------------
Currently the ALPS touchpad driver supports seven protocol versions in use by Currently the ALPS touchpad driver supports seven protocol versions in use by
ALPS touchpads, called versions 1, 2, 3, 4, 5, 6 and 7. ALPS touchpads, called versions 1, 2, 3, 4, 5, 6, 7 and 8.
Since roughly mid-2010 several new ALPS touchpads have been released and Since roughly mid-2010 several new ALPS touchpads have been released and
integrated into a variety of laptops and netbooks. These new touchpads integrated into a variety of laptops and netbooks. These new touchpads
@ -78,7 +79,7 @@ of the EC response.
Packet Format Packet Format
------------- -------------
In the following tables, the following notation is used. In the following tables, the following notation is used::
CAPITALS = stick, miniscules = touchpad CAPITALS = stick, miniscules = touchpad
@ -88,6 +89,8 @@ extra buttons, stick buttons on a dualpoint, etc.
PS/2 packet format PS/2 packet format
------------------ ------------------
::
byte 0: 0 0 YSGN XSGN 1 M R L byte 0: 0 0 YSGN XSGN 1 M R L
byte 1: X7 X6 X5 X4 X3 X2 X1 X0 byte 1: X7 X6 X5 X4 X3 X2 X1 X0
byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
@ -99,7 +102,9 @@ are on the touchpad, the M R L bits signal the combined status of both the
pointingstick and touchpad buttons. pointingstick and touchpad buttons.
ALPS Absolute Mode - Protocol Version 1 ALPS Absolute Mode - Protocol Version 1
-------------------------------------- ---------------------------------------
::
byte 0: 1 0 0 0 1 x9 x8 x7 byte 0: 1 0 0 0 1 x9 x8 x7
byte 1: 0 x6 x5 x4 x3 x2 x1 x0 byte 1: 0 x6 x5 x4 x3 x2 x1 x0
@ -111,6 +116,8 @@ ALPS Absolute Mode - Protocol Version 1
ALPS Absolute Mode - Protocol Version 2 ALPS Absolute Mode - Protocol Version 2
--------------------------------------- ---------------------------------------
::
byte 0: 1 ? ? ? 1 PSM PSR PSL byte 0: 1 ? ? ? 1 PSM PSR PSL
byte 1: 0 x6 x5 x4 x3 x2 x1 x0 byte 1: 0 x6 x5 x4 x3 x2 x1 x0
byte 2: 0 x10 x9 x8 x7 ? fin ges byte 2: 0 x10 x9 x8 x7 ? fin ges
@ -127,6 +134,8 @@ and PSL bits.
Dualpoint device -- interleaved packet format Dualpoint device -- interleaved packet format
--------------------------------------------- ---------------------------------------------
::
byte 0: 1 1 0 0 1 1 1 1 byte 0: 1 1 0 0 1 1 1 1
byte 1: 0 x6 x5 x4 x3 x2 x1 x0 byte 1: 0 x6 x5 x4 x3 x2 x1 x0
byte 2: 0 x10 x9 x8 x7 0 fin ges byte 2: 0 x10 x9 x8 x7 0 fin ges
@ -149,7 +158,7 @@ ALPS protocol version 3 has three different packet formats. The first two are
associated with touchpad events, and the third is associated with trackstick associated with touchpad events, and the third is associated with trackstick
events. events.
The first type is the touchpad position packet. The first type is the touchpad position packet::
byte 0: 1 ? x1 x0 1 1 1 1 byte 0: 1 ? x1 x0 1 1 1 1
byte 1: 0 x10 x9 x8 x7 x6 x5 x4 byte 1: 0 x10 x9 x8 x7 x6 x5 x4
@ -165,7 +174,7 @@ The second packet type contains bitmaps representing the x and y axes. In the
bitmaps a given bit is set if there is a finger covering that position on the bitmaps a given bit is set if there is a finger covering that position on the
given axis. Thus the bitmap packet can be used for low-resolution multi-touch given axis. Thus the bitmap packet can be used for low-resolution multi-touch
data, although finger tracking is not possible. This packet also encodes the data, although finger tracking is not possible. This packet also encodes the
number of contacts (f1 and f0 in the table below). number of contacts (f1 and f0 in the table below)::
byte 0: 1 1 x1 x0 1 1 1 1 byte 0: 1 1 x1 x0 1 1 1 1
byte 1: 0 x8 x7 x6 x5 x4 x3 x2 byte 1: 0 x8 x7 x6 x5 x4 x3 x2
@ -178,7 +187,7 @@ This packet only appears after a position packet with the mt bit set, and
usually only appears when there are two or more contacts (although usually only appears when there are two or more contacts (although
occasionally it's seen with only a single contact). occasionally it's seen with only a single contact).
The final v3 packet type is the trackstick packet. The final v3 packet type is the trackstick packet::
byte 0: 1 1 x7 y7 1 1 1 1 byte 0: 1 1 x7 y7 1 1 1 1
byte 1: 0 x6 x5 x4 x3 x2 x1 x0 byte 1: 0 x6 x5 x4 x3 x2 x1 x0
@ -190,7 +199,7 @@ The final v3 packet type is the trackstick packet.
ALPS Absolute Mode - Protocol Version 4 ALPS Absolute Mode - Protocol Version 4
--------------------------------------- ---------------------------------------
Protocol version 4 has an 8-byte packet format. Protocol version 4 has an 8-byte packet format::
byte 0: 1 ? x1 x0 1 1 1 1 byte 0: 1 ? x1 x0 1 1 1 1
byte 1: 0 x10 x9 x8 x7 x6 x5 x4 byte 1: 0 x10 x9 x8 x7 x6 x5 x4
@ -203,7 +212,7 @@ Protocol version 4 has an 8-byte packet format.
The last two bytes represent a partial bitmap packet, with 3 full packets The last two bytes represent a partial bitmap packet, with 3 full packets
required to construct a complete bitmap packet. Once assembled, the 6-byte required to construct a complete bitmap packet. Once assembled, the 6-byte
bitmap packet has the following format: bitmap packet has the following format::
byte 0: 0 1 x7 x6 x5 x4 x3 x2 byte 0: 0 1 x7 x6 x5 x4 x3 x2
byte 1: 0 x1 x0 y4 y3 y2 y1 y0 byte 1: 0 x1 x0 y4 y3 y2 y1 y0
@ -238,7 +247,7 @@ decode. It uses the same alps_process_touchpad_packet_v3 call with a
specialized decode_fields function pointer to correctly interpret the specialized decode_fields function pointer to correctly interpret the
packets. This appears to only be used by the Dolphin devices. packets. This appears to only be used by the Dolphin devices.
For single-touch, the 6-byte packet format is: For single-touch, the 6-byte packet format is::
byte 0: 1 1 0 0 1 0 0 0 byte 0: 1 1 0 0 1 0 0 0
byte 1: 0 x6 x5 x4 x3 x2 x1 x0 byte 1: 0 x6 x5 x4 x3 x2 x1 x0
@ -247,7 +256,7 @@ For single-touch, the 6-byte packet format is:
byte 4: y10 y9 y8 y7 x10 x9 x8 x7 byte 4: y10 y9 y8 y7 x10 x9 x8 x7
byte 5: 0 z6 z5 z4 z3 z2 z1 z0 byte 5: 0 z6 z5 z4 z3 z2 z1 z0
For mt, the format is: For mt, the format is::
byte 0: 1 1 1 n3 1 n2 n1 x24 byte 0: 1 1 1 n3 1 n2 n1 x24
byte 1: 1 y7 y6 y5 y4 y3 y2 y1 byte 1: 1 y7 y6 y5 y4 y3 y2 y1
@ -259,7 +268,7 @@ For mt, the format is:
ALPS Absolute Mode - Protocol Version 6 ALPS Absolute Mode - Protocol Version 6
--------------------------------------- ---------------------------------------
For trackstick packet, the format is: For trackstick packet, the format is::
byte 0: 1 1 1 1 1 1 1 1 byte 0: 1 1 1 1 1 1 1 1
byte 1: 0 X6 X5 X4 X3 X2 X1 X0 byte 1: 0 X6 X5 X4 X3 X2 X1 X0
@ -268,7 +277,7 @@ For trackstick packet, the format is:
byte 4: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 byte 4: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0
byte 5: 0 1 1 1 1 1 1 1 byte 5: 0 1 1 1 1 1 1 1
For touchpad packet, the format is: For touchpad packet, the format is::
byte 0: 1 1 1 1 1 1 1 1 byte 0: 1 1 1 1 1 1 1 1
byte 1: 0 0 0 0 x3 x2 x1 x0 byte 1: 0 0 0 0 x3 x2 x1 x0
@ -282,7 +291,7 @@ For touchpad packet, the format is:
ALPS Absolute Mode - Protocol Version 7 ALPS Absolute Mode - Protocol Version 7
--------------------------------------- ---------------------------------------
For trackstick packet, the format is: For trackstick packet, the format is::
byte 0: 0 1 0 0 1 0 0 0 byte 0: 0 1 0 0 1 0 0 0
byte 1: 1 1 * * 1 M R L byte 1: 1 1 * * 1 M R L
@ -291,7 +300,7 @@ For trackstick packet, the format is:
byte 4: Y7 0 Y5 Y4 Y3 1 1 0 byte 4: Y7 0 Y5 Y4 Y3 1 1 0
byte 5: T&P 0 Z5 Z4 Z3 Z2 Z1 Z0 byte 5: T&P 0 Z5 Z4 Z3 Z2 Z1 Z0
For touchpad packet, the format is: For touchpad packet, the format is::
packet-fmt b7 b6 b5 b4 b3 b2 b1 b0 packet-fmt b7 b6 b5 b4 b3 b2 b1 b0
byte 0: TWO & MULTI L 1 R M 1 Y0-2 Y0-1 Y0-0 byte 0: TWO & MULTI L 1 R M 1 Y0-2 Y0-1 Y0-0
@ -328,7 +337,7 @@ Spoken by SS4 (73 03 14) and SS5 (73 03 28) hardware.
The packet type is given by the APD field, bits 4-5 of byte 3. The packet type is given by the APD field, bits 4-5 of byte 3.
Touchpad packet (APD = 0x2): Touchpad packet (APD = 0x2)::
b7 b6 b5 b4 b3 b2 b1 b0 b7 b6 b5 b4 b3 b2 b1 b0
byte 0: SWM SWR SWL 1 1 0 0 X7 byte 0: SWM SWR SWL 1 1 0 0 X7
@ -340,7 +349,7 @@ Touchpad packet (APD = 0x2):
SWM, SWR, SWL: Middle, Right, and Left button states SWM, SWR, SWL: Middle, Right, and Left button states
Touchpad 1 Finger packet (APD = 0x0): Touchpad 1 Finger packet (APD = 0x0)::
b7 b6 b5 b4 b3 b2 b1 b0 b7 b6 b5 b4 b3 b2 b1 b0
byte 0: SWM SWR SWL 1 1 X2 X1 X0 byte 0: SWM SWR SWL 1 1 X2 X1 X0
@ -353,7 +362,7 @@ Touchpad 1 Finger packet (APD = 0x0):
TAPF: ??? TAPF: ???
LFB: ??? LFB: ???
Touchpad 2 Finger packet (APD = 0x1): Touchpad 2 Finger packet (APD = 0x1)::
b7 b6 b5 b4 b3 b2 b1 b0 b7 b6 b5 b4 b3 b2 b1 b0
byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4 byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4
@ -365,7 +374,7 @@ Touchpad 2 Finger packet (APD = 0x1):
CONT: A 3-or-4 Finger packet is to follow CONT: A 3-or-4 Finger packet is to follow
Touchpad 3-or-4 Finger packet (APD = 0x3): Touchpad 3-or-4 Finger packet (APD = 0x3)::
b7 b6 b5 b4 b3 b2 b1 b0 b7 b6 b5 b4 b3 b2 b1 b0
byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4 byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4

View File

@ -1,67 +1,101 @@
~~~~~~~~~~~~~~~~~~~~~~~~~
Amiga joystick extensions
~~~~~~~~~~~~~~~~~~~~~~~~~
Amiga 4-joystick parport extension Amiga 4-joystick parport extension
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Parallel port pins: Parallel port pins:
(2) - Up1 (6) - Up2
(3) - Down1 (7) - Down2 ===== ======== ==== ==========
(4) - Left1 (8) - Left2 Pin Meaning Pin Meaning
(5) - Right1 (9) - Right2 ===== ======== ==== ==========
(13) - Fire1 (11) - Fire2 2 Up1 6 Up2
(18) - Gnd1 (18) - Gnd2 3 Down1 7 Down2
4 Left1 8 Left2
5 Right1 9 Right2
13 Fire1 11 Fire2
18 Gnd1 18 Gnd2
===== ======== ==== ==========
Amiga digital joystick pinout Amiga digital joystick pinout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(1) - Up
(2) - Down === ============
(3) - Left Pin Meaning
(4) - Right === ============
(5) - n/c 1 Up
(6) - Fire button 2 Down
(7) - +5V (50mA) 3 Left
(8) - Gnd 4 Right
(9) - Thumb button 5 n/c
6 Fire button
7 +5V (50mA)
8 Gnd
9 Thumb button
=== ============
Amiga mouse pinout Amiga mouse pinout
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
(1) - V-pulse
(2) - H-pulse === ============
(3) - VQ-pulse Pin Meaning
(4) - HQ-pulse === ============
(5) - Middle button 1 V-pulse
(6) - Left button 2 H-pulse
(7) - +5V (50mA) 3 VQ-pulse
(8) - Gnd 4 HQ-pulse
(9) - Right button 5 Middle button
6 Left button
7 +5V (50mA)
8 Gnd
9 Right button
=== ============
Amiga analog joystick pinout Amiga analog joystick pinout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(1) - Top button
(2) - Top2 button === ==============
(3) - Trigger button Pin Meaning
(4) - Thumb button === ==============
(5) - Analog X 1 Top button
(6) - n/c 2 Top2 button
(7) - +5V (50mA) 3 Trigger button
(8) - Gnd 4 Thumb button
(9) - Analog Y 5 Analog X
6 n/c
7 +5V (50mA)
8 Gnd
9 Analog Y
=== ==============
Amiga lightpen pinout Amiga lightpen pinout
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
(1) - n/c
(2) - n/c === =============
(3) - n/c Pin Meaning
(4) - n/c === =============
(5) - Touch button 1 n/c
(6) - /Beamtrigger 2 n/c
(7) - +5V (50mA) 3 n/c
(8) - Gnd 4 n/c
(9) - Stylus button 5 Touch button
6 /Beamtrigger
7 +5V (50mA)
8 Gnd
9 Stylus button
=== =============
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
======== === ==== ==== ====== ========================================
NAME rev ADDR type chip Description NAME rev ADDR type chip Description
======== === ==== ==== ====== ========================================
JOY0DAT 00A R Denise Joystick-mouse 0 data (left vert, horiz) JOY0DAT 00A R Denise Joystick-mouse 0 data (left vert, horiz)
JOY1DAT 00C R Denise Joystick-mouse 1 data (right vert,horiz) JOY1DAT 00C R Denise Joystick-mouse 1 data (right vert,horiz)
======== === ==== ==== ====== ========================================
These addresses each read a 16 bit register. These in turn These addresses each read a 16 bit register. These in turn
are loaded from the MDAT serial stream and are clocked in on are loaded from the MDAT serial stream and are clocked in on
@ -71,12 +105,17 @@ JOY1DAT 00C R Denise Joystick-mouse 1 data (right vert,horiz)
controller ports (8 total) plus 8 miscellaneous control bits controller ports (8 total) plus 8 miscellaneous control bits
which are new for LISA and can be read in upper 8 bits of which are new for LISA and can be read in upper 8 bits of
LISAID. LISAID.
Register bits are as follows:
Mouse counter usage (pins 1,3 =Yclock, pins 2,4 =Xclock)
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 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 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 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. 0=LEFT CONTROLLER PAIR, 1=RIGHT CONTROLLER PAIR.
(4 counters total). The bit usage for both left and right (4 counters total). The bit usage for both left and right
@ -86,14 +125,21 @@ JOY1DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
+-------------------+-----------------------------------------+ +-------------------+-----------------------------------------+
| Serial | Bit Name | Description | | Serial | Bit Name | Description |
+--------+----------+-----------------------------------------+ +========+==========+=========================================+
| 0 | M0H | JOY0DAT Horizontal Clock | | 0 | M0H | JOY0DAT Horizontal Clock |
+--------+----------+-----------------------------------------+
| 1 | M0HQ | JOY0DAT Horizontal Clock (quadrature) | | 1 | M0HQ | JOY0DAT Horizontal Clock (quadrature) |
+--------+----------+-----------------------------------------+
| 2 | M0V | JOY0DAT Vertical Clock | | 2 | M0V | JOY0DAT Vertical Clock |
+--------+----------+-----------------------------------------+
| 3 | M0VQ | JOY0DAT Vertical Clock (quadrature) | | 3 | M0VQ | JOY0DAT Vertical Clock (quadrature) |
+--------+----------+-----------------------------------------+
| 4 | M1V | JOY1DAT Horizontal Clock | | 4 | M1V | JOY1DAT Horizontal Clock |
+--------+----------+-----------------------------------------+
| 5 | M1VQ | JOY1DAT Horizontal Clock (quadrature) | | 5 | M1VQ | JOY1DAT Horizontal Clock (quadrature) |
+--------+----------+-----------------------------------------+
| 6 | M1V | JOY1DAT Vertical Clock | | 6 | M1V | JOY1DAT Vertical Clock |
+--------+----------+-----------------------------------------+
| 7 | M1VQ | JOY1DAT Vertical Clock (quadrature) | | 7 | M1VQ | JOY1DAT Vertical Clock (quadrature) |
+--------+----------+-----------------------------------------+ +--------+----------+-----------------------------------------+
@ -104,46 +150,65 @@ JOY1DAT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
+------------+------+---------------------------------+ +------------+------+---------------------------------+
| Directions | Pin# | Counter bits | | Directions | Pin# | Counter bits |
+------------+------+---------------------------------+ +============+======+=================================+
| Forward | 1 | Y1 xor Y0 (BIT#09 xor BIT#08) | | Forward | 1 | Y1 xor Y0 (BIT#09 xor BIT#08) |
+------------+------+---------------------------------+
| Left | 3 | Y1 | | Left | 3 | Y1 |
+------------+------+---------------------------------+
| Back | 2 | X1 xor X0 (BIT#01 xor BIT#00) | | Back | 2 | X1 xor X0 (BIT#01 xor BIT#00) |
+------------+------+---------------------------------+
| Right | 4 | X1 | | Right | 4 | X1 |
+------------+------+---------------------------------+ +------------+------+---------------------------------+
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
======== === ==== ==== ====== =================================================
NAME rev ADDR type chip Description NAME rev ADDR type chip Description
======== === ==== ==== ====== =================================================
JOYTEST 036 W Denise Write to all 4 joystick-mouse counters at once. JOYTEST 036 W Denise Write to all 4 joystick-mouse counters at once.
======== === ==== ==== ====== =================================================
Mouse counter write test data: Mouse counter write test data:
========= === === === === === === === === ====== === === === === === === ===
BIT# 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 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
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 NAME rev ADDR type chip Description
======= === ==== ==== ====== ========================================
POT0DAT h 012 R Paula Pot counter data left pair (vert, horiz) POT0DAT h 012 R Paula Pot counter data left pair (vert, horiz)
POT1DAT h 014 R Paula Pot counter data right 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. These addresses each read a pair of 8 bit pot counters.
(4 counters total). The bit assignment for both (4 counters total). The bit assignment for both
addresses is shown below. The counters are stopped by signals addresses is shown below. The counters are stopped by signals
from 2 controller connectors (left-right) with 2 pins each. 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 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 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 LEFT Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 X7 X6 X5 X4 X3 X2 X1 X0
====== === === === === === === === === ====== === === === === === === ===
+--------------------------+-------+ +--------------------------+-------+
| CONNECTORS | PAULA | | CONNECTORS | PAULA |
+-------+------+-----+-----+-------+ +-------+------+-----+-----+-------+
| Loc. | Dir. | Sym | pin | pin | | Loc. | Dir. | Sym | pin | pin |
+-------+------+-----+-----+-------+ +=======+======+=====+=====+=======+
| RIGHT | Y | RX | 9 | 33 | | RIGHT | Y | RX | 9 | 33 |
+-------+------+-----+-----+-------+
| RIGHT | X | RX | 5 | 32 | | RIGHT | X | RX | 5 | 32 |
+-------+------+-----+-----+-------+
| LEFT | Y | LY | 9 | 36 | | LEFT | Y | LY | 9 | 36 |
+-------+------+-----+-----+-------+
| LEFT | X | LX | 5 | 35 | | LEFT | X | LX | 5 | 35 |
+-------+------+-----+-----+-------+ +-------+------+-----+-----+-------+
@ -155,30 +220,44 @@ POT1DAT h 014 R Paula Pot counter data right pair (vert,horiz)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
====== === ==== ==== ====== ================================================
NAME rev ADDR type chip Description NAME rev ADDR type chip Description
POTGO 034 W Paula Pot port (4 bit) bi-direction and data, and pot counter start. ====== === ==== ==== ====== ================================================
POTGO 034 W Paula Pot port (4 bit) bi-direction and data, and pot
counter start.
====== === ==== ==== ====== ================================================
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
====== === ==== ==== ====== ================================================
NAME rev ADDR type chip Description NAME rev ADDR type chip Description
====== === ==== ==== ====== ================================================
POTINP 016 R Paula Pot pin data read POTINP 016 R Paula Pot pin data read
====== === ==== ==== ====== ================================================
This register controls a 4 bit bi-direction I/O port This register controls a 4 bit bi-direction I/O port
that shares the same 4 pins as the 4 pot counters above. that shares the same 4 pins as the 4 pot counters above.
+-------+----------+---------------------------------------------+ +-------+----------+---------------------------------------------+
| BIT# | FUNCTION | DESCRIPTION | | BIT# | FUNCTION | DESCRIPTION |
+-------+----------+---------------------------------------------+ +=======+==========+=============================================+
| 15 | OUTRY | Output enable for Paula pin 33 | | 15 | OUTRY | Output enable for Paula pin 33 |
+-------+----------+---------------------------------------------+
| 14 | DATRY | I/O data Paula pin 33 | | 14 | DATRY | I/O data Paula pin 33 |
+-------+----------+---------------------------------------------+
| 13 | OUTRX | Output enable for Paula pin 32 | | 13 | OUTRX | Output enable for Paula pin 32 |
+-------+----------+---------------------------------------------+
| 12 | DATRX | I/O data Paula pin 32 | | 12 | DATRX | I/O data Paula pin 32 |
+-------+----------+---------------------------------------------+
| 11 | OUTLY | Out put enable for Paula pin 36 | | 11 | OUTLY | Out put enable for Paula pin 36 |
+-------+----------+---------------------------------------------+
| 10 | DATLY | I/O data Paula pin 36 | | 10 | DATLY | I/O data Paula pin 36 |
+-------+----------+---------------------------------------------+
| 09 | OUTLX | Output enable for Paula pin 35 | | 09 | OUTLX | Output enable for Paula pin 35 |
+-------+----------+---------------------------------------------+
| 08 | DATLX | I/O data Paula pin 35 | | 08 | DATLX | I/O data Paula pin 35 |
+-------+----------+---------------------------------------------+
| 07-01 | X | Not used | | 07-01 | X | Not used |
+-------+----------+---------------------------------------------+
| 00 | START | Start pots (dump capacitors,start counters) | | 00 | START | Start pots (dump capacitors,start counters) |
+-------+----------+---------------------------------------------+ +-------+----------+---------------------------------------------+
-------------------------------------------------------------------------------

View File

@ -1,12 +1,17 @@
.. include:: <isonum.txt>
----------------------------------
Apple Touchpad Driver (appletouch) Apple Touchpad Driver (appletouch)
---------------------------------- ----------------------------------
Copyright (C) 2005 Stelian Pop <stelian@popies.net>
:Copyright: |copy| 2005 Stelian Pop <stelian@popies.net>
appletouch is a Linux kernel driver for the USB touchpad found on post appletouch is a Linux kernel driver for the USB touchpad found on post
February 2005 and October 2005 Apple Aluminium Powerbooks. February 2005 and October 2005 Apple Aluminium Powerbooks.
This driver is derived from Johannes Berg's appletrackpad driver[1], but it has This driver is derived from Johannes Berg's appletrackpad driver [#f1]_,
been improved in some areas: but it has been improved in some areas:
* appletouch is a full kernel driver, no userspace program is necessary * appletouch is a full kernel driver, no userspace program is necessary
* appletouch can be interfaced with the synaptics X11 driver, in order * appletouch can be interfaced with the synaptics X11 driver, in order
to have touchpad acceleration, scrolling, etc. to have touchpad acceleration, scrolling, etc.
@ -16,8 +21,8 @@ Frank Arnold for further improvements, and Alex Harper for some additional
information about the inner workings of the touchpad sensors. Michael information about the inner workings of the touchpad sensors. Michael
Hanselmann added support for the October 2005 models. Hanselmann added support for the October 2005 models.
Usage: Usage
------ -----
In order to use the touchpad in the basic mode, compile the driver and load In order to use the touchpad in the basic mode, compile the driver and load
the module. A new input device will be detected and you will be able to read the module. A new input device will be detected and you will be able to read
@ -27,13 +32,13 @@ In X11, you can configure the touchpad to use the synaptics X11 driver, which
will give additional functionalities, like acceleration, scrolling, 2 finger will give additional functionalities, like acceleration, scrolling, 2 finger
tap for middle button mouse emulation, 3 finger tap for right button mouse tap for middle button mouse emulation, 3 finger tap for right button mouse
emulation, etc. In order to do this, make sure you're using a recent version of emulation, etc. In order to do this, make sure you're using a recent version of
the synaptics driver (tested with 0.14.2, available from [2]), and configure a the synaptics driver (tested with 0.14.2, available from [#f2]_), and configure
new input device in your X11 configuration file (take a look below for an a new input device in your X11 configuration file (take a look below for an
example). For additional configuration, see the synaptics driver documentation. example). For additional configuration, see the synaptics driver documentation::
Section "InputDevice" Section "InputDevice"
Identifier "Synaptics Touchpad" Identifier "Synaptics Touchpad"
Driver "synaptics" Driver "synaptics"
Option "SendCoreEvents" "true" Option "SendCoreEvents" "true"
Option "Device" "/dev/input/mice" Option "Device" "/dev/input/mice"
Option "Protocol" "auto-dev" Option "Protocol" "auto-dev"
@ -60,8 +65,8 @@ example). For additional configuration, see the synaptics driver documentation.
... ...
EndSection EndSection
Fuzz problems: Fuzz problems
-------------- -------------
The touchpad sensors are very sensitive to heat, and will generate a lot of The touchpad sensors are very sensitive to heat, and will generate a lot of
noise when the temperature changes. This is especially true when you power-on noise when the temperature changes. This is especially true when you power-on
@ -73,13 +78,17 @@ the driver.
You can activate debugging using the 'debug' module parameter. A value of 0 You can activate debugging using the 'debug' module parameter. A value of 0
deactivates any debugging, 1 activates tracing of invalid samples, 2 activates deactivates any debugging, 1 activates tracing of invalid samples, 2 activates
full tracing (each sample is being traced): full tracing (each sample is being traced)::
modprobe appletouch debug=1 modprobe appletouch debug=1
or
or::
echo "1" > /sys/module/appletouch/parameters/debug echo "1" > /sys/module/appletouch/parameters/debug
Links:
------
[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/ .. Links:
[2]: http://web.archive.org/web/*/http://web.telia.com/~u89404340/touchpad/index.html
.. [#f1] http://johannes.sipsolutions.net/PowerBook/touchpad/
.. [#f2] `<http://web.archive.org/web/*/http://web.telia.com/~u89404340/touchpad/index.html>`_

View File

@ -1,7 +1,10 @@
====================================
Intelligent Keyboard (ikbd) Protocol Intelligent Keyboard (ikbd) Protocol
====================================
1. Introduction Introduction
============
The Atari Corp. Intelligent Keyboard (ikbd) is a general purpose keyboard The Atari Corp. Intelligent Keyboard (ikbd) is a general purpose keyboard
controller that is flexible enough that it can be used in a variety of controller that is flexible enough that it can be used in a variety of
@ -18,7 +21,8 @@ different applications of the keyboard, joysticks, or mouse. Limited use of
the controller is possible in applications in which only a unidirectional the controller is possible in applications in which only a unidirectional
communications medium is available by carefully designing the default modes. communications medium is available by carefully designing the default modes.
3. Keyboard Keyboard
========
The keyboard always returns key make/break scan codes. The ikbd generates The keyboard always returns key make/break scan codes. The ikbd generates
keyboard scan codes for each key press and release. The key scan make (key keyboard scan codes for each key press and release. The key scan make (key
@ -28,19 +32,25 @@ exists in that position on a particular keyboard. The break code for each key
is obtained by ORing 0x80 with the make code. is obtained by ORing 0x80 with the make code.
The special codes 0xF6 through 0xFF are reserved for use as follows: The special codes 0xF6 through 0xFF are reserved for use as follows:
=================== ====================================================
Code Command
=================== ====================================================
0xF6 status report 0xF6 status report
0xF7 absolute mouse position record 0xF7 absolute mouse position record
0xF8-0xFB relative mouse position records (lsbs determined by 0xF8-0xFB relative mouse position records (lsbs determined by
mouse button states) mouse button states)
0xFC time-of-day 0xFC time-of-day
0xFD joystick report (both sticks) 0xFD joystick report (both sticks)
0xFE joystick 0 event 0xFE joystick 0 event
0xFF joystick 1 event 0xFF joystick 1 event
=================== ====================================================
The two shift keys return different scan codes in this mode. The ENTER key The two shift keys return different scan codes in this mode. The ENTER key
and the RETurn key are also distinct. and the RETurn key are also distinct.
4. Mouse Mouse
=====
The mouse port should be capable of supporting a mouse with resolution of The mouse port should be capable of supporting a mouse with resolution of
approximately 200 counts (phase changes or 'clicks') per inch of travel. The approximately 200 counts (phase changes or 'clicks') per inch of travel. The
@ -53,7 +63,8 @@ key equivalents.
The mouse buttons can be treated as part of the mouse or as additional The mouse buttons can be treated as part of the mouse or as additional
keyboard keys. keyboard keys.
4.1 Relative Position Reporting Relative Position Reporting
---------------------------
In relative position mode, the ikbd will return relative mouse position In relative position mode, the ikbd will return relative mouse position
records whenever a mouse event occurs. A mouse event consists of a mouse records whenever a mouse event occurs. A mouse event consists of a mouse
@ -67,7 +78,8 @@ been 'paused' ( the event will be stored until keyboard communications is
resumed) (b) while any event is being transmitted. resumed) (b) while any event is being transmitted.
The relative mouse position record is a three byte record of the form The relative mouse position record is a three byte record of the form
(regardless of keyboard mode): (regardless of keyboard mode)::
%111110xy ; mouse position record flag %111110xy ; mouse position record flag
; where y is the right button state ; where y is the right button state
; and x is the left button state ; and x is the left button state
@ -81,13 +93,15 @@ If the accumulated motion before the report packet is generated exceeds the
Note that the sign of the delta y reported is a function of the Y origin Note that the sign of the delta y reported is a function of the Y origin
selected. selected.
4.2 Absolute Position reporting Absolute Position reporting
---------------------------
The ikbd can also maintain absolute mouse position. Commands exist for The ikbd can also maintain absolute mouse position. Commands exist for
resetting the mouse position, setting X/Y scaling, and interrogating the resetting the mouse position, setting X/Y scaling, and interrogating the
current mouse position. current mouse position.
4.3 Mouse Cursor Key Mode Mouse Cursor Key Mode
---------------------
The ikbd can translate mouse motion into the equivalent cursor keystrokes. The ikbd can translate mouse motion into the equivalent cursor keystrokes.
The number of mouse clicks per keystroke is independently programmable in The number of mouse clicks per keystroke is independently programmable in
@ -99,32 +113,38 @@ break code for the appropriate cursor key. The mouse buttons produce scan
codes above those normally assigned for the largest envisioned keyboard (i.e. codes above those normally assigned for the largest envisioned keyboard (i.e.
LEFT=0x74 & RIGHT=0x75). LEFT=0x74 & RIGHT=0x75).
5. Joystick Joystick
========
5.1 Joystick Event Reporting Joystick Event Reporting
------------------------
In this mode, the ikbd generates a record whenever the joystick position is In this mode, the ikbd generates a record whenever the joystick position is
changed (i.e. for each opening or closing of a joystick switch or trigger). changed (i.e. for each opening or closing of a joystick switch or trigger).
The joystick event record is two bytes of the form: The joystick event record is two bytes of the form::
%1111111x ; Joystick event marker %1111111x ; Joystick event marker
; where x is Joystick 0 or 1 ; where x is Joystick 0 or 1
%x000yyyy ; where yyyy is the stick position %x000yyyy ; where yyyy is the stick position
; and x is the trigger ; and x is the trigger
5.2 Joystick Interrogation Joystick Interrogation
----------------------
The current state of the joystick ports may be interrogated at any time in The current state of the joystick ports may be interrogated at any time in
this mode by sending an 'Interrogate Joystick' command to the ikbd. this mode by sending an 'Interrogate Joystick' command to the ikbd.
The ikbd response to joystick interrogation is a three byte report of the form The ikbd response to joystick interrogation is a three byte report of the form::
0xFD ; joystick report header 0xFD ; joystick report header
%x000yyyy ; Joystick 0 %x000yyyy ; Joystick 0
%x000yyyy ; Joystick 1 %x000yyyy ; Joystick 1
; where x is the trigger ; where x is the trigger
; and yyy is the stick position ; and yyy is the stick position
5.3 Joystick Monitoring Joystick Monitoring
-------------------
A mode is available that devotes nearly all of the keyboard communications A mode is available that devotes nearly all of the keyboard communications
time to reporting the state of the joystick ports at a user specifiable rate. time to reporting the state of the joystick ports at a user specifiable rate.
@ -132,7 +152,8 @@ It remains in this mode until reset or commanded into another mode. The PAUSE
command in this mode not only stop the output but also temporarily stops command in this mode not only stop the output but also temporarily stops
scanning the joysticks (samples are not queued). scanning the joysticks (samples are not queued).
5.4 Fire Button Monitoring Fire Button Monitoring
----------------------
A mode is provided to permit monitoring a single input bit at a high rate. In A mode is provided to permit monitoring a single input bit at a high rate. In
this mode the ikbd monitors the state of the Joystick 1 fire button at the this mode the ikbd monitors the state of the Joystick 1 fire button at the
@ -142,7 +163,8 @@ until reset or commanded into another mode. The PAUSE command in this mode not
only stops the output but also temporarily stops scanning the button (samples only stops the output but also temporarily stops scanning the button (samples
are not queued). are not queued).
5.5 Joystick Key Code Mode Joystick Key Code Mode
----------------------
The ikbd may be commanded to translate the use of either joystick into the The ikbd may be commanded to translate the use of either joystick into the
equivalent cursor control keystroke(s). The ikbd provides a single breakpoint equivalent cursor control keystroke(s). The ikbd provides a single breakpoint
@ -152,18 +174,21 @@ for the appropriate cursor motion keys. The trigger or fire buttons of the
joysticks produce pseudo key scan codes above those used by the largest key joysticks produce pseudo key scan codes above those used by the largest key
matrix envisioned (i.e. JOYSTICK0=0x74, JOYSTICK1=0x75). matrix envisioned (i.e. JOYSTICK0=0x74, JOYSTICK1=0x75).
6. Time-of-Day Clock Time-of-Day Clock
=================
The ikbd also maintains a time-of-day clock for the system. Commands are The ikbd also maintains a time-of-day clock for the system. Commands are
available to set and interrogate the timer-of-day clock. Time-keeping is available to set and interrogate the timer-of-day clock. Time-keeping is
maintained down to a resolution of one second. maintained down to a resolution of one second.
7. Status Inquiries Status Inquiries
================
The current state of ikbd modes and parameters may be found by sending status The current state of ikbd modes and parameters may be found by sending status
inquiry commands that correspond to the ikbd set commands. inquiry commands that correspond to the ikbd set commands.
8. Power-Up Mode Power-Up Mode
=============
The keyboard controller will perform a simple self-test on power-up to detect The keyboard controller will perform a simple self-test on power-up to detect
major controller faults (ROM checksum and RAM test) and such things as stuck major controller faults (ROM checksum and RAM test) and such things as stuck
@ -183,13 +208,17 @@ both buttons are logically connected to it. If a mouse disable command is
received while port 0 is presumed to be a mouse, the button is logically received while port 0 is presumed to be a mouse, the button is logically
assigned to Joystick1 (until the mouse is reenabled by another mouse command). assigned to Joystick1 (until the mouse is reenabled by another mouse command).
9. ikbd Command Set ikbd Command Set
================
This section contains a list of commands that can be sent to the ikbd. Command This section contains a list of commands that can be sent to the ikbd. Command
codes (such as 0x00) which are not specified should perform no operation codes (such as 0x00) which are not specified should perform no operation
(NOPs). (NOPs).
9.1 RESET RESET
-----
::
0x80 0x80
0x01 0x01
@ -208,7 +237,10 @@ ikbd will then scan the key matrix for any stuck (closed) keys. Any keys found
closed will cause the break scan code to be generated (the break code arriving closed will cause the break scan code to be generated (the break code arriving
without being preceded by the make code is a flag for a key matrix error). without being preceded by the make code is a flag for a key matrix error).
9.2. SET MOUSE BUTTON ACTION SET MOUSE BUTTON ACTION
-----------------------
::
0x07 0x07
%00000mss ; mouse button action %00000mss ; mouse button action
@ -217,14 +249,17 @@ without being preceded by the make code is a flag for a key matrix error).
; position report ; position report
; where y=1, mouse key press causes absolute report ; where y=1, mouse key press causes absolute report
; and x=1, mouse key release causes absolute report ; and x=1, mouse key release causes absolute report
; mss=100, mouse buttons act like keys ; mss=100, mouse buttons act like keys
This command sets how the ikbd should treat the buttons on the mouse. The This command sets how the ikbd should treat the buttons on the mouse. The
default mouse button action mode is %00000000, the buttons are treated as part default mouse button action mode is %00000000, the buttons are treated as part
of the mouse logically. of the mouse logically.
When buttons act like keys, LEFT=0x74 & RIGHT=0x75. When buttons act like keys, LEFT=0x74 & RIGHT=0x75.
9.3 SET RELATIVE MOUSE POSITION REPORTING SET RELATIVE MOUSE POSITION REPORTING
-------------------------------------
::
0x08 0x08
@ -235,14 +270,17 @@ key mode, mouse position reports may also be generated when either mouse
button is pressed or released. Otherwise the mouse buttons behave as if they button is pressed or released. Otherwise the mouse buttons behave as if they
were keyboard keys. were keyboard keys.
9.4 SET ABSOLUTE MOUSE POSITIONING SET ABSOLUTE MOUSE POSITIONING
------------------------------
::
0x09 0x09
XMSB ; X maximum (in scaled mouse clicks) XMSB ; X maximum (in scaled mouse clicks)
XLSB XLSB
YMSB ; Y maximum (in scaled mouse clicks) YMSB ; Y maximum (in scaled mouse clicks)
YLSB YLSB
Set absolute mouse position maintenance. Resets the ikbd maintained X and Y Set absolute mouse position maintenance. Resets the ikbd maintained X and Y
coordinates. coordinates.
In this mode, the value of the internally maintained coordinates does NOT wrap In this mode, the value of the internally maintained coordinates does NOT wrap
@ -250,7 +288,10 @@ between 0 and large positive numbers. Excess motion below 0 is ignored. The
command sets the maximum positive value that can be attained in the scaled command sets the maximum positive value that can be attained in the scaled
coordinate system. Motion beyond that value is also ignored. coordinate system. Motion beyond that value is also ignored.
9.5 SET MOUSE KEYCODE MOSE SET MOUSE KEYCODE MOSE
----------------------
::
0x0A 0x0A
deltax ; distance in X clicks to return (LEFT) or (RIGHT) deltax ; distance in X clicks to return (LEFT) or (RIGHT)
@ -263,7 +304,10 @@ either axis. When the keyboard is in key scan code mode, mouse motion will
cause the make code immediately followed by the break code. Note that this cause the make code immediately followed by the break code. Note that this
command is not affected by the mouse motion origin. command is not affected by the mouse motion origin.
9..6 SET MOUSE THRESHOLD SET MOUSE THRESHOLD
-------------------
::
0x0B 0x0B
X ; x threshold in mouse ticks (positive integers) X ; x threshold in mouse ticks (positive integers)
@ -274,7 +318,10 @@ it does NOT affect the resolution of the data returned to the host. This
command is valid only in RELATIVE MOUSE POSITIONING mode. The thresholds command is valid only in RELATIVE MOUSE POSITIONING mode. The thresholds
default to 1 at RESET (or power-up). default to 1 at RESET (or power-up).
9.7 SET MOUSE SCALE SET MOUSE SCALE
---------------
::
0x0C 0x0C
X ; horizontal mouse ticks per internal X X ; horizontal mouse ticks per internal X
@ -288,7 +335,10 @@ information is available only by interrogating the ikbd in the ABSOLUTE MOUSE
POSITIONING mode unless the ikbd has been commanded to report on button press POSITIONING mode unless the ikbd has been commanded to report on button press
or release (see SET MOSE BUTTON ACTION). or release (see SET MOSE BUTTON ACTION).
9.8 INTERROGATE MOUSE POSITION INTERROGATE MOUSE POSITION
--------------------------
::
0x0D 0x0D
Returns: Returns:
@ -306,7 +356,10 @@ or release (see SET MOSE BUTTON ACTION).
The INTERROGATE MOUSE POSITION command is valid when in the ABSOLUTE MOUSE The INTERROGATE MOUSE POSITION command is valid when in the ABSOLUTE MOUSE
POSITIONING mode, regardless of the setting of the MOUSE BUTTON ACTION. POSITIONING mode, regardless of the setting of the MOUSE BUTTON ACTION.
9.9 LOAD MOUSE POSITION LOAD MOUSE POSITION
-------------------
::
0x0E 0x0E
0x00 ; filler 0x00 ; filler
@ -318,7 +371,10 @@ POSITIONING mode, regardless of the setting of the MOUSE BUTTON ACTION.
This command allows the user to preset the internally maintained absolute This command allows the user to preset the internally maintained absolute
mouse position. mouse position.
9.10 SET Y=0 AT BOTTOM SET Y=0 AT BOTTOM
-----------------
::
0x0F 0x0F
@ -327,7 +383,10 @@ logical coordinate system internal to the ikbd for all relative or absolute
mouse motion. This causes mouse motion toward the user to be negative in sign mouse motion. This causes mouse motion toward the user to be negative in sign
and away from the user to be positive. and away from the user to be positive.
9.11 SET Y=0 AT TOP SET Y=0 AT TOP
--------------
::
0x10 0x10
@ -336,7 +395,10 @@ system within the ikbd for all relative or absolute mouse motion. (DEFAULT)
This causes mouse motion toward the user to be positive in sign and away from This causes mouse motion toward the user to be positive in sign and away from
the user to be negative. the user to be negative.
9.12 RESUME RESUME
------
::
0x11 0x11
@ -345,7 +407,10 @@ its output has been paused also causes an implicit RESUME this command can be
thought of as a NO OPERATION command. If this command is received by the ikbd thought of as a NO OPERATION command. If this command is received by the ikbd
and it is not PAUSED, it is simply ignored. and it is not PAUSED, it is simply ignored.
9.13 DISABLE MOUSE DISABLE MOUSE
-------------
::
0x12 0x12
@ -356,7 +421,10 @@ ABSOLUTE MOUSE POSITIONING, and SET MOUSE KEYCODE MODE. )
N.B. If the mouse buttons have been commanded to act like keyboard keys, this N.B. If the mouse buttons have been commanded to act like keyboard keys, this
command DOES affect their actions. command DOES affect their actions.
9.14 PAUSE OUTPUT PAUSE OUTPUT
------------
::
0x13 0x13
@ -381,21 +449,30 @@ When the ikbd is in either the JOYSTICK MONITORING mode or the FIRE BUTTON
MONITORING mode, the PAUSE OUTPUT command also temporarily stops the MONITORING mode, the PAUSE OUTPUT command also temporarily stops the
monitoring process (i.e. the samples are not enqueued for transmission). monitoring process (i.e. the samples are not enqueued for transmission).
0.15 SET JOYSTICK EVENT REPORTING SET JOYSTICK EVENT REPORTING
----------------------------
::
0x14 0x14
Enter JOYSTICK EVENT REPORTING mode (DEFAULT). Each opening or closure of a Enter JOYSTICK EVENT REPORTING mode (DEFAULT). Each opening or closure of a
joystick switch or trigger causes a joystick event record to be generated. joystick switch or trigger causes a joystick event record to be generated.
9.16 SET JOYSTICK INTERROGATION MODE SET JOYSTICK INTERROGATION MODE
-------------------------------
::
0x15 0x15
Disables JOYSTICK EVENT REPORTING. Host must send individual JOYSTICK Disables JOYSTICK EVENT REPORTING. Host must send individual JOYSTICK
INTERROGATE commands to sense joystick state. INTERROGATE commands to sense joystick state.
9.17 JOYSTICK INTERROGATE JOYSTICK INTERROGATE
--------------------
::
0x16 0x16
@ -403,7 +480,10 @@ Return a record indicating the current state of the joysticks. This command
is valid in either the JOYSTICK EVENT REPORTING mode or the JOYSTICK is valid in either the JOYSTICK EVENT REPORTING mode or the JOYSTICK
INTERROGATION MODE. INTERROGATION MODE.
9.18 SET JOYSTICK MONITORING SET JOYSTICK MONITORING
-----------------------
::
0x17 0x17
rate ; time between samples in hundredths of a second rate ; time between samples in hundredths of a second
@ -419,7 +499,10 @@ between joystick samples.
N.B. The user should not set the rate higher than the serial communications N.B. The user should not set the rate higher than the serial communications
channel will allow the 2 bytes packets to be transmitted. channel will allow the 2 bytes packets to be transmitted.
9.19 SET FIRE BUTTON MONITORING SET FIRE BUTTON MONITORING
--------------------------
::
0x18 0x18
Returns: (as long as in mode) Returns: (as long as in mode)
@ -432,7 +515,10 @@ is scanned at a rate that causes 8 samples to be made in the time it takes for
the previous byte to be sent to the host (i.e. scan rate = 8/10 * baud rate). the previous byte to be sent to the host (i.e. scan rate = 8/10 * baud rate).
The sample interval should be as constant as possible. The sample interval should be as constant as possible.
9.20 SET JOYSTICK KEYCODE MODE SET JOYSTICK KEYCODE MODE
-------------------------
::
0x19 0x19
RX ; length of time (in tenths of seconds) until RX ; length of time (in tenths of seconds) until
@ -462,7 +548,10 @@ Note that by setting RX and/or Ry to zero, the velocity feature can be
disabled. The values of TX and TY then become meaningless, and the generation disabled. The values of TX and TY then become meaningless, and the generation
of cursor 'keystrokes' is set by VX and VY. of cursor 'keystrokes' is set by VX and VY.
9.21 DISABLE JOYSTICKS DISABLE JOYSTICKS
-----------------
::
0x1A 0x1A
@ -472,7 +561,10 @@ joystick mode commands are SET JOYSTICK EVENT REPORTING, SET JOYSTICK
INTERROGATION MODE, SET JOYSTICK MONITORING, SET FIRE BUTTON MONITORING, and INTERROGATION MODE, SET JOYSTICK MONITORING, SET FIRE BUTTON MONITORING, and
SET JOYSTICK KEYCODE MODE.) SET JOYSTICK KEYCODE MODE.)
9.22 TIME-OF-DAY CLOCK SET TIME-OF-DAY CLOCK SET
---------------------
::
0x1B 0x1B
YY ; year (2 least significant digits) YY ; year (2 least significant digits)
@ -487,7 +579,10 @@ Any digit that is not a valid BCD digit should be treated as a 'don't care'
and not alter that particular field of the date or time. This permits setting and not alter that particular field of the date or time. This permits setting
only some subfields of the time-of-day clock. only some subfields of the time-of-day clock.
9.23 INTERROGATE TIME-OF-DAT CLOCK INTERROGATE TIME-OF-DAT CLOCK
-----------------------------
::
0x1C 0x1C
Returns: Returns:
@ -501,7 +596,10 @@ only some subfields of the time-of-day clock.
All time-of-day is sent in packed BCD format. All time-of-day is sent in packed BCD format.
9.24 MEMORY LOAD MEMORY LOAD
-----------
::
0x20 0x20
ADRMSB ; address in controller ADRMSB ; address in controller
@ -512,7 +610,10 @@ only some subfields of the time-of-day clock.
This command permits the host to load arbitrary values into the ikbd This command permits the host to load arbitrary values into the ikbd
controller memory. The time between data bytes must be less than 20ms. controller memory. The time between data bytes must be less than 20ms.
9.25 MEMORY READ MEMORY READ
-----------
::
0x21 0x21
ADRMSB ; address in controller ADRMSB ; address in controller
@ -524,7 +625,10 @@ controller memory. The time between data bytes must be less than 20ms.
This command permits the host to read from the ikbd controller memory. This command permits the host to read from the ikbd controller memory.
9.26 CONTROLLER EXECUTE CONTROLLER EXECUTE
------------------
::
0x22 0x22
ADRMSB ; address of subroutine in ADRMSB ; address of subroutine in
@ -533,8 +637,11 @@ This command permits the host to read from the ikbd controller memory.
This command allows the host to command the execution of a subroutine in the This command allows the host to command the execution of a subroutine in the
ikbd controller memory. ikbd controller memory.
9.27 STATUS INQUIRIES STATUS INQUIRIES
----------------
::
Status commands are formed by inclusively ORing 0x80 with the Status commands are formed by inclusively ORing 0x80 with the
relevant SET command. relevant SET command.
@ -568,7 +675,7 @@ off the status report header byte) and later send them back as commands to
ikbd to restore its state. The 0 pad bytes will be treated as NOPs by the ikbd to restore its state. The 0 pad bytes will be treated as NOPs by the
ikbd. ikbd.
Valid STATUS INQUIRY commands are: Valid STATUS INQUIRY commands are::
0x87 mouse button action 0x87 mouse button action
0x88 mouse mode 0x88 mouse mode
@ -595,14 +702,17 @@ STATUS INQUIRY commands are not valid if the ikbd is in JOYSTICK MONITORING
mode or FIRE BUTTON MONITORING mode. mode or FIRE BUTTON MONITORING mode.
10. SCAN CODES SCAN CODES
==========
The key scan codes returned by the ikbd are chosen to simplify the The key scan codes returned by the ikbd are chosen to simplify the
implementation of GSX. implementation of GSX.
GSX Standard Keyboard Mapping. GSX Standard Keyboard Mapping
======= ============
Hex Keytop Hex Keytop
======= ============
01 Esc 01 Esc
02 1 02 1
03 2 03 2
@ -614,8 +724,8 @@ Hex Keytop
09 8 09 8
0A 9 0A 9
0B 0 0B 0
0C - 0C \-
0D == 0D \=
0E BS 0E BS
0F TAB 0F TAB
10 Q 10 Q
@ -643,9 +753,9 @@ Hex Keytop
26 L 26 L
27 ; 27 ;
28 ' 28 '
29 ` 29 \`
2A (LEFT) SHIFT 2A (LEFT) SHIFT
2B \ 2B \\
2C Z 2C Z
2D X 2D X
2E C 2E C
@ -707,3 +817,4 @@ Hex Keytop
70 KEYPAD 0 70 KEYPAD 0
71 KEYPAD . 71 KEYPAD .
72 KEYPAD ENTER 72 KEYPAD ENTER
======= ============

View File

@ -1,19 +1,25 @@
.. include:: <isonum.txt>
------------------------
BCM5974 Driver (bcm5974) BCM5974 Driver (bcm5974)
------------------------ ------------------------
Copyright (C) 2008-2009 Henrik Rydberg <rydberg@euromail.se>
:Copyright: |copy| 2008-2009 Henrik Rydberg <rydberg@euromail.se>
The USB initialization and package decoding was made by Scott Shawcroft as The USB initialization and package decoding was made by Scott Shawcroft as
part of the touchd user-space driver project: part of the touchd user-space driver project:
Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
:Copyright: |copy| 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
The BCM5974 driver is based on the appletouch driver: The BCM5974 driver is based on the appletouch driver:
Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) :Copyright: |copy| 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
Copyright (C) 2005 Stelian Pop (stelian@popies.net) :Copyright: |copy| 2005 Johannes Berg (johannes@sipsolutions.net)
Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) :Copyright: |copy| 2005 Stelian Pop (stelian@popies.net)
Copyright (C) 2005 Peter Osterlund (petero2@telia.com) :Copyright: |copy| 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) :Copyright: |copy| 2005 Peter Osterlund (petero2@telia.com)
Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) :Copyright: |copy| 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
:Copyright: |copy| 2006 Nicolas Boichat (nicolas@boichat.ch)
This driver adds support for the multi-touch trackpad on the new Apple This driver adds support for the multi-touch trackpad on the new Apple
Macbook Air and Macbook Pro laptops. It replaces the appletouch driver on Macbook Air and Macbook Pro laptops. It replaces the appletouch driver on
@ -44,22 +50,21 @@ Debug output
To ease the development for new hardware version, verbose packet output can To ease the development for new hardware version, verbose packet output can
be switched on with the debug kernel module parameter. The range [1-9] be switched on with the debug kernel module parameter. The range [1-9]
yields different levels of verbosity. Example (as root): yields different levels of verbosity. Example (as root)::
echo -n 9 > /sys/module/bcm5974/parameters/debug echo -n 9 > /sys/module/bcm5974/parameters/debug
tail -f /var/log/debug tail -f /var/log/debug
echo -n 0 > /sys/module/bcm5974/parameters/debug echo -n 0 > /sys/module/bcm5974/parameters/debug
Trivia Trivia
------ ------
The driver was developed at the ubuntu forums in June 2008 [1], and now has The driver was developed at the ubuntu forums in June 2008 [#f1]_, and now has
a more permanent home at bitmath.org [2]. a more permanent home at bitmath.org [#f2]_.
Links .. Links
-----
[1] http://ubuntuforums.org/showthread.php?t=840040 .. [#f1] http://ubuntuforums.org/showthread.php?t=840040
[2] http://bitmath.org/code/ .. [#f2] http://bitmath.org/code/

View File

@ -1,30 +1,37 @@
Kernel driver for CMA3000-D0x CMA3000-D0x Accelerometer
============================ =========================
Supported chips: Supported chips:
* VTI CMA3000-D0x * VTI CMA3000-D0x
Datasheet: Datasheet:
CMA3000-D0X Product Family Specification 8281000A.02.pdf CMA3000-D0X Product Family Specification 8281000A.02.pdf
<http://www.vti.fi/en/> <http://www.vti.fi/en/>
Author: Hemanth V <hemanthv@ti.com> :Author: Hemanth V <hemanthv@ti.com>
Description Description
----------- -----------
CMA3000 Tri-axis accelerometer supports Motion detect, Measurement and CMA3000 Tri-axis accelerometer supports Motion detect, Measurement and
Free fall modes. Free fall modes.
Motion Detect Mode: Its the low power mode where interrupts are generated only Motion Detect Mode:
when motion exceeds the defined thresholds. Its the low power mode where interrupts are generated only
when motion exceeds the defined thresholds.
Measurement Mode: This mode is used to read the acceleration data on X,Y,Z Measurement Mode:
axis and supports 400, 100, 40 Hz sample frequency. This mode is used to read the acceleration data on X,Y,Z
axis and supports 400, 100, 40 Hz sample frequency.
Free fall Mode: This mode is intended to save system resources. Free fall Mode:
This mode is intended to save system resources.
Threshold values: Chip supports defining threshold values for above modes Threshold values:
which includes time and g value. Refer product specifications for more details. Chip supports defining threshold values for above modes
which includes time and g value. Refer product specifications for
more details.
CMA3000 chip supports mutually exclusive I2C and SPI interfaces for CMA3000 chip supports mutually exclusive I2C and SPI interfaces for
communication, currently the driver supports I2C based communication only. communication, currently the driver supports I2C based communication only.
@ -38,28 +45,40 @@ Platform data need to be configured for initial default values.
Platform Data Platform Data
------------- -------------
fuzz_x: Noise on X Axis
fuzz_y: Noise on Y Axis fuzz_x:
Noise on X Axis
fuzz_z: Noise on Z Axis fuzz_y:
Noise on Y Axis
g_range: G range in milli g i.e 2000 or 8000 fuzz_z:
Noise on Z Axis
mode: Default Operating mode g_range:
G range in milli g i.e 2000 or 8000
mdthr: Motion detect g range threshold value mode:
Default Operating mode
mdfftmr: Motion detect and free fall time threshold value mdthr:
Motion detect g range threshold value
ffthr: Free fall g range threshold value mdfftmr:
Motion detect and free fall time threshold value
ffthr:
Free fall g range threshold value
Input Interface Input Interface
-------------- ---------------
Input driver version is 1.0.0 Input driver version is 1.0.0
Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0 Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0
Input device name: "cma3000-accelerometer" Input device name: "cma3000-accelerometer"
Supported events:
Supported events::
Event type 0 (Sync) Event type 0 (Sync)
Event type 3 (Absolute) Event type 3 (Absolute)
Event code 0 (X) Event code 0 (X)
@ -87,7 +106,8 @@ Supported events:
Register/Platform parameters Description Register/Platform parameters Description
---------------------------------------- ----------------------------------------
mode: mode::
0: power down mode 0: power down mode
1: 100 Hz Measurement mode 1: 100 Hz Measurement mode
2: 400 Hz Measurement mode 2: 400 Hz Measurement mode
@ -97,19 +117,23 @@ mode:
6: 40 Hz Free fall mode 6: 40 Hz Free fall mode
7: Power off mode 7: Power off mode
grange: grange::
2000: 2000 mg or 2G Range 2000: 2000 mg or 2G Range
8000: 8000 mg or 8G Range 8000: 8000 mg or 8G Range
mdthr: mdthr::
X: X * 71mg (8G Range) X: X * 71mg (8G Range)
X: X * 18mg (2G Range) X: X * 18mg (2G Range)
mdfftmr: mdfftmr::
X: (X & 0x70) * 100 ms (MDTMR) X: (X & 0x70) * 100 ms (MDTMR)
(X & 0x0F) * 2.5 ms (FFTMR 400 Hz) (X & 0x0F) * 2.5 ms (FFTMR 400 Hz)
(X & 0x0F) * 10 ms (FFTMR 100 Hz) (X & 0x0F) * 10 ms (FFTMR 100 Hz)
ffthr: ffthr::
X: (X >> 2) * 18mg (2G Range) X: (X >> 2) * 18mg (2G Range)
X: (X & 0x0F) * 71 mg (8G Range) X: (X & 0x0F) * 71 mg (8G Range)

View File

@ -1,36 +1,34 @@
Preface. Crystal SoundFusion CS4610/CS4612/CS461 joystick
================================================
This is a new low-level driver to support analog joystick attached to This is a new low-level driver to support analog joystick attached to
Crystal SoundFusion CS4610/CS4612/CS4615. This code is based upon Crystal SoundFusion CS4610/CS4612/CS4615. This code is based upon
Vortex/Solo drivers as an example of decoration style, and ALSA Vortex/Solo drivers as an example of decoration style, and ALSA
0.5.8a kernel drivers as an chipset documentation and samples. 0.5.8a kernel drivers as an chipset documentation and samples.
This version does not have cooked mode support; the basic code This version does not have cooked mode support; the basic code
is present here, but have not tested completely. The button analysis is present here, but have not tested completely. The button analysis
is completed in this mode, but the axis movement is not. is completed in this mode, but the axis movement is not.
Raw mode works fine with analog joystick front-end driver and cs461x 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 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 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 play in xracer game using joystick, and the result is better than
keyboard only mode. keyboard only mode.
The sensitivity and calibrate quality have not been tested; the two The sensitivity and calibrate quality have not been tested; the two
reasons are performed: the same hardware cannot work under Win95 (blue reasons are performed: the same hardware cannot work under Win95 (blue
screen in VJOYD); I have no documentation on my chip; and the existing 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. behavior in my case was not raised the requirement of joystick calibration.
So the driver have no code to perform hardware related 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 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 or PnP ISA cards supported.
ISA and PnP ISA series.
The driver works with ALSA drivers simultaneously. For example, the xracer The driver works with ALSA drivers simultaneously. For example, the xracer
uses joystick as input device and PCM device as sound output in one time. 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 There are no sound or input collisions detected. The source code have
comments about them; but I've found the joystick can be initialized comments about them; but I've found the joystick can be initialized
separately of ALSA modules. So, you can use only one joystick driver separately of ALSA modules. So, you can use only one joystick driver
without ALSA drivers. The ALSA drivers are not needed to compile or without ALSA drivers. The ALSA drivers are not needed to compile or
run this driver. run this driver.
@ -38,7 +36,7 @@ run this driver.
There are no debug information print have been placed in source, and no There are no debug information print have been placed in source, and no
specific options required to work this driver. The found chipset parameters specific options required to work this driver. The found chipset parameters
are printed via printk(KERN_INFO "..."), see the /var/log/messages to are printed via printk(KERN_INFO "..."), see the /var/log/messages to
inspect cs461x: prefixed messages to determine possible card detection inspect cs461x: prefixed messages to determine possible card detection
errors. errors.
Regards, Regards,

View File

@ -10,9 +10,7 @@ Elantech Touchpad Driver
received from Woody at Xandros and forwarded to me received from Woody at Xandros and forwarded to me
by user StewieGriffin at the eeeuser.com forum by user StewieGriffin at the eeeuser.com forum
.. Contents
Contents
~~~~~~~~
1. Introduction 1. Introduction
2. Extra knobs 2. Extra knobs
@ -45,8 +43,8 @@ Contents
1. Introduction Introduction
~~~~~~~~~~~~ ~~~~~~~~~~~~
Currently the Linux Elantech touchpad driver is aware of four different Currently the Linux Elantech touchpad driver is aware of four different
hardware versions unimaginatively called version 1,version 2, version 3 hardware versions unimaginatively called version 1,version 2, version 3
@ -88,11 +86,8 @@ available Elantech documentation the information is provided here anyway for
completeness sake. completeness sake.
///////////////////////////////////////////////////////////////////////////// Extra knobs
~~~~~~~~~~~
2. Extra knobs
~~~~~~~~~~~
Currently the Linux Elantech touchpad driver provides three extra knobs under Currently the Linux Elantech touchpad driver provides three extra knobs under
/sys/bus/serio/drivers/psmouse/serio? for the user. /sys/bus/serio/drivers/psmouse/serio? for the user.
@ -142,18 +137,17 @@ Currently the Linux Elantech touchpad driver provides three extra knobs under
Reading the crc_enabled value will show the active value. Echoing Reading the crc_enabled value will show the active value. Echoing
"0" or "1" to this file will set the state to "0" or "1". "0" or "1" to this file will set the state to "0" or "1".
///////////////////////////////////////////////////////////////////////////// Differentiating hardware versions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3. Differentiating hardware versions To detect the hardware version, read the version number as param[0].param[1].param[2]::
=================================
To detect the hardware version, read the version number as param[0].param[1].param[2]
4 bytes version: (after the arrow is the name given in the Dell-provided driver) 4 bytes version: (after the arrow is the name given in the Dell-provided driver)
02.00.22 => EF013 02.00.22 => EF013
02.06.00 => EF019 02.06.00 => EF019
In the wild, there appear to be more versions, such as 00.01.64, 01.00.21, In the wild, there appear to be more versions, such as 00.01.64, 01.00.21,
02.00.00, 02.00.04, 02.00.06. 02.00.00, 02.00.04, 02.00.06::
6 bytes: 6 bytes:
02.00.30 => EF113 02.00.30 => EF113
@ -162,6 +156,7 @@ In the wild, there appear to be more versions, such as 00.01.64, 01.00.21,
02.0B.00 => EF215 02.0B.00 => EF215
04.01.XX => Scroll_EF051 04.01.XX => Scroll_EF051
04.02.XX => EF051 04.02.XX => EF051
In the wild, there appear to be more versions, such as 04.03.01, 04.04.11. There In the wild, there appear to be more versions, such as 04.03.01, 04.04.11. There
appears to be almost no difference, except for EF113, which does not report appears to be almost no difference, except for EF113, which does not report
pressure/width and has different data consistency checks. pressure/width and has different data consistency checks.
@ -170,21 +165,20 @@ Probably all the versions with param[0] <= 01 can be considered as
4 bytes/firmware 1. The versions < 02.08.00, with the exception of 02.00.30, as 4 bytes/firmware 1. The versions < 02.08.00, with the exception of 02.00.30, as
4 bytes/firmware 2. Everything >= 02.08.00 can be considered as 6 bytes. 4 bytes/firmware 2. Everything >= 02.08.00 can be considered as 6 bytes.
/////////////////////////////////////////////////////////////////////////////
4. Hardware version 1 Hardware version 1
================== ~~~~~~~~~~~~~~~~~~
4.1 Registers Registers
~~~~~~~~~ ---------
By echoing a hexadecimal value to a register it contents can be altered. By echoing a hexadecimal value to a register it contents can be altered.
For example: For example::
echo -n 0x16 > reg_10 echo -n 0x16 > reg_10
* reg_10 * reg_10::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
B C T D L A S E B C T D L A S E
@ -198,7 +192,7 @@ For example:
C: 1 = enable corner tap C: 1 = enable corner tap
B: 1 = swap left and right button B: 1 = swap left and right button
* reg_11 * reg_11::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
1 0 0 H V 1 F P 1 0 0 H V 1 F P
@ -208,40 +202,41 @@ For example:
V: 1 = enable vertical scroll area V: 1 = enable vertical scroll area
H: 1 = enable horizontal scroll area H: 1 = enable horizontal scroll area
* reg_20 * reg_20::
single finger width? single finger width?
* reg_21 * reg_21::
scroll area width (small: 0x40 ... wide: 0xff) scroll area width (small: 0x40 ... wide: 0xff)
* reg_22 * reg_22::
drag lock time out (short: 0x14 ... long: 0xfe; drag lock time out (short: 0x14 ... long: 0xfe;
0xff = tap again to release) 0xff = tap again to release)
* reg_23 * reg_23::
tap make timeout? tap make timeout?
* reg_24 * reg_24::
tap release timeout? tap release timeout?
* reg_25 * reg_25::
smart edge cursor speed (0x02 = slow, 0x03 = medium, 0x04 = fast) smart edge cursor speed (0x02 = slow, 0x03 = medium, 0x04 = fast)
* reg_26 * reg_26::
smart edge activation area width? smart edge activation area width?
4.2 Native relative mode 4 byte packet format Native relative mode 4 byte packet format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------------------
byte 0::
byte 0:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
c c p2 p1 1 M R L c c p2 p1 1 M R L
@ -251,20 +246,23 @@ byte 0:
p1..p2 = byte 1 and 2 odd parity bit p1..p2 = byte 1 and 2 odd parity bit
c = 1 when corner tap detected c = 1 when corner tap detected
byte 1: byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
dx7 dx6 dx5 dx4 dx3 dx2 dx1 dx0 dx7 dx6 dx5 dx4 dx3 dx2 dx1 dx0
dx7..dx0 = x movement; positive = right, negative = left dx7..dx0 = x movement; positive = right, negative = left
byte 1 = 0xf0 when corner tap detected byte 1 = 0xf0 when corner tap detected
byte 2: byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
dy7 dy6 dy5 dy4 dy3 dy2 dy1 dy0 dy7 dy6 dy5 dy4 dy3 dy2 dy1 dy0
dy7..dy0 = y movement; positive = up, negative = down dy7..dy0 = y movement; positive = up, negative = down
byte 3: byte 3::
parity checking enabled (reg_11, P = 1): parity checking enabled (reg_11, P = 1):
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
@ -296,14 +294,15 @@ byte 3:
positive = down positive = down
4.3 Native absolute mode 4 byte packet format Native absolute mode 4 byte packet format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------------------
EF013 and EF019 have a special behaviour (due to a bug in the firmware?), and EF013 and EF019 have a special behaviour (due to a bug in the firmware?), and
when 1 finger is touching, the first 2 position reports must be discarded. when 1 finger is touching, the first 2 position reports must be discarded.
This counting is reset whenever a different number of fingers is reported. This counting is reset whenever a different number of fingers is reported.
byte 0: byte 0::
firmware version 1.x: firmware version 1.x:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
@ -322,7 +321,8 @@ byte 0:
p1..p3 = byte 1..3 odd parity bit p1..p3 = byte 1..3 odd parity bit
n1..n0 = number of fingers on touchpad n1..n0 = number of fingers on touchpad
byte 1: byte 1::
firmware version 1.x: firmware version 1.x:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
@ -337,65 +337,68 @@ byte 1:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
. . . . x9 x8 y9 y8 . . . . x9 x8 y9 y8
byte 2: byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0 x7 x6 x5 x4 x3 x2 x1 x0
x9..x0 = absolute x value (horizontal) x9..x0 = absolute x value (horizontal)
byte 3: byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0
y9..y0 = absolute y value (vertical) y9..y0 = absolute y value (vertical)
///////////////////////////////////////////////////////////////////////////// Hardware version 2
~~~~~~~~~~~~~~~~~~
5. Hardware version 2 Registers
================== ---------
5.1 Registers
~~~~~~~~~
By echoing a hexadecimal value to a register it contents can be altered. By echoing a hexadecimal value to a register it contents can be altered.
For example: For example::
echo -n 0x56 > reg_10 echo -n 0x56 > reg_10
* reg_10 * reg_10::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
0 1 0 1 0 1 D 0 0 1 0 1 0 1 D 0
D: 1 = enable drag and drop D: 1 = enable drag and drop
* reg_11 * reg_11::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
1 0 0 0 S 0 1 0 1 0 0 0 S 0 1 0
S: 1 = enable vertical scroll S: 1 = enable vertical scroll
* reg_21 * reg_21::
unknown (0x00) unknown (0x00)
* reg_22 * reg_22::
drag and drop release time out (short: 0x70 ... long 0x7e; drag and drop release time out (short: 0x70 ... long 0x7e;
0x7f = never i.e. tap again to release) 0x7f = never i.e. tap again to release)
5.2 Native absolute mode 6 byte packet format Native absolute mode 6 byte packet format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------------------
5.2.1 Parity checking and packet re-synchronization
Parity checking and packet re-synchronization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There is no parity checking, however some consistency checks can be performed. There is no parity checking, however some consistency checks can be performed.
For instance for EF113: For instance for EF113::
SA1= packet[0]; SA1= packet[0];
A1 = packet[1]; A1 = packet[1];
B1 = packet[2]; B1 = packet[2];
@ -410,7 +413,8 @@ For instance for EF113:
(((SA1 & 0xC0) != 0x80) && (( C1 & 0xF0) != 0x00)) ) // check Byte 5 (((SA1 & 0xC0) != 0x80) && (( C1 & 0xF0) != 0x00)) ) // check Byte 5
// error detected // error detected
For all the other ones, there are just a few constant bits: For all the other ones, there are just a few constant bits::
if( ((packet[0] & 0x0C) != 0x04) || if( ((packet[0] & 0x0C) != 0x04) ||
((packet[3] & 0x0f) != 0x02) ) ((packet[3] & 0x0f) != 0x02) )
// error detected // error detected
@ -418,10 +422,10 @@ For all the other ones, there are just a few constant bits:
In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). In case an error is detected, all the packets are shifted by one (and packet[0] is discarded).
5.2.2 One/Three finger touch One/Three finger touch
~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^
byte 0: byte 0::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
n1 n0 w3 w2 . . R L n1 n0 w3 w2 . . R L
@ -429,19 +433,19 @@ byte 0:
L, R = 1 when Left, Right mouse button pressed L, R = 1 when Left, Right mouse button pressed
n1..n0 = number of fingers on touchpad n1..n0 = number of fingers on touchpad
byte 1: byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
p7 p6 p5 p4 x11 x10 x9 x8 p7 p6 p5 p4 x11 x10 x9 x8
byte 2: byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0 x7 x6 x5 x4 x3 x2 x1 x0
x11..x0 = absolute x value (horizontal) x11..x0 = absolute x value (horizontal)
byte 3: byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
n4 vf w1 w0 . . . b2 n4 vf w1 w0 . . . b2
@ -460,14 +464,14 @@ byte 3:
6 = Another one 6 = Another one
7 = Another one 7 = Another one
byte 4: byte 4::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
p3 p1 p2 p0 y11 y10 y9 y8 p3 p1 p2 p0 y11 y10 y9 y8
p7..p0 = pressure (not EF113) p7..p0 = pressure (not EF113)
byte 5: byte 5::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0
@ -475,15 +479,15 @@ byte 5:
y11..y0 = absolute y value (vertical) y11..y0 = absolute y value (vertical)
5.2.3 Two finger touch Two finger touch
~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^
Note that the two pairs of coordinates are not exactly the coordinates of the Note that the two pairs of coordinates are not exactly the coordinates of the
two fingers, but only the pair of the lower-left and upper-right coordinates. two fingers, but only the pair of the lower-left and upper-right coordinates.
So the actual fingers might be situated on the other diagonal of the square So the actual fingers might be situated on the other diagonal of the square
defined by these two points. defined by these two points.
byte 0: byte 0::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
n1 n0 ay8 ax8 . . R L n1 n0 ay8 ax8 . . R L
@ -491,47 +495,46 @@ byte 0:
L, R = 1 when Left, Right mouse button pressed L, R = 1 when Left, Right mouse button pressed
n1..n0 = number of fingers on touchpad n1..n0 = number of fingers on touchpad
byte 1: byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
ax8..ax0 = lower-left finger absolute x value ax8..ax0 = lower-left finger absolute x value
byte 2: byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0
ay8..ay0 = lower-left finger absolute y value ay8..ay0 = lower-left finger absolute y value
byte 3: byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
. . by8 bx8 . . . . . . by8 bx8 . . . .
byte 4: byte 4::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
bx8..bx0 = upper-right finger absolute x value bx8..bx0 = upper-right finger absolute x value
byte 5: byte 5::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
by7 by8 by5 by4 by3 by2 by1 by0 by7 by8 by5 by4 by3 by2 by1 by0
by8..by0 = upper-right finger absolute y value by8..by0 = upper-right finger absolute y value
///////////////////////////////////////////////////////////////////////////// Hardware version 3
~~~~~~~~~~~~~~~~~~
6. Hardware version 3 Registers
================== ---------
6.1 Registers * reg_10::
~~~~~~~~~
* reg_10
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
0 0 0 0 R F T A 0 0 0 0 R F T A
@ -541,8 +544,9 @@ byte 5:
F: 1 = disable ABS Position Filter F: 1 = disable ABS Position Filter
R: 1 = enable real hardware resolution R: 1 = enable real hardware resolution
6.2 Native absolute mode 6 byte packet format Native absolute mode 6 byte packet format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------------------
1 and 3 finger touch shares the same 6-byte packet format, except that 1 and 3 finger touch shares the same 6-byte packet format, except that
3 finger touch only reports the position of the center of all three fingers. 3 finger touch only reports the position of the center of all three fingers.
@ -552,19 +556,21 @@ Note on debounce:
In case the box has unstable power supply or other electricity issues, or In case the box has unstable power supply or other electricity issues, or
when number of finger changes, F/W would send "debounce packet" to inform when number of finger changes, F/W would send "debounce packet" to inform
driver that the hardware is in debounce status. driver that the hardware is in debounce status.
The debouce packet has the following signature: The debouce packet has the following signature::
byte 0: 0xc4 byte 0: 0xc4
byte 1: 0xff byte 1: 0xff
byte 2: 0xff byte 2: 0xff
byte 3: 0x02 byte 3: 0x02
byte 4: 0xff byte 4: 0xff
byte 5: 0xff byte 5: 0xff
When we encounter this kind of packet, we just ignore it. When we encounter this kind of packet, we just ignore it.
6.2.1 One/Three finger touch One/Three finger touch
~~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^
byte 0: byte 0::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
n1 n0 w3 w2 0 1 R L n1 n0 w3 w2 0 1 R L
@ -572,63 +578,63 @@ byte 0:
L, R = 1 when Left, Right mouse button pressed L, R = 1 when Left, Right mouse button pressed
n1..n0 = number of fingers on touchpad n1..n0 = number of fingers on touchpad
byte 1: byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
p7 p6 p5 p4 x11 x10 x9 x8 p7 p6 p5 p4 x11 x10 x9 x8
byte 2: byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0 x7 x6 x5 x4 x3 x2 x1 x0
x11..x0 = absolute x value (horizontal) x11..x0 = absolute x value (horizontal)
byte 3: byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
0 0 w1 w0 0 0 1 0 0 0 w1 w0 0 0 1 0
w3..w0 = width of the finger touch w3..w0 = width of the finger touch
byte 4: byte 4::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
p3 p1 p2 p0 y11 y10 y9 y8 p3 p1 p2 p0 y11 y10 y9 y8
p7..p0 = pressure p7..p0 = pressure
byte 5: byte 5::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0
y11..y0 = absolute y value (vertical) y11..y0 = absolute y value (vertical)
6.2.2 Two finger touch Two finger touch
~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^
The packet format is exactly the same for two finger touch, except the hardware The packet format is exactly the same for two finger touch, except the hardware
sends two 6 byte packets. The first packet contains data for the first finger, sends two 6 byte packets. The first packet contains data for the first finger,
the second packet has data for the second finger. So for two finger touch a the second packet has data for the second finger. So for two finger touch a
total of 12 bytes are sent. total of 12 bytes are sent.
///////////////////////////////////////////////////////////////////////////// Hardware version 4
~~~~~~~~~~~~~~~~~~
7. Hardware version 4 Registers
================== ---------
7.1 Registers * reg_07::
~~~~~~~~~
* reg_07
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 A 0 0 0 0 0 0 0 A
A: 1 = enable absolute tracking A: 1 = enable absolute tracking
7.2 Native absolute mode 6 byte packet format Native absolute mode 6 byte packet format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------------------
v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers.
Unfortunately, due to PS/2's limited bandwidth, its packet format is rather Unfortunately, due to PS/2's limited bandwidth, its packet format is rather
complex. complex.
@ -647,45 +653,49 @@ position, until we receive a status packet.
One exception is one finger touch. when a status packet tells us there is only One exception is one finger touch. when a status packet tells us there is only
one finger, the hardware would just send head packets afterwards. one finger, the hardware would just send head packets afterwards.
7.2.1 Status packet Status packet
~~~~~~~~~~~~~ ^^^^^^^^^^^^^
byte 0: byte 0::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
. . . . 0 1 R L . . . . 0 1 R L
L, R = 1 when Left, Right mouse button pressed L, R = 1 when Left, Right mouse button pressed
byte 1: byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
. . . ft4 ft3 ft2 ft1 ft0 . . . ft4 ft3 ft2 ft1 ft0
ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad
byte 2: not used byte 2::
byte 3: not used
byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
. . . 1 0 0 0 0 . . . 1 0 0 0 0
constant bits constant bits
byte 4: byte 4::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
p . . . . . . . p . . . . . . .
p = 1 for palm p = 1 for palm
byte 5: not used byte 5::
7.2.2 Head packet not used
~~~~~~~~~~~
byte 0: Head packet
^^^^^^^^^^^
byte 0::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
w3 w2 w1 w0 0 1 R L w3 w2 w1 w0 0 1 R L
@ -693,43 +703,43 @@ byte 0:
L, R = 1 when Left, Right mouse button pressed L, R = 1 when Left, Right mouse button pressed
w3..w0 = finger width (spans how many trace lines) w3..w0 = finger width (spans how many trace lines)
byte 1: byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
p7 p6 p5 p4 x11 x10 x9 x8 p7 p6 p5 p4 x11 x10 x9 x8
byte 2: byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0 x7 x6 x5 x4 x3 x2 x1 x0
x11..x0 = absolute x value (horizontal) x11..x0 = absolute x value (horizontal)
byte 3: byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
id2 id1 id0 1 0 0 0 1 id2 id1 id0 1 0 0 0 1
id2..id0 = finger id id2..id0 = finger id
byte 4: byte 4::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
p3 p1 p2 p0 y11 y10 y9 y8 p3 p1 p2 p0 y11 y10 y9 y8
p7..p0 = pressure p7..p0 = pressure
byte 5: byte 5::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0
y11..y0 = absolute y value (vertical) y11..y0 = absolute y value (vertical)
7.2.3 Motion packet Motion packet
~~~~~~~~~~~~~ ^^^^^^^^^^^^^
byte 0: byte 0::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
id2 id1 id0 w 0 1 R L id2 id1 id0 w 0 1 R L
@ -739,35 +749,35 @@ byte 0:
w = 1 when delta overflows (> 127 or < -128), in this case w = 1 when delta overflows (> 127 or < -128), in this case
firmware sends us (delta x / 5) and (delta y / 5) firmware sends us (delta x / 5) and (delta y / 5)
byte 1: byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0 x7 x6 x5 x4 x3 x2 x1 x0
x7..x0 = delta x (two's complement) x7..x0 = delta x (two's complement)
byte 2: byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0
y7..y0 = delta y (two's complement) y7..y0 = delta y (two's complement)
byte 3: byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
id2 id1 id0 1 0 0 1 0 id2 id1 id0 1 0 0 1 0
id2..id0 = finger id id2..id0 = finger id
byte 4: byte 4::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0 x7 x6 x5 x4 x3 x2 x1 x0
x7..x0 = delta x (two's complement) x7..x0 = delta x (two's complement)
byte 5: byte 5::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0
@ -778,33 +788,47 @@ byte 5:
byte 3 ~ 5 for another byte 3 ~ 5 for another
8. Trackpoint (for Hardware version 3 and 4) Trackpoint (for Hardware version 3 and 4)
========================================= ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8.1 Registers
~~~~~~~~~ Registers
---------
No special registers have been identified. No special registers have been identified.
8.2 Native relative mode 6 byte packet format Native relative mode 6 byte packet format
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------------------
8.2.1 Status Packet
~~~~~~~~~~~~~ Status Packet
^^^^^^^^^^^^^
byte 0::
byte 0:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
0 0 sx sy 0 M R L 0 0 sx sy 0 M R L
byte 1:
byte 1::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
~sx 0 0 0 0 0 0 0 ~sx 0 0 0 0 0 0 0
byte 2:
byte 2::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
~sy 0 0 0 0 0 0 0 ~sy 0 0 0 0 0 0 0
byte 3:
byte 3::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
0 0 ~sy ~sx 0 1 1 0 0 0 ~sy ~sx 0 1 1 0
byte 4:
byte 4::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x3 x2 x1 x0 x7 x6 x5 x4 x3 x2 x1 x0
byte 5:
byte 5::
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0

View File

@ -0,0 +1,103 @@
Driver for tilt-switches connected via GPIOs
============================================
Generic driver to read data from tilt switches connected via gpios.
Orientation can be provided by one or more than one tilt switches,
i.e. each tilt switch providing one axis, and the number of axes
is also not limited.
Data structures
---------------
The array of struct gpio in the gpios field is used to list the gpios
that represent the current tilt state.
The array of struct gpio_tilt_axis describes the axes that are reported
to the input system. The values set therein are used for the
input_set_abs_params calls needed to init the axes.
The array of struct gpio_tilt_state maps gpio states to the corresponding
values to report. The gpio state is represented as a bitfield where the
bit-index corresponds to the index of the gpio in the struct gpio array.
In the same manner the values stored in the axes array correspond to
the elements of the gpio_tilt_axis-array.
Example
-------
Example configuration for a single TS1003 tilt switch that rotates around
one axis in 4 steps and emits the current tilt via two GPIOs::
static int sg060_tilt_enable(struct device *dev) {
/* code to enable the sensors */
};
static void sg060_tilt_disable(struct device *dev) {
/* code to disable the sensors */
};
static struct gpio sg060_tilt_gpios[] = {
{ SG060_TILT_GPIO_SENSOR1, GPIOF_IN, "tilt_sensor1" },
{ SG060_TILT_GPIO_SENSOR2, GPIOF_IN, "tilt_sensor2" },
};
static struct gpio_tilt_state sg060_tilt_states[] = {
{
.gpios = (0 << 1) | (0 << 0),
.axes = (int[]) {
0,
},
}, {
.gpios = (0 << 1) | (1 << 0),
.axes = (int[]) {
1, /* 90 degrees */
},
}, {
.gpios = (1 << 1) | (1 << 0),
.axes = (int[]) {
2, /* 180 degrees */
},
}, {
.gpios = (1 << 1) | (0 << 0),
.axes = (int[]) {
3, /* 270 degrees */
},
},
};
static struct gpio_tilt_axis sg060_tilt_axes[] = {
{
.axis = ABS_RY,
.min = 0,
.max = 3,
.fuzz = 0,
.flat = 0,
},
};
static struct gpio_tilt_platform_data sg060_tilt_pdata= {
.gpios = sg060_tilt_gpios,
.nr_gpios = ARRAY_SIZE(sg060_tilt_gpios),
.axes = sg060_tilt_axes,
.nr_axes = ARRAY_SIZE(sg060_tilt_axes),
.states = sg060_tilt_states,
.nr_states = ARRAY_SIZE(sg060_tilt_states),
.debounce_interval = 100,
.poll_interval = 1000,
.enable = sg060_tilt_enable,
.disable = sg060_tilt_disable,
};
static struct platform_device sg060_device_tilt = {
.name = "gpio-tilt-polled",
.id = -1,
.dev = {
.platform_data = &sg060_tilt_pdata,
},
};

View File

@ -0,0 +1,381 @@
===============
Iforce Protocol
===============
:Author: Johann Deneux <johann.deneux@gmail.com>
Home page at `<http://web.archive.org/web/*/http://www.esil.univ-mrs.fr>`_
:Additions: by Vojtech Pavlik.
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: johann.deneux@gmail.com
.. warning::
I shall not be held responsible for any damage 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 parameters
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
responses 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 additional 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
~~~~~~~~~~~
.. note::
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
~~~~~~~~~~~
::
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 software seems, hum, well... buggy. In fact, data appear with a
few seconds latency. Personally, I restart it every time I play an effect.
Remember it's free (as in free beer) and alpha!
URLS
====
Check http://www.immerse.com for Immersion Studio,
and http://www.fcoder.com for ComPortSpy.
I-Force is trademark of Immersion Corp.

View File

@ -0,0 +1,19 @@
Driver-specific documentation
=============================
This section provides information about various devices supported by the
Linux kernel, their protocols, and driver details.
.. toctree::
:maxdepth: 2
:numbered:
:glob:
*
.. only:: subproject and html
Indices
=======
* :ref:`genindex`

View File

@ -0,0 +1,611 @@
.. include:: <isonum.txt>
.. _joystick-parport:
==============================
Parallel Port Joystick Drivers
==============================
:Copyright: |copy| 1998-2000 Vojtech Pavlik <vojtech@ucw.cz>
:Copyright: |copy| 1998 Andree Borrmann <a.borrmann@tu-bs.de>
Sponsored by SuSE
Disclaimer
==========
Any information in this file is provided as-is, without any guarantee that
it will be true. So, use it at your own risk. The possible damages that can
happen include burning your parallel port, and/or the sticks and joystick
and maybe even more. Like when a lightning kills you it is not our problem.
Introduction
============
The joystick parport drivers are used for joysticks and gamepads not
originally designed for PCs and other computers Linux runs on. Because of
that, PCs usually lack the right ports to connect these devices to. Parallel
port, because of its ability to change single bits at will, and providing
both output and input bits is the most suitable port on the PC for
connecting such devices.
Devices supported
=================
Many console and 8-bit computer gamepads and joysticks are supported. The
following subsections discuss usage of each.
NES and SNES
------------
The Nintendo Entertainment System and Super Nintendo Entertainment System
gamepads are widely available, and easy to get. Also, they are quite easy to
connect to a PC, and don't need much processing speed (108 us for NES and
165 us for SNES, compared to about 1000 us for PC gamepads) to communicate
with them.
All NES and SNES use the same synchronous serial protocol, clocked from
the computer's side (and thus timing insensitive). To allow up to 5 NES
and/or SNES gamepads and/or SNES mice connected to the parallel port at once,
the output lines of the parallel port are shared, while one of 5 available
input lines is assigned to each gamepad.
This protocol is handled by the gamecon.c driver, so that's the one
you'll use for NES, SNES gamepads and SNES mice.
The main problem with PC parallel ports is that they don't have +5V power
source on any of their pins. So, if you want a reliable source of power
for your pads, use either keyboard or joystick port, and make a pass-through
cable. You can also pull the power directly from the power supply (the red
wire is +5V).
If you want to use the parallel port only, you can take the power is from
some data pin. For most gamepad and parport implementations only one pin is
needed, and I'd recommend pin 9 for that, the highest data bit. On the other
hand, if you are not planning to use anything else than NES / SNES on the
port, anything between and including pin 4 and pin 9 will work::
(pin 9) -----> Power
Unfortunately, there are pads that need a lot more of power, and parallel
ports that can't give much current through the data pins. If this is your
case, you'll need to use diodes (as a prevention of destroying your parallel
port), and combine the currents of two or more data bits together::
Diodes
(pin 9) ----|>|-------+------> Power
|
(pin 8) ----|>|-------+
|
(pin 7) ----|>|-------+
|
<and so on> :
|
(pin 4) ----|>|-------+
Ground is quite easy. On PC's parallel port the ground is on any of the
pins from pin 18 to pin 25. So use any pin of these you like for the ground::
(pin 18) -----> Ground
NES and SNES pads have two input bits, Clock and Latch, which drive the
serial transfer. These are connected to pins 2 and 3 of the parallel port,
respectively::
(pin 2) -----> Clock
(pin 3) -----> Latch
And the last thing is the NES / SNES data wire. Only that isn't shared and
each pad needs its own data pin. The parallel port pins are::
(pin 10) -----> Pad 1 data
(pin 11) -----> Pad 2 data
(pin 12) -----> Pad 3 data
(pin 13) -----> Pad 4 data
(pin 15) -----> Pad 5 data
Note that pin 14 is not used, since it is not an input pin on the parallel
port.
This is everything you need on the PC's side of the connection, now on to
the gamepads side. The NES and SNES have different connectors. Also, there
are quite a lot of NES clones, and because Nintendo used proprietary
connectors for their machines, the cloners couldn't and used standard D-Cannon
connectors. Anyway, if you've got a gamepad, and it has buttons A, B, Turbo
A, Turbo B, Select and Start, and is connected through 5 wires, then it is
either a NES or NES clone and will work with this connection. SNES gamepads
also use 5 wires, but have more buttons. They will work as well, of course::
Pinout for NES gamepads Pinout for SNES gamepads and mice
+----> Power +-----------------------\
| 7 | o o o o | x x o | 1
5 +---------+ 7 +-----------------------/
| x x o \ | | | | |
| o o o o | | | | | +-> Ground
4 +------------+ 1 | | | +------------> Data
| | | | | | +---------------> Latch
| | | +-> Ground | +------------------> Clock
| | +----> Clock +---------------------> Power
| +-------> Latch
+----------> Data
Pinout for NES clone (db9) gamepads Pinout for NES clone (db15) gamepads
+---------> Clock +-----------------> Data
| +-------> Latch | +---> Ground
| | +-----> Data | |
| | | ___________________
_____________ 8 \ o x x x x x x o / 1
5 \ x o o o x / 1 \ o x x o x x o /
\ x o x o / 15 `~~~~~~~~~~~~~' 9
9 `~~~~~~~' 6 | | |
| | | | +----> Clock
| +----> Power | +----------> Latch
+--------> Ground +----------------> Power
Multisystem joysticks
---------------------
In the era of 8-bit machines, there was something like de-facto standard
for joystick ports. They were all digital, and all used D-Cannon 9 pin
connectors (db9). Because of that, a single joystick could be used without
hassle on Atari (130, 800XE, 800XL, 2600, 7200), Amiga, Commodore C64,
Amstrad CPC, Sinclair ZX Spectrum and many other machines. That's why these
joysticks are called "Multisystem".
Now their pinout::
+---------> Right
| +-------> Left
| | +-----> Down
| | | +---> Up
| | | |
_____________
5 \ x o o o o / 1
\ x o x o /
9 `~~~~~~~' 6
| |
| +----> Button
+--------> Ground
However, as time passed, extensions to this standard developed, and these
were not compatible with each other::
Atari 130, 800/XL/XE MSX
+-----------> Power
+---------> Right | +---------> Right
| +-------> Left | | +-------> Left
| | +-----> Down | | | +-----> Down
| | | +---> Up | | | | +---> Up
| | | | | | | | |
_____________ _____________
5 \ x o o o o / 1 5 \ o o o o o / 1
\ x o o o / \ o o o o /
9 `~~~~~~~' 6 9 `~~~~~~~' 6
| | | | | | |
| | +----> Button | | | +----> Button 1
| +------> Power | | +------> Button 2
+--------> Ground | +--------> Output 3
+----------> Ground
Amstrad CPC Commodore C64
+-----------> Analog Y
+---------> Right | +---------> Right
| +-------> Left | | +-------> Left
| | +-----> Down | | | +-----> Down
| | | +---> Up | | | | +---> Up
| | | | | | | | |
_____________ _____________
5 \ x o o o o / 1 5 \ o o o o o / 1
\ x o o o / \ o o o o /
9 `~~~~~~~' 6 9 `~~~~~~~' 6
| | | | | | |
| | +----> Button 1 | | | +----> Button
| +------> Button 2 | | +------> Power
+--------> Ground | +--------> Ground
+----------> Analog X
Sinclair Spectrum +2A/+3 Amiga 1200
+-----------> Up +-----------> Button 3
| +---------> Fire | +---------> Right
| | | | +-------> Left
| | +-----> Ground | | | +-----> Down
| | | | | | | +---> Up
| | | | | | | |
_____________ _____________
5 \ o o x o x / 1 5 \ o o o o o / 1
\ o o o o / \ o o o o /
9 `~~~~~~~' 6 9 `~~~~~~~' 6
| | | | | | | |
| | | +----> Right | | | +----> Button 1
| | +------> Left | | +------> Power
| +--------> Ground | +--------> Ground
+----------> Down +----------> Button 2
And there were many others.
Multisystem joysticks using db9.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For the Multisystem joysticks, and their derivatives, the db9.c driver
was written. It allows only one joystick / gamepad per parallel port, but
the interface is easy to build and works with almost anything.
For the basic 1-button Multisystem joystick you connect its wires to the
parallel port like this::
(pin 1) -----> Power
(pin 18) -----> Ground
(pin 2) -----> Up
(pin 3) -----> Down
(pin 4) -----> Left
(pin 5) -----> Right
(pin 6) -----> Button 1
However, if the joystick is switch based (eg. clicks when you move it),
you might or might not, depending on your parallel port, need 10 kOhm pullup
resistors on each of the direction and button signals, like this::
(pin 2) ------------+------> Up
Resistor |
(pin 1) --[10kOhm]--+
Try without, and if it doesn't work, add them. For TTL based joysticks /
gamepads the pullups are not needed.
For joysticks with two buttons you connect the second button to pin 7 on
the parallel port::
(pin 7) -----> Button 2
And that's it.
On a side note, if you have already built a different adapter for use with
the digital joystick driver 0.8.0.2, this is also supported by the db9.c
driver, as device type 8. (See section 3.2)
Multisystem joysticks using gamecon.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For some people just one joystick per parallel port is not enough, and/or
want to use them on one parallel port together with NES/SNES/PSX pads. This is
possible using the gamecon.c. It supports up to 5 devices of the above types,
including 1 and 2 buttons Multisystem joysticks.
However, there is nothing for free. To allow more sticks to be used at
once, you need the sticks to be purely switch based (that is non-TTL), and
not to need power. Just a plain simple six switches inside. If your
joystick can do more (eg. turbofire) you'll need to disable it totally first
if you want to use gamecon.c.
Also, the connection is a bit more complex. You'll need a bunch of diodes,
and one pullup resistor. First, you connect the Directions and the button
the same as for db9, however with the diodes between::
Diodes
(pin 2) -----|<|----> Up
(pin 3) -----|<|----> Down
(pin 4) -----|<|----> Left
(pin 5) -----|<|----> Right
(pin 6) -----|<|----> Button 1
For two button sticks you also connect the other button::
(pin 7) -----|<|----> Button 2
And finally, you connect the Ground wire of the joystick, like done in
this little schematic to Power and Data on the parallel port, as described
for the NES / SNES pads in section 2.1 of this file - that is, one data pin
for each joystick. The power source is shared::
Data ------------+-----> Ground
Resistor |
Power --[10kOhm]--+
And that's all, here we go!
Multisystem joysticks using turbografx.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The TurboGraFX interface, designed by
Steffen Schwenke <schwenke@burg-halle.de>
allows up to 7 Multisystem joysticks connected to the parallel port. In
Steffen's version, there is support for up to 5 buttons per joystick. However,
since this doesn't work reliably on all parallel ports, the turbografx.c driver
supports only one button per joystick. For more information on how to build the
interface, see:
http://www2.burg-halle.de/~schwenke/parport.html
Sony Playstation
----------------
The PSX controller is supported by the gamecon.c. Pinout of the PSX
controller (compatible with DirectPadPro)::
+---------+---------+---------+
9 | o o o | o o o | o o o | 1 parallel
\________|_________|________/ port pins
| | | | | |
| | | | | +--------> Clock --- (4)
| | | | +------------> Select --- (3)
| | | +---------------> Power --- (5-9)
| | +------------------> Ground --- (18-25)
| +-------------------------> Command --- (2)
+----------------------------> Data --- (one of 10,11,12,13,15)
The driver supports these controllers:
* Standard PSX Pad
* NegCon PSX Pad
* Analog PSX Pad (red mode)
* Analog PSX Pad (green mode)
* PSX Rumble Pad
* PSX DDR Pad
Sega
----
All the Sega controllers are more or less based on the standard 2-button
Multisystem joystick. However, since they don't use switches and use TTL
logic, the only driver usable with them is the db9.c driver.
Sega Master System
~~~~~~~~~~~~~~~~~~
The SMS gamepads are almost exactly the same as normal 2-button
Multisystem joysticks. Set the driver to Multi2 mode, use the corresponding
parallel port pins, and the following schematic::
+-----------> Power
| +---------> Right
| | +-------> Left
| | | +-----> Down
| | | | +---> Up
| | | | |
_____________
5 \ o o o o o / 1
\ o o x o /
9 `~~~~~~~' 6
| | |
| | +----> Button 1
| +--------> Ground
+----------> Button 2
Sega Genesis aka MegaDrive
~~~~~~~~~~~~~~~~~~~~~~~~~~
The Sega Genesis (in Europe sold as Sega MegaDrive) pads are an extension
to the Sega Master System pads. They use more buttons (3+1, 5+1, 6+1). Use
the following schematic::
+-----------> Power
| +---------> Right
| | +-------> Left
| | | +-----> Down
| | | | +---> Up
| | | | |
_____________
5 \ o o o o o / 1
\ o o o o /
9 `~~~~~~~' 6
| | | |
| | | +----> Button 1
| | +------> Select
| +--------> Ground
+----------> Button 2
The Select pin goes to pin 14 on the parallel port::
(pin 14) -----> Select
The rest is the same as for Multi2 joysticks using db9.c
Sega Saturn
~~~~~~~~~~~
Sega Saturn has eight buttons, and to transfer that, without hacks like
Genesis 6 pads use, it needs one more select pin. Anyway, it is still
handled by the db9.c driver. Its pinout is very different from anything
else. Use this schematic::
+-----------> Select 1
| +---------> Power
| | +-------> Up
| | | +-----> Down
| | | | +---> Ground
| | | | |
_____________
5 \ o o o o o / 1
\ o o o o /
9 `~~~~~~~' 6
| | | |
| | | +----> Select 2
| | +------> Right
| +--------> Left
+----------> Power
Select 1 is pin 14 on the parallel port, Select 2 is pin 16 on the
parallel port::
(pin 14) -----> Select 1
(pin 16) -----> Select 2
The other pins (Up, Down, Right, Left, Power, Ground) are the same as for
Multi joysticks using db9.c
Amiga CD32
----------
Amiga CD32 joypad uses the following pinout::
+-----------> Button 3
| +---------> Right
| | +-------> Left
| | | +-----> Down
| | | | +---> Up
| | | | |
_____________
5 \ o o o o o / 1
\ o o o o /
9 `~~~~~~~' 6
| | | |
| | | +----> Button 1
| | +------> Power
| +--------> Ground
+----------> Button 2
It can be connected to the parallel port and driven by db9.c driver. 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 (Button 3) 14 (AUTOFD)
6 (Button 1) 17 (SELIN)
7 (+5V) 1 (STROBE)
8 (Gnd) 18 (Gnd)
9 (Button 2) 7 (D5)
============ =============
The drivers
===========
There are three drivers for the parallel port interfaces. Each, as
described above, allows to connect a different group of joysticks and pads.
Here are described their command lines:
gamecon.c
---------
Using gamecon.c you can connect up to five devices to one parallel port. It
uses the following kernel/module command line::
gamecon.map=port,pad1,pad2,pad3,pad4,pad5
Where ``port`` the number of the parport interface (eg. 0 for parport0).
And ``pad1`` to ``pad5`` are pad types connected to different data input pins
(10,11,12,13,15), as described in section 2.1 of this file.
The types are:
===== =============================
Type Joystick/Pad
===== =============================
0 None
1 SNES pad
2 NES pad
4 Multisystem 1-button joystick
5 Multisystem 2-button joystick
6 N64 pad
7 Sony PSX controller
8 Sony PSX DDR controller
9 SNES mouse
===== =============================
The exact type of the PSX controller type is autoprobed when used, so
hot swapping should work (but is not recommended).
Should you want to use more than one of parallel ports at once, you can use
gamecon.map2 and gamecon.map3 as additional command line parameters for two
more parallel ports.
There are two options specific to PSX driver portion. gamecon.psx_delay sets
the command delay when talking to the controllers. The default of 25 should
work but you can try lowering it for better performance. If your pads don't
respond try raising it until they work. Setting the type to 8 allows the
driver to be used with Dance Dance Revolution or similar games. Arrow keys are
registered as key presses instead of X and Y axes.
db9.c
-----
Apart from making an interface, there is nothing difficult on using the
db9.c driver. It uses the following kernel/module command line::
db9.dev=port,type
Where ``port`` is the number of the parport interface (eg. 0 for parport0).
Caveat here: This driver only works on bidirectional parallel ports. If
your parallel port is recent enough, you should have no trouble with this.
Old parallel ports may not have this feature.
``Type`` is the type of joystick or pad attached:
===== ======================================================
Type Joystick/Pad
===== ======================================================
0 None
1 Multisystem 1-button joystick
2 Multisystem 2-button joystick
3 Genesis pad (3+1 buttons)
5 Genesis pad (5+1 buttons)
6 Genesis pad (6+2 buttons)
7 Saturn pad (8 buttons)
8 Multisystem 1-button joystick (v0.8.0.2 pin-out)
9 Two Multisystem 1-button joysticks (v0.8.0.2 pin-out)
10 Amiga CD32 pad
===== ======================================================
Should you want to use more than one of these joysticks/pads at once, you
can use db9.dev2 and db9.dev3 as additional command line parameters for two
more joysticks/pads.
turbografx.c
------------
The turbografx.c driver uses a very simple kernel/module command line::
turbografx.map=port,js1,js2,js3,js4,js5,js6,js7
Where ``port`` is the number of the parport interface (eg. 0 for parport0).
``jsX`` is the number of buttons the Multisystem joysticks connected to the
interface ports 1-7 have. For a standard multisystem joystick, this is 1.
Should you want to use more than one of these interfaces at once, you can
use turbografx.map2 and turbografx.map3 as additional command line parameters
for two more interfaces.
PC parallel port pinout
=======================
::
.----------------------------------------.
At the PC: \ 13 12 11 10 9 8 7 6 5 4 3 2 1 /
\ 25 24 23 22 21 20 19 18 17 16 15 14 /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
====== ======= =============
Pin Name Description
====== ======= =============
1 /STROBE Strobe
2-9 D0-D7 Data Bit 0-7
10 /ACK Acknowledge
11 BUSY Busy
12 PE Paper End
13 SELIN Select In
14 /AUTOFD Autofeed
15 /ERROR Error
16 /INIT Initialize
17 /SEL Select
18-25 GND Signal Ground
====== ======= =============
That's all, folks! Have fun!

View File

@ -1,7 +1,11 @@
.. include:: <isonum.txt>
=========================
N-Trig touchscreen Driver N-Trig touchscreen Driver
------------------------- =========================
Copyright (c) 2008-2010 Rafi Rubin <rafi@seas.upenn.edu>
Copyright (c) 2009-2010 Stephane Chatty :Copyright: |copy| 2008-2010 Rafi Rubin <rafi@seas.upenn.edu>
:Copyright: |copy| 2009-2010 Stephane Chatty
This driver provides support for N-Trig pen and multi-touch sensors. Single This driver provides support for N-Trig pen and multi-touch sensors. Single
and multi-touch events are translated to the appropriate protocols for and multi-touch events are translated to the appropriate protocols for
@ -22,16 +26,18 @@ but only for that one device.
The following parameters are used to configure filters to reduce noise: The following parameters are used to configure filters to reduce noise:
activate_slack number of fingers to ignore before processing events +-----------------------+-----------------------------------------------------+
|activate_slack |number of fingers to ignore before processing events |
activation_height size threshold to activate immediately +-----------------------+-----------------------------------------------------+
activation_width |activation_height, |size threshold to activate immediately |
|activation_width | |
min_height size threshold bellow which fingers are ignored +-----------------------+-----------------------------------------------------+
min_width both to decide activation and during activity |min_height, |size threshold bellow which fingers are ignored |
|min_width |both to decide activation and during activity |
deactivate_slack the number of "no contact" frames to ignore before +-----------------------+-----------------------------------------------------+
propagating the end of activity events |deactivate_slack |the number of "no contact" frames to ignore before |
| |propagating the end of activity events |
+-----------------------+-----------------------------------------------------+
When the last finger is removed from the device, it sends a number of empty When the last finger is removed from the device, it sends a number of empty
frames. By holding off on deactivation for a few frames we can tolerate false frames. By holding off on deactivation for a few frames we can tolerate false
@ -44,15 +50,20 @@ Additional sysfs items
---------------------- ----------------------
These nodes just provide easy access to the ranges reported by the device. These nodes just provide easy access to the ranges reported by the device.
sensor_logical_height the range for positions reported during activity
sensor_logical_width
sensor_physical_height internal ranges not used for normal events but +-----------------------+-----------------------------------------------------+
sensor_physical_width useful for tuning |sensor_logical_height, | the range for positions reported during activity |
|sensor_logical_width | |
+-----------------------+-----------------------------------------------------+
|sensor_physical_height,| internal ranges not used for normal events but |
|sensor_physical_width | useful for tuning |
+-----------------------+-----------------------------------------------------+
All N-Trig devices with product id of 1 report events in the ranges of All N-Trig devices with product id of 1 report events in the ranges of
X: 0-9600
Y: 0-7200 * X: 0-9600
* Y: 0-7200
However not all of these devices have the same physical dimensions. Most However not all of these devices have the same physical dimensions. Most
seem to be 12" sensors (Dell Latitude XT and XT2 and the HP TX2), and seem to be 12" sensors (Dell Latitude XT and XT2 and the HP TX2), and
at least one model (Dell Studio 17) has a 17" sensor. The ratio of physical at least one model (Dell Studio 17) has a 17" sensor. The ratio of physical

View File

@ -1,8 +1,11 @@
============================================================
rotary-encoder - a generic driver for GPIO connected devices rotary-encoder - a generic driver for GPIO connected devices
Daniel Mack <daniel@caiaq.de>, Feb 2009 ============================================================
0. Function :Author: Daniel Mack <daniel@caiaq.de>, Feb 2009
-----------
Function
--------
Rotary encoders are devices which are connected to the CPU or other Rotary encoders are devices which are connected to the CPU or other
peripherals with two wires. The outputs are phase-shifted by 90 degrees peripherals with two wires. The outputs are phase-shifted by 90 degrees
@ -13,7 +16,7 @@ Some encoders have both outputs low in stable states, others also have
a stable state with both outputs high (half-period mode) and some have a stable state with both outputs high (half-period mode) and some have
a stable state in all steps (quarter-period mode). a stable state in all steps (quarter-period mode).
The phase diagram of these two outputs look like this: The phase diagram of these two outputs look like this::
_____ _____ _____ _____ _____ _____
| | | | | | | | | | | |
@ -40,8 +43,8 @@ For more information, please see
https://en.wikipedia.org/wiki/Rotary_encoder https://en.wikipedia.org/wiki/Rotary_encoder
1. Events / state machine Events / state machine
------------------------- ----------------------
In half-period mode, state a) and c) above are used to determine the In half-period mode, state a) and c) above are used to determine the
rotational direction based on the last stable state. Events are reported in rotational direction based on the last stable state. Events are reported in
@ -65,62 +68,64 @@ d) Falling edge on channel B, channel A in low state
should have happened, unless it flipped back on half the way. The should have happened, unless it flipped back on half the way. The
'armed' state tells us about that. 'armed' state tells us about that.
2. Platform requirements Platform requirements
------------------------ ---------------------
As there is no hardware dependent call in this driver, the platform it is As there is no hardware dependent call in this driver, the platform it is
used with must support gpiolib. Another requirement is that IRQs must be used with must support gpiolib. Another requirement is that IRQs must be
able to fire on both edges. able to fire on both edges.
3. Board integration Board integration
-------------------- -----------------
To use this driver in your system, register a platform_device with the To use this driver in your system, register a platform_device with the
name 'rotary-encoder' and associate the IRQs and some specific platform name 'rotary-encoder' and associate the IRQs and some specific platform
data with it. data with it. Because the driver uses generic device properties, this can
be done either via device tree, ACPI, or using static board files, like in
example below:
struct rotary_encoder_platform_data is declared in ::
include/linux/rotary-encoder.h and needs to be filled with the number of
steps the encoder has and can carry information about externally inverted
signals (because of an inverting buffer or other reasons). The encoder
can be set up to deliver input information as either an absolute or relative
axes. For relative axes the input event returns +/-1 for each step. For
absolute axes the position of the encoder can either roll over between zero
and the number of steps or will clamp at the maximum and zero depending on
the configuration.
Because GPIO to IRQ mapping is platform specific, this information must /* board support file example */
be given in separately to the driver. See the example below.
---------<snip>--------- #include <linux/input.h>
#include <linux/gpio/machine.h>
#include <linux/property.h>
/* board support file example */ #define GPIO_ROTARY_A 1
#define GPIO_ROTARY_B 2
#include <linux/input.h> static struct gpiod_lookup_table rotary_encoder_gpios = {
#include <linux/rotary_encoder.h> .dev_id = "rotary-encoder.0",
.table = {
GPIO_LOOKUP_IDX("gpio-0",
GPIO_ROTARY_A, NULL, 0, GPIO_ACTIVE_LOW),
GPIO_LOOKUP_IDX("gpio-0",
GPIO_ROTARY_B, NULL, 1, GPIO_ACTIVE_HIGH),
{ },
},
};
#define GPIO_ROTARY_A 1 static const struct property_entry rotary_encoder_properties[] __initconst = {
#define GPIO_ROTARY_B 2 PROPERTY_ENTRY_INTEGER("rotary-encoder,steps-per-period", u32, 24),
PROPERTY_ENTRY_INTEGER("linux,axis", u32, ABS_X),
PROPERTY_ENTRY_INTEGER("rotary-encoder,relative_axis", u32, 0),
{ },
};
static struct rotary_encoder_platform_data my_rotary_encoder_info = { static struct platform_device rotary_encoder_device = {
.steps = 24, .name = "rotary-encoder",
.axis = ABS_X, .id = 0,
.relative_axis = false, };
.rollover = false,
.gpio_a = GPIO_ROTARY_A,
.gpio_b = GPIO_ROTARY_B,
.inverted_a = 0,
.inverted_b = 0,
.half_period = false,
.wakeup_source = false,
};
static struct platform_device rotary_encoder_device = { ...
.name = "rotary-encoder",
.id = 0,
.dev = {
.platform_data = &my_rotary_encoder_info,
}
};
gpiod_add_lookup_table(&rotary_encoder_gpios);
device_add_properties(&rotary_encoder_device, rotary_encoder_properties);
platform_device_register(&rotary_encoder_device);
...
Please consult device tree binding documentation to see all properties
supported by the driver.

View File

@ -0,0 +1,901 @@
.. include:: <isonum.txt>
=================
Sentelic Touchpad
=================
:Copyright: |copy| 2002-2011 Sentelic Corporation.
:Last update: Dec-07-2011
Finger Sensing Pad Intellimouse Mode (scrolling wheel, 4th and 5th buttons)
============================================================================
A) MSID 4: Scrolling wheel mode plus Forward page(4th button) and Backward
page (5th button)
1. Set sample rate to 200;
2. Set sample rate to 200;
3. Set sample rate to 80;
4. Issuing the "Get device ID" command (0xF2) and waits for the response;
5. FSP will respond 0x04.
::
Packet 1
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|W|W|W|W|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7 => Y overflow
Bit6 => X overflow
Bit5 => Y sign bit
Bit4 => X sign bit
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X Movement(9-bit 2's complement integers)
Byte 3: Y Movement(9-bit 2's complement integers)
Byte 4: Bit3~Bit0 => the scrolling wheel's movement since the last data report.
valid values, -8 ~ +7
Bit4 => 1 = 4th mouse button is pressed, Forward one page.
0 = 4th mouse button is not pressed.
Bit5 => 1 = 5th mouse button is pressed, Backward one page.
0 = 5th mouse button is not pressed.
B) MSID 6: Horizontal and Vertical scrolling
- Set bit 1 in register 0x40 to 1
FSP replaces scrolling wheel's movement as 4 bits to show horizontal and
vertical scrolling.
::
Packet 1
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|r|l|u|d|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7 => Y overflow
Bit6 => X overflow
Bit5 => Y sign bit
Bit4 => X sign bit
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X Movement(9-bit 2's complement integers)
Byte 3: Y Movement(9-bit 2's complement integers)
Byte 4: Bit0 => the Vertical scrolling movement downward.
Bit1 => the Vertical scrolling movement upward.
Bit2 => the Horizontal scrolling movement leftward.
Bit3 => the Horizontal scrolling movement rightward.
Bit4 => 1 = 4th mouse button is pressed, Forward one page.
0 = 4th mouse button is not pressed.
Bit5 => 1 = 5th mouse button is pressed, Backward one page.
0 = 5th mouse button is not pressed.
C) MSID 7
FSP uses 2 packets (8 Bytes) to represent Absolute Position.
so we have PACKET NUMBER to identify packets.
If PACKET NUMBER is 0, the packet is Packet 1.
If PACKET NUMBER is 1, the packet is Packet 2.
Please count this number in program.
MSID6 special packet will be enable at the same time when enable MSID 7.
Absolute position for STL3886-G0
================================
1. Set bit 2 or 3 in register 0x40 to 1
2. Set bit 6 in register 0x40 to 1
::
Packet 1 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|1|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|d|u|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => valid bit
Bit4 => 1
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll up
Bit5 => scroll down
Bit6 => scroll left
Bit7 => scroll right
Notify Packet for G0
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|0|1|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |M|M|M|M|M|M|M|M| 4 |0|0|0|0|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => 0
Bit4 => 1
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message Type => 0x5A (Enable/Disable status packet)
Mode Type => 0xA5 (Normal/Icon mode status)
Byte 3: Message Type => 0x00 (Disabled)
=> 0x01 (Enabled)
Mode Type => 0x00 (Normal)
=> 0x01 (Icon)
Byte 4: Bit7~Bit0 => Don't Care
Absolute position for STL3888-Ax
================================
::
Packet 1 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|A|1|L|0|1| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |x|x|y|y|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => arc
Bit3 => 1
Bit2 => Left Button, 1 is pressed, 0 is released.
Bit1 => 0
Bit0 => 1
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit5~Bit4 => y1_g
Bit7~Bit6 => x1_g
Packet 2 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|A|1|R|1|0| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |x|x|y|y|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => arc
Bit3 => 1
Bit2 => Right Button, 1 is pressed, 0 is released.
Bit1 => 1
Bit0 => 0
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit5~Bit4 => y2_g
Bit7~Bit6 => x2_g
Notify Packet for STL3888-Ax
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|1|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|d|u|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => 1
Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
0: left button is generated by the on-pad command
1: left button is generated by the external button
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message Type => 0xB7 (Multi Finger, Multi Coordinate mode)
Byte 3: Bit7~Bit6 => Don't care
Bit5~Bit4 => Number of fingers
Bit3~Bit1 => Reserved
Bit0 => 1: enter gesture mode; 0: leaving gesture mode
Byte 4: Bit7 => scroll right button
Bit6 => scroll left button
Bit5 => scroll down button
Bit4 => scroll up button
* Note that if gesture and additional button (Bit4~Bit7)
happen at the same time, the button information will not
be sent.
Bit3~Bit0 => Reserved
Sample sequence of Multi-finger, Multi-coordinate mode:
notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
abs pkt 2, ..., notify packet (valid bit == 0)
Absolute position for STL3888-B0
================================
::
Packet 1(ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|F|1|0|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|u|d|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => finger up/down information. 1: finger down, 0: finger up.
Bit3 => 1
Bit2 => finger index, 0 is the first finger, 1 is the second finger.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll down button
Bit5 => scroll up button
Bit6 => scroll left button
Bit7 => scroll right button
Packet 2 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|F|1|1|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|u|d|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => finger up/down information. 1: finger down, 0: finger up.
Bit3 => 1
Bit2 => finger index, 0 is the first finger, 1 is the second finger.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll down button
Bit5 => scroll up button
Bit6 => scroll left button
Bit7 => scroll right button
Notify Packet for STL3888-B0::
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|1|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|u|d|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => 1
Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
0: left button is generated by the on-pad command
1: left button is generated by the external button
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message Type => 0xB7 (Multi Finger, Multi Coordinate mode)
Byte 3: Bit7~Bit6 => Don't care
Bit5~Bit4 => Number of fingers
Bit3~Bit1 => Reserved
Bit0 => 1: enter gesture mode; 0: leaving gesture mode
Byte 4: Bit7 => scroll right button
Bit6 => scroll left button
Bit5 => scroll up button
Bit4 => scroll down button
* Note that if gesture and additional button(Bit4~Bit7)
happen at the same time, the button information will not
be sent.
Bit3~Bit0 => Reserved
Sample sequence of Multi-finger, Multi-coordinate mode:
notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
abs pkt 2, ..., notify packet (valid bit == 0)
Absolute position for STL3888-Cx and STL3888-Dx
===============================================
::
Single Finger, Absolute Coordinate Mode (SFAC)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|0|P|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|B|F|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
Bit5 => Coordinate mode(always 0 in SFAC mode):
0: single-finger absolute coordinates (SFAC) mode
1: multi-finger, multiple coordinates (MFMC) mode
Bit4 => 0: The LEFT button is generated by on-pad command (OPC)
1: The LEFT button is generated by external button
Default is 1 even if the LEFT button is not pressed.
Bit3 => Always 1, as specified by PS/2 protocol.
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => 4th mouse button(forward one page)
Bit5 => 5th mouse button(backward one page)
Bit6 => scroll left button
Bit7 => scroll right button
Multi Finger, Multiple Coordinates Mode (MFMC):
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|1|P|1|F|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|B|F|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => Coordinate mode (always 1 in MFMC mode):
0: single-finger absolute coordinates (SFAC) mode
1: multi-finger, multiple coordinates (MFMC) mode
Bit4 => 0: The LEFT button is generated by on-pad command (OPC)
1: The LEFT button is generated by external button
Default is 1 even if the LEFT button is not pressed.
Bit3 => Always 1, as specified by PS/2 protocol.
Bit2 => Finger index, 0 is the first finger, 1 is the second finger.
If bit 1 and 0 are all 1 and bit 4 is 0, the middle external
button is pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => 4th mouse button(forward one page)
Bit5 => 5th mouse button(backward one page)
Bit6 => scroll left button
Bit7 => scroll right button
When one of the two fingers is up, the device will output four consecutive
MFMC#0 report packets with zero X and Y to represent 1st finger is up or
four consecutive MFMC#1 report packets with zero X and Y to represent that
the 2nd finger is up. On the other hand, if both fingers are up, the device
will output four consecutive single-finger, absolute coordinate(SFAC) packets
with zero X and Y.
Notify Packet for STL3888-Cx/Dx::
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|0|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|u|d|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
Bit5 => Always 0
Bit4 => 0: The LEFT button is generated by on-pad command(OPC)
1: The LEFT button is generated by external button
Default is 1 even if the LEFT button is not pressed.
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message type:
0xba => gesture information
0xc0 => one finger hold-rotating gesture
Byte 3: The first parameter for the received message:
0xba => gesture ID (refer to the 'Gesture ID' section)
0xc0 => region ID
Byte 4: The second parameter for the received message:
0xba => N/A
0xc0 => finger up/down information
Sample sequence of Multi-finger, Multi-coordinates mode:
notify packet (valid bit == 1), MFMC packet 1 (byte 1, bit 2 == 0),
MFMC packet 2 (byte 1, bit 2 == 1), MFMC packet 1, MFMC packet 2,
..., notify packet (valid bit == 0)
That is, when the device is in MFMC mode, the host will receive
interleaved absolute coordinate packets for each finger.
FSP Enable/Disable packet
=========================
::
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |Y|X|0|0|1|M|R|L| 2 |0|1|0|1|1|0|1|E| 3 | | | | | | | | | 4 | | | | | | | | |
|---------------| |---------------| |---------------| |---------------|
FSP will send out enable/disable packet when FSP receive PS/2 enable/disable
command. Host will receive the packet which Middle, Right, Left button will
be set. The packet only use byte 0 and byte 1 as a pattern of original packet.
Ignore the other bytes of the packet.
Byte 1: Bit7 => 0, Y overflow
Bit6 => 0, X overflow
Bit5 => 0, Y sign bit
Bit4 => 0, X sign bit
Bit3 => 1
Bit2 => 1, Middle Button
Bit1 => 1, Right Button
Bit0 => 1, Left Button
Byte 2: Bit7~1 => (0101101b)
Bit0 => 1 = Enable
0 = Disable
Byte 3: Don't care
Byte 4: Don't care (MOUSE ID 3, 4)
Byte 5~8: Don't care (Absolute packet)
PS/2 Command Set
================
FSP supports basic PS/2 commanding set and modes, refer to following URL for
details about PS/2 commands:
http://www.computer-engineering.org/ps2mouse/
Programming Sequence for Determining Packet Parsing Flow
========================================================
1. Identify FSP by reading device ID(0x00) and version(0x01) register
2. For FSP version < STL3888 Cx, determine number of buttons by reading
the 'test mode status' (0x20) register::
buttons = reg[0x20] & 0x30
if buttons == 0x30 or buttons == 0x20:
# two/four buttons
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section A for packet parsing detail(ignore byte 4, bit ~ 7)
elif buttons == 0x10:
# 6 buttons
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section B for packet parsing detail
elif buttons == 0x00:
# 6 buttons
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section A for packet parsing detail
3. For FSP version >= STL3888 Cx:
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section A for packet parsing detail (ignore byte 4, bit ~ 7)
Programming Sequence for Register Reading/Writing
=================================================
Register inversion requirement:
Following values needed to be inverted(the '~' operator in C) before being
sent to FSP::
0xe8, 0xe9, 0xee, 0xf2, 0xf3 and 0xff.
Register swapping requirement:
Following values needed to have their higher 4 bits and lower 4 bits being
swapped before being sent to FSP::
10, 20, 40, 60, 80, 100 and 200.
Register reading sequence:
1. send 0xf3 PS/2 command to FSP;
2. send 0x66 PS/2 command to FSP;
3. send 0x88 PS/2 command to FSP;
4. send 0xf3 PS/2 command to FSP;
5. if the register address being to read is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 6
a. send 0x68 PS/2 command to FSP;
b. send the inverted register address to FSP and goto step 8;
6. if the register address being to read is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 7
a. send 0xcc PS/2 command to FSP;
b. send the swapped register address to FSP and goto step 8;
7. send 0x66 PS/2 command to FSP;
a. send the original register address to FSP and goto step 8;
8. send 0xe9(status request) PS/2 command to FSP;
9. the 4th byte of the response read from FSP should be the
requested register value(?? indicates don't care byte)::
host: 0xe9
3888: 0xfa (??) (??) (val)
* Note that since the Cx release, the hardware will return 1's
complement of the register value at the 3rd byte of status request
result::
host: 0xe9
3888: 0xfa (??) (~val) (val)
Register writing sequence:
1. send 0xf3 PS/2 command to FSP;
2. if the register address being to write is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 3
a. send 0x74 PS/2 command to FSP;
b. send the inverted register address to FSP and goto step 5;
3. if the register address being to write is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 4
a. send 0x77 PS/2 command to FSP;
b. send the swapped register address to FSP and goto step 5;
4. send 0x55 PS/2 command to FSP;
a. send the register address to FSP and goto step 5;
5. send 0xf3 PS/2 command to FSP;
6. if the register value being to write is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 7
a. send 0x47 PS/2 command to FSP;
b. send the inverted register value to FSP and goto step 9;
7. if the register value being to write is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 8
a. send 0x44 PS/2 command to FSP;
b. send the swapped register value to FSP and goto step 9;
8. send 0x33 PS/2 command to FSP;
a. send the register value to FSP;
9. the register writing sequence is completed.
* Since the Cx release, the hardware will return 1's
complement of the register value at the 3rd byte of status request
result. Host can optionally send another 0xe9 (status request) PS/2
command to FSP at the end of register writing to verify that the
register writing operation is successful (?? indicates don't care
byte)::
host: 0xe9
3888: 0xfa (??) (~val) (val)
Programming Sequence for Page Register Reading/Writing
======================================================
In order to overcome the limitation of maximum number of registers
supported, the hardware separates register into different groups called
'pages.' Each page is able to include up to 255 registers.
The default page after power up is 0x82; therefore, if one has to get
access to register 0x8301, one has to use following sequence to switch
to page 0x83, then start reading/writing from/to offset 0x01 by using
the register read/write sequence described in previous section.
Page register reading sequence:
1. send 0xf3 PS/2 command to FSP;
2. send 0x66 PS/2 command to FSP;
3. send 0x88 PS/2 command to FSP;
4. send 0xf3 PS/2 command to FSP;
5. send 0x83 PS/2 command to FSP;
6. send 0x88 PS/2 command to FSP;
7. send 0xe9(status request) PS/2 command to FSP;
8. the response read from FSP should be the requested page value.
Page register writing sequence:
1. send 0xf3 PS/2 command to FSP;
2. send 0x38 PS/2 command to FSP;
3. send 0x88 PS/2 command to FSP;
4. send 0xf3 PS/2 command to FSP;
5. if the page address being written is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 6
a. send 0x47 PS/2 command to FSP;
b. send the inverted page address to FSP and goto step 9;
6. if the page address being written is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 7
a. send 0x44 PS/2 command to FSP;
b. send the swapped page address to FSP and goto step 9;
7. send 0x33 PS/2 command to FSP;
8. send the page address to FSP;
9. the page register writing sequence is completed.
Gesture ID
==========
Unlike other devices which sends multiple fingers' coordinates to host,
FSP processes multiple fingers' coordinates internally and convert them
into a 8 bits integer, namely 'Gesture ID.' Following is a list of
supported gesture IDs:
======= ==================================
ID Description
======= ==================================
0x86 2 finger straight up
0x82 2 finger straight down
0x80 2 finger straight right
0x84 2 finger straight left
0x8f 2 finger zoom in
0x8b 2 finger zoom out
0xc0 2 finger curve, counter clockwise
0xc4 2 finger curve, clockwise
0x2e 3 finger straight up
0x2a 3 finger straight down
0x28 3 finger straight right
0x2c 3 finger straight left
0x38 palm
======= ==================================
Register Listing
================
Registers are represented in 16 bits values. The higher 8 bits represent
the page address and the lower 8 bits represent the relative offset within
that particular page. Refer to the 'Programming Sequence for Page Register
Reading/Writing' section for instructions on how to change current page
address::
offset width default r/w name
0x8200 bit7~bit0 0x01 RO device ID
0x8201 bit7~bit0 RW version ID
0xc1: STL3888 Ax
0xd0 ~ 0xd2: STL3888 Bx
0xe0 ~ 0xe1: STL3888 Cx
0xe2 ~ 0xe3: STL3888 Dx
0x8202 bit7~bit0 0x01 RO vendor ID
0x8203 bit7~bit0 0x01 RO product ID
0x8204 bit3~bit0 0x01 RW revision ID
0x820b test mode status 1
bit3 1 RO 0: rotate 180 degree
1: no rotation
*only supported by H/W prior to Cx
0x820f register file page control
bit2 0 RW 1: rotate 180 degree
0: no rotation
*supported since Cx
bit0 0 RW 1 to enable page 1 register files
*only supported by H/W prior to Cx
0x8210 RW system control 1
bit0 1 RW Reserved, must be 1
bit1 0 RW Reserved, must be 0
bit4 0 RW Reserved, must be 0
bit5 1 RW register clock gating enable
0: read only, 1: read/write enable
(Note that following registers does not require clock gating being
enabled prior to write: 05 06 07 08 09 0c 0f 10 11 12 16 17 18 23 2e
40 41 42 43. In addition to that, this bit must be 1 when gesture
mode is enabled)
0x8220 test mode status
bit5~bit4 RO number of buttons
11 => 2, lbtn/rbtn
10 => 4, lbtn/rbtn/scru/scrd
01 => 6, lbtn/rbtn/scru/scrd/scrl/scrr
00 => 6, lbtn/rbtn/scru/scrd/fbtn/bbtn
*only supported by H/W prior to Cx
0x8231 RW on-pad command detection
bit7 0 RW on-pad command left button down tag
enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8234 RW on-pad command control 5
bit4~bit0 0x05 RW XLO in 0s/4/1, so 03h = 0010.1b = 2.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
bit7 0 RW on-pad tap zone enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8235 RW on-pad command control 6
bit4~bit0 0x1d RW XHI in 0s/4/1, so 19h = 1100.1b = 12.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
0x8236 RW on-pad command control 7
bit4~bit0 0x04 RW YLO in 0s/4/1, so 03h = 0010.1b = 2.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
0x8237 RW on-pad command control 8
bit4~bit0 0x13 RW YHI in 0s/4/1, so 11h = 1000.1b = 8.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
0x8240 RW system control 5
bit1 0 RW FSP Intellimouse mode enable
0: disable, 1: enable
*only supported by H/W prior to Cx
bit2 0 RW movement + abs. coordinate mode enable
0: disable, 1: enable
(Note that this function has the functionality of bit 1 even when
bit 1 is not set. However, the format is different from that of bit 1.
In addition, when bit 1 and bit 2 are set at the same time, bit 2 will
override bit 1.)
*only supported by H/W prior to Cx
bit3 0 RW abs. coordinate only mode enable
0: disable, 1: enable
(Note that this function has the functionality of bit 1 even when
bit 1 is not set. However, the format is different from that of bit 1.
In addition, when bit 1, bit 2 and bit 3 are set at the same time,
bit 3 will override bit 1 and 2.)
*only supported by H/W prior to Cx
bit5 0 RW auto switch enable
0: disable, 1: enable
*only supported by H/W prior to Cx
bit6 0 RW G0 abs. + notify packet format enable
0: disable, 1: enable
(Note that the absolute/relative coordinate output still depends on
bit 2 and 3. That is, if any of those bit is 1, host will receive
absolute coordinates; otherwise, host only receives packets with
relative coordinate.)
*only supported by H/W prior to Cx
bit7 0 RW EN_PS2_F2: PS/2 gesture mode 2nd
finger packet enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8243 RW on-pad control
bit0 0 RW on-pad control enable
0: disable, 1: enable
(Note that if this bit is cleared, bit 3/5 will be ineffective)
*only supported by H/W prior to Cx
bit3 0 RW on-pad fix vertical scrolling enable
0: disable, 1: enable
*only supported by H/W prior to Cx
bit5 0 RW on-pad fix horizontal scrolling enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8290 RW software control register 1
bit0 0 RW absolute coordination mode
0: disable, 1: enable
*supported since Cx
bit1 0 RW gesture ID output
0: disable, 1: enable
*supported since Cx
bit2 0 RW two fingers' coordinates output
0: disable, 1: enable
*supported since Cx
bit3 0 RW finger up one packet output
0: disable, 1: enable
*supported since Cx
bit4 0 RW absolute coordination continuous mode
0: disable, 1: enable
*supported since Cx
bit6~bit5 00 RW gesture group selection
00: basic
01: suite
10: suite pro
11: advanced
*supported since Cx
bit7 0 RW Bx packet output compatible mode
0: disable, 1: enable
*supported since Cx
*supported since Cx
0x833d RW on-pad command control 1
bit7 1 RW on-pad command detection enable
0: disable, 1: enable
*supported since Cx
0x833e RW on-pad command detection
bit7 0 RW on-pad command left button down tag
enable. Works only in H/W based PS/2
data packet mode.
0: disable, 1: enable
*supported since Cx

View File

@ -1,3 +1,6 @@
===========================
Walkera WK-0701 transmitter
===========================
Walkera WK-0701 transmitter is supplied with a ready to fly Walkera Walkera WK-0701 transmitter is supplied with a ready to fly Walkera
helicopters such as HM36, HM37, HM60. The walkera0701 module enables to use helicopters such as HM36, HM37, HM60. The walkera0701 module enables to use
@ -10,7 +13,8 @@ or use cogito:
cg-clone http://zub.fei.tuke.sk/GIT/walkera0701-joystick cg-clone http://zub.fei.tuke.sk/GIT/walkera0701-joystick
Connecting to PC: Connecting to PC
================
At back side of transmitter S-video connector can be found. Modulation At back side of transmitter S-video connector can be found. Modulation
pulses from processor to HF part can be found at pin 2 of this connector, pulses from processor to HF part can be found at pin 2 of this connector,
@ -19,7 +23,8 @@ modulation pulses to PC, signal pulses must be amplified.
Cable: (walkera TX to parport) Cable: (walkera TX to parport)
Walkera WK-0701 TX S-VIDEO connector: Walkera WK-0701 TX S-VIDEO connector::
(back side of TX) (back side of TX)
__ __ S-video: canon25 __ __ S-video: canon25
/ |_| \ pin 2 (signal) NPN parport / |_| \ pin 2 (signal) NPN parport
@ -30,10 +35,10 @@ Walkera WK-0701 TX S-VIDEO connector:
------- 3 __________________________________|________________ 25 GND ------- 3 __________________________________|________________ 25 GND
E E
I use green LED and BC109 NPN transistor. I use green LED and BC109 NPN transistor.
Software: Software
========
Build kernel with walkera0701 module. Module walkera0701 need exclusive Build kernel with walkera0701 module. Module walkera0701 need exclusive
access to parport, modules like lp must be unloaded before loading access to parport, modules like lp must be unloaded before loading
@ -44,7 +49,8 @@ be changed by TX "joystick", check output from /proc/interrupts. Value for
Technical details: Technical details
=================
Driver use interrupt from parport ACK input bit to measure pulse length Driver use interrupt from parport ACK input bit to measure pulse length
using hrtimers. using hrtimers.
@ -53,17 +59,29 @@ Frame format:
Based on walkera WK-0701 PCM Format description by Shaul Eizikovich. Based on walkera WK-0701 PCM Format description by Shaul Eizikovich.
(downloaded from http://www.smartpropoplus.com/Docs/Walkera_Wk-0701_PCM.pdf) (downloaded from http://www.smartpropoplus.com/Docs/Walkera_Wk-0701_PCM.pdf)
Signal pulses: Signal pulses
(ANALOG) -------------
SYNC BIN OCT
+---------+ +------+ ::
| | | |
--+ +------+ +--- (ANALOG)
SYNC BIN OCT
+---------+ +------+
| | | |
--+ +------+ +---
Frame
-----
::
Frame:
SYNC , BIN1, OCT1, BIN2, OCT2 ... BIN24, OCT24, BIN25, next frame SYNC .. SYNC , BIN1, OCT1, BIN2, OCT2 ... BIN24, OCT24, BIN25, next frame SYNC ..
pulse length: pulse length
------------
::
Binary values: Analog octal values: Binary values: Analog octal values:
288 uS Binary 0 318 uS 000 288 uS Binary 0 318 uS 000
@ -80,7 +98,8 @@ pulse length:
(Warning, pulses on ACK are inverted by transistor, irq is raised up on sync (Warning, pulses on ACK are inverted by transistor, irq is raised up on sync
to bin change or octal value to bin change). to bin change or octal value to bin change).
Binary data representations: Binary data representations
---------------------------
One binary and octal value can be grouped to nibble. 24 nibbles + one binary One binary and octal value can be grouped to nibble. 24 nibbles + one binary
values can be sampled between sync pulses. values can be sampled between sync pulses.
@ -100,10 +119,10 @@ binary value can be sampled. This bit and magic number is not used in
software driver. Some details about this magic numbers can be found in software driver. Some details about this magic numbers can be found in
Walkera_Wk-0701_PCM.pdf. Walkera_Wk-0701_PCM.pdf.
Checksum calculation: Checksum calculation
--------------------
Summary of octal values in nibbles must be same as octal value in checksum Summary of octal values in nibbles must be same as octal value in checksum
nibble (only first 3 bits are used). Binary value for checksum nibble is nibble (only first 3 bits are used). Binary value for checksum nibble is
calculated by sum of binary values in checked nibbles + sum of octal values calculated by sum of binary values in checked nibbles + sum of octal values
in checked nibbles divided by 8. Only bit 0 of this sum is used. in checked nibbles divided by 8. Only bit 0 of this sum is used.

View File

@ -1,4 +1,6 @@
=======================================================
xpad - Linux USB driver for Xbox compatible controllers xpad - Linux USB driver for Xbox compatible controllers
=======================================================
This driver exposes all first-party and third-party Xbox compatible This driver exposes all first-party and third-party Xbox compatible
controllers. It has a long history and has enjoyed considerable usage controllers. It has a long history and has enjoyed considerable usage
@ -15,9 +17,11 @@ the Xbox One's rumble protocol has not been reverse engineered but in
the future could be supported. the future could be supported.
0. Notes Notes
-------- =====
The number of buttons/axes reported varies based on 3 things: The number of buttons/axes reported varies based on 3 things:
- if you are using a known controller - if you are using a known controller
- if you are using a known dance pad - if you are using a known dance pad
- if using an unknown device (one not listed below), what you set in the - if using an unknown device (one not listed below), what you set in the
@ -35,8 +39,9 @@ This is not true. Both dpad_to_buttons and triggers_to_buttons only affect
unknown controllers. unknown controllers.
0.1 Normal Controllers Normal Controllers
---------------------- ------------------
With a normal controller, the directional pad is mapped to its own X/Y axes. With a normal controller, the directional pad is mapped to its own X/Y axes.
The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) will report 8 The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) will report 8
axes and 10 buttons. axes and 10 buttons.
@ -55,8 +60,9 @@ in game functionality were OK. However, I find it rather difficult to
play first person shooters with a pad. Your mileage may vary. play first person shooters with a pad. Your mileage may vary.
0.2 Xbox Dance Pads Xbox Dance Pads
------------------- ---------------
When using a known dance pad, jstest will report 6 axes and 14 buttons. When using a known dance pad, jstest will report 6 axes and 14 buttons.
For dance style pads (like the redoctane pad) several changes For dance style pads (like the redoctane pad) several changes
@ -73,24 +79,21 @@ of buttons, see section 0.3 - Unknown Controllers
I've tested this with Stepmania, and it works quite well. I've tested this with Stepmania, and it works quite well.
0.3 Unknown Controllers Unknown Controllers
---------------------- -------------------
If you have an unknown xbox controller, it should work just fine with If you have an unknown xbox controller, it should work just fine with
the default settings. the default settings.
HOWEVER if you have an unknown dance pad not listed below, it will not HOWEVER if you have an unknown dance pad not listed below, it will not
work UNLESS you set "dpad_to_buttons" to 1 in the module configuration. work UNLESS you set "dpad_to_buttons" to 1 in the module configuration.
PLEASE, if you have an unknown controller, email Dom <binary1230@yahoo.com> with
a dump from /proc/bus/usb and a description of the pad (manufacturer, country,
whether it is a dance pad or normal controller) so that we can add your pad
to the list of supported devices, ensuring that it will work out of the
box in the future.
USB adapters
============
1. USB adapters
--------------
All generations of Xbox controllers speak USB over the wire. All generations of Xbox controllers speak USB over the wire.
- Original Xbox controllers use a proprietary connector and require adapters. - Original Xbox controllers use a proprietary connector and require adapters.
- Wireless Xbox 360 controllers require a 'Xbox 360 Wireless Gaming Receiver - Wireless Xbox 360 controllers require a 'Xbox 360 Wireless Gaming Receiver
for Windows' for Windows'
@ -101,8 +104,9 @@ All generations of Xbox controllers speak USB over the wire.
1.1 Original Xbox USB adapters Original Xbox USB adapters
-------------- --------------------------
Using this driver with an Original Xbox controller requires an Using this driver with an Original Xbox controller requires an
adapter cable to break out the proprietary connector's pins to USB. adapter cable to break out the proprietary connector's pins to USB.
You can buy these online fairly cheap, or build your own. You can buy these online fairly cheap, or build your own.
@ -115,7 +119,7 @@ the controller device) with the only difference in a nonstandard connector
You just need to solder a USB connector onto the cable and keep the 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 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 connectors so there is no magic to it. Detailed info on these matters
can be found on the net ([1], [2], [3]). 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 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, original one. You can buy an extension cable and cut that instead. That way,
@ -123,22 +127,46 @@ you can still use the controller with your X-Box, if you have one ;)
2. Driver Installation Driver Installation
---------------------- ===================
Once you have the adapter cable, if needed, and the controller connected Once you have the adapter cable, if needed, and the controller connected
the xpad module should be auto loaded. To confirm you can cat the xpad module should be auto loaded. To confirm you can cat
/proc/bus/usb/devices. There should be an entry like the one at the end [4]. /sys/kernel/debug/usb/devices. There should be an entry like those:
.. code-block:: none
:caption: 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
.. code-block:: none
:caption: dump from Redoctane Xbox Dance Pad (US)
T: Bus=01 Lev=02 Prnt=09 Port=00 Cnt=01 Dev#= 10 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0c12 ProdID=8809 Rev= 0.01
S: Product=XBOX DDR
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=xpad
E: Ad=82(I) Atr=03(Int.) MxPS= 32 Ivl=4ms
E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl=4ms
Supported Controllers
=====================
3. Supported Controllers
------------------------
For a full list of supported controllers and associated vendor and product For a full list of supported controllers and associated vendor and product
IDs see the xpad_device[] array[6]. IDs see the xpad_device[] array\ [4]_.
As of the historic version 0.0.6 (2006-10-10) the following devices As of the historic version 0.0.6 (2006-10-10) the following devices
were supported: were supported::
original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202 original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202
smaller Microsoft XBOX controller (US), vendor=0x045e, product=0x0289 smaller Microsoft XBOX controller (US), vendor=0x045e, product=0x0289
original Microsoft XBOX controller (Japan), vendor=0x045e, product=0x0285 original Microsoft XBOX controller (Japan), vendor=0x045e, product=0x0285
@ -152,14 +180,16 @@ the module option 'dpad_to_buttons'.
If you have an unrecognized controller please see 0.3 - Unknown Controllers If you have an unrecognized controller please see 0.3 - Unknown Controllers
4. Manual Testing Manual Testing
----------------- ==============
To test this driver's functionality you may use 'jstest'. To test this driver's functionality you may use 'jstest'.
For example: For example::
> modprobe xpad
> modprobe joydev > modprobe xpad
> jstest /dev/js0 > modprobe joydev
> jstest /dev/js0
If you're using a normal controller, there should be a single line showing If you're using a normal controller, there should be a single line showing
18 inputs (8 axes, 10 buttons), and its values should change if you move 18 inputs (8 axes, 10 buttons), and its values should change if you move
@ -170,57 +200,34 @@ It works? Voila, you're done ;)
5. Thanks Thanks
--------- ======
I have to thank ITO Takayuki for the detailed info on his site I have to thank ITO Takayuki for the detailed info on his site
http://euc.jp/periphs/xbox-controller.ja.html. http://euc.jp/periphs/xbox-controller.ja.html.
His useful info and both the usb-skeleton as well as the iforce input driver 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 (Greg Kroah-Hartmann; Vojtech Pavlik) helped a lot in rapid prototyping
the basic functionality. the basic functionality.
6. References References
------------- ==========
[1]: http://euc.jp/periphs/xbox-controller.ja.html (ITO Takayuki) .. [1] http://euc.jp/periphs/xbox-controller.ja.html (ITO Takayuki)
[2]: http://xpad.xbox-scene.com/ .. [2] http://xpad.xbox-scene.com/
[3]: http://www.markosweb.com/www/xboxhackz.com/ .. [3] http://www.markosweb.com/www/xboxhackz.com/
[4]: /proc/bus/usb/devices - dump from InterAct PowerPad Pro (Germany): .. [4] http://lxr.free-electrons.com/ident?i=xpad_device
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
[5]: /proc/bus/usb/devices - dump from Redoctane Xbox Dance Pad (US):
T: Bus=01 Lev=02 Prnt=09 Port=00 Cnt=01 Dev#= 10 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0c12 ProdID=8809 Rev= 0.01
S: Product=XBOX DDR
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=xpad
E: Ad=82(I) Atr=03(Int.) MxPS= 32 Ivl=4ms
E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl=4ms
[6]: http://lxr.free-electrons.com/ident?i=xpad_device
Historic Edits
==============
7. Historic Edits 2002-07-16 - Marko Friedemann <mfr@bmx-chemnitz.de>
-----------------
Marko Friedemann <mfr@bmx-chemnitz.de>
2002-07-16
- original doc - original doc
Dominic Cerquetti <binary1230@yahoo.com> 2005-03-19 - Dominic Cerquetti <binary1230@yahoo.com>
2005-03-19
- added stuff for dance pads, new d-pad->axes mappings - added stuff for dance pads, new d-pad->axes mappings
Later changes may be viewed with 'git log Documentation/input/xpad.txt' Later changes may be viewed with 'git log Documentation/input/xpad.txt'

View File

@ -1,8 +1,12 @@
===============================================
Driver documentation for yealink usb-p1k phones Driver documentation for yealink usb-p1k phones
===============================================
Status
======
0. Status
~~~~~~~~~
The p1k is a relatively cheap usb 1.1 phone with: The p1k is a relatively cheap usb 1.1 phone with:
- keyboard full support, yealink.ko / input event API - keyboard full support, yealink.ko / input event API
- LCD full support, yealink.ko / sysfs API - LCD full support, yealink.ko / sysfs API
- LED full support, yealink.ko / sysfs API - LED full support, yealink.ko / sysfs API
@ -14,38 +18,11 @@ The p1k is a relatively cheap usb 1.1 phone with:
For vendor documentation see http://www.yealink.com For vendor documentation see http://www.yealink.com
1. Compilation (stand alone version) keyboard features
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ =================
Currently only kernel 2.6.x.y versions are supported.
In order to build the yealink.ko module do
make
If you encounter problems please check if in the MAKE_OPTS variable in
the Makefile is pointing to the location where your kernel sources
are located, default /usr/src/linux.
1.1 Troubleshooting
~~~~~~~~~~~~~~~~~~~
Q: Module yealink compiled and installed without any problem but phone
is not initialized and does not react to any actions.
A: If you see something like:
hiddev0: USB HID v1.00 Device [Yealink Network Technology Ltd. VOIP USB Phone
in dmesg, it means that the hid driver has grabbed the device first. Try to
load module yealink before any other usb hid driver. Please see the
instructions provided by your distribution on module configuration.
Q: Phone is working now (displays version and accepts keypad input) but I can't
find the sysfs files.
A: The sysfs files are located on the particular usb endpoint. On most
distributions you can do: "find /sys/ -name get_icons" for a hint.
2. keyboard features
~~~~~~~~~~~~~~~~~~~~
The current mapping in the kernel is provided by the map_p1k_to_key The current mapping in the kernel is provided by the map_p1k_to_key
function: function::
Physical USB-P1K button layout input events Physical USB-P1K button layout input events
@ -60,14 +37,15 @@ function:
7 8 9 7, 8, 9, 7 8 9 7, 8, 9,
* 0 # *, 0, #, * 0 # *, 0, #,
The "up" and "down" keys, are symbolised by arrows on the button. The "up" and "down" keys, are symbolised by arrows on the button.
The "pickup" and "hangup" keys are symbolised by a green and red phone The "pickup" and "hangup" keys are symbolised by a green and red phone
on the button. on the button.
3. LCD features LCD features
~~~~~~~~~~~~~~~ ============
The LCD is divided and organised as a 3 line display:
The LCD is divided and organised as a 3 line display::
|[] [][] [][] [][] in |[][] |[] [][] [][] [][] in |[][]
|[] M [][] D [][] : [][] out |[][] |[] M [][] D [][] : [][] out |[][]
@ -79,18 +57,19 @@ The LCD is divided and organised as a 3 line display:
[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] []
Line 1 Format (see below) : 18.e8.M8.88...188 Line 1 Format (see below) : 18.e8.M8.88...188
Icon names : M D : IN OUT STORE Icon names : M D : IN OUT STORE
Line 2 Format : ......... Line 2 Format : .........
Icon name : NEW REP SU MO TU WE TH FR SA Icon name : NEW REP SU MO TU WE TH FR SA
Line 3 Format : 888888888888 Line 3 Format : 888888888888
Format description: Format description:
From a userspace perspective the world is separated into "digits" and "icons". From a userspace perspective the world is separated into "digits" and "icons".
A digit can have a character set, an icon can only be ON or OFF. A digit can have a character set, an icon can only be ON or OFF.
Format specifier Format specifier::
'8' : Generic 7 segment digit with individual addressable segments '8' : Generic 7 segment digit with individual addressable segments
Reduced capability 7 segment digit, when segments are hard wired together. Reduced capability 7 segment digit, when segments are hard wired together.
@ -105,9 +84,11 @@ Format description:
elements. elements.
4. Driver usage Driver usage
~~~~~~~~~~~~~~~ ============
For userland the following interfaces are available using the sysfs interface:
For userland the following interfaces are available using the sysfs interface::
/sys/.../ /sys/.../
line1 Read/Write, lcd line1 line1 Read/Write, lcd line1
line2 Read/Write, lcd line2 line2 Read/Write, lcd line2
@ -118,38 +99,43 @@ For userland the following interfaces are available using the sysfs interface:
show_icon Write, display the element by writing the icon name. show_icon Write, display the element by writing the icon name.
map_seg7 Read/Write, the 7 segments char set, common for all map_seg7 Read/Write, the 7 segments char set, common for all
yealink phones. (see map_to_7segment.h) yealink phones. (see map_to_7segment.h)
ringtone Write, upload binary representation of a ringtone, ringtone Write, upload binary representation of a ringtone,
see yealink.c. status EXPERIMENTAL due to potential see yealink.c. status EXPERIMENTAL due to potential
races between async. and sync usb calls. races between async. and sync usb calls.
4.1 lineX lineX
~~~~~~~~~ ~~~~~
Reading /sys/../lineX will return the format string with its current value:
Example: Reading /sys/../lineX will return the format string with its current value.
cat ./line3
888888888888 Example::
Linux Rocks!
cat ./line3
888888888888
Linux Rocks!
Writing to /sys/../lineX will set the corresponding LCD line. Writing to /sys/../lineX will set the corresponding LCD line.
- Excess characters are ignored. - Excess characters are ignored.
- If less characters are written than allowed, the remaining digits are - If less characters are written than allowed, the remaining digits are
unchanged. unchanged.
- The tab '\t'and '\n' char does not overwrite the original content. - The tab '\t'and '\n' char does not overwrite the original content.
- Writing a space to an icon will always hide its content. - Writing a space to an icon will always hide its content.
Example: Example::
date +"%m.%e.%k:%M" | sed 's/^0/ /' > ./line1
date +"%m.%e.%k:%M" | sed 's/^0/ /' > ./line1
Will update the LCD with the current date & time. Will update the LCD with the current date & time.
4.2 get_icons get_icons
~~~~~~~~~~~~~ ~~~~~~~~~
Reading will return all available icon names and its current settings:
Reading will return all available icon names and its current settings::
cat ./get_icons cat ./get_icons
on M on M
@ -172,45 +158,68 @@ Reading will return all available icon names and its current settings:
RINGTONE RINGTONE
4.3 show/hide icons show/hide icons
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
Writing to these files will update the state of the icon. Writing to these files will update the state of the icon.
Only one icon at a time can be updated. Only one icon at a time can be updated.
If an icon is also on a ./lineX the corresponding value is If an icon is also on a ./lineX the corresponding value is
updated with the first letter of the icon. updated with the first letter of the icon.
Example - light up the store icon: Example - light up the store icon::
echo -n "STORE" > ./show_icon
cat ./line1 echo -n "STORE" > ./show_icon
18.e8.M8.88...188
S
Example - sound the ringtone for 10 seconds: cat ./line1
echo -n RINGTONE > /sys/..../show_icon 18.e8.M8.88...188
sleep 10 S
echo -n RINGTONE > /sys/..../hide_icon
Example - sound the ringtone for 10 seconds::
echo -n RINGTONE > /sys/..../show_icon
sleep 10
echo -n RINGTONE > /sys/..../hide_icon
5. Sound features Sound features
~~~~~~~~~~~~~~~~~ ==============
Sound is supported by the ALSA driver: snd_usb_audio Sound is supported by the ALSA driver: snd_usb_audio
One 16-bit channel with sample and playback rates of 8000 Hz is the practical One 16-bit channel with sample and playback rates of 8000 Hz is the practical
limit of the device. limit of the device.
Example - recording test: Example - recording test::
arecord -v -d 10 -r 8000 -f S16_LE -t wav foobar.wav
Example - playback test: arecord -v -d 10 -r 8000 -f S16_LE -t wav foobar.wav
aplay foobar.wav
Example - playback test::
aplay foobar.wav
6. Credits & Acknowledgments Troubleshooting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ===============
:Q: Module yealink compiled and installed without any problem but phone
is not initialized and does not react to any actions.
:A: If you see something like:
hiddev0: USB HID v1.00 Device [Yealink Network Technology Ltd. VOIP USB Phone
in dmesg, it means that the hid driver has grabbed the device first. Try to
load module yealink before any other usb hid driver. Please see the
instructions provided by your distribution on module configuration.
:Q: Phone is working now (displays version and accepts keypad input) but I can't
find the sysfs files.
:A: The sysfs files are located on the particular usb endpoint. On most
distributions you can do: "find /sys/ -name get_icons" for a hint.
Credits & Acknowledgments
=========================
- Olivier Vandorpe, for starting the usbb2k-api project doing much of - Olivier Vandorpe, for starting the usbb2k-api project doing much of
the reverse engineering. the reverse engineering.
- Martin Diehl, for pointing out how to handle USB memory allocation. - Martin Diehl, for pointing out how to handle USB memory allocation.
- Dmitry Torokhov, for the numerous code reviews and suggestions. - Dmitry Torokhov, for the numerous code reviews and suggestions.

View File

@ -1,3 +1,10 @@
.. _input-event-codes:
=================
Input event codes
=================
The input protocol uses a map of types and codes to express input device values The input protocol uses a map of types and codes to express input device values
to userspace. This document describes the types and codes and how and when they to userspace. This document describes the types and codes and how and when they
may be used. may be used.
@ -17,82 +24,102 @@ reports supported by a device are also provided by sysfs in
class/input/event*/device/capabilities/, and the properties of a device are class/input/event*/device/capabilities/, and the properties of a device are
provided in class/input/event*/device/properties. provided in class/input/event*/device/properties.
Event types: Event types
=========== ===========
Event types are groupings of codes under a logical input construct. Each Event types are groupings of codes under a logical input construct. Each
type has a set of applicable codes to be used in generating events. See the type has a set of applicable codes to be used in generating events. See the
Codes section for details on valid codes for each type. Codes section for details on valid codes for each type.
* EV_SYN: * EV_SYN:
- Used as markers to separate events. Events may be separated in time or in - Used as markers to separate events. Events may be separated in time or in
space, such as with the multitouch protocol. space, such as with the multitouch protocol.
* EV_KEY: * EV_KEY:
- Used to describe state changes of keyboards, buttons, or other key-like - Used to describe state changes of keyboards, buttons, or other key-like
devices. devices.
* EV_REL: * EV_REL:
- Used to describe relative axis value changes, e.g. moving the mouse 5 units - Used to describe relative axis value changes, e.g. moving the mouse 5 units
to the left. to the left.
* EV_ABS: * EV_ABS:
- Used to describe absolute axis value changes, e.g. describing the - Used to describe absolute axis value changes, e.g. describing the
coordinates of a touch on a touchscreen. coordinates of a touch on a touchscreen.
* EV_MSC: * EV_MSC:
- Used to describe miscellaneous input data that do not fit into other types. - Used to describe miscellaneous input data that do not fit into other types.
* EV_SW: * EV_SW:
- Used to describe binary state input switches. - Used to describe binary state input switches.
* EV_LED: * EV_LED:
- Used to turn LEDs on devices on and off. - Used to turn LEDs on devices on and off.
* EV_SND: * EV_SND:
- Used to output sound to devices. - Used to output sound to devices.
* EV_REP: * EV_REP:
- Used for autorepeating devices. - Used for autorepeating devices.
* EV_FF: * EV_FF:
- Used to send force feedback commands to an input device. - Used to send force feedback commands to an input device.
* EV_PWR: * EV_PWR:
- A special type for power button and switch input. - A special type for power button and switch input.
* EV_FF_STATUS: * EV_FF_STATUS:
- Used to receive force feedback device status. - Used to receive force feedback device status.
Event codes: Event codes
=========== ===========
Event codes define the precise type of event. Event codes define the precise type of event.
EV_SYN: EV_SYN
---------- ------
EV_SYN event values are undefined. Their usage is defined only by when they are EV_SYN event values are undefined. Their usage is defined only by when they are
sent in the evdev event stream. sent in the evdev event stream.
* SYN_REPORT: * SYN_REPORT:
- Used to synchronize and separate events into packets of input data changes - Used to synchronize and separate events into packets of input data changes
occurring at the same moment in time. For example, motion of a mouse may set occurring at the same moment in time. For example, motion of a mouse may set
the REL_X and REL_Y values for one motion, then emit a SYN_REPORT. The next the REL_X and REL_Y values for one motion, then emit a SYN_REPORT. The next
motion will emit more REL_X and REL_Y values and send another SYN_REPORT. motion will emit more REL_X and REL_Y values and send another SYN_REPORT.
* SYN_CONFIG: * SYN_CONFIG:
- TBD - TBD
* SYN_MT_REPORT: * SYN_MT_REPORT:
- Used to synchronize and separate touch events. See the - Used to synchronize and separate touch events. See the
multi-touch-protocol.txt document for more information. multi-touch-protocol.txt document for more information.
* SYN_DROPPED: * SYN_DROPPED:
- Used to indicate buffer overrun in the evdev client's event queue. - Used to indicate buffer overrun in the evdev client's event queue.
Client should ignore all events up to and including next SYN_REPORT Client should ignore all events up to and including next SYN_REPORT
event and query the device (using EVIOCG* ioctls) to obtain its event and query the device (using EVIOCG* ioctls) to obtain its
current state. current state.
EV_KEY: EV_KEY
---------- ------
EV_KEY events take the form KEY_<name> or BTN_<name>. For example, KEY_A is used EV_KEY events take the form KEY_<name> or BTN_<name>. For example, KEY_A is used
to represent the 'A' key on a keyboard. When a key is depressed, an event with to represent the 'A' key on a keyboard. When a key is depressed, an event with
the key's code is emitted with value 1. When the key is released, an event is the key's code is emitted with value 1. When the key is released, an event is
@ -103,6 +130,7 @@ BTN_<name> is used for other types of momentary switch events.
A few EV_KEY codes have special meanings: A few EV_KEY codes have special meanings:
* BTN_TOOL_<name>: * BTN_TOOL_<name>:
- These codes are used in conjunction with input trackpads, tablets, and - These codes are used in conjunction with input trackpads, tablets, and
touchscreens. These devices may be used with fingers, pens, or other tools. touchscreens. These devices may be used with fingers, pens, or other tools.
When an event occurs and a tool is used, the corresponding BTN_TOOL_<name> When an event occurs and a tool is used, the corresponding BTN_TOOL_<name>
@ -112,6 +140,7 @@ A few EV_KEY codes have special meanings:
code when events are generated. code when events are generated.
* BTN_TOUCH: * BTN_TOUCH:
BTN_TOUCH is used for touch contact. While an input tool is determined to be BTN_TOUCH is used for touch contact. While an input tool is determined to be
within meaningful physical contact, the value of this property must be set within meaningful physical contact, the value of this property must be set
to 1. Meaningful physical contact may mean any contact, or it may mean to 1. Meaningful physical contact may mean any contact, or it may mean
@ -132,6 +161,7 @@ future, this distinction will be deprecated and the device properties ioctl
EVIOCGPROP, defined in linux/input.h, will be used to convey the device type. EVIOCGPROP, defined in linux/input.h, will be used to convey the device type.
* BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP: * BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP:
- These codes denote one, two, three, and four finger interaction on a - These codes denote one, two, three, and four finger interaction on a
trackpad or touchscreen. For example, if the user uses two fingers and moves trackpad or touchscreen. For example, if the user uses two fingers and moves
them on the touchpad in an effort to scroll content on screen, them on the touchpad in an effort to scroll content on screen,
@ -147,8 +177,9 @@ a value of 1 in the same synchronization frame. This usage is deprecated.
Note: In multitouch drivers, the input_mt_report_finger_count() function should Note: In multitouch drivers, the input_mt_report_finger_count() function should
be used to emit these codes. Please see multi-touch-protocol.txt for details. be used to emit these codes. Please see multi-touch-protocol.txt for details.
EV_REL: EV_REL
---------- ------
EV_REL events describe relative changes in a property. For example, a mouse may EV_REL events describe relative changes in a property. For example, a mouse may
move to the left by a certain number of units, but its absolute position in move to the left by a certain number of units, but its absolute position in
space is unknown. If the absolute position is known, EV_ABS codes should be used space is unknown. If the absolute position is known, EV_ABS codes should be used
@ -157,17 +188,20 @@ instead of EV_REL codes.
A few EV_REL codes have special meanings: A few EV_REL codes have special meanings:
* REL_WHEEL, REL_HWHEEL: * REL_WHEEL, REL_HWHEEL:
- These codes are used for vertical and horizontal scroll wheels, - These codes are used for vertical and horizontal scroll wheels,
respectively. respectively.
EV_ABS: EV_ABS
---------- ------
EV_ABS events describe absolute changes in a property. For example, a touchpad EV_ABS events describe absolute changes in a property. For example, a touchpad
may emit coordinates for a touch location. may emit coordinates for a touch location.
A few EV_ABS codes have special meanings: A few EV_ABS codes have special meanings:
* ABS_DISTANCE: * ABS_DISTANCE:
- Used to describe the distance of a tool from an interaction surface. This - Used to describe the distance of a tool from an interaction surface. This
event should only be emitted while the tool is hovering, meaning in close event should only be emitted while the tool is hovering, meaning in close
proximity of the device and while the value of the BTN_TOUCH code is 0. If proximity of the device and while the value of the BTN_TOUCH code is 0. If
@ -179,11 +213,13 @@ A few EV_ABS codes have special meanings:
hardware and is otherwise independent of ABS_DISTANCE and/or BTN_TOUCH. hardware and is otherwise independent of ABS_DISTANCE and/or BTN_TOUCH.
* ABS_MT_<name>: * ABS_MT_<name>:
- Used to describe multitouch input events. Please see - Used to describe multitouch input events. Please see
multi-touch-protocol.txt for details. multi-touch-protocol.txt for details.
EV_SW: EV_SW
---------- -----
EV_SW events describe stateful binary switches. For example, the SW_LID code is EV_SW events describe stateful binary switches. For example, the SW_LID code is
used to denote when a laptop lid is closed. used to denote when a laptop lid is closed.
@ -195,14 +231,16 @@ Upon resume, if the switch state is the same as before suspend, then the input
subsystem will filter out the duplicate switch state reports. The driver does subsystem will filter out the duplicate switch state reports. The driver does
not need to keep the state of the switch at any time. not need to keep the state of the switch at any time.
EV_MSC: EV_MSC
---------- ------
EV_MSC events are used for input and output events that do not fall under other EV_MSC events are used for input and output events that do not fall under other
categories. categories.
A few EV_MSC codes have special meaning: A few EV_MSC codes have special meaning:
* MSC_TIMESTAMP: * MSC_TIMESTAMP:
- Used to report the number of microseconds since the last reset. This event - Used to report the number of microseconds since the last reset. This event
should be coded as an uint32 value, which is allowed to wrap around with should be coded as an uint32 value, which is allowed to wrap around with
no special consequence. It is assumed that the time difference between two no special consequence. It is assumed that the time difference between two
@ -211,39 +249,46 @@ A few EV_MSC codes have special meaning:
unknown. If the device does not provide this information, the driver must unknown. If the device does not provide this information, the driver must
not provide it to user space. not provide it to user space.
EV_LED: EV_LED
---------- ------
EV_LED events are used for input and output to set and query the state of EV_LED events are used for input and output to set and query the state of
various LEDs on devices. various LEDs on devices.
EV_REP: EV_REP
---------- ------
EV_REP events are used for specifying autorepeating events. EV_REP events are used for specifying autorepeating events.
EV_SND: EV_SND
---------- ------
EV_SND events are used for sending sound commands to simple sound output EV_SND events are used for sending sound commands to simple sound output
devices. devices.
EV_FF: EV_FF
---------- -----
EV_FF events are used to initialize a force feedback capable device and to cause EV_FF events are used to initialize a force feedback capable device and to cause
such device to feedback. such device to feedback.
EV_PWR: EV_PWR
---------- ------
EV_PWR events are a special type of event used specifically for power EV_PWR events are a special type of event used specifically for power
management. Its usage is not well defined. To be addressed later. management. Its usage is not well defined. To be addressed later.
Device properties: Device properties
================= =================
Normally, userspace sets up an input device based on the data it emits, Normally, userspace sets up an input device based on the data it emits,
i.e., the event types. In the case of two devices emitting the same event i.e., the event types. In the case of two devices emitting the same event
types, additional information can be provided in the form of device types, additional information can be provided in the form of device
properties. properties.
INPUT_PROP_DIRECT + INPUT_PROP_POINTER: INPUT_PROP_DIRECT + INPUT_PROP_POINTER
-------------------------------------- --------------------------------------
The INPUT_PROP_DIRECT property indicates that device coordinates should be The INPUT_PROP_DIRECT property indicates that device coordinates should be
directly mapped to screen coordinates (not taking into account trivial directly mapped to screen coordinates (not taking into account trivial
transformations, such as scaling, flipping and rotating). Non-direct input transformations, such as scaling, flipping and rotating). Non-direct input
@ -260,8 +305,9 @@ If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is
considered undefined and the device type should be deduced in the considered undefined and the device type should be deduced in the
traditional way, using emitted event types. traditional way, using emitted event types.
INPUT_PROP_BUTTONPAD: INPUT_PROP_BUTTONPAD
-------------------- --------------------
For touchpads where the button is placed beneath the surface, such that For touchpads where the button is placed beneath the surface, such that
pressing down on the pad causes a button click, this property should be pressing down on the pad causes a button click, this property should be
set. Common in clickpad notebooks and macbooks from 2009 and onwards. set. Common in clickpad notebooks and macbooks from 2009 and onwards.
@ -270,8 +316,9 @@ Originally, the buttonpad property was coded into the bcm5974 driver
version field under the name integrated button. For backwards version field under the name integrated button. For backwards
compatibility, both methods need to be checked in userspace. compatibility, both methods need to be checked in userspace.
INPUT_PROP_SEMI_MT: INPUT_PROP_SEMI_MT
------------------ ------------------
Some touchpads, most common between 2008 and 2011, can detect the presence Some touchpads, most common between 2008 and 2011, can detect the presence
of multiple contacts without resolving the individual positions; only the of multiple contacts without resolving the individual positions; only the
number of contacts and a rectangular shape is known. For such number of contacts and a rectangular shape is known. For such
@ -285,9 +332,10 @@ gestures can normally be extracted from it.
If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT
device. device.
INPUT_PROP_TOPBUTTONPAD: INPUT_PROP_TOPBUTTONPAD
----------------------- -----------------------
Some laptops, most notably the Lenovo *40 series provide a trackstick
Some laptops, most notably the Lenovo 40 series provide a trackstick
device but do not have physical buttons associated with the trackstick device but do not have physical buttons associated with the trackstick
device. Instead, the top area of the touchpad is marked to show device. Instead, the top area of the touchpad is marked to show
visual/haptic areas for left, middle, right buttons intended to be used visual/haptic areas for left, middle, right buttons intended to be used
@ -299,7 +347,8 @@ The kernel does not provide button emulation for such devices but treats
them as any other INPUT_PROP_BUTTONPAD device. them as any other INPUT_PROP_BUTTONPAD device.
INPUT_PROP_ACCELEROMETER INPUT_PROP_ACCELEROMETER
------------------------- ------------------------
Directional axes on this device (absolute and/or relative x, y, z) represent Directional axes on this device (absolute and/or relative x, y, z) represent
accelerometer data. Some devices also report gyroscope data, which devices accelerometer data. Some devices also report gyroscope data, which devices
can report through the rotational axes (absolute and/or relative rx, ry, rz). can report through the rotational axes (absolute and/or relative rx, ry, rz).
@ -307,21 +356,24 @@ can report through the rotational axes (absolute and/or relative rx, ry, rz).
All other axes retain their meaning. A device must not mix All other axes retain their meaning. A device must not mix
regular directional axes and accelerometer axes on the same event node. regular directional axes and accelerometer axes on the same event node.
Guidelines: Guidelines
========== ==========
The guidelines below ensure proper single-touch and multi-finger functionality. The guidelines below ensure proper single-touch and multi-finger functionality.
For multi-touch functionality, see the multi-touch-protocol.txt document for For multi-touch functionality, see the multi-touch-protocol.txt document for
more information. more information.
Mice: Mice
---------- ----
REL_{X,Y} must be reported when the mouse moves. BTN_LEFT must be used to report REL_{X,Y} must be reported when the mouse moves. BTN_LEFT must be used to report
the primary button press. BTN_{MIDDLE,RIGHT,4,5,etc.} should be used to report the primary button press. BTN_{MIDDLE,RIGHT,4,5,etc.} should be used to report
further buttons of the device. REL_WHEEL and REL_HWHEEL should be used to report further buttons of the device. REL_WHEEL and REL_HWHEEL should be used to report
scroll wheel events where available. scroll wheel events where available.
Touchscreens: Touchscreens
---------- ------------
ABS_{X,Y} must be reported with the location of the touch. BTN_TOUCH must be ABS_{X,Y} must be reported with the location of the touch. BTN_TOUCH must be
used to report when a touch is active on the screen. used to report when a touch is active on the screen.
BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch
@ -329,8 +381,9 @@ contact. BTN_TOOL_<name> events should be reported where possible.
For new hardware, INPUT_PROP_DIRECT should be set. For new hardware, INPUT_PROP_DIRECT should be set.
Trackpads: Trackpads
---------- ---------
Legacy trackpads that only provide relative position information must report Legacy trackpads that only provide relative position information must report
events like mice described above. events like mice described above.
@ -341,8 +394,9 @@ be used to report the number of touches active on the trackpad.
For new hardware, INPUT_PROP_POINTER should be set. For new hardware, INPUT_PROP_POINTER should be set.
Tablets: Tablets
---------- -------
BTN_TOOL_<name> events must be reported when a stylus or other tool is active on BTN_TOOL_<name> events must be reported when a stylus or other tool is active on
the tablet. ABS_{X,Y} must be reported with the location of the tool. BTN_TOUCH the tablet. ABS_{X,Y} must be reported with the location of the tool. BTN_TOUCH
should be used to report when the tool is in contact with the tablet. should be used to report when the tool is in contact with the tablet.

View File

@ -1,12 +1,16 @@
Force feedback for Linux. ========================
By Johann Deneux <johann.deneux@gmail.com> on 2001/04/22. Force feedback for Linux
Updated by Anssi Hannula <anssi.hannula@gmail.com> on 2006/04/09. ========================
You may redistribute this file. Please remember to include shape.fig and
interactive.fig as well. :Author: Johann Deneux <johann.deneux@gmail.com> on 2001/04/22.
---------------------------------------------------------------------------- :Updated: Anssi Hannula <anssi.hannula@gmail.com> on 2006/04/09.
You may redistribute this file. Please remember to include shape.svg and
interactive.svg as well.
Introduction
~~~~~~~~~~~~
1. Introduction
~~~~~~~~~~~~~~~
This document describes how to use force feedback devices under Linux. The 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 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 (as it is already the case), but to really enable the rendering of force
@ -15,8 +19,9 @@ This document only describes the force feedback part of the Linux input
interface. Please read joystick.txt and input.txt before reading further this interface. Please read joystick.txt and input.txt before reading further this
document. document.
2. Instructions to the user Instructions to the user
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
To enable force feedback, you have to: To enable force feedback, you have to:
1. have your kernel configured with evdev and a driver that supports your 1. have your kernel configured with evdev and a driver that supports your
@ -33,39 +38,48 @@ something goes wrong.
If you have a serial iforce device, you need to start inputattach. See If you have a serial iforce device, you need to start inputattach. See
joystick.txt for details. joystick.txt for details.
2.1 Does it work ? Does it work ?
~~~~~~~~~~~~~~~~~~ --------------
There is an utility called fftest that will allow you to test the driver.
% fftest /dev/input/eventXX There is an utility called fftest that will allow you to test the driver::
% fftest /dev/input/eventXX
Instructions to the developer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3. Instructions to the developer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All interactions are done using the event API. That is, you can use ioctl() All interactions are done using the event API. That is, you can use ioctl()
and write() on /dev/input/eventXX. and write() on /dev/input/eventXX.
This information is subject to change. This information is subject to change.
3.1 Querying device capabilities Querying device capabilities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ----------------------------
#include <linux/input.h>
#include <sys/ioctl.h>
#define BITS_TO_LONGS(x) \ ::
(((x) + 8 * sizeof (unsigned long) - 1) / (8 * sizeof (unsigned long)))
unsigned long features[BITS_TO_LONGS(FF_CNT)]; #include <linux/input.h>
int ioctl(int file_descriptor, int request, unsigned long *features); #include <sys/ioctl.h>
#define BITS_TO_LONGS(x) \
(((x) + 8 * sizeof (unsigned long) - 1) / (8 * sizeof (unsigned long)))
unsigned long features[BITS_TO_LONGS(FF_CNT)];
int ioctl(int file_descriptor, int request, unsigned long *features);
"request" must be EVIOCGBIT(EV_FF, size of features array in bytes ) "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 Returns the features supported by the device. features is a bitfield with the
following bits: following bits:
- FF_CONSTANT can render constant force effects - FF_CONSTANT can render constant force effects
- FF_PERIODIC can render periodic effects with the following waveforms: - FF_PERIODIC can render periodic effects with the following waveforms:
- FF_SQUARE square waveform - FF_SQUARE square waveform
- FF_TRIANGLE triangle waveform - FF_TRIANGLE triangle waveform
- FF_SINE sine waveform - FF_SINE sine waveform
- FF_SAW_UP sawtooth up waveform - FF_SAW_UP sawtooth up waveform
- FF_SAW_DOWN sawtooth down waveform - FF_SAW_DOWN sawtooth down waveform
- FF_CUSTOM custom waveform - FF_CUSTOM custom waveform
- FF_RAMP can render ramp effects - FF_RAMP can render ramp effects
- FF_SPRING can simulate the presence of a spring - FF_SPRING can simulate the presence of a spring
- FF_FRICTION can simulate friction - FF_FRICTION can simulate friction
@ -75,24 +89,30 @@ following bits:
- FF_GAIN gain is adjustable - FF_GAIN gain is adjustable
- FF_AUTOCENTER autocenter is adjustable - FF_AUTOCENTER autocenter is adjustable
Note: In most cases you should use FF_PERIODIC instead of FF_RUMBLE. All .. note::
- In most cases you should use FF_PERIODIC instead of FF_RUMBLE. All
devices that support FF_RUMBLE support FF_PERIODIC (square, triangle, devices that support FF_RUMBLE support FF_PERIODIC (square, triangle,
sine) and the other way around. sine) and the other way around.
Note: The exact syntax FF_CUSTOM is undefined for the time being as no driver - The exact syntax FF_CUSTOM is undefined for the time being as no driver
supports it yet. supports it yet.
::
int ioctl(int fd, EVIOCGEFFECTS, int *n); int ioctl(int fd, EVIOCGEFFECTS, int *n);
Returns the number of effects the device can keep in its memory. Returns the number of effects the device can keep in its memory.
3.2 Uploading effects to the device Uploading effects to the device
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -------------------------------
#include <linux/input.h>
#include <sys/ioctl.h>
int ioctl(int file_descriptor, int request, struct ff_effect *effect); ::
#include <linux/input.h>
#include <sys/ioctl.h>
int ioctl(int file_descriptor, int request, struct ff_effect *effect);
"request" must be EVIOCSFF. "request" must be EVIOCSFF.
@ -106,38 +126,53 @@ allocate a new effect.
Effects are file descriptor specific. Effects are file descriptor specific.
See <uapi/linux/input.h> for a description of the ff_effect struct. You should See <uapi/linux/input.h> for a description of the ff_effect struct. You
also find help in a few sketches, contained in files shape.fig and should also find help in a few sketches, contained in files shape.svg
interactive.fig. You need xfig to visualize these files. and interactive.svg:
3.3 Removing an effect from the device .. figure:: shape.svg
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int ioctl(int fd, EVIOCRMFF, effect.id); Shape
.. figure:: interactive.svg
Interactive
Removing an effect from the device
----------------------------------
::
int ioctl(int fd, EVIOCRMFF, effect.id);
This makes room for new effects in the device's memory. Note that this also This makes room for new effects in the device's memory. Note that this also
stops the effect if it was playing. stops the effect if it was playing.
3.4 Controlling the playback of effects Controlling the playback of effects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------------
Control of playing is done with write(). Below is an example: Control of playing is done with write(). Below is an example:
#include <linux/input.h> ::
#include <unistd.h>
#include <linux/input.h>
#include <unistd.h>
struct input_event play; struct input_event play;
struct input_event stop; struct input_event stop;
struct ff_effect effect; struct ff_effect effect;
int fd; int fd;
... ...
fd = open("/dev/input/eventXX", O_RDWR); fd = open("/dev/input/eventXX", O_RDWR);
... ...
/* Play three times */ /* Play three times */
play.type = EV_FF; play.type = EV_FF;
play.code = effect.id; play.code = effect.id;
play.value = 3; play.value = 3;
write(fd, (const void*) &play, sizeof(play)); write(fd, (const void*) &play, sizeof(play));
... ...
/* Stop an effect */ /* Stop an effect */
stop.type = EV_FF; stop.type = EV_FF;
stop.code = effect.id; stop.code = effect.id;
@ -145,43 +180,50 @@ Control of playing is done with write(). Below is an example:
write(fd, (const void*) &play, sizeof(stop)); write(fd, (const void*) &play, sizeof(stop));
3.5 Setting the gain Setting the gain
~~~~~~~~~~~~~~~~~~~~ ----------------
Not all devices have the same strength. Therefore, users should set a 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 factor depending on how strong they want effects to be. This setting is
persistent across access to the driver. persistent across access to the driver.
/* 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; /* Set the gain of the device
ie.code = FF_GAIN; int gain; /* between 0 and 100 */
ie.value = 0xFFFFUL * gain / 100; struct input_event ie; /* structure used to communicate with the driver */
if (write(fd, &ie, sizeof(ie)) == -1) ie.type = EV_FF;
ie.code = FF_GAIN;
ie.value = 0xFFFFUL * gain / 100;
if (write(fd, &ie, sizeof(ie)) == -1)
perror("set gain"); perror("set gain");
3.6 Enabling/Disabling autocenter Enabling/Disabling autocenter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -----------------------------
The autocenter feature quite disturbs the rendering of effects in my opinion, 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 and I think it should be an effect, which computation depends on the game
type. But you can enable it if you want. type. But you can enable it if you want.
int autocenter; /* between 0 and 100 */ ::
struct input_event ie;
ie.type = EV_FF; int autocenter; /* between 0 and 100 */
ie.code = FF_AUTOCENTER; struct input_event ie;
ie.value = 0xFFFFUL * autocenter / 100;
if (write(fd, &ie, sizeof(ie)) == -1) ie.type = EV_FF;
ie.code = FF_AUTOCENTER;
ie.value = 0xFFFFUL * autocenter / 100;
if (write(fd, &ie, sizeof(ie)) == -1)
perror("set auto-center"); perror("set auto-center");
A value of 0 means "no auto-center". A value of 0 means "no auto-center".
3.7 Dynamic update of an effect Dynamic update of an effect
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ---------------------------
Proceed as if you wanted to upload a new effect, except that instead of 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. 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 Normally, the effect is not stopped and restarted. However, depending on the
@ -192,30 +234,32 @@ case, the driver stops the effect, up-load it, and restart it.
Therefore it is recommended to dynamically change direction while the effect Therefore it is recommended to dynamically change direction while the effect
is playing only when it is ok to restart the effect with a replay count of 1. is playing only when it is ok to restart the effect with a replay count of 1.
3.8 Information about the status of effects Information about the status of effects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ---------------------------------------
Every time the status of an effect is changed, an event is sent. The values 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: and meanings of the fields of the event are as follows::
struct input_event { struct input_event {
/* When the status of the effect changed */ /* When the status of the effect changed */
struct timeval time; struct timeval time;
/* Set to EV_FF_STATUS */ /* Set to EV_FF_STATUS */
unsigned short type; unsigned short type;
/* Contains the id of the effect */ /* Contains the id of the effect */
unsigned short code; unsigned short code;
/* Indicates the status */ /* Indicates the status */
unsigned int value; unsigned int value;
}; };
FF_STATUS_STOPPED The effect stopped playing FF_STATUS_STOPPED The effect stopped playing
FF_STATUS_PLAYING The effect started to play FF_STATUS_PLAYING The effect started to play
NOTE: Status feedback is only supported by iforce driver. If you have .. note::
- Status feedback is only supported by iforce driver. If you have
a really good reason to use this, please contact a really good reason to use this, please contact
linux-joystick@atrey.karlin.mff.cuni.cz or anssi.hannula@gmail.com linux-joystick@atrey.karlin.mff.cuni.cz or anssi.hannula@gmail.com
so that support for it can be added to the rest of the drivers. so that support for it can be added to the rest of the drivers.

View File

@ -1,15 +1,19 @@
Linux Gamepad API ---------------------------
---------------------------------------------------------------------------- Linux Gamepad Specification
---------------------------
1. Intro :Author: 2013 by David Herrmann <dh.herrmann@gmail.com>
~~~~~~~~
Introduction
~~~~~~~~~~~~
Linux provides many different input drivers for gamepad hardware. To avoid Linux provides many different input drivers for gamepad hardware. To avoid
having user-space deal with different button-mappings for each gamepad, this having user-space deal with different button-mappings for each gamepad, this
document defines how gamepads are supposed to report their data. document defines how gamepads are supposed to report their data.
2. Geometry Geometry
~~~~~~~~~~~ ~~~~~~~~
As "gamepad" we define devices which roughly look like this: As "gamepad" we define devices which roughly look like this::
____________________________ __ ____________________________ __
/ [__ZL__] [__ZR__] \ | / [__ZL__] [__ZR__] \ |
@ -35,6 +39,7 @@ As "gamepad" we define devices which roughly look like this:
Menu Pad Menu Pad
Most gamepads have the following features: Most gamepads have the following features:
- Action-Pad - Action-Pad
4 buttons in diamonds-shape (on the right side). The buttons are 4 buttons in diamonds-shape (on the right side). The buttons are
differently labeled on most devices so we define them as NORTH, differently labeled on most devices so we define them as NORTH,
@ -58,8 +63,9 @@ Most gamepads have the following features:
Many devices provide force-feedback features. But are mostly just Many devices provide force-feedback features. But are mostly just
simple rumble motors. simple rumble motors.
3. Detection Detection
~~~~~~~~~~~~ ~~~~~~~~~
All gamepads that follow the protocol described here map BTN_GAMEPAD. This is All gamepads that follow the protocol described here map BTN_GAMEPAD. This is
an alias for BTN_SOUTH/BTN_A. It can be used to identify a gamepad as such. an alias for BTN_SOUTH/BTN_A. It can be used to identify a gamepad as such.
However, not all gamepads provide all features, so you need to test for all However, not all gamepads provide all features, so you need to test for all
@ -85,75 +91,101 @@ devices that report a small subset of the events.
No other devices, that do not look/feel like a gamepad, shall report these No other devices, that do not look/feel like a gamepad, shall report these
events. events.
4. Events Events
~~~~~~~~~ ~~~~~~
Gamepads report the following events: Gamepads report the following events:
Action-Pad: - Action-Pad:
Every gamepad device has at least 2 action buttons. This means, that every Every gamepad device has at least 2 action buttons. This means, that every
device reports BTN_SOUTH (which BTN_GAMEPAD is an alias for). Regardless device reports BTN_SOUTH (which BTN_GAMEPAD is an alias for). Regardless
of the labels on the buttons, the codes are sent according to the of the labels on the buttons, the codes are sent according to the
physical position of the buttons. physical position of the buttons.
Please note that 2- and 3-button pads are fairly rare and old. You might Please note that 2- and 3-button pads are fairly rare and old. You might
want to filter gamepads that do not report all four. want to filter gamepads that do not report all four.
2-Button Pad:
- 2-Button Pad:
If only 2 action-buttons are present, they are reported as BTN_SOUTH and If only 2 action-buttons are present, they are reported as BTN_SOUTH and
BTN_EAST. For vertical layouts, the upper button is BTN_EAST. For BTN_EAST. For vertical layouts, the upper button is BTN_EAST. For
horizontal layouts, the button more on the right is BTN_EAST. horizontal layouts, the button more on the right is BTN_EAST.
3-Button Pad:
- 3-Button Pad:
If only 3 action-buttons are present, they are reported as (from left If only 3 action-buttons are present, they are reported as (from left
to right): BTN_WEST, BTN_SOUTH, BTN_EAST to right): BTN_WEST, BTN_SOUTH, BTN_EAST
If the buttons are aligned perfectly vertically, they are reported as If the buttons are aligned perfectly vertically, they are reported as
(from top down): BTN_WEST, BTN_SOUTH, BTN_EAST (from top down): BTN_WEST, BTN_SOUTH, BTN_EAST
4-Button Pad:
- 4-Button Pad:
If all 4 action-buttons are present, they can be aligned in two If all 4 action-buttons are present, they can be aligned in two
different formations. If diamond-shaped, they are reported as BTN_NORTH, different formations. If diamond-shaped, they are reported as BTN_NORTH,
BTN_WEST, BTN_SOUTH, BTN_EAST according to their physical location. BTN_WEST, BTN_SOUTH, BTN_EAST according to their physical location.
If rectangular-shaped, the upper-left button is BTN_NORTH, lower-left If rectangular-shaped, the upper-left button is BTN_NORTH, lower-left
is BTN_WEST, lower-right is BTN_SOUTH and upper-right is BTN_EAST. is BTN_WEST, lower-right is BTN_SOUTH and upper-right is BTN_EAST.
D-Pad: - D-Pad:
Every gamepad provides a D-Pad with four directions: Up, Down, Left, Right Every gamepad provides a D-Pad with four directions: Up, Down, Left, Right
Some of these are available as digital buttons, some as analog buttons. Some Some of these are available as digital buttons, some as analog buttons. Some
may even report both. The kernel does not convert between these so may even report both. The kernel does not convert between these so
applications should support both and choose what is more appropriate if applications should support both and choose what is more appropriate if
both are reported. both are reported.
Digital buttons are reported as:
BTN_DPAD_*
Analog buttons are reported as:
ABS_HAT0X and ABS_HAT0Y
(for ABS values negative is left/up, positive is right/down)
Analog-Sticks: - Digital buttons are reported as:
BTN_DPAD_*
- Analog buttons are reported as:
ABS_HAT0X and ABS_HAT0Y
(for ABS values negative is left/up, positive is right/down)
- Analog-Sticks:
The left analog-stick is reported as ABS_X, ABS_Y. The right analog stick is The left analog-stick is reported as ABS_X, ABS_Y. The right analog stick is
reported as ABS_RX, ABS_RY. Zero, one or two sticks may be present. reported as ABS_RX, ABS_RY. Zero, one or two sticks may be present.
If analog-sticks provide digital buttons, they are mapped accordingly as If analog-sticks provide digital buttons, they are mapped accordingly as
BTN_THUMBL (first/left) and BTN_THUMBR (second/right). BTN_THUMBL (first/left) and BTN_THUMBR (second/right).
(for ABS values negative is left/up, positive is right/down)
Triggers: (for ABS values negative is left/up, positive is right/down)
- Triggers:
Trigger buttons can be available as digital or analog buttons or both. User- Trigger buttons can be available as digital or analog buttons or both. User-
space must correctly deal with any situation and choose the most appropriate space must correctly deal with any situation and choose the most appropriate
mode. mode.
Upper trigger buttons are reported as BTN_TR or ABS_HAT1X (right) and BTN_TL Upper trigger buttons are reported as BTN_TR or ABS_HAT1X (right) and BTN_TL
or ABS_HAT1Y (left). Lower trigger buttons are reported as BTN_TR2 or or ABS_HAT1Y (left). Lower trigger buttons are reported as BTN_TR2 or
ABS_HAT2X (right/ZR) and BTN_TL2 or ABS_HAT2Y (left/ZL). ABS_HAT2X (right/ZR) and BTN_TL2 or ABS_HAT2Y (left/ZL).
If only one trigger-button combination is present (upper+lower), they are If only one trigger-button combination is present (upper+lower), they are
reported as "right" triggers (BTN_TR/ABS_HAT1X). reported as "right" triggers (BTN_TR/ABS_HAT1X).
(ABS trigger values start at 0, pressure is reported as positive values)
Menu-Pad: (ABS trigger values start at 0, pressure is reported as positive values)
- Menu-Pad:
Menu buttons are always digital and are mapped according to their location Menu buttons are always digital and are mapped according to their location
instead of their labels. That is: instead of their labels. That is:
1-button Pad: Mapped as BTN_START
2-button Pad: Left button mapped as BTN_SELECT, right button mapped as - 1-button Pad:
BTN_START
Mapped as BTN_START
- 2-button Pad:
Left button mapped as BTN_SELECT, right button mapped as BTN_START
Many pads also have a third button which is branded or has a special symbol Many pads also have a third button which is branded or has a special symbol
and meaning. Such buttons are mapped as BTN_MODE. Examples are the Nintendo and meaning. Such buttons are mapped as BTN_MODE. Examples are the Nintendo
"HOME" button, the XBox "X"-button or Sony "PS" button. "HOME" button, the XBox "X"-button or Sony "PS" button.
Rumble: - Rumble:
Rumble is advertised as FF_RUMBLE.
---------------------------------------------------------------------------- Rumble is advertised as FF_RUMBLE.
Written 2013 by David Herrmann <dh.herrmann@gmail.com>

View File

@ -1,11 +1,12 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Programming gameport drivers Programming gameport drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. A basic classic gameport A basic classic gameport
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
If the gameport doesn't provide more than the inb()/outb() functionality, If the gameport doesn't provide more than the inb()/outb() functionality,
the code needed to register it with the joystick drivers is simple: the code needed to register it with the joystick drivers is simple::
struct gameport gameport; struct gameport gameport;
@ -37,12 +38,12 @@ space only when something really is using it. Disable it again in the
callback, so that it doesn't fail if some of the possible addresses are callback, so that it doesn't fail if some of the possible addresses are
already occupied by other gameports. already occupied by other gameports.
2. Memory mapped gameport Memory mapped gameport
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
When a gameport can be accessed through MMIO, this way is preferred, because 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 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: isn't as easy as a basic IO one, but not so much complex::
struct gameport gameport; struct gameport gameport;
@ -53,19 +54,21 @@ isn't as easy as a basic IO one, but not so much complex:
unsigned char my_read(struct gameport *gameport) unsigned char my_read(struct gameport *gameport)
{ {
return my_mmio; return my_mmio;
} }
gameport.read = my_read; gameport.read = my_read;
gameport.trigger = my_trigger; gameport.trigger = my_trigger;
gameport_register_port(&gameport); gameport_register_port(&gameport);
3. Cooked mode gameport .. _gameport_pgm_cooked_mode:
~~~~~~~~~~~~~~~~~~~~~~~
Cooked mode gameport
~~~~~~~~~~~~~~~~~~~~
There are gameports that can report the axis values as numbers, that means 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 driver doesn't have to measure them the old way - an ADC is built into
the gameport. To register a cooked gameport: the gameport. To register a cooked gameport::
struct gameport gameport; struct gameport gameport;
@ -95,8 +98,8 @@ 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 the size of a gaussian filter window that is used to eliminate the noise
in the data. in the data.
4. More complex gameports More complex gameports
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
Gameports can support both raw and cooked modes. In that case combine either 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, examples 1+2 or 1+3. Gameports can support internal calibration - see below,
@ -104,65 +107,91 @@ 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 more than one gameport instance simultaneously, use the ->private member of
the gameport struct to point to your data. the gameport struct to point to your data.
5. Unregistering a gameport Unregistering a gameport
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
Simple: Simple::
gameport_unregister_port(&gameport); gameport_unregister_port(&gameport);
6. The gameport structure The gameport structure
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
struct gameport { .. note::
This section is outdated. There are several fields here that don't
match what's there at include/linux/gameport.h.
::
struct gameport {
void *private; void *private;
A private pointer for free use in the gameport driver. (Not the joystick A private pointer for free use in the gameport driver. (Not the joystick
driver!) driver!)
::
int number; int number;
Number assigned to the gameport when registered. Informational purpose only. Number assigned to the gameport when registered. Informational purpose only.
::
int io; int io;
I/O address for use with raw mode. You have to either set this, or ->read() 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. to some value if your gameport supports raw mode.
::
int speed; int speed;
Raw mode speed of the gameport reads in thousands of reads per second. Raw mode speed of the gameport reads in thousands of reads per second.
::
int fuzz; int fuzz;
If the gameport supports cooked mode, this should be set to a value that 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. represents the amount of noise in the data. See
:ref:`gameport_pgm_cooked_mode`.
::
void (*trigger)(struct gameport *); void (*trigger)(struct gameport *);
Trigger. This function should trigger the ns558 oneshots. If set to NULL, Trigger. This function should trigger the ns558 oneshots. If set to NULL,
outb(0xff, io) will be used. outb(0xff, io) will be used.
::
unsigned char (*read)(struct gameport *); unsigned char (*read)(struct gameport *);
Read the buttons and ns558 oneshot bits. If set to NULL, inb(io) will be Read the buttons and ns558 oneshot bits. If set to NULL, inb(io) will be
used instead. used instead.
int (*cooked_read)(struct gameport *, int *axes, int *buttons); ::
int (*cooked_read)(struct gameport *, int *axes, int *buttons);
If the gameport supports cooked mode, it should point this to its cooked 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 read function. It should fill axes[0..3] with four values of the joystick axes
and buttons[0] with four bits representing the buttons. and buttons[0] with four bits representing the buttons.
int (*calibrate)(struct gameport *, int *axes, int *max); ::
int (*calibrate)(struct gameport *, int *axes, int *max);
Function for calibrating the ADC hardware. When called, axes[0..3] should be 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 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 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 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 recompute the axes[] values to match the new sensitivity or re-read them from
the hardware so that they give valid values. the hardware so that they give valid values.
::
int (*open)(struct gameport *, int mode); int (*open)(struct gameport *, int mode);
@ -172,16 +201,22 @@ 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 here. Prior to this call, other fields of the gameport struct (namely the io
member) need not to be valid. member) need not to be valid.
::
void (*close)(struct gameport *); void (*close)(struct gameport *);
Close() should free the resources allocated by open, possibly disabling the Close() should free the resources allocated by open, possibly disabling the
gameport. gameport.
::
struct gameport_dev *dev; struct gameport_dev *dev;
struct gameport *next; struct gameport *next;
For internal use by the gameport layer. For internal use by the gameport layer.
}; ::
};
Enjoy! Enjoy!

View File

@ -1,103 +0,0 @@
Driver for tilt-switches connected via GPIOs
============================================
Generic driver to read data from tilt switches connected via gpios.
Orientation can be provided by one or more than one tilt switches,
i.e. each tilt switch providing one axis, and the number of axes
is also not limited.
Data structures:
----------------
The array of struct gpio in the gpios field is used to list the gpios
that represent the current tilt state.
The array of struct gpio_tilt_axis describes the axes that are reported
to the input system. The values set therein are used for the
input_set_abs_params calls needed to init the axes.
The array of struct gpio_tilt_state maps gpio states to the corresponding
values to report. The gpio state is represented as a bitfield where the
bit-index corresponds to the index of the gpio in the struct gpio array.
In the same manner the values stored in the axes array correspond to
the elements of the gpio_tilt_axis-array.
Example:
--------
Example configuration for a single TS1003 tilt switch that rotates around
one axis in 4 steps and emits the current tilt via two GPIOs.
static int sg060_tilt_enable(struct device *dev) {
/* code to enable the sensors */
};
static void sg060_tilt_disable(struct device *dev) {
/* code to disable the sensors */
};
static struct gpio sg060_tilt_gpios[] = {
{ SG060_TILT_GPIO_SENSOR1, GPIOF_IN, "tilt_sensor1" },
{ SG060_TILT_GPIO_SENSOR2, GPIOF_IN, "tilt_sensor2" },
};
static struct gpio_tilt_state sg060_tilt_states[] = {
{
.gpios = (0 << 1) | (0 << 0),
.axes = (int[]) {
0,
},
}, {
.gpios = (0 << 1) | (1 << 0),
.axes = (int[]) {
1, /* 90 degrees */
},
}, {
.gpios = (1 << 1) | (1 << 0),
.axes = (int[]) {
2, /* 180 degrees */
},
}, {
.gpios = (1 << 1) | (0 << 0),
.axes = (int[]) {
3, /* 270 degrees */
},
},
};
static struct gpio_tilt_axis sg060_tilt_axes[] = {
{
.axis = ABS_RY,
.min = 0,
.max = 3,
.fuzz = 0,
.flat = 0,
},
};
static struct gpio_tilt_platform_data sg060_tilt_pdata= {
.gpios = sg060_tilt_gpios,
.nr_gpios = ARRAY_SIZE(sg060_tilt_gpios),
.axes = sg060_tilt_axes,
.nr_axes = ARRAY_SIZE(sg060_tilt_axes),
.states = sg060_tilt_states,
.nr_states = ARRAY_SIZE(sg060_tilt_states),
.debounce_interval = 100,
.poll_interval = 1000,
.enable = sg060_tilt_enable,
.disable = sg060_tilt_disable,
};
static struct platform_device sg060_device_tilt = {
.name = "gpio-tilt-polled",
.id = -1,
.dev = {
.platform_data = &sg060_tilt_pdata,
},
};

View File

@ -1,258 +0,0 @@
** 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: johann.deneux@gmail.com
** WARNING **
I shall not be held responsible for any damage 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 parameters
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
responses 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 additional 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 software seems, hum, well... buggy. In fact, data appear with a
few seconds latency. Personally, 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 <johann.deneux@gmail.com>
Home page at http://web.archive.org/web/*/http://www.esil.univ-mrs.fr
Additions by Vojtech Pavlik.
I-Force is trademark of Immersion Corp.

View File

@ -0,0 +1,20 @@
=============================
The Linux Input Documentation
=============================
Contents:
.. toctree::
:maxdepth: 2
:numbered:
input_uapi
input_kapi
devices/index
.. only:: subproject and html
Indices
=======
* :ref:`genindex`

View File

@ -1,77 +1,75 @@
Programming input drivers ===============================
~~~~~~~~~~~~~~~~~~~~~~~~~ Creating an input device driver
===============================
1. Creating an input device driver The simplest example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
1.0 The simplest example
~~~~~~~~~~~~~~~~~~~~~~~~
Here comes a very simple example of an input device driver. The device has 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 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: pressed or released a BUTTON_IRQ happens. The driver could look like::
#include <linux/input.h> #include <linux/input.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
static struct input_dev *button_dev; static struct input_dev *button_dev;
static irqreturn_t button_interrupt(int irq, void *dummy) static irqreturn_t button_interrupt(int irq, void *dummy)
{ {
input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1); input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);
input_sync(button_dev); input_sync(button_dev);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int __init button_init(void) static int __init button_init(void)
{ {
int error; int error;
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) { if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq); printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
return -EBUSY; return -EBUSY;
} }
button_dev = input_allocate_device(); button_dev = input_allocate_device();
if (!button_dev) { if (!button_dev) {
printk(KERN_ERR "button.c: Not enough memory\n"); printk(KERN_ERR "button.c: Not enough memory\n");
error = -ENOMEM; error = -ENOMEM;
goto err_free_irq; goto err_free_irq;
} }
button_dev->evbit[0] = BIT_MASK(EV_KEY); button_dev->evbit[0] = BIT_MASK(EV_KEY);
button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); button_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
error = input_register_device(button_dev); error = input_register_device(button_dev);
if (error) { if (error) {
printk(KERN_ERR "button.c: Failed to register device\n"); printk(KERN_ERR "button.c: Failed to register device\n");
goto err_free_dev; goto err_free_dev;
} }
return 0; return 0;
err_free_dev: err_free_dev:
input_free_device(button_dev); input_free_device(button_dev);
err_free_irq: err_free_irq:
free_irq(BUTTON_IRQ, button_interrupt); free_irq(BUTTON_IRQ, button_interrupt);
return error; return error;
} }
static void __exit button_exit(void) static void __exit button_exit(void)
{ {
input_unregister_device(button_dev); input_unregister_device(button_dev);
free_irq(BUTTON_IRQ, button_interrupt); free_irq(BUTTON_IRQ, button_interrupt);
} }
module_init(button_init); module_init(button_init);
module_exit(button_exit); module_exit(button_exit);
1.1 What the example does What the example does
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
First it has to include the <linux/input.h> file, which interfaces to the First it has to include the <linux/input.h> file, which interfaces to the
input subsystem. This provides all the definitions needed. input subsystem. This provides all the definitions needed.
@ -85,7 +83,7 @@ and sets up input bitfields. This way the device driver tells the other
parts of the input systems what it is - what events can be generated or 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 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 type events, and from those only BTN_0 event code. Thus we only set these
two bits. We could have used two bits. We could have used::
set_bit(EV_KEY, button_dev.evbit); set_bit(EV_KEY, button_dev.evbit);
set_bit(BTN_0, button_dev.keybit); set_bit(BTN_0, button_dev.keybit);
@ -93,7 +91,7 @@ two bits. We could have used
as well, but with more than single bits the first approach tends to be as well, but with more than single bits the first approach tends to be
shorter. shorter.
Then the example driver registers the input device structure by calling Then the example driver registers the input device structure by calling::
input_register_device(&button_dev); input_register_device(&button_dev);
@ -102,12 +100,12 @@ calls device handler modules _connect functions to tell them a new input
device has appeared. input_register_device() may sleep and therefore must device has appeared. input_register_device() may sleep and therefore must
not be called from an interrupt or with a spinlock held. not be called from an interrupt or with a spinlock held.
While in use, the only used function of the driver is While in use, the only used function of the driver is::
button_interrupt() button_interrupt()
which upon every interrupt from the button checks its state and reports it which upon every interrupt from the button checks its state and reports it
via the via the::
input_report_key() input_report_key()
@ -116,7 +114,7 @@ routine isn't reporting two same value events (press, press for example) to
the input system, because the input_report_* functions check that the input system, because the input_report_* functions check that
themselves. themselves.
Then there is the Then there is the::
input_sync() input_sync()
@ -125,38 +123,38 @@ 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 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. to be interpreted separately, because that'd result in a different movement.
1.2 dev->open() and dev->close() dev->open() and dev->close()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In case the driver has to repeatedly poll the device, because it doesn't 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 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 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 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 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: again. To do that, we would add this to our example driver::
static int button_open(struct input_dev *dev) static int button_open(struct input_dev *dev)
{ {
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) { if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq); printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
return -EBUSY; return -EBUSY;
} }
return 0; return 0;
} }
static void button_close(struct input_dev *dev) static void button_close(struct input_dev *dev)
{ {
free_irq(IRQ_AMIGA_VERTB, button_interrupt); free_irq(IRQ_AMIGA_VERTB, button_interrupt);
} }
static int __init button_init(void) static int __init button_init(void)
{ {
... ...
button_dev->open = button_open; button_dev->open = button_open;
button_dev->close = button_close; button_dev->close = button_close;
... ...
} }
Note that input core keeps track of number of users for the device and Note that input core keeps track of number of users for the device and
makes sure that dev->open() is called only when the first user connects makes sure that dev->open() is called only when the first user connects
@ -166,11 +164,11 @@ disconnects. Calls to both callbacks are serialized.
The open() callback should return a 0 in case of success or any nonzero value 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. in case of failure. The close() callback (which is void) must always succeed.
1.3 Basic event types Basic event types
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
The most simple event type is EV_KEY, which is used for keys and buttons. The most simple event type is EV_KEY, which is used for keys and buttons.
It's reported to the input system via: It's reported to the input system via::
input_report_key(struct input_dev *dev, int code, int value) input_report_key(struct input_dev *dev, int code, int value)
@ -188,7 +186,7 @@ events are namely for joysticks and digitizers - devices that do work in an
absolute coordinate systems. absolute coordinate systems.
Having the device report EV_REL buttons is as simple as with EV_KEY, simply Having the device report EV_REL buttons is as simple as with EV_KEY, simply
set the corresponding bits and call the set the corresponding bits and call the::
input_report_rel(struct input_dev *dev, int code, int value) input_report_rel(struct input_dev *dev, int code, int value)
@ -197,14 +195,14 @@ function. Events are generated only for nonzero value.
However EV_ABS requires a little special care. Before calling However EV_ABS requires a little special care. Before calling
input_register_device, you have to fill additional fields in the input_dev 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 struct for each absolute axis your device has. If our button device had also
the ABS_X axis: the ABS_X axis::
button_dev.absmin[ABS_X] = 0; button_dev.absmin[ABS_X] = 0;
button_dev.absmax[ABS_X] = 255; button_dev.absmax[ABS_X] = 255;
button_dev.absfuzz[ABS_X] = 4; button_dev.absfuzz[ABS_X] = 4;
button_dev.absflat[ABS_X] = 8; button_dev.absflat[ABS_X] = 8;
Or, you can just say: Or, you can just say::
input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8); input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);
@ -218,18 +216,18 @@ 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 that the thing is precise and always returns to exactly the center position
(if it has any). (if it has any).
1.4 BITS_TO_LONGS(), BIT_WORD(), BIT_MASK() BITS_TO_LONGS(), BIT_WORD(), BIT_MASK()
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These three macros from bitops.h help some bitfield computations: These three macros from bitops.h help some bitfield computations::
BITS_TO_LONGS(x) - returns the length of a bitfield array in longs for BITS_TO_LONGS(x) - returns the length of a bitfield array in longs for
x bits x bits
BIT_WORD(x) - returns the index in the array in longs for bit x BIT_WORD(x) - returns the index in the array in longs for bit x
BIT_MASK(x) - returns the index in a long for bit x BIT_MASK(x) - returns the index in a long for bit x
1.5 The id* and name fields The id* and name fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
The dev->name should be set before registering the input device by the input 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 device driver. It's a string like 'Generic button device' containing a
@ -245,8 +243,8 @@ driver.
The id and name fields can be passed to userland via the evdev interface. The id and name fields can be passed to userland via the evdev interface.
1.6 The keycode, keycodemax, keycodesize fields The keycode, keycodemax, keycodesize fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These three fields should be used by input devices that have dense keymaps. These three fields should be used by input devices that have dense keymaps.
The keycode is an array used to map from scancodes to input system keycodes. The keycode is an array used to map from scancodes to input system keycodes.
@ -259,14 +257,15 @@ When a device has all 3 aforementioned fields filled in, the driver may
rely on kernel's default implementation of setting and querying keycode rely on kernel's default implementation of setting and querying keycode
mappings. mappings.
1.7 dev->getkeycode() and dev->setkeycode() dev->getkeycode() and dev->setkeycode()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getkeycode() and setkeycode() callbacks allow drivers to override default getkeycode() and setkeycode() callbacks allow drivers to override default
keycode/keycodesize/keycodemax mapping mechanism provided by input core keycode/keycodesize/keycodemax mapping mechanism provided by input core
and implement sparse keycode maps. and implement sparse keycode maps.
1.8 Key autorepeat Key autorepeat
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
... is simple. It is handled by the input.c module. Hardware autorepeat is ... 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 not used, because it's not present in many devices and even where it is
@ -274,29 +273,30 @@ 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 autorepeat for your device, just set EV_REP in dev->evbit. All will be
handled by the input system. handled by the input system.
1.9 Other event types, handling output events Other event types, handling output events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The other event types up to now are: The other event types up to now are:
EV_LED - used for the keyboard LEDs. - EV_LED - used for the keyboard LEDs.
EV_SND - used for keyboard beeps. - EV_SND - used for keyboard beeps.
They are very similar to for example key events, but they go in the other 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 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, driver can handle these events, it has to set the respective bits in evbit,
*and* also the callback routine: *and* also the callback routine::
button_dev->event = button_event; button_dev->event = button_event;
int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); 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); if (type == EV_SND && code == SND_BELL) {
return 0; outb(value, BUTTON_BELL);
} return 0;
return -1; }
} return -1;
}
This callback routine can be called from an interrupt or a BH (although that 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. isn't a rule), and thus must not sleep, and must not take too long to finish.

View File

@ -0,0 +1,281 @@
.. include:: <isonum.txt>
============
Introduction
============
:Copyright: |copy| 1999-2001 Vojtech Pavlik <vojtech@ucw.cz> - Sponsored by SuSE
Architecture
============
Input subsystem a collection of drivers that is designed to support
all input devices under Linux. Most of the drivers reside in
drivers/input, although quite a few live in drivers/hid and
drivers/platform.
The core of the input subsystem 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:
Device drivers
--------------
These modules talk to the hardware (for example via USB), and provide
events (keystrokes, mouse movements) to the input module.
Event handlers
--------------
These modules get events from input core 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.
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
usbcore
uhci_hcd or ohci_hcd or ehci_hcd
usbhid
hid_generic
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 usually created automatically by the system. The commands
to 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.
Detailed Description
====================
Event handlers
--------------
Event handlers distribute the events from the devices to userspace and
in-kernel consumers, as needed.
evdev
~~~~~
``evdev`` is the generic input event interface. It passes the events
generated in the kernel straight to the program, with timestamps. The
event codes are the same on all architectures and are hardware
independent.
This is the preferred interface for userspace to consume user
input, and all clients are encouraged to use it.
See :ref:`event-interface` for notes on API.
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
...
There are two ranges of minors: 64 through 95 is the static legacy
range. If there are more than 32 input devices in a system, additional
evdev nodes are created with minors starting with 256.
keyboard
~~~~~~~~
``keyboard`` is in-kernel input handler ad is a part of VT code. It
consumes keyboard keystrokes and handles user input for VT consoles.
mousedev
~~~~~~~~
``mousedev`` is a hack to make legacy 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.
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 older programs
that do not handle hotplug 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.
joydev
~~~~~~
``joydev`` implements v0.x and v1.x Linux joystick API. See
:ref:`joystick-api` 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 in legacy range, and additional nodes with minors
above 256 if there are more joystick devices.
Device drivers
--------------
Device drivers are the modules that generate events.
hid-generic
~~~~~~~~~~~
``hid-generic`` is one of 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/hid/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.
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.
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.
psmouse
~~~~~~~
This is driver for all flavors of pointing devices using PS/2
protocol, including Synaptics and ALPS touchpads, Intellimouse
Explorer devices, Logitech PS/2 mice and so on.
atkbd
~~~~~
This is driver for PS/2 (AT) keyboards.
iforce
~~~~~~
A driver for I-Force joysticks and wheels, both over USB and RS232.
It includes Force Feedback support now, even though Immersion
Corp. considers the protocol a trade secret and won't disclose a word
about it.
Verifying if it works
=====================
Typing a couple keys on the keyboard should be enough to check that
a 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 :ref:`joystick-doc`).
You can test the event devices with the ``evtest`` utility.
.. _event-interface:
Event interface
===============
You can use blocking and nonblocking reads, and 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 moment, EV_KEY for a keypress or
release. More types are defined in include/uapi/linux/input-event-codes.h.
``code`` is event code, for example REL_X or KEY_BACKSPACE, again a complete
list is in include/uapi/linux/input-event-codes.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.
See :ref:`input-event-codes` for more information about various even codes.

View File

@ -1,290 +0,0 @@
Linux Input drivers v1.0
(c) 1999-2001 Vojtech Pavlik <vojtech@ucw.cz>
Sponsored by SuSE
----------------------------------------------------------------------------
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.
The commands to 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/hid/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 distribute 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 usable now. It's described in
section 5.
This should be the way for GPM and X to get keyboard and 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 moment, EV_KEY for a keypress or
release. More types are defined in include/uapi/linux/input-event-codes.h.
'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
list is in include/uapi/linux/input-event-codes.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.

View File

@ -0,0 +1,17 @@
.. include:: <isonum.txt>
################################
Linux Input Subsystem kernel API
################################
.. class:: toc-title
Table of Contents
.. toctree::
:maxdepth: 2
:numbered:
input-programming
gameport-programming
notifier

View File

@ -0,0 +1,22 @@
.. include:: <isonum.txt>
###################################
Linux Input Subsystem userspace API
###################################
.. class:: toc-title
Table of Contents
.. toctree::
:maxdepth: 2
:numbered:
input
event-codes
multi-touch-protocol
gamepad
ff
joydev/index
uinput
userio

View File

@ -1,42 +0,0 @@
#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

View File

@ -0,0 +1,24 @@
<svg width="5.75in" height="3.90in" version="1.1" viewBox="1178 3138 6779.9424 4671.3427" xmlns="http://www.w3.org/2000/svg">
<polyline transform="translate(-18.5,-16.294)" points="1200 3600 1800 3600 2400 4800 3e3 4800 4200 5700 4800 5700" fill="none" stroke="#000" stroke-width="15"/>
<rect x="1181.5" y="3133.7" width="3600" height="3150" rx="0" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="1200 4800 4800 4800" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="2400 4800 2400 6525 1950 7125 1950 7800" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="3e3 4800 3e3 6525 3600 7125 3600 7800" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="3837 5389 4125 5100 5400 5100" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="3889 5292 3826 5398 3932 5334" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="2112 4189 2400 3900 5400 3900" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="2164 4092 2101 4198 2207 4134" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="4800 5700 5400 5700" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="1800 3600 5400 3600" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="2700 4784 2700 4425 5400 4425" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="2670 4678 2700 4798 2730 4678" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="1967 7800 3583 7800" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="3478 7830 3598 7800 3478 7770" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-18.5,-16.294)" points="2072 7770 1952 7800 2072 7830" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<text x="2775" y="7725" font-family="sans-serif" font-size="144px" stroke="#000000" stroke-width=".025in" text-anchor="middle" xml:space="preserve">Dead band</text>
<text x="5400" y="5700" font-family="sans-serif" font-size="144px" stroke="#000000" stroke-width=".025in" xml:space="preserve">right saturation</text>
<text x="5400" y="3600" font-family="sans-serif" font-size="144px" stroke="#000000" stroke-width=".025in" xml:space="preserve">left saturation</text>
<text x="5400" y="3900" font-family="sans-serif" font-size="144px" stroke="#000000" stroke-width=".025in" xml:space="preserve">left coeff ( positive in that case )</text>
<text x="5475" y="5100" font-family="sans-serif" font-size="144px" stroke="#000000" stroke-width=".025in" xml:space="preserve">right coeff ( negative in that case )</text>
<text x="5400" y="4425" font-family="sans-serif" font-size="144px" stroke="#000000" stroke-width=".025in" xml:space="preserve">center</text>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,18 @@
.. include:: <isonum.txt>
======================
Linux Joystick support
======================
:Copyright: |copy| 1996-2000 Vojtech Pavlik <vojtech@ucw.cz> - Sponsored by SuSE
.. class:: toc-title
Table of Contents
.. toctree::
:maxdepth: 3
:numbered:
joystick
joystick-api

View File

@ -1,31 +1,54 @@
Joystick API Documentation -*-Text-*- .. _joystick-api:
Ragnar Hojland Espinosa =====================
<ragnar@macula.net> Programming Interface
=====================
7 Aug 1998 :Author: Ragnar Hojland Espinosa <ragnar@macula.net> - 7 Aug 1998
1. Initialization 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.
Initialization
==============
Open the joystick device following the usual semantics (that is, with open). Open the joystick device following the usual semantics (that is, with open).
Since the driver now reports events instead of polling for changes, Since the driver now reports events instead of polling for changes,
immediately after the open it will issue a series of synthetic events 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 (JS_EVENT_INIT) that you can read to obtain the initial state of the
joystick. joystick.
By default, the device is opened in blocking mode. By default, the device is opened in blocking mode::
int fd = open ("/dev/input/js0", O_RDONLY); int fd = open ("/dev/input/js0", O_RDONLY);
2. Event Reading Event Reading
~~~~~~~~~~~~~~~~ =============
::
struct js_event e; struct js_event e;
read (fd, &e, sizeof(e)); read (fd, &e, sizeof(e));
where js_event is defined as where js_event is defined as::
struct js_event { struct js_event {
__u32 time; /* event timestamp in milliseconds */ __u32 time; /* event timestamp in milliseconds */
@ -38,10 +61,10 @@ 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. more than one event per read as described in section 3.1.
2.1 js_event.type js_event.type
~~~~~~~~~~~~~~~~~ -------------
The possible values of ``type'' are The possible values of ``type`` are::
#define JS_EVENT_BUTTON 0x01 /* button pressed/released */ #define JS_EVENT_BUTTON 0x01 /* button pressed/released */
#define JS_EVENT_AXIS 0x02 /* joystick moved */ #define JS_EVENT_AXIS 0x02 /* joystick moved */
@ -49,47 +72,50 @@ The possible values of ``type'' are
As mentioned above, the driver will issue synthetic JS_EVENT_INIT ORed 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 events on open. That is, if it's issuing a INIT BUTTON event, the
current type value will be current type value will be::
int type = JS_EVENT_BUTTON | JS_EVENT_INIT; /* 0x81 */ int type = JS_EVENT_BUTTON | JS_EVENT_INIT; /* 0x81 */
If you choose not to differentiate between synthetic or real events If you choose not to differentiate between synthetic or real events
you can turn off the JS_EVENT_INIT bits you can turn off the JS_EVENT_INIT bits::
type &= ~JS_EVENT_INIT; /* 0x01 */ type &= ~JS_EVENT_INIT; /* 0x01 */
2.2 js_event.number js_event.number
~~~~~~~~~~~~~~~~~~~ ---------------
The values of ``number'' correspond to the axis or button that The values of ``number`` correspond to the axis or button that
generated the event. Note that they carry separate numeration (that generated the event. Note that they carry separate numeration (that
is, you have both an axis 0 and a button 0). Generally, is, you have both an axis 0 and a button 0). Generally,
number =============== =======
Axis number
=============== =======
1st Axis X 0 1st Axis X 0
1st Axis Y 1 1st Axis Y 1
2nd Axis X 2 2nd Axis X 2
2nd Axis Y 3 2nd Axis Y 3
...and so on ...and so on
=============== =======
Hats vary from one joystick type to another. Some can be moved in 8 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 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. independent axis, even if the hardware doesn't allow independent movement.
2.3 js_event.value js_event.value
~~~~~~~~~~~~~~~~~~ --------------
For an axis, ``value'' is a signed integer between -32767 and +32767 For an axis, ``value`` is a signed integer between -32767 and +32767
representing the position of the joystick along that axis. If you 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 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). 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 For a button, ``value`` for a press button event is 1 and for a release
button event is 0. button event is 0.
Though this Though this::
if (js_event.type == JS_EVENT_BUTTON) { if (js_event.type == JS_EVENT_BUTTON) {
buttons_state ^= (1 << js_event.number); buttons_state ^= (1 << js_event.number);
@ -97,6 +123,8 @@ Though this
may work well if you handle JS_EVENT_INIT events separately, may work well if you handle JS_EVENT_INIT events separately,
::
if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) { if ((js_event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) {
if (js_event.value) if (js_event.value)
buttons_state |= (1 << js_event.number); buttons_state |= (1 << js_event.number);
@ -109,17 +137,17 @@ have to write a separate handler for JS_EVENT_INIT events in the first
snippet, this ends up being shorter. snippet, this ends up being shorter.
2.4 js_event.time js_event.time
~~~~~~~~~~~~~~~~~ -------------
The time an event was generated is stored in ``js_event.time''. It's a 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 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 task of detecting double clicks, figuring out if movement of axis and button
presses happened at the same time, and similar. presses happened at the same time, and similar.
3. Reading Reading
~~~~~~~~~~ =======
If you open the device in blocking mode, a read will block (that is, 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 wait) forever until an event is generated and effectively read. There
@ -133,8 +161,8 @@ admittedly, a long time;)
b) open the device in non-blocking mode (O_NONBLOCK) b) open the device in non-blocking mode (O_NONBLOCK)
3.1 O_NONBLOCK O_NONBLOCK
~~~~~~~~~~~~~~ ----------
If read returns -1 when reading in O_NONBLOCK mode, this isn't 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 necessarily a "real" error (check errno(3)); it can just mean there
@ -143,6 +171,8 @@ all events on the queue (that is, until you get a -1).
For example, For example,
::
while (1) { while (1) {
while (read (fd, &e, sizeof(e)) > 0) { while (read (fd, &e, sizeof(e)) > 0) {
process_event (e); process_event (e);
@ -171,14 +201,17 @@ 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 synthetic events (JS_EVENT_INIT) will be generated to inform you of
the actual state of the joystick. the actual state of the joystick.
[As for version 1.2.8, the queue is circular and able to hold 64
.. note::
As of 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 events. You can increment this size bumping up JS_BUFF_SIZE in
joystick.h and recompiling the driver.] joystick.h and recompiling the driver.
In the above code, you might as well want to read more than one event 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 at a time using the typical read(2) functionality. For that, you would
replace the read above with something like replace the read above with something like::
struct js_event mybuffer[0xff]; struct js_event mybuffer[0xff];
int i = read (fd, mybuffer, sizeof(mybuffer)); int i = read (fd, mybuffer, sizeof(mybuffer));
@ -189,10 +222,10 @@ 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. process the events and keep reading it until you empty the driver queue.
4. IOCTLs IOCTLs
~~~~~~~~~ ======
The joystick driver defines the following ioctl(2) operations. The joystick driver defines the following ioctl(2) operations::
/* function 3rd arg */ /* function 3rd arg */
#define JSIOCGAXES /* get number of axes char */ #define JSIOCGAXES /* get number of axes char */
@ -202,31 +235,31 @@ The joystick driver defines the following ioctl(2) operations.
#define JSIOCSCORR /* set correction values &js_corr */ #define JSIOCSCORR /* set correction values &js_corr */
#define JSIOCGCORR /* get correction values &js_corr */ #define JSIOCGCORR /* get correction values &js_corr */
For example, to read the number of axes For example, to read the number of axes::
char number_of_axes; char number_of_axes;
ioctl (fd, JSIOCGAXES, &number_of_axes); ioctl (fd, JSIOCGAXES, &number_of_axes);
4.1 JSIOGCVERSION JSIOGCVERSION
~~~~~~~~~~~~~~~~~ -------------
JSIOGCVERSION is a good way to check in run-time whether the running 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 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 IOCTL will fail. For a compile-time decision, you can test the
JS_VERSION symbol JS_VERSION symbol::
#ifdef JS_VERSION #ifdef JS_VERSION
#if JS_VERSION > 0xsomething #if JS_VERSION > 0xsomething
4.2 JSIOCGNAME JSIOCGNAME
~~~~~~~~~~~~~~ ----------
JSIOCGNAME(len) allows you to get the name string of the joystick - the same 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 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 buffer provided by the application asking for the name. It is used to avoid
possible overrun should the name be too long. possible overrun should the name be too long::
char name[128]; char name[128];
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0) if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
@ -234,8 +267,8 @@ possible overrun should the name be too long.
printf("Name: %s\n", name); printf("Name: %s\n", name);
4.3 JSIOC[SG]CORR JSIOC[SG]CORR
~~~~~~~~~~~~~~~~~ -------------
For usage on JSIOC[SG]CORR I suggest you to look into jscal.c They are 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 not needed in a normal program, only in joystick calibration software
@ -246,7 +279,7 @@ warning in following releases of the driver.
Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold Both JSIOCSCORR and JSIOCGCORR expect &js_corr to be able to hold
information for all axis. That is, struct js_corr corr[MAX_AXIS]; information for all axis. That is, struct js_corr corr[MAX_AXIS];
struct js_corr is defined as struct js_corr is defined as::
struct js_corr { struct js_corr {
__s32 coef[8]; __s32 coef[8];
@ -254,17 +287,17 @@ struct js_corr is defined as
__u16 type; __u16 type;
}; };
and ``type'' and ``type``::
#define JS_CORR_NONE 0x00 /* returns raw values */ #define JS_CORR_NONE 0x00 /* returns raw values */
#define JS_CORR_BROKEN 0x01 /* broken line */ #define JS_CORR_BROKEN 0x01 /* broken line */
5. Backward compatibility Backward compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~ ======================
The 0.x joystick driver API is quite limited and its usage is deprecated. 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: The driver offers backward compatibility, though. Here's a quick summary::
struct JS_DATA_TYPE js; struct JS_DATA_TYPE js;
while (1) { while (1) {
@ -275,7 +308,7 @@ The driver offers backward compatibility, though. Here's a quick summary:
} }
As you can figure out from the example, the read returns immediately, As you can figure out from the example, the read returns immediately,
with the actual state of the joystick. with the actual state of the joystick::
struct JS_DATA_TYPE { struct JS_DATA_TYPE {
int buttons; /* immediate button state */ int buttons; /* immediate button state */
@ -283,12 +316,14 @@ with the actual state of the joystick.
int y; /* immediate y axis value */ int y; /* immediate y axis value */
}; };
and JS_RETURN is defined as and JS_RETURN is defined as::
#define JS_RETURN sizeof(struct JS_DATA_TYPE) #define JS_RETURN sizeof(struct JS_DATA_TYPE)
To test the state of the buttons, To test the state of the buttons,
::
first_button_state = js.buttons & 1; first_button_state = js.buttons & 1;
second_button_state = js.buttons & 2; second_button_state = js.buttons & 2;
@ -302,13 +337,12 @@ called Multisystem joysticks in this driver), under /dev/djsX. This driver
doesn't try to be compatible with that interface. doesn't try to be compatible with that interface.
6. Final Notes 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 ____/| Comments, additions, and specially corrections are welcome.
EOF \ 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 ;)

View File

@ -0,0 +1,585 @@
.. include:: <isonum.txt>
.. _joystick-doc:
Introduction
============
The joystick driver for Linux provides support for a variety of joysticks
and similar devices. It is based on a larger project aiming to support all
input devices in Linux.
The mailing list for the project is:
linux-input@vger.kernel.org
send "subscribe linux-input" to majordomo@vger.kernel.org to subscribe to it.
Usage
=====
For basic usage you just choose the right options in kernel config and
you should be set.
Utilities
---------
For testing and other purposes (for example serial devices), there is a set
of utilities, such as ``jstest``, ``jscal``, and ``evtest``,
usually packaged as ``joystick``, ``input-utils``, ``evtest``, and so on.
``inputattach`` utility is required if your joystick is connected to a
serial port.
Device nodes
------------
For applications to be able to use the joysticks, device nodes should be
created in /dev. Normally it is done automatically by the system, but
it can also be done by hand::
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
For testing with inpututils it's also convenient to create these::
mknod input/event0 c 13 64
mknod input/event1 c 13 65
mknod input/event2 c 13 66
mknod input/event3 c 13 67
Modules needed
--------------
For all joystick drivers to function, you'll need the userland interface
module in kernel, either loaded or compiled in::
modprobe joydev
For gameport joysticks, you'll have to load the gameport driver as well::
modprobe ns558
And for serial port joysticks, you'll need the serial input line
discipline module loaded and the inputattach utility started::
modprobe serport
inputattach -xxx /dev/tts/X &
In addition to that, you'll need the joystick driver module itself, most
usually you'll have an analog joystick::
modprobe analog
For automatic module loading, something like this might work - tailor to
your needs::
alias tty-ldisc-2 serport
alias char-major-13 input
above input joydev ns558 analog
options analog map=gamepad,none,2btn
Verifying that it works
-----------------------
For testing the joystick driver functionality, there is the jstest
program in the utilities package. You run it by typing::
jstest /dev/input/js0
And it should show a line with the joystick values, which update as you
move the stick, and press its buttons. The axes should all be zero when the
joystick is in the center position. They should not jitter by themselves to
other close values, and they also should be steady in any other position of
the stick. They should have the full range from -32767 to 32767. If all this
is met, then it's all fine, and you can play the games. :)
If it's not, then there might be a problem. Try to calibrate the joystick,
and if it still doesn't work, read the drivers section of this file, the
troubleshooting section, and the FAQ.
Calibration
-----------
For most joysticks you won't need any manual calibration, since the
joystick should be autocalibrated by the driver automagically. However, with
some analog joysticks, that either do not use linear resistors, or if you
want better precision, you can use the jscal program::
jscal -c /dev/input/js0
included in the joystick package to set better correction coefficients than
what the driver would choose itself.
After calibrating the joystick you can verify if you like the new
calibration using the jstest command, and if you do, you then can save the
correction coefficients into a file::
jscal -p /dev/input/js0 > /etc/joystick.cal
And add a line to your rc script executing that file::
source /etc/joystick.cal
This way, after the next reboot your joystick will remain calibrated. You
can also add the ``jscal -p`` line to your shutdown script.
HW specific driver information
==============================
In this section each of the separate hardware specific drivers is described.
Analog joysticks
----------------
The analog.c uses the standard analog inputs of the gameport, and thus
supports all standard joysticks and gamepads. It uses a very advanced
routine for this, allowing for data precision that can't be found on any
other system.
It also supports extensions like additional hats and buttons compatible
with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads. Saitek
Cyborg 'digital' joysticks are also supported by this driver, because
they're basically souped up CHF sticks.
However the only types that can be autodetected are:
* 2-axis, 4-button joystick
* 3-axis, 4-button joystick
* 4-axis, 4-button joystick
* Saitek Cyborg 'digital' joysticks
For other joystick types (more/less axes, hats, and buttons) support
you'll need to specify the types either on the kernel command line or on the
module command line, when inserting analog into the kernel. The
parameters are::
analog.map=<type1>,<type2>,<type3>,....
'type' is type of the joystick from the table below, defining joysticks
present on gameports in the system, starting with gameport0, second 'type'
entry defining joystick on gameport1 and so on.
========= =====================================================
Type Meaning
========= =====================================================
none No analog joystick on that port
auto Autodetect joystick
2btn 2-button n-axis joystick
y-joy Two 2-button 2-axis joysticks on an Y-cable
y-pad Two 2-button 2-axis gamepads on an Y-cable
fcs Thrustmaster FCS compatible joystick
chf Joystick with a CH Flightstick compatible hat
fullchf CH Flightstick compatible with two hats and 6 buttons
gamepad 4/6-button n-axis gamepad
gamepad8 8-button 2-axis gamepad
========= =====================================================
In case your joystick doesn't fit in any of the above categories, you can
specify the type as a number by combining the bits in the table below. This
is not recommended unless you really know what are you doing. It's not
dangerous, but not simple either.
==== =========================
Bit Meaning
==== =========================
0 Axis X1
1 Axis Y1
2 Axis X2
3 Axis Y2
4 Button A
5 Button B
6 Button C
7 Button D
8 CHF Buttons X and Y
9 CHF Hat 1
10 CHF Hat 2
11 FCS Hat
12 Pad Button X
13 Pad Button Y
14 Pad Button U
15 Pad Button V
16 Saitek F1-F4 Buttons
17 Saitek Digital Mode
19 GamePad
20 Joy2 Axis X1
21 Joy2 Axis Y1
22 Joy2 Axis X2
23 Joy2 Axis Y2
24 Joy2 Button A
25 Joy2 Button B
26 Joy2 Button C
27 Joy2 Button D
31 Joy2 GamePad
==== =========================
Microsoft SideWinder joysticks
------------------------------
Microsoft 'Digital Overdrive' protocol is supported by the sidewinder.c
module. All currently supported joysticks:
* Microsoft SideWinder 3D Pro
* Microsoft SideWinder Force Feedback Pro
* Microsoft SideWinder Force Feedback Wheel
* Microsoft SideWinder FreeStyle Pro
* Microsoft SideWinder GamePad (up to four, chained)
* Microsoft SideWinder Precision Pro
* Microsoft SideWinder Precision Pro USB
are autodetected, and thus no module parameters are needed.
There is one caveat with the 3D Pro. There are 9 buttons reported,
although the joystick has only 8. The 9th button is the mode switch on the
rear side of the joystick. However, moving it, you'll reset the joystick,
and make it unresponsive for about a one third of a second. Furthermore, the
joystick will also re-center itself, taking the position it was in during
this time as a new center position. Use it if you want, but think first.
The SideWinder Standard is not a digital joystick, and thus is supported
by the analog driver described above.
Logitech ADI devices
--------------------
Logitech ADI protocol is supported by the adi.c module. It should support
any Logitech device using this protocol. This includes, but is not limited
to:
* Logitech CyberMan 2
* Logitech ThunderPad Digital
* Logitech WingMan Extreme Digital
* Logitech WingMan Formula
* Logitech WingMan Interceptor
* Logitech WingMan GamePad
* Logitech WingMan GamePad USB
* Logitech WingMan GamePad Extreme
* Logitech WingMan Extreme Digital 3D
ADI devices are autodetected, and the driver supports up to two (any
combination of) devices on a single gameport, using an Y-cable or chained
together.
Logitech WingMan Joystick, Logitech WingMan Attack, Logitech WingMan
Extreme and Logitech WingMan ThunderPad are not digital joysticks and are
handled by the analog driver described above. Logitech WingMan Warrior and
Logitech Magellan are supported by serial drivers described below. Logitech
WingMan Force and Logitech WingMan Formula Force are supported by the
I-Force driver described below. Logitech CyberMan is not supported yet.
Gravis GrIP
-----------
Gravis GrIP protocol is supported by the grip.c module. It currently
supports:
* Gravis GamePad Pro
* Gravis BlackHawk Digital
* Gravis Xterminator
* Gravis Xterminator DualControl
All these devices are autodetected, and you can even use any combination
of up to two of these pads either chained together or using an Y-cable on a
single gameport.
GrIP MultiPort isn't supported yet. Gravis Stinger is a serial device and is
supported by the stinger driver. Other Gravis joysticks are supported by the
analog driver.
FPGaming A3D and MadCatz A3D
----------------------------
The Assassin 3D protocol created by FPGaming, is used both by FPGaming
themselves and is licensed to MadCatz. A3D devices are supported by the
a3d.c module. It currently supports:
* FPGaming Assassin 3D
* MadCatz Panther
* MadCatz Panther XL
All these devices are autodetected. Because the Assassin 3D and the Panther
allow connecting analog joysticks to them, you'll need to load the analog
driver as well to handle the attached joysticks.
The trackball should work with USB mousedev module as a normal mouse. See
the USB documentation for how to setup an USB mouse.
ThrustMaster DirectConnect (BSP)
--------------------------------
The TM DirectConnect (BSP) protocol is supported by the tmdc.c
module. This includes, but is not limited to:
* ThrustMaster Millennium 3D Interceptor
* ThrustMaster 3D Rage Pad
* ThrustMaster Fusion Digital Game Pad
Devices not directly supported, but hopefully working are:
* ThrustMaster FragMaster
* ThrustMaster Attack Throttle
If you have one of these, contact me.
TMDC devices are autodetected, and thus no parameters to the module
are needed. Up to two TMDC devices can be connected to one gameport, using
an Y-cable.
Creative Labs Blaster
---------------------
The Blaster protocol is supported by the cobra.c module. It supports only
the:
* Creative Blaster GamePad Cobra
Up to two of these can be used on a single gameport, using an Y-cable.
Genius Digital joysticks
------------------------
The Genius digitally communicating joysticks are supported by the gf2k.c
module. This includes:
* Genius Flight2000 F-23 joystick
* Genius Flight2000 F-31 joystick
* Genius G-09D gamepad
Other Genius digital joysticks are not supported yet, but support can be
added fairly easily.
InterAct Digital joysticks
--------------------------
The InterAct digitally communicating joysticks are supported by the
interact.c module. This includes:
* InterAct HammerHead/FX gamepad
* InterAct ProPad8 gamepad
Other InterAct digital joysticks are not supported yet, but support can be
added fairly easily.
PDPI Lightning 4 gamecards
--------------------------
PDPI Lightning 4 gamecards are supported by the lightning.c module.
Once the module is loaded, the analog driver can be used to handle the
joysticks. Digitally communicating joystick will work only on port 0, while
using Y-cables, you can connect up to 8 analog joysticks to a single L4
card, 16 in case you have two in your system.
Trident 4DWave / Aureal Vortex
------------------------------
Soundcards with a Trident 4DWave DX/NX or Aureal Vortex/Vortex2 chipsets
provide an "Enhanced Game Port" mode where the soundcard handles polling the
joystick. This mode is supported by the pcigame.c module. Once loaded the
analog driver can use the enhanced features of these gameports..
Crystal SoundFusion
-------------------
Soundcards with Crystal SoundFusion chipsets provide an "Enhanced Game
Port", much like the 4DWave or Vortex above. This, and also the normal mode
for the port of the SoundFusion is supported by the cs461x.c module.
SoundBlaster Live!
------------------
The Live! has a special PCI gameport, which, although it doesn't provide
any "Enhanced" stuff like 4DWave and friends, is quite a bit faster than
its ISA counterparts. It also requires special support, hence the
emu10k1-gp.c module for it instead of the normal ns558.c one.
SoundBlaster 64 and 128 - ES1370 and ES1371, ESS Solo1 and S3 SonicVibes
------------------------------------------------------------------------
These PCI soundcards have specific gameports. They are handled by the
sound drivers themselves. Make sure you select gameport support in the
joystick menu and sound card support in the sound menu for your appropriate
card.
Amiga
-----
Amiga joysticks, connected to an Amiga, are supported by the amijoy.c
driver. Since they can't be autodetected, the driver has a command line:
amijoy.map=<a>,<b>
a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of
the Amiga.
====== ===========================
Value Joystick type
====== ===========================
0 None
1 1-button digital joystick
====== ===========================
No more joystick types are supported now, but that should change in the
future if I get an Amiga in the reach of my fingers.
Game console and 8-bit pads and joysticks
-----------------------------------------
These pads and joysticks are not designed for PCs and other computers
Linux runs on, and usually require a special connector for attaching
them through a parallel port.
See :ref:`joystick-parport` for more info.
SpaceTec/LabTec devices
-----------------------
SpaceTec serial devices communicate using the SpaceWare protocol. It is
supported by the spaceorb.c and spaceball.c drivers. The devices currently
supported by spaceorb.c are:
* SpaceTec SpaceBall Avenger
* SpaceTec SpaceOrb 360
Devices currently supported by spaceball.c are:
* SpaceTec SpaceBall 4000 FLX
In addition to having the spaceorb/spaceball and serport modules in the
kernel, you also need to attach a serial port to it. to do that, run the
inputattach program::
inputattach --spaceorb /dev/tts/x &
or::
inputattach --spaceball /dev/tts/x &
where /dev/tts/x is the serial port which the device is connected to. After
doing this, the device will be reported and will start working.
There is one caveat with the SpaceOrb. The button #6, the on the bottom
side of the orb, although reported as an ordinary button, causes internal
recentering of the spaceorb, moving the zero point to the position in which
the ball is at the moment of pressing the button. So, think first before
you bind it to some other function.
SpaceTec SpaceBall 2003 FLX and 3003 FLX are not supported yet.
Logitech SWIFT devices
----------------------
The SWIFT serial protocol is supported by the warrior.c module. It
currently supports only the:
* Logitech WingMan Warrior
but in the future, Logitech CyberMan (the original one, not CM2) could be
supported as well. To use the module, you need to run inputattach after you
insert/compile the module into your kernel::
inputattach --warrior /dev/tts/x &
/dev/tts/x is the serial port your Warrior is attached to.
Magellan / Space Mouse
----------------------
The Magellan (or Space Mouse), manufactured by LogiCad3d (formerly Space
Systems), for many other companies (Logitech, HP, ...) is supported by the
joy-magellan module. It currently supports only the:
* Magellan 3D
* Space Mouse
models, the additional buttons on the 'Plus' versions are not supported yet.
To use it, you need to attach the serial port to the driver using the::
inputattach --magellan /dev/tts/x &
command. After that the Magellan will be detected, initialized, will beep,
and the /dev/input/jsX device should become usable.
I-Force devices
---------------
All I-Force devices are supported by the iforce module. This includes:
* AVB Mag Turbo Force
* AVB Top Shot Pegasus
* AVB Top Shot Force Feedback Racing Wheel
* Logitech WingMan Force
* Logitech WingMan Force Wheel
* Guillemot Race Leader Force Feedback
* Guillemot Force Feedback Racing Wheel
* Thrustmaster Motor Sport GT
To use it, you need to attach the serial port to the driver using the::
inputattach --iforce /dev/tts/x &
command. After that the I-Force device will be detected, and the
/dev/input/jsX device should become usable.
In case you're using the device via the USB port, the inputattach command
isn't needed.
The I-Force driver now supports force feedback via the event interface.
Please note that Logitech WingMan 3D devices are _not_ supported by this
module, rather by hid. Force feedback is not supported for those devices.
Logitech gamepads are also hid devices.
Gravis Stinger gamepad
----------------------
The Gravis Stinger serial port gamepad, designed for use with laptop
computers, is supported by the stinger.c module. To use it, attach the
serial port to the driver using::
inputattach --stinger /dev/tty/x &
where x is the number of the serial port.
Troubleshooting
===============
There is quite a high probability that you run into some problems. For
testing whether the driver works, if in doubt, use the jstest utility in
some of its modes. The most useful modes are "normal" - for the 1.x
interface, and "old" for the "0.x" interface. You run it by typing::
jstest --normal /dev/input/js0
jstest --old /dev/input/js0
Additionally you can do a test with the evtest utility::
evtest /dev/input/event0
Oh, and read the FAQ! :)
FAQ
===
:Q: Running 'jstest /dev/input/js0' results in "File not found" error. What's the
cause?
:A: The device files don't exist. Create them (see section 2.2).
:Q: Is it possible to connect my old Atari/Commodore/Amiga/console joystick
or pad that uses a 9-pin D-type cannon connector to the serial port of my
PC?
:A: Yes, it is possible, but it'll burn your serial port or the pad. It
won't work, of course.
:Q: My joystick doesn't work with Quake / Quake 2. What's the cause?
:A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses
for them.

View File

@ -1,542 +0,0 @@
Linux Joystick parport drivers v2.0
(c) 1998-2000 Vojtech Pavlik <vojtech@ucw.cz>
(c) 1998 Andree Borrmann <a.borrmann@tu-bs.de>
Sponsored by SuSE
----------------------------------------------------------------------------
0. Disclaimer
~~~~~~~~~~~~~
Any information in this file is provided as-is, without any guarantee that
it will be true. So, use it at your own risk. The possible damages that can
happen include burning your parallel port, and/or the sticks and joystick
and maybe even more. Like when a lightning kills you it is not our problem.
1. Intro
~~~~~~~~
The joystick parport drivers are used for joysticks and gamepads not
originally designed for PCs and other computers Linux runs on. Because of
that, PCs usually lack the right ports to connect these devices to. Parallel
port, because of its ability to change single bits at will, and providing
both output and input bits is the most suitable port on the PC for
connecting such devices.
2. Devices supported
~~~~~~~~~~~~~~~~~~~~
Many console and 8-bit computer gamepads and joysticks are supported. The
following subsections discuss usage of each.
2.1 NES and SNES
~~~~~~~~~~~~~~~~
The Nintendo Entertainment System and Super Nintendo Entertainment System
gamepads are widely available, and easy to get. Also, they are quite easy to
connect to a PC, and don't need much processing speed (108 us for NES and
165 us for SNES, compared to about 1000 us for PC gamepads) to communicate
with them.
All NES and SNES use the same synchronous serial protocol, clocked from
the computer's side (and thus timing insensitive). To allow up to 5 NES
and/or SNES gamepads and/or SNES mice connected to the parallel port at once,
the output lines of the parallel port are shared, while one of 5 available
input lines is assigned to each gamepad.
This protocol is handled by the gamecon.c driver, so that's the one
you'll use for NES, SNES gamepads and SNES mice.
The main problem with PC parallel ports is that they don't have +5V power
source on any of their pins. So, if you want a reliable source of power
for your pads, use either keyboard or joystick port, and make a pass-through
cable. You can also pull the power directly from the power supply (the red
wire is +5V).
If you want to use the parallel port only, you can take the power is from
some data pin. For most gamepad and parport implementations only one pin is
needed, and I'd recommend pin 9 for that, the highest data bit. On the other
hand, if you are not planning to use anything else than NES / SNES on the
port, anything between and including pin 4 and pin 9 will work.
(pin 9) -----> Power
Unfortunately, there are pads that need a lot more of power, and parallel
ports that can't give much current through the data pins. If this is your
case, you'll need to use diodes (as a prevention of destroying your parallel
port), and combine the currents of two or more data bits together.
Diodes
(pin 9) ----|>|-------+------> Power
|
(pin 8) ----|>|-------+
|
(pin 7) ----|>|-------+
|
<and so on> :
|
(pin 4) ----|>|-------+
Ground is quite easy. On PC's parallel port the ground is on any of the
pins from pin 18 to pin 25. So use any pin of these you like for the ground.
(pin 18) -----> Ground
NES and SNES pads have two input bits, Clock and Latch, which drive the
serial transfer. These are connected to pins 2 and 3 of the parallel port,
respectively.
(pin 2) -----> Clock
(pin 3) -----> Latch
And the last thing is the NES / SNES data wire. Only that isn't shared and
each pad needs its own data pin. The parallel port pins are:
(pin 10) -----> Pad 1 data
(pin 11) -----> Pad 2 data
(pin 12) -----> Pad 3 data
(pin 13) -----> Pad 4 data
(pin 15) -----> Pad 5 data
Note that pin 14 is not used, since it is not an input pin on the parallel
port.
This is everything you need on the PC's side of the connection, now on to
the gamepads side. The NES and SNES have different connectors. Also, there
are quite a lot of NES clones, and because Nintendo used proprietary
connectors for their machines, the cloners couldn't and used standard D-Cannon
connectors. Anyway, if you've got a gamepad, and it has buttons A, B, Turbo
A, Turbo B, Select and Start, and is connected through 5 wires, then it is
either a NES or NES clone and will work with this connection. SNES gamepads
also use 5 wires, but have more buttons. They will work as well, of course.
Pinout for NES gamepads Pinout for SNES gamepads and mice
+----> Power +-----------------------\
| 7 | o o o o | x x o | 1
5 +---------+ 7 +-----------------------/
| x x o \ | | | | |
| o o o o | | | | | +-> Ground
4 +------------+ 1 | | | +------------> Data
| | | | | | +---------------> Latch
| | | +-> Ground | +------------------> Clock
| | +----> Clock +---------------------> Power
| +-------> Latch
+----------> Data
Pinout for NES clone (db9) gamepads Pinout for NES clone (db15) gamepads
+---------> Clock +-----------------> Data
| +-------> Latch | +---> Ground
| | +-----> Data | |
| | | ___________________
_____________ 8 \ o x x x x x x o / 1
5 \ x o o o x / 1 \ o x x o x x o /
\ x o x o / 15 `~~~~~~~~~~~~~' 9
9 `~~~~~~~' 6 | | |
| | | | +----> Clock
| +----> Power | +----------> Latch
+--------> Ground +----------------> Power
2.2 Multisystem joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~
In the era of 8-bit machines, there was something like de-facto standard
for joystick ports. They were all digital, and all used D-Cannon 9 pin
connectors (db9). Because of that, a single joystick could be used without
hassle on Atari (130, 800XE, 800XL, 2600, 7200), Amiga, Commodore C64,
Amstrad CPC, Sinclair ZX Spectrum and many other machines. That's why these
joysticks are called "Multisystem".
Now their pinout:
+---------> Right
| +-------> Left
| | +-----> Down
| | | +---> Up
| | | |
_____________
5 \ x o o o o / 1
\ x o x o /
9 `~~~~~~~' 6
| |
| +----> Button
+--------> Ground
However, as time passed, extensions to this standard developed, and these
were not compatible with each other:
Atari 130, 800/XL/XE MSX
+-----------> Power
+---------> Right | +---------> Right
| +-------> Left | | +-------> Left
| | +-----> Down | | | +-----> Down
| | | +---> Up | | | | +---> Up
| | | | | | | | |
_____________ _____________
5 \ x o o o o / 1 5 \ o o o o o / 1
\ x o o o / \ o o o o /
9 `~~~~~~~' 6 9 `~~~~~~~' 6
| | | | | | |
| | +----> Button | | | +----> Button 1
| +------> Power | | +------> Button 2
+--------> Ground | +--------> Output 3
+----------> Ground
Amstrad CPC Commodore C64
+-----------> Analog Y
+---------> Right | +---------> Right
| +-------> Left | | +-------> Left
| | +-----> Down | | | +-----> Down
| | | +---> Up | | | | +---> Up
| | | | | | | | |
_____________ _____________
5 \ x o o o o / 1 5 \ o o o o o / 1
\ x o o o / \ o o o o /
9 `~~~~~~~' 6 9 `~~~~~~~' 6
| | | | | | |
| | +----> Button 1 | | | +----> Button
| +------> Button 2 | | +------> Power
+--------> Ground | +--------> Ground
+----------> Analog X
Sinclair Spectrum +2A/+3 Amiga 1200
+-----------> Up +-----------> Button 3
| +---------> Fire | +---------> Right
| | | | +-------> Left
| | +-----> Ground | | | +-----> Down
| | | | | | | +---> Up
| | | | | | | |
_____________ _____________
5 \ o o x o x / 1 5 \ o o o o o / 1
\ o o o o / \ o o o o /
9 `~~~~~~~' 6 9 `~~~~~~~' 6
| | | | | | | |
| | | +----> Right | | | +----> Button 1
| | +------> Left | | +------> Power
| +--------> Ground | +--------> Ground
+----------> Down +----------> Button 2
And there were many others.
2.2.1 Multisystem joysticks using db9.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For the Multisystem joysticks, and their derivatives, the db9.c driver
was written. It allows only one joystick / gamepad per parallel port, but
the interface is easy to build and works with almost anything.
For the basic 1-button Multisystem joystick you connect its wires to the
parallel port like this:
(pin 1) -----> Power
(pin 18) -----> Ground
(pin 2) -----> Up
(pin 3) -----> Down
(pin 4) -----> Left
(pin 5) -----> Right
(pin 6) -----> Button 1
However, if the joystick is switch based (eg. clicks when you move it),
you might or might not, depending on your parallel port, need 10 kOhm pullup
resistors on each of the direction and button signals, like this:
(pin 2) ------------+------> Up
Resistor |
(pin 1) --[10kOhm]--+
Try without, and if it doesn't work, add them. For TTL based joysticks /
gamepads the pullups are not needed.
For joysticks with two buttons you connect the second button to pin 7 on
the parallel port.
(pin 7) -----> Button 2
And that's it.
On a side note, if you have already built a different adapter for use with
the digital joystick driver 0.8.0.2, this is also supported by the db9.c
driver, as device type 8. (See section 3.2)
2.2.2 Multisystem joysticks using gamecon.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For some people just one joystick per parallel port is not enough, and/or
want to use them on one parallel port together with NES/SNES/PSX pads. This is
possible using the gamecon.c. It supports up to 5 devices of the above types,
including 1 and 2 buttons Multisystem joysticks.
However, there is nothing for free. To allow more sticks to be used at
once, you need the sticks to be purely switch based (that is non-TTL), and
not to need power. Just a plain simple six switches inside. If your
joystick can do more (eg. turbofire) you'll need to disable it totally first
if you want to use gamecon.c.
Also, the connection is a bit more complex. You'll need a bunch of diodes,
and one pullup resistor. First, you connect the Directions and the button
the same as for db9, however with the diodes between.
Diodes
(pin 2) -----|<|----> Up
(pin 3) -----|<|----> Down
(pin 4) -----|<|----> Left
(pin 5) -----|<|----> Right
(pin 6) -----|<|----> Button 1
For two button sticks you also connect the other button.
(pin 7) -----|<|----> Button 2
And finally, you connect the Ground wire of the joystick, like done in
this little schematic to Power and Data on the parallel port, as described
for the NES / SNES pads in section 2.1 of this file - that is, one data pin
for each joystick. The power source is shared.
Data ------------+-----> Ground
Resistor |
Power --[10kOhm]--+
And that's all, here we go!
2.2.3 Multisystem joysticks using turbografx.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The TurboGraFX interface, designed by
Steffen Schwenke <schwenke@burg-halle.de>
allows up to 7 Multisystem joysticks connected to the parallel port. In
Steffen's version, there is support for up to 5 buttons per joystick. However,
since this doesn't work reliably on all parallel ports, the turbografx.c driver
supports only one button per joystick. For more information on how to build the
interface, see
http://www2.burg-halle.de/~schwenke/parport.html
2.3 Sony Playstation
~~~~~~~~~~~~~~~~~~~~
The PSX controller is supported by the gamecon.c. Pinout of the PSX
controller (compatible with DirectPadPro):
+---------+---------+---------+
9 | o o o | o o o | o o o | 1 parallel
\________|_________|________/ port pins
| | | | | |
| | | | | +--------> Clock --- (4)
| | | | +------------> Select --- (3)
| | | +---------------> Power --- (5-9)
| | +------------------> Ground --- (18-25)
| +-------------------------> Command --- (2)
+----------------------------> Data --- (one of 10,11,12,13,15)
The driver supports these controllers:
* Standard PSX Pad
* NegCon PSX Pad
* Analog PSX Pad (red mode)
* Analog PSX Pad (green mode)
* PSX Rumble Pad
* PSX DDR Pad
2.4 Sega
~~~~~~~~
All the Sega controllers are more or less based on the standard 2-button
Multisystem joystick. However, since they don't use switches and use TTL
logic, the only driver usable with them is the db9.c driver.
2.4.1 Sega Master System
~~~~~~~~~~~~~~~~~~~~~~~~
The SMS gamepads are almost exactly the same as normal 2-button
Multisystem joysticks. Set the driver to Multi2 mode, use the corresponding
parallel port pins, and the following schematic:
+-----------> Power
| +---------> Right
| | +-------> Left
| | | +-----> Down
| | | | +---> Up
| | | | |
_____________
5 \ o o o o o / 1
\ o o x o /
9 `~~~~~~~' 6
| | |
| | +----> Button 1
| +--------> Ground
+----------> Button 2
2.4.2 Sega Genesis aka MegaDrive
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Sega Genesis (in Europe sold as Sega MegaDrive) pads are an extension
to the Sega Master System pads. They use more buttons (3+1, 5+1, 6+1). Use
the following schematic:
+-----------> Power
| +---------> Right
| | +-------> Left
| | | +-----> Down
| | | | +---> Up
| | | | |
_____________
5 \ o o o o o / 1
\ o o o o /
9 `~~~~~~~' 6
| | | |
| | | +----> Button 1
| | +------> Select
| +--------> Ground
+----------> Button 2
The Select pin goes to pin 14 on the parallel port.
(pin 14) -----> Select
The rest is the same as for Multi2 joysticks using db9.c
2.4.3 Sega Saturn
~~~~~~~~~~~~~~~~~
Sega Saturn has eight buttons, and to transfer that, without hacks like
Genesis 6 pads use, it needs one more select pin. Anyway, it is still
handled by the db9.c driver. Its pinout is very different from anything
else. Use this schematic:
+-----------> Select 1
| +---------> Power
| | +-------> Up
| | | +-----> Down
| | | | +---> Ground
| | | | |
_____________
5 \ o o o o o / 1
\ o o o o /
9 `~~~~~~~' 6
| | | |
| | | +----> Select 2
| | +------> Right
| +--------> Left
+----------> Power
Select 1 is pin 14 on the parallel port, Select 2 is pin 16 on the
parallel port.
(pin 14) -----> Select 1
(pin 16) -----> Select 2
The other pins (Up, Down, Right, Left, Power, Ground) are the same as for
Multi joysticks using db9.c
3. The drivers
~~~~~~~~~~~~~~
There are three drivers for the parallel port interfaces. Each, as
described above, allows to connect a different group of joysticks and pads.
Here are described their command lines:
3.1 gamecon.c
~~~~~~~~~~~~~
Using gamecon.c you can connect up to five devices to one parallel port. It
uses the following kernel/module command line:
gamecon.map=port,pad1,pad2,pad3,pad4,pad5
Where 'port' the number of the parport interface (eg. 0 for parport0).
And 'pad1' to 'pad5' are pad types connected to different data input pins
(10,11,12,13,15), as described in section 2.1 of this file.
The types are:
Type | Joystick/Pad
--------------------
0 | None
1 | SNES pad
2 | NES pad
4 | Multisystem 1-button joystick
5 | Multisystem 2-button joystick
6 | N64 pad
7 | Sony PSX controller
8 | Sony PSX DDR controller
9 | SNES mouse
The exact type of the PSX controller type is autoprobed when used, so
hot swapping should work (but is not recommended).
Should you want to use more than one of parallel ports at once, you can use
gamecon.map2 and gamecon.map3 as additional command line parameters for two
more parallel ports.
There are two options specific to PSX driver portion. gamecon.psx_delay sets
the command delay when talking to the controllers. The default of 25 should
work but you can try lowering it for better performance. If your pads don't
respond try raising it until they work. Setting the type to 8 allows the
driver to be used with Dance Dance Revolution or similar games. Arrow keys are
registered as key presses instead of X and Y axes.
3.2 db9.c
~~~~~~~~~
Apart from making an interface, there is nothing difficult on using the
db9.c driver. It uses the following kernel/module command line:
db9.dev=port,type
Where 'port' is the number of the parport interface (eg. 0 for parport0).
Caveat here: This driver only works on bidirectional parallel ports. If
your parallel port is recent enough, you should have no trouble with this.
Old parallel ports may not have this feature.
'Type' is the type of joystick or pad attached:
Type | Joystick/Pad
--------------------
0 | None
1 | Multisystem 1-button joystick
2 | Multisystem 2-button joystick
3 | Genesis pad (3+1 buttons)
5 | Genesis pad (5+1 buttons)
6 | Genesis pad (6+2 buttons)
7 | Saturn pad (8 buttons)
8 | Multisystem 1-button joystick (v0.8.0.2 pin-out)
9 | Two Multisystem 1-button joysticks (v0.8.0.2 pin-out)
10 | Amiga CD32 pad
Should you want to use more than one of these joysticks/pads at once, you
can use db9.dev2 and db9.dev3 as additional command line parameters for two
more joysticks/pads.
3.3 turbografx.c
~~~~~~~~~~~~~~~~
The turbografx.c driver uses a very simple kernel/module command line:
turbografx.map=port,js1,js2,js3,js4,js5,js6,js7
Where 'port' is the number of the parport interface (eg. 0 for parport0).
'jsX' is the number of buttons the Multisystem joysticks connected to the
interface ports 1-7 have. For a standard multisystem joystick, this is 1.
Should you want to use more than one of these interfaces at once, you can
use turbografx.map2 and turbografx.map3 as additional command line parameters
for two more interfaces.
3.4 PC parallel port pinout
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.----------------------------------------.
At the PC: \ 13 12 11 10 9 8 7 6 5 4 3 2 1 /
\ 25 24 23 22 21 20 19 18 17 16 15 14 /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Pin | Name | Description
~~~~~~|~~~~~~~~~|~~~~~~~~~~
1 | /STROBE | Strobe
2-9 | D0-D7 | Data Bit 0-7
10 | /ACK | Acknowledge
11 | BUSY | Busy
12 | PE | Paper End
13 | SELIN | Select In
14 | /AUTOFD | Autofeed
15 | /ERROR | Error
16 | /INIT | Initialize
17 | /SEL | Select
18-25 | GND | Signal Ground
3.5 End
~~~~~~~
That's all, folks! Have fun!

View File

@ -1,586 +0,0 @@
Linux Joystick driver v2.0.0
(c) 1996-2000 Vojtech Pavlik <vojtech@ucw.cz>
Sponsored by SuSE
----------------------------------------------------------------------------
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. Intro
~~~~~~~~
The joystick driver for Linux provides support for a variety of joysticks
and similar devices. It is based on a larger project aiming to support all
input devices in Linux.
Should you encounter any problems while using the driver, or joysticks
this driver can't make complete use of, I'm very interested in hearing about
them. Bug reports and success stories are also welcome.
The input project website is at:
http://atrey.karlin.mff.cuni.cz/~vojtech/input/
There is also a mailing list for the driver at:
listproc@atrey.karlin.mff.cuni.cz
send "subscribe linux-joystick Your Name" to subscribe to it.
2. Usage
~~~~~~~~
For basic usage you just choose the right options in kernel config and
you should be set.
2.1 inpututils
~~~~~~~~~~~~~~
For testing and other purposes (for example serial devices), a set of
utilities is available at the abovementioned website. I suggest you download
and install it before going on.
2.2 Device nodes
~~~~~~~~~~~~~~~~
For applications to be able to use the joysticks,
you'll have to manually create these nodes in /dev:
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
For testing with inpututils it's also convenient to create these:
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.4 Modules needed
~~~~~~~~~~~~~~~~~~
For all joystick drivers to function, you'll need the userland interface
module in kernel, either loaded or compiled in:
modprobe joydev
For gameport joysticks, you'll have to load the gameport driver as well;
modprobe ns558
And for serial port joysticks, you'll need the serial input line
discipline module loaded and the inputattach utility started:
modprobe serport
inputattach -xxx /dev/tts/X &
In addition to that, you'll need the joystick driver module itself, most
usually you'll have an analog joystick:
modprobe analog
For automatic module loading, something like this might work - tailor to
your needs:
alias tty-ldisc-2 serport
alias char-major-13 input
above input joydev ns558 analog
options analog map=gamepad,none,2btn
2.5 Verifying that it works
~~~~~~~~~~~~~~~~~~~~~~~~~~~
For testing the joystick driver functionality, there is the jstest
program in the utilities package. You run it by typing:
jstest /dev/input/js0
And it should show a line with the joystick values, which update as you
move the stick, and press its buttons. The axes should all be zero when the
joystick is in the center position. They should not jitter by themselves to
other close values, and they also should be steady in any other position of
the stick. They should have the full range from -32767 to 32767. If all this
is met, then it's all fine, and you can play the games. :)
If it's not, then there might be a problem. Try to calibrate the joystick,
and if it still doesn't work, read the drivers section of this file, the
troubleshooting section, and the FAQ.
2.6. Calibration
~~~~~~~~~~~~~~~~
For most joysticks you won't need any manual calibration, since the
joystick should be autocalibrated by the driver automagically. However, with
some analog joysticks, that either do not use linear resistors, or if you
want better precision, you can use the jscal program
jscal -c /dev/input/js0
included in the joystick package to set better correction coefficients than
what the driver would choose itself.
After calibrating the joystick you can verify if you like the new
calibration using the jstest command, and if you do, you then can save the
correction coefficients into a file
jscal -p /dev/input/js0 > /etc/joystick.cal
And add a line to your rc script executing that file
source /etc/joystick.cal
This way, after the next reboot your joystick will remain calibrated. You
can also add the jscal -p line to your shutdown script.
3. HW specific driver information
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this section each of the separate hardware specific drivers is described.
3.1 Analog joysticks
~~~~~~~~~~~~~~~~~~~~
The analog.c uses the standard analog inputs of the gameport, and thus
supports all standard joysticks and gamepads. It uses a very advanced
routine for this, allowing for data precision that can't be found on any
other system.
It also supports extensions like additional hats and buttons compatible
with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads. Saitek
Cyborg 'digital' joysticks are also supported by this driver, because
they're basically souped up CHF sticks.
However the only types that can be autodetected are:
* 2-axis, 4-button joystick
* 3-axis, 4-button joystick
* 4-axis, 4-button joystick
* Saitek Cyborg 'digital' joysticks
For other joystick types (more/less axes, hats, and buttons) support
you'll need to specify the types either on the kernel command line or on the
module command line, when inserting analog into the kernel. The
parameters are:
analog.map=<type1>,<type2>,<type3>,....
'type' is type of the joystick from the table below, defining joysticks
present on gameports in the system, starting with gameport0, second 'type'
entry defining joystick on gameport1 and so on.
Type | Meaning
-----------------------------------
none | No analog joystick on that port
auto | Autodetect joystick
2btn | 2-button n-axis joystick
y-joy | Two 2-button 2-axis joysticks on an Y-cable
y-pad | Two 2-button 2-axis gamepads on an Y-cable
fcs | Thrustmaster FCS compatible joystick
chf | Joystick with a CH Flightstick compatible hat
fullchf | CH Flightstick compatible with two hats and 6 buttons
gamepad | 4/6-button n-axis gamepad
gamepad8 | 8-button 2-axis gamepad
In case your joystick doesn't fit in any of the above categories, you can
specify the type as a number by combining the bits in the table below. This
is not recommended unless you really know what are you doing. It's not
dangerous, but not simple either.
Bit | Meaning
--------------------------
0 | Axis X1
1 | Axis Y1
2 | Axis X2
3 | Axis Y2
4 | Button A
5 | Button B
6 | Button C
7 | Button D
8 | CHF Buttons X and Y
9 | CHF Hat 1
10 | CHF Hat 2
11 | FCS Hat
12 | Pad Button X
13 | Pad Button Y
14 | Pad Button U
15 | Pad Button V
16 | Saitek F1-F4 Buttons
17 | Saitek Digital Mode
19 | GamePad
20 | Joy2 Axis X1
21 | Joy2 Axis Y1
22 | Joy2 Axis X2
23 | Joy2 Axis Y2
24 | Joy2 Button A
25 | Joy2 Button B
26 | Joy2 Button C
27 | Joy2 Button D
31 | Joy2 GamePad
3.2 Microsoft SideWinder joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Microsoft 'Digital Overdrive' protocol is supported by the sidewinder.c
module. All currently supported joysticks:
* Microsoft SideWinder 3D Pro
* Microsoft SideWinder Force Feedback Pro
* Microsoft SideWinder Force Feedback Wheel
* Microsoft SideWinder FreeStyle Pro
* Microsoft SideWinder GamePad (up to four, chained)
* Microsoft SideWinder Precision Pro
* Microsoft SideWinder Precision Pro USB
are autodetected, and thus no module parameters are needed.
There is one caveat with the 3D Pro. There are 9 buttons reported,
although the joystick has only 8. The 9th button is the mode switch on the
rear side of the joystick. However, moving it, you'll reset the joystick,
and make it unresponsive for about a one third of a second. Furthermore, the
joystick will also re-center itself, taking the position it was in during
this time as a new center position. Use it if you want, but think first.
The SideWinder Standard is not a digital joystick, and thus is supported
by the analog driver described above.
3.3 Logitech ADI devices
~~~~~~~~~~~~~~~~~~~~~~~~
Logitech ADI protocol is supported by the adi.c module. It should support
any Logitech device using this protocol. This includes, but is not limited
to:
* Logitech CyberMan 2
* Logitech ThunderPad Digital
* Logitech WingMan Extreme Digital
* Logitech WingMan Formula
* Logitech WingMan Interceptor
* Logitech WingMan GamePad
* Logitech WingMan GamePad USB
* Logitech WingMan GamePad Extreme
* Logitech WingMan Extreme Digital 3D
ADI devices are autodetected, and the driver supports up to two (any
combination of) devices on a single gameport, using an Y-cable or chained
together.
Logitech WingMan Joystick, Logitech WingMan Attack, Logitech WingMan
Extreme and Logitech WingMan ThunderPad are not digital joysticks and are
handled by the analog driver described above. Logitech WingMan Warrior and
Logitech Magellan are supported by serial drivers described below. Logitech
WingMan Force and Logitech WingMan Formula Force are supported by the
I-Force driver described below. Logitech CyberMan is not supported yet.
3.4 Gravis GrIP
~~~~~~~~~~~~~~~
Gravis GrIP protocol is supported by the grip.c module. It currently
supports:
* Gravis GamePad Pro
* Gravis BlackHawk Digital
* Gravis Xterminator
* Gravis Xterminator DualControl
All these devices are autodetected, and you can even use any combination
of up to two of these pads either chained together or using an Y-cable on a
single gameport.
GrIP MultiPort isn't supported yet. Gravis Stinger is a serial device and is
supported by the stinger driver. Other Gravis joysticks are supported by the
analog driver.
3.5 FPGaming A3D and MadCatz A3D
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Assassin 3D protocol created by FPGaming, is used both by FPGaming
themselves and is licensed to MadCatz. A3D devices are supported by the
a3d.c module. It currently supports:
* FPGaming Assassin 3D
* MadCatz Panther
* MadCatz Panther XL
All these devices are autodetected. Because the Assassin 3D and the Panther
allow connecting analog joysticks to them, you'll need to load the analog
driver as well to handle the attached joysticks.
The trackball should work with USB mousedev module as a normal mouse. See
the USB documentation for how to setup an USB mouse.
3.6 ThrustMaster DirectConnect (BSP)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The TM DirectConnect (BSP) protocol is supported by the tmdc.c
module. This includes, but is not limited to:
* ThrustMaster Millennium 3D Interceptor
* ThrustMaster 3D Rage Pad
* ThrustMaster Fusion Digital Game Pad
Devices not directly supported, but hopefully working are:
* ThrustMaster FragMaster
* ThrustMaster Attack Throttle
If you have one of these, contact me.
TMDC devices are autodetected, and thus no parameters to the module
are needed. Up to two TMDC devices can be connected to one gameport, using
an Y-cable.
3.7 Creative Labs Blaster
~~~~~~~~~~~~~~~~~~~~~~~~~
The Blaster protocol is supported by the cobra.c module. It supports only
the:
* Creative Blaster GamePad Cobra
Up to two of these can be used on a single gameport, using an Y-cable.
3.8 Genius Digital joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Genius digitally communicating joysticks are supported by the gf2k.c
module. This includes:
* Genius Flight2000 F-23 joystick
* Genius Flight2000 F-31 joystick
* Genius G-09D gamepad
Other Genius digital joysticks are not supported yet, but support can be
added fairly easily.
3.9 InterAct Digital joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The InterAct digitally communicating joysticks are supported by the
interact.c module. This includes:
* InterAct HammerHead/FX gamepad
* InterAct ProPad8 gamepad
Other InterAct digital joysticks are not supported yet, but support can be
added fairly easily.
3.10 PDPI Lightning 4 gamecards
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PDPI Lightning 4 gamecards are supported by the lightning.c module.
Once the module is loaded, the analog driver can be used to handle the
joysticks. Digitally communicating joystick will work only on port 0, while
using Y-cables, you can connect up to 8 analog joysticks to a single L4
card, 16 in case you have two in your system.
3.11 Trident 4DWave / Aureal Vortex
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Soundcards with a Trident 4DWave DX/NX or Aureal Vortex/Vortex2 chipsets
provide an "Enhanced Game Port" mode where the soundcard handles polling the
joystick. This mode is supported by the pcigame.c module. Once loaded the
analog driver can use the enhanced features of these gameports..
3.13 Crystal SoundFusion
~~~~~~~~~~~~~~~~~~~~~~~~
Soundcards with Crystal SoundFusion chipsets provide an "Enhanced Game
Port", much like the 4DWave or Vortex above. This, and also the normal mode
for the port of the SoundFusion is supported by the cs461x.c module.
3.14 SoundBlaster Live!
~~~~~~~~~~~~~~~~~~~~~~~~
The Live! has a special PCI gameport, which, although it doesn't provide
any "Enhanced" stuff like 4DWave and friends, is quite a bit faster than
its ISA counterparts. It also requires special support, hence the
emu10k1-gp.c module for it instead of the normal ns558.c one.
3.15 SoundBlaster 64 and 128 - ES1370 and ES1371, ESS Solo1 and S3 SonicVibes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These PCI soundcards have specific gameports. They are handled by the
sound drivers themselves. Make sure you select gameport support in the
joystick menu and sound card support in the sound menu for your appropriate
card.
3.16 Amiga
~~~~~~~~~~
Amiga joysticks, connected to an Amiga, are supported by the amijoy.c
driver. Since they can't be autodetected, the driver has a command line.
amijoy.map=<a>,<b>
a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of
the Amiga.
Value | Joystick type
---------------------
0 | None
1 | 1-button digital joystick
No more joystick types are supported now, but that should change in the
future if I get an Amiga in the reach of my fingers.
3.17 Game console and 8-bit pads and joysticks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See joystick-parport.txt for more info.
3.18 SpaceTec/LabTec devices
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SpaceTec serial devices communicate using the SpaceWare protocol. It is
supported by the spaceorb.c and spaceball.c drivers. The devices currently
supported by spaceorb.c are:
* SpaceTec SpaceBall Avenger
* SpaceTec SpaceOrb 360
Devices currently supported by spaceball.c are:
* SpaceTec SpaceBall 4000 FLX
In addition to having the spaceorb/spaceball and serport modules in the
kernel, you also need to attach a serial port to it. to do that, run the
inputattach program:
inputattach --spaceorb /dev/tts/x &
or
inputattach --spaceball /dev/tts/x &
where /dev/tts/x is the serial port which the device is connected to. After
doing this, the device will be reported and will start working.
There is one caveat with the SpaceOrb. The button #6, the on the bottom
side of the orb, although reported as an ordinary button, causes internal
recentering of the spaceorb, moving the zero point to the position in which
the ball is at the moment of pressing the button. So, think first before
you bind it to some other function.
SpaceTec SpaceBall 2003 FLX and 3003 FLX are not supported yet.
3.19 Logitech SWIFT devices
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The SWIFT serial protocol is supported by the warrior.c module. It
currently supports only the:
* Logitech WingMan Warrior
but in the future, Logitech CyberMan (the original one, not CM2) could be
supported as well. To use the module, you need to run inputattach after you
insert/compile the module into your kernel:
inputattach --warrior /dev/tts/x &
/dev/tts/x is the serial port your Warrior is attached to.
3.20 Magellan / Space Mouse
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Magellan (or Space Mouse), manufactured by LogiCad3d (formerly Space
Systems), for many other companies (Logitech, HP, ...) is supported by the
joy-magellan module. It currently supports only the:
* Magellan 3D
* Space Mouse
models, the additional buttons on the 'Plus' versions are not supported yet.
To use it, you need to attach the serial port to the driver using the
inputattach --magellan /dev/tts/x &
command. After that the Magellan will be detected, initialized, will beep,
and the /dev/input/jsX device should become usable.
3.21 I-Force devices
~~~~~~~~~~~~~~~~~~~~
All I-Force devices are supported by the iforce module. This includes:
* AVB Mag Turbo Force
* AVB Top Shot Pegasus
* AVB Top Shot Force Feedback Racing Wheel
* Logitech WingMan Force
* Logitech WingMan Force Wheel
* Guillemot Race Leader Force Feedback
* Guillemot Force Feedback Racing Wheel
* Thrustmaster Motor Sport GT
To use it, you need to attach the serial port to the driver using the
inputattach --iforce /dev/tts/x &
command. After that the I-Force device will be detected, and the
/dev/input/jsX device should become usable.
In case you're using the device via the USB port, the inputattach command
isn't needed.
The I-Force driver now supports force feedback via the event interface.
Please note that Logitech WingMan *3D devices are _not_ supported by this
module, rather by hid. Force feedback is not supported for those devices.
Logitech gamepads are also hid devices.
3.22 Gravis Stinger gamepad
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Gravis Stinger serial port gamepad, designed for use with laptop
computers, is supported by the stinger.c module. To use it, attach the
serial port to the driver using:
inputattach --stinger /dev/tty/x &
where x is the number of the serial port.
4. Troubleshooting
~~~~~~~~~~~~~~~~~~
There is quite a high probability that you run into some problems. For
testing whether the driver works, if in doubt, use the jstest utility in
some of its modes. The most useful modes are "normal" - for the 1.x
interface, and "old" for the "0.x" interface. You run it by typing:
jstest --normal /dev/input/js0
jstest --old /dev/input/js0
Additionally you can do a test with the evtest utility:
evtest /dev/input/event0
Oh, and read the FAQ! :)
5. FAQ
~~~~~~
Q: Running 'jstest /dev/input/js0' results in "File not found" error. What's the
cause?
A: The device files don't exist. Create them (see section 2.2).
Q: Is it possible to connect my old Atari/Commodore/Amiga/console joystick
or pad that uses a 9-pin D-type cannon connector to the serial port of my
PC?
A: Yes, it is possible, but it'll burn your serial port or the pad. It
won't work, of course.
Q: My joystick doesn't work with Quake / Quake 2. What's the cause?
A: Quake / Quake 2 don't support joystick. Use joy2key to simulate keypresses
for them.
6. Programming 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.

View File

@ -1,6 +1,10 @@
.. include:: <isonum.txt>
=========================
Multi-touch (MT) Protocol Multi-touch (MT) Protocol
------------------------- =========================
Copyright (C) 2009-2010 Henrik Rydberg <rydberg@euromail.se>
:Copyright: |copy| 2009-2010 Henrik Rydberg <rydberg@euromail.se>
Introduction Introduction
@ -18,6 +22,9 @@ describes how to send the raw data for all contacts to the receiver. For
devices capable of tracking identifiable contacts (type B), the protocol devices capable of tracking identifiable contacts (type B), the protocol
describes how to send updates for individual contacts via event slots. describes how to send updates for individual contacts via event slots.
.. note::
MT potocol type A is obsolete, all kernel drivers have been
converted to use type B.
Protocol Usage Protocol Usage
-------------- --------------
@ -47,12 +54,12 @@ The main difference between the stateless type A protocol and the stateful
type B slot protocol lies in the usage of identifiable contacts to reduce type B slot protocol lies in the usage of identifiable contacts to reduce
the amount of data sent to userspace. The slot protocol requires the use of the amount of data sent to userspace. The slot protocol requires the use of
the ABS_MT_TRACKING_ID, either provided by the hardware or computed from the ABS_MT_TRACKING_ID, either provided by the hardware or computed from
the raw data [5]. the raw data [#f5]_.
For type A devices, the kernel driver should generate an arbitrary For type A devices, the kernel driver should generate an arbitrary
enumeration of the full set of anonymous contacts currently on the enumeration of the full set of anonymous contacts currently on the
surface. The order in which the packets appear in the event stream is not surface. The order in which the packets appear in the event stream is not
important. Event filtering and finger tracking is left to user space [3]. important. Event filtering and finger tracking is left to user space [#f3]_.
For type B devices, the kernel driver should associate a slot with each For type B devices, the kernel driver should associate a slot with each
identified contact, and use that slot to propagate changes for the contact. identified contact, and use that slot to propagate changes for the contact.
@ -86,7 +93,7 @@ Protocol Example A
------------------ ------------------
Here is what a minimal event sequence for a two-contact touch would look Here is what a minimal event sequence for a two-contact touch would look
like for a type A device: like for a type A device::
ABS_MT_POSITION_X x[0] ABS_MT_POSITION_X x[0]
ABS_MT_POSITION_Y y[0] ABS_MT_POSITION_Y y[0]
@ -100,14 +107,14 @@ The sequence after moving one of the contacts looks exactly the same; the
raw data for all present contacts are sent between every synchronization raw data for all present contacts are sent between every synchronization
with SYN_REPORT. with SYN_REPORT.
Here is the sequence after lifting the first contact: Here is the sequence after lifting the first contact::
ABS_MT_POSITION_X x[1] ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1] ABS_MT_POSITION_Y y[1]
SYN_MT_REPORT SYN_MT_REPORT
SYN_REPORT SYN_REPORT
And here is the sequence after lifting the second contact: And here is the sequence after lifting the second contact::
SYN_MT_REPORT SYN_MT_REPORT
SYN_REPORT SYN_REPORT
@ -122,7 +129,7 @@ Protocol Example B
------------------ ------------------
Here is what a minimal event sequence for a two-contact touch would look Here is what a minimal event sequence for a two-contact touch would look
like for a type B device: like for a type B device::
ABS_MT_SLOT 0 ABS_MT_SLOT 0
ABS_MT_TRACKING_ID 45 ABS_MT_TRACKING_ID 45
@ -134,13 +141,13 @@ like for a type B device:
ABS_MT_POSITION_Y y[1] ABS_MT_POSITION_Y y[1]
SYN_REPORT SYN_REPORT
Here is the sequence after moving contact 45 in the x direction: Here is the sequence after moving contact 45 in the x direction::
ABS_MT_SLOT 0 ABS_MT_SLOT 0
ABS_MT_POSITION_X x[0] ABS_MT_POSITION_X x[0]
SYN_REPORT SYN_REPORT
Here is the sequence after lifting the contact in slot 0: Here is the sequence after lifting the contact in slot 0::
ABS_MT_TRACKING_ID -1 ABS_MT_TRACKING_ID -1
SYN_REPORT SYN_REPORT
@ -149,7 +156,7 @@ The slot being modified is already 0, so the ABS_MT_SLOT is omitted. The
message removes the association of slot 0 with contact 45, thereby message removes the association of slot 0 with contact 45, thereby
destroying contact 45 and freeing slot 0 to be reused for another contact. destroying contact 45 and freeing slot 0 to be reused for another contact.
Finally, here is the sequence after lifting the second contact: Finally, here is the sequence after lifting the second contact::
ABS_MT_SLOT 1 ABS_MT_SLOT 1
ABS_MT_TRACKING_ID -1 ABS_MT_TRACKING_ID -1
@ -181,6 +188,8 @@ ABS_MT_PRESSURE may be used to provide the pressure on the contact area
instead. Devices capable of contact hovering can use ABS_MT_DISTANCE to instead. Devices capable of contact hovering can use ABS_MT_DISTANCE to
indicate the distance between the contact and the surface. indicate the distance between the contact and the surface.
::
Linux MT Win8 Linux MT Win8
__________ _______________________ __________ _______________________
@ -212,7 +221,7 @@ via ABS_MT_BLOB_ID.
The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a The ABS_MT_TOOL_TYPE may be used to specify whether the touching tool is a
finger or a pen or something else. Finally, the ABS_MT_TRACKING_ID event finger or a pen or something else. Finally, the ABS_MT_TRACKING_ID event
may be used to track identified contacts over time [5]. may be used to track identified contacts over time [#f5]_.
In the type B protocol, ABS_MT_TOOL_TYPE and ABS_MT_TRACKING_ID are In the type B protocol, ABS_MT_TOOL_TYPE and ABS_MT_TRACKING_ID are
implicitly handled by input core; drivers should instead call implicitly handled by input core; drivers should instead call
@ -223,117 +232,103 @@ Event Semantics
--------------- ---------------
ABS_MT_TOUCH_MAJOR ABS_MT_TOUCH_MAJOR
The length of the major axis of the contact. The length should be given in
The length of the major axis of the contact. The length should be given in surface units. If the surface has an X times Y resolution, the largest
surface units. If the surface has an X times Y resolution, the largest possible value of ABS_MT_TOUCH_MAJOR is sqrt(X^2 + Y^2), the diagonal [#f4]_.
possible value of ABS_MT_TOUCH_MAJOR is sqrt(X^2 + Y^2), the diagonal [4].
ABS_MT_TOUCH_MINOR ABS_MT_TOUCH_MINOR
The length, in surface units, of the minor axis of the contact. If the
The length, in surface units, of the minor axis of the contact. If the contact is circular, this event can be omitted [#f4]_.
contact is circular, this event can be omitted [4].
ABS_MT_WIDTH_MAJOR ABS_MT_WIDTH_MAJOR
The length, in surface units, of the major axis of the approaching
The length, in surface units, of the major axis of the approaching tool. This should be understood as the size of the tool itself. The
tool. This should be understood as the size of the tool itself. The orientation of the contact and the approaching tool are assumed to be the
orientation of the contact and the approaching tool are assumed to be the same [#f4]_.
same [4].
ABS_MT_WIDTH_MINOR ABS_MT_WIDTH_MINOR
The length, in surface units, of the minor axis of the approaching
tool. Omit if circular [#f4]_.
The length, in surface units, of the minor axis of the approaching The above four values can be used to derive additional information about
tool. Omit if circular [4]. the contact. The ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR approximates
the notion of pressure. The fingers of the hand and the palm all have
The above four values can be used to derive additional information about different characteristic widths.
the contact. The ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR approximates
the notion of pressure. The fingers of the hand and the palm all have
different characteristic widths.
ABS_MT_PRESSURE ABS_MT_PRESSURE
The pressure, in arbitrary units, on the contact area. May be used instead
The pressure, in arbitrary units, on the contact area. May be used instead of TOUCH and WIDTH for pressure-based devices or any device with a spatial
of TOUCH and WIDTH for pressure-based devices or any device with a spatial signal intensity distribution.
signal intensity distribution.
ABS_MT_DISTANCE ABS_MT_DISTANCE
The distance, in surface units, between the contact and the surface. Zero
The distance, in surface units, between the contact and the surface. Zero distance means the contact is touching the surface. A positive number means
distance means the contact is touching the surface. A positive number means the contact is hovering above the surface.
the contact is hovering above the surface.
ABS_MT_ORIENTATION ABS_MT_ORIENTATION
The orientation of the touching ellipse. The value should describe a signed
quarter of a revolution clockwise around the touch center. The signed value
range is arbitrary, but zero should be returned for an ellipse aligned with
the Y axis of the surface, a negative value when the ellipse is turned to
the left, and a positive value when the ellipse is turned to the
right. When completely aligned with the X axis, the range max should be
returned.
The orientation of the touching ellipse. The value should describe a signed Touch ellipsis are symmetrical by default. For devices capable of true 360
quarter of a revolution clockwise around the touch center. The signed value degree orientation, the reported orientation must exceed the range max to
range is arbitrary, but zero should be returned for an ellipse aligned with indicate more than a quarter of a revolution. For an upside-down finger,
the Y axis of the surface, a negative value when the ellipse is turned to range max * 2 should be returned.
the left, and a positive value when the ellipse is turned to the
right. When completely aligned with the X axis, the range max should be
returned.
Touch ellipsis are symmetrical by default. For devices capable of true 360 Orientation can be omitted if the touch area is circular, or if the
degree orientation, the reported orientation must exceed the range max to information is not available in the kernel driver. Partial orientation
indicate more than a quarter of a revolution. For an upside-down finger, support is possible if the device can distinguish between the two axis, but
range max * 2 should be returned. not (uniquely) any values in between. In such cases, the range of
ABS_MT_ORIENTATION should be [0, 1] [#f4]_.
Orientation can be omitted if the touch area is circular, or if the
information is not available in the kernel driver. Partial orientation
support is possible if the device can distinguish between the two axis, but
not (uniquely) any values in between. In such cases, the range of
ABS_MT_ORIENTATION should be [0, 1] [4].
ABS_MT_POSITION_X ABS_MT_POSITION_X
The surface X coordinate of the center of the touching ellipse.
The surface X coordinate of the center of the touching ellipse.
ABS_MT_POSITION_Y ABS_MT_POSITION_Y
The surface Y coordinate of the center of the touching ellipse.
The surface Y coordinate of the center of the touching ellipse.
ABS_MT_TOOL_X ABS_MT_TOOL_X
The surface X coordinate of the center of the approaching tool. Omit if
The surface X coordinate of the center of the approaching tool. Omit if the device cannot distinguish between the intended touch point and the
the device cannot distinguish between the intended touch point and the tool itself.
tool itself.
ABS_MT_TOOL_Y ABS_MT_TOOL_Y
The surface Y coordinate of the center of the approaching tool. Omit if the
device cannot distinguish between the intended touch point and the tool
itself.
The surface Y coordinate of the center of the approaching tool. Omit if the The four position values can be used to separate the position of the touch
device cannot distinguish between the intended touch point and the tool from the position of the tool. If both positions are present, the major
itself. tool axis points towards the touch point [#f1]_. Otherwise, the tool axes are
aligned with the touch axes.
The four position values can be used to separate the position of the touch
from the position of the tool. If both positions are present, the major
tool axis points towards the touch point [1]. Otherwise, the tool axes are
aligned with the touch axes.
ABS_MT_TOOL_TYPE ABS_MT_TOOL_TYPE
The type of approaching tool. A lot of kernel drivers cannot distinguish
The type of approaching tool. A lot of kernel drivers cannot distinguish between different tool types, such as a finger or a pen. In such cases, the
between different tool types, such as a finger or a pen. In such cases, the event should be omitted. The protocol currently supports MT_TOOL_FINGER,
event should be omitted. The protocol currently supports MT_TOOL_FINGER, MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_. For type B devices, this event is
MT_TOOL_PEN, and MT_TOOL_PALM [2]. For type B devices, this event is handled handled by input core; drivers should instead use
by input core; drivers should instead use input_mt_report_slot_state(). input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may change over
A contact's ABS_MT_TOOL_TYPE may change over time while still touching the time while still touching the device, because the firmware may not be able
device, because the firmware may not be able to determine which tool is being to determine which tool is being used when it first appears.
used when it first appears.
ABS_MT_BLOB_ID ABS_MT_BLOB_ID
The BLOB_ID groups several packets together into one arbitrarily shaped
The BLOB_ID groups several packets together into one arbitrarily shaped contact. The sequence of points forms a polygon which defines the shape of
contact. The sequence of points forms a polygon which defines the shape of the contact. This is a low-level anonymous grouping for type A devices, and
the contact. This is a low-level anonymous grouping for type A devices, and should not be confused with the high-level trackingID [#f5]_. Most type A
should not be confused with the high-level trackingID [5]. Most type A devices do not have blob capability, so drivers can safely omit this event.
devices do not have blob capability, so drivers can safely omit this event.
ABS_MT_TRACKING_ID ABS_MT_TRACKING_ID
The TRACKING_ID identifies an initiated contact throughout its life cycle
The TRACKING_ID identifies an initiated contact throughout its life cycle [#f5]_. The value range of the TRACKING_ID should be large enough to ensure
[5]. The value range of the TRACKING_ID should be large enough to ensure unique identification of a contact maintained over an extended period of
unique identification of a contact maintained over an extended period of time. For type B devices, this event is handled by input core; drivers
time. For type B devices, this event is handled by input core; drivers should instead use input_mt_report_slot_state().
should instead use input_mt_report_slot_state().
Event Computation Event Computation
@ -346,7 +341,7 @@ this section gives recipes for how to compute certain events.
For devices reporting contacts as rectangular shapes, signed orientation For devices reporting contacts as rectangular shapes, signed orientation
cannot be obtained. Assuming X and Y are the lengths of the sides of the cannot be obtained. Assuming X and Y are the lengths of the sides of the
touching rectangle, here is a simple formula that retains the most touching rectangle, here is a simple formula that retains the most
information possible: information possible::
ABS_MT_TOUCH_MAJOR := max(X, Y) ABS_MT_TOUCH_MAJOR := max(X, Y)
ABS_MT_TOUCH_MINOR := min(X, Y) ABS_MT_TOUCH_MINOR := min(X, Y)
@ -356,7 +351,7 @@ The range of ABS_MT_ORIENTATION should be set to [0, 1], to indicate that
the device can distinguish between a finger along the Y axis (0) and a the device can distinguish between a finger along the Y axis (0) and a
finger along the X axis (1). finger along the X axis (1).
For win8 devices with both T and C coordinates, the position mapping is For win8 devices with both T and C coordinates, the position mapping is::
ABS_MT_POSITION_X := T_X ABS_MT_POSITION_X := T_X
ABS_MT_POSITION_Y := T_Y ABS_MT_POSITION_Y := T_Y
@ -365,7 +360,7 @@ For win8 devices with both T and C coordinates, the position mapping is
Unfortunately, there is not enough information to specify both the touching Unfortunately, there is not enough information to specify both the touching
ellipse and the tool ellipse, so one has to resort to approximations. One ellipse and the tool ellipse, so one has to resort to approximations. One
simple scheme, which is compatible with earlier usage, is: simple scheme, which is compatible with earlier usage, is::
ABS_MT_TOUCH_MAJOR := min(X, Y) ABS_MT_TOUCH_MAJOR := min(X, Y)
ABS_MT_TOUCH_MINOR := <not used> ABS_MT_TOUCH_MINOR := <not used>
@ -386,7 +381,7 @@ The process of finger tracking, i.e., to assign a unique trackingID to each
initiated contact on the surface, is a Euclidian Bipartite Matching initiated contact on the surface, is a Euclidian Bipartite Matching
problem. At each event synchronization, the set of actual contacts is problem. At each event synchronization, the set of actual contacts is
matched to the set of contacts from the previous synchronization. A full matched to the set of contacts from the previous synchronization. A full
implementation can be found in [3]. implementation can be found in [#f3]_.
Gestures Gestures
@ -408,11 +403,8 @@ in a finger packet must not be recognized as single-touch events.
For type A devices, all finger data bypasses input filtering, since For type A devices, all finger data bypasses input filtering, since
subsequent events of the same type refer to different fingers. subsequent events of the same type refer to different fingers.
For example usage of the type A protocol, see the bcm5974 driver. For .. [#f1] Also, the difference (TOOL_X - POSITION_X) can be used to model tilt.
example usage of the type B protocol, see the hid-egalax driver. .. [#f2] The list can of course be extended.
.. [#f3] The mtdev project: http://bitmath.org/code/mtdev/.
[1] Also, the difference (TOOL_X - POSITION_X) can be used to model tilt. .. [#f4] See the section on event computation.
[2] The list can of course be extended. .. [#f5] See the section on finger tracking.
[3] The mtdev project: http://bitmath.org/code/mtdev/.
[4] See the section on event computation.
[5] See the section on finger tracking.

View File

@ -1,4 +1,6 @@
=================
Keyboard notifier Keyboard notifier
=================
One can use register_keyboard_notifier to get called back on keyboard One can use register_keyboard_notifier to get called back on keyboard
events (see kbd_keycode() function for details). The passed structure is events (see kbd_keycode() function for details). The passed structure is
@ -23,9 +25,9 @@ For each kind of event but the last, the callback may return NOTIFY_STOP in
order to "eat" the event: the notify loop is stopped and the keyboard event is order to "eat" the event: the notify loop is stopped and the keyboard event is
dropped. dropped.
In a rough C snippet, we have: In a rough C snippet, we have::
kbd_keycode(keycode) { kbd_keycode(keycode) {
... ...
params.value = keycode; params.value = keycode;
if (notifier_call_chain(KBD_KEYCODE,&params) == NOTIFY_STOP) if (notifier_call_chain(KBD_KEYCODE,&params) == NOTIFY_STOP)
@ -47,6 +49,6 @@ kbd_keycode(keycode) {
return; return;
apply keysym; apply keysym;
notifier_call_chain(KBD_POST_KEYSYM,&params); notifier_call_chain(KBD_POST_KEYSYM,&params);
} }
NOTE: This notifier is usually called from interrupt context. .. note:: This notifier is usually called from interrupt context.

View File

@ -1,873 +0,0 @@
Copyright (C) 2002-2011 Sentelic Corporation.
Last update: Dec-07-2011
==============================================================================
* Finger Sensing Pad Intellimouse Mode(scrolling wheel, 4th and 5th buttons)
==============================================================================
A) MSID 4: Scrolling wheel mode plus Forward page(4th button) and Backward
page (5th button)
@1. Set sample rate to 200;
@2. Set sample rate to 200;
@3. Set sample rate to 80;
@4. Issuing the "Get device ID" command (0xF2) and waits for the response;
@5. FSP will respond 0x04.
Packet 1
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|W|W|W|W|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7 => Y overflow
Bit6 => X overflow
Bit5 => Y sign bit
Bit4 => X sign bit
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X Movement(9-bit 2's complement integers)
Byte 3: Y Movement(9-bit 2's complement integers)
Byte 4: Bit3~Bit0 => the scrolling wheel's movement since the last data report.
valid values, -8 ~ +7
Bit4 => 1 = 4th mouse button is pressed, Forward one page.
0 = 4th mouse button is not pressed.
Bit5 => 1 = 5th mouse button is pressed, Backward one page.
0 = 5th mouse button is not pressed.
B) MSID 6: Horizontal and Vertical scrolling.
@ Set bit 1 in register 0x40 to 1
# FSP replaces scrolling wheel's movement as 4 bits to show horizontal and
vertical scrolling.
Packet 1
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|r|l|u|d|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7 => Y overflow
Bit6 => X overflow
Bit5 => Y sign bit
Bit4 => X sign bit
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X Movement(9-bit 2's complement integers)
Byte 3: Y Movement(9-bit 2's complement integers)
Byte 4: Bit0 => the Vertical scrolling movement downward.
Bit1 => the Vertical scrolling movement upward.
Bit2 => the Horizontal scrolling movement leftward.
Bit3 => the Horizontal scrolling movement rightward.
Bit4 => 1 = 4th mouse button is pressed, Forward one page.
0 = 4th mouse button is not pressed.
Bit5 => 1 = 5th mouse button is pressed, Backward one page.
0 = 5th mouse button is not pressed.
C) MSID 7:
# FSP uses 2 packets (8 Bytes) to represent Absolute Position.
so we have PACKET NUMBER to identify packets.
If PACKET NUMBER is 0, the packet is Packet 1.
If PACKET NUMBER is 1, the packet is Packet 2.
Please count this number in program.
# MSID6 special packet will be enable at the same time when enable MSID 7.
==============================================================================
* Absolute position for STL3886-G0.
==============================================================================
@ Set bit 2 or 3 in register 0x40 to 1
@ Set bit 6 in register 0x40 to 1
Packet 1 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|1|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|d|u|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => valid bit
Bit4 => 1
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll up
Bit5 => scroll down
Bit6 => scroll left
Bit7 => scroll right
Notify Packet for G0
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|0|1|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |M|M|M|M|M|M|M|M| 4 |0|0|0|0|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => 0
Bit4 => 1
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message Type => 0x5A (Enable/Disable status packet)
Mode Type => 0xA5 (Normal/Icon mode status)
Byte 3: Message Type => 0x00 (Disabled)
=> 0x01 (Enabled)
Mode Type => 0x00 (Normal)
=> 0x01 (Icon)
Byte 4: Bit7~Bit0 => Don't Care
==============================================================================
* Absolute position for STL3888-Ax.
==============================================================================
Packet 1 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|A|1|L|0|1| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |x|x|y|y|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => arc
Bit3 => 1
Bit2 => Left Button, 1 is pressed, 0 is released.
Bit1 => 0
Bit0 => 1
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit5~Bit4 => y1_g
Bit7~Bit6 => x1_g
Packet 2 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|A|1|R|1|0| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |x|x|y|y|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => arc
Bit3 => 1
Bit2 => Right Button, 1 is pressed, 0 is released.
Bit1 => 1
Bit0 => 0
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit5~Bit4 => y2_g
Bit7~Bit6 => x2_g
Notify Packet for STL3888-Ax
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|1|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|d|u|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => 1
Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
0: left button is generated by the on-pad command
1: left button is generated by the external button
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message Type => 0xB7 (Multi Finger, Multi Coordinate mode)
Byte 3: Bit7~Bit6 => Don't care
Bit5~Bit4 => Number of fingers
Bit3~Bit1 => Reserved
Bit0 => 1: enter gesture mode; 0: leaving gesture mode
Byte 4: Bit7 => scroll right button
Bit6 => scroll left button
Bit5 => scroll down button
Bit4 => scroll up button
* Note that if gesture and additional button (Bit4~Bit7)
happen at the same time, the button information will not
be sent.
Bit3~Bit0 => Reserved
Sample sequence of Multi-finger, Multi-coordinate mode:
notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
abs pkt 2, ..., notify packet (valid bit == 0)
==============================================================================
* Absolute position for STL3888-B0.
==============================================================================
Packet 1(ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|F|1|0|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|u|d|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => finger up/down information. 1: finger down, 0: finger up.
Bit3 => 1
Bit2 => finger index, 0 is the first finger, 1 is the second finger.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll down button
Bit5 => scroll up button
Bit6 => scroll left button
Bit7 => scroll right button
Packet 2 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|F|1|1|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|u|d|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => finger up/down information. 1: finger down, 0: finger up.
Bit3 => 1
Bit2 => finger index, 0 is the first finger, 1 is the second finger.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll down button
Bit5 => scroll up button
Bit6 => scroll left button
Bit7 => scroll right button
Notify Packet for STL3888-B0
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|1|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|u|d|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
=> 11, Normal data packet with on-pad click
Bit5 => 1
Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
0: left button is generated by the on-pad command
1: left button is generated by the external button
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message Type => 0xB7 (Multi Finger, Multi Coordinate mode)
Byte 3: Bit7~Bit6 => Don't care
Bit5~Bit4 => Number of fingers
Bit3~Bit1 => Reserved
Bit0 => 1: enter gesture mode; 0: leaving gesture mode
Byte 4: Bit7 => scroll right button
Bit6 => scroll left button
Bit5 => scroll up button
Bit4 => scroll down button
* Note that if gesture and additional button(Bit4~Bit7)
happen at the same time, the button information will not
be sent.
Bit3~Bit0 => Reserved
Sample sequence of Multi-finger, Multi-coordinate mode:
notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
abs pkt 2, ..., notify packet (valid bit == 0)
==============================================================================
* Absolute position for STL3888-Cx and STL3888-Dx.
==============================================================================
Single Finger, Absolute Coordinate Mode (SFAC)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|0|P|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|B|F|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
Bit5 => Coordinate mode(always 0 in SFAC mode):
0: single-finger absolute coordinates (SFAC) mode
1: multi-finger, multiple coordinates (MFMC) mode
Bit4 => 0: The LEFT button is generated by on-pad command (OPC)
1: The LEFT button is generated by external button
Default is 1 even if the LEFT button is not pressed.
Bit3 => Always 1, as specified by PS/2 protocol.
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => 4th mouse button(forward one page)
Bit5 => 5th mouse button(backward one page)
Bit6 => scroll left button
Bit7 => scroll right button
Multi Finger, Multiple Coordinates Mode (MFMC):
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|1|P|1|F|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|B|F|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => Coordinate mode (always 1 in MFMC mode):
0: single-finger absolute coordinates (SFAC) mode
1: multi-finger, multiple coordinates (MFMC) mode
Bit4 => 0: The LEFT button is generated by on-pad command (OPC)
1: The LEFT button is generated by external button
Default is 1 even if the LEFT button is not pressed.
Bit3 => Always 1, as specified by PS/2 protocol.
Bit2 => Finger index, 0 is the first finger, 1 is the second finger.
If bit 1 and 0 are all 1 and bit 4 is 0, the middle external
button is pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => 4th mouse button(forward one page)
Bit5 => 5th mouse button(backward one page)
Bit6 => scroll left button
Bit7 => scroll right button
When one of the two fingers is up, the device will output four consecutive
MFMC#0 report packets with zero X and Y to represent 1st finger is up or
four consecutive MFMC#1 report packets with zero X and Y to represent that
the 2nd finger is up. On the other hand, if both fingers are up, the device
will output four consecutive single-finger, absolute coordinate(SFAC) packets
with zero X and Y.
Notify Packet for STL3888-Cx/Dx
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|0|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|u|d|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
Bit5 => Always 0
Bit4 => 0: The LEFT button is generated by on-pad command(OPC)
1: The LEFT button is generated by external button
Default is 1 even if the LEFT button is not pressed.
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message type:
0xba => gesture information
0xc0 => one finger hold-rotating gesture
Byte 3: The first parameter for the received message:
0xba => gesture ID (refer to the 'Gesture ID' section)
0xc0 => region ID
Byte 4: The second parameter for the received message:
0xba => N/A
0xc0 => finger up/down information
Sample sequence of Multi-finger, Multi-coordinates mode:
notify packet (valid bit == 1), MFMC packet 1 (byte 1, bit 2 == 0),
MFMC packet 2 (byte 1, bit 2 == 1), MFMC packet 1, MFMC packet 2,
..., notify packet (valid bit == 0)
That is, when the device is in MFMC mode, the host will receive
interleaved absolute coordinate packets for each finger.
==============================================================================
* FSP Enable/Disable packet
==============================================================================
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |Y|X|0|0|1|M|R|L| 2 |0|1|0|1|1|0|1|E| 3 | | | | | | | | | 4 | | | | | | | | |
|---------------| |---------------| |---------------| |---------------|
FSP will send out enable/disable packet when FSP receive PS/2 enable/disable
command. Host will receive the packet which Middle, Right, Left button will
be set. The packet only use byte 0 and byte 1 as a pattern of original packet.
Ignore the other bytes of the packet.
Byte 1: Bit7 => 0, Y overflow
Bit6 => 0, X overflow
Bit5 => 0, Y sign bit
Bit4 => 0, X sign bit
Bit3 => 1
Bit2 => 1, Middle Button
Bit1 => 1, Right Button
Bit0 => 1, Left Button
Byte 2: Bit7~1 => (0101101b)
Bit0 => 1 = Enable
0 = Disable
Byte 3: Don't care
Byte 4: Don't care (MOUSE ID 3, 4)
Byte 5~8: Don't care (Absolute packet)
==============================================================================
* PS/2 Command Set
==============================================================================
FSP supports basic PS/2 commanding set and modes, refer to following URL for
details about PS/2 commands:
http://www.computer-engineering.org/ps2mouse/
==============================================================================
* Programming Sequence for Determining Packet Parsing Flow
==============================================================================
1. Identify FSP by reading device ID(0x00) and version(0x01) register
2a. For FSP version < STL3888 Cx, determine number of buttons by reading
the 'test mode status' (0x20) register:
buttons = reg[0x20] & 0x30
if buttons == 0x30 or buttons == 0x20:
# two/four buttons
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section A for packet parsing detail(ignore byte 4, bit ~ 7)
elif buttons == 0x10:
# 6 buttons
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section B for packet parsing detail
elif buttons == 0x00:
# 6 buttons
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section A for packet parsing detail
2b. For FSP version >= STL3888 Cx:
Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
section A for packet parsing detail (ignore byte 4, bit ~ 7)
==============================================================================
* Programming Sequence for Register Reading/Writing
==============================================================================
Register inversion requirement:
Following values needed to be inverted(the '~' operator in C) before being
sent to FSP:
0xe8, 0xe9, 0xee, 0xf2, 0xf3 and 0xff.
Register swapping requirement:
Following values needed to have their higher 4 bits and lower 4 bits being
swapped before being sent to FSP:
10, 20, 40, 60, 80, 100 and 200.
Register reading sequence:
1. send 0xf3 PS/2 command to FSP;
2. send 0x66 PS/2 command to FSP;
3. send 0x88 PS/2 command to FSP;
4. send 0xf3 PS/2 command to FSP;
5. if the register address being to read is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 6
5a. send 0x68 PS/2 command to FSP;
5b. send the inverted register address to FSP and goto step 8;
6. if the register address being to read is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 7
6a. send 0xcc PS/2 command to FSP;
6b. send the swapped register address to FSP and goto step 8;
7. send 0x66 PS/2 command to FSP;
7a. send the original register address to FSP and goto step 8;
8. send 0xe9(status request) PS/2 command to FSP;
9. the 4th byte of the response read from FSP should be the
requested register value(?? indicates don't care byte):
host: 0xe9
3888: 0xfa (??) (??) (val)
* Note that since the Cx release, the hardware will return 1's
complement of the register value at the 3rd byte of status request
result:
host: 0xe9
3888: 0xfa (??) (~val) (val)
Register writing sequence:
1. send 0xf3 PS/2 command to FSP;
2. if the register address being to write is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 3
2a. send 0x74 PS/2 command to FSP;
2b. send the inverted register address to FSP and goto step 5;
3. if the register address being to write is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 4
3a. send 0x77 PS/2 command to FSP;
3b. send the swapped register address to FSP and goto step 5;
4. send 0x55 PS/2 command to FSP;
4a. send the register address to FSP and goto step 5;
5. send 0xf3 PS/2 command to FSP;
6. if the register value being to write is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 7
6a. send 0x47 PS/2 command to FSP;
6b. send the inverted register value to FSP and goto step 9;
7. if the register value being to write is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 8
7a. send 0x44 PS/2 command to FSP;
7b. send the swapped register value to FSP and goto step 9;
8. send 0x33 PS/2 command to FSP;
8a. send the register value to FSP;
9. the register writing sequence is completed.
* Note that since the Cx release, the hardware will return 1's
complement of the register value at the 3rd byte of status request
result. Host can optionally send another 0xe9 (status request) PS/2
command to FSP at the end of register writing to verify that the
register writing operation is successful (?? indicates don't care
byte):
host: 0xe9
3888: 0xfa (??) (~val) (val)
==============================================================================
* Programming Sequence for Page Register Reading/Writing
==============================================================================
In order to overcome the limitation of maximum number of registers
supported, the hardware separates register into different groups called
'pages.' Each page is able to include up to 255 registers.
The default page after power up is 0x82; therefore, if one has to get
access to register 0x8301, one has to use following sequence to switch
to page 0x83, then start reading/writing from/to offset 0x01 by using
the register read/write sequence described in previous section.
Page register reading sequence:
1. send 0xf3 PS/2 command to FSP;
2. send 0x66 PS/2 command to FSP;
3. send 0x88 PS/2 command to FSP;
4. send 0xf3 PS/2 command to FSP;
5. send 0x83 PS/2 command to FSP;
6. send 0x88 PS/2 command to FSP;
7. send 0xe9(status request) PS/2 command to FSP;
8. the response read from FSP should be the requested page value.
Page register writing sequence:
1. send 0xf3 PS/2 command to FSP;
2. send 0x38 PS/2 command to FSP;
3. send 0x88 PS/2 command to FSP;
4. send 0xf3 PS/2 command to FSP;
5. if the page address being written is not required to be
inverted(refer to the 'Register inversion requirement' section),
goto step 6
5a. send 0x47 PS/2 command to FSP;
5b. send the inverted page address to FSP and goto step 9;
6. if the page address being written is not required to be
swapped(refer to the 'Register swapping requirement' section),
goto step 7
6a. send 0x44 PS/2 command to FSP;
6b. send the swapped page address to FSP and goto step 9;
7. send 0x33 PS/2 command to FSP;
8. send the page address to FSP;
9. the page register writing sequence is completed.
==============================================================================
* Gesture ID
==============================================================================
Unlike other devices which sends multiple fingers' coordinates to host,
FSP processes multiple fingers' coordinates internally and convert them
into a 8 bits integer, namely 'Gesture ID.' Following is a list of
supported gesture IDs:
ID Description
0x86 2 finger straight up
0x82 2 finger straight down
0x80 2 finger straight right
0x84 2 finger straight left
0x8f 2 finger zoom in
0x8b 2 finger zoom out
0xc0 2 finger curve, counter clockwise
0xc4 2 finger curve, clockwise
0x2e 3 finger straight up
0x2a 3 finger straight down
0x28 3 finger straight right
0x2c 3 finger straight left
0x38 palm
==============================================================================
* Register Listing
==============================================================================
Registers are represented in 16 bits values. The higher 8 bits represent
the page address and the lower 8 bits represent the relative offset within
that particular page. Refer to the 'Programming Sequence for Page Register
Reading/Writing' section for instructions on how to change current page
address.
offset width default r/w name
0x8200 bit7~bit0 0x01 RO device ID
0x8201 bit7~bit0 RW version ID
0xc1: STL3888 Ax
0xd0 ~ 0xd2: STL3888 Bx
0xe0 ~ 0xe1: STL3888 Cx
0xe2 ~ 0xe3: STL3888 Dx
0x8202 bit7~bit0 0x01 RO vendor ID
0x8203 bit7~bit0 0x01 RO product ID
0x8204 bit3~bit0 0x01 RW revision ID
0x820b test mode status 1
bit3 1 RO 0: rotate 180 degree
1: no rotation
*only supported by H/W prior to Cx
0x820f register file page control
bit2 0 RW 1: rotate 180 degree
0: no rotation
*supported since Cx
bit0 0 RW 1 to enable page 1 register files
*only supported by H/W prior to Cx
0x8210 RW system control 1
bit0 1 RW Reserved, must be 1
bit1 0 RW Reserved, must be 0
bit4 0 RW Reserved, must be 0
bit5 1 RW register clock gating enable
0: read only, 1: read/write enable
(Note that following registers does not require clock gating being
enabled prior to write: 05 06 07 08 09 0c 0f 10 11 12 16 17 18 23 2e
40 41 42 43. In addition to that, this bit must be 1 when gesture
mode is enabled)
0x8220 test mode status
bit5~bit4 RO number of buttons
11 => 2, lbtn/rbtn
10 => 4, lbtn/rbtn/scru/scrd
01 => 6, lbtn/rbtn/scru/scrd/scrl/scrr
00 => 6, lbtn/rbtn/scru/scrd/fbtn/bbtn
*only supported by H/W prior to Cx
0x8231 RW on-pad command detection
bit7 0 RW on-pad command left button down tag
enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8234 RW on-pad command control 5
bit4~bit0 0x05 RW XLO in 0s/4/1, so 03h = 0010.1b = 2.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
bit7 0 RW on-pad tap zone enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8235 RW on-pad command control 6
bit4~bit0 0x1d RW XHI in 0s/4/1, so 19h = 1100.1b = 12.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
0x8236 RW on-pad command control 7
bit4~bit0 0x04 RW YLO in 0s/4/1, so 03h = 0010.1b = 2.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
0x8237 RW on-pad command control 8
bit4~bit0 0x13 RW YHI in 0s/4/1, so 11h = 1000.1b = 8.5
(Note that position unit is in 0.5 scanline)
*only supported by H/W prior to Cx
0x8240 RW system control 5
bit1 0 RW FSP Intellimouse mode enable
0: disable, 1: enable
*only supported by H/W prior to Cx
bit2 0 RW movement + abs. coordinate mode enable
0: disable, 1: enable
(Note that this function has the functionality of bit 1 even when
bit 1 is not set. However, the format is different from that of bit 1.
In addition, when bit 1 and bit 2 are set at the same time, bit 2 will
override bit 1.)
*only supported by H/W prior to Cx
bit3 0 RW abs. coordinate only mode enable
0: disable, 1: enable
(Note that this function has the functionality of bit 1 even when
bit 1 is not set. However, the format is different from that of bit 1.
In addition, when bit 1, bit 2 and bit 3 are set at the same time,
bit 3 will override bit 1 and 2.)
*only supported by H/W prior to Cx
bit5 0 RW auto switch enable
0: disable, 1: enable
*only supported by H/W prior to Cx
bit6 0 RW G0 abs. + notify packet format enable
0: disable, 1: enable
(Note that the absolute/relative coordinate output still depends on
bit 2 and 3. That is, if any of those bit is 1, host will receive
absolute coordinates; otherwise, host only receives packets with
relative coordinate.)
*only supported by H/W prior to Cx
bit7 0 RW EN_PS2_F2: PS/2 gesture mode 2nd
finger packet enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8243 RW on-pad control
bit0 0 RW on-pad control enable
0: disable, 1: enable
(Note that if this bit is cleared, bit 3/5 will be ineffective)
*only supported by H/W prior to Cx
bit3 0 RW on-pad fix vertical scrolling enable
0: disable, 1: enable
*only supported by H/W prior to Cx
bit5 0 RW on-pad fix horizontal scrolling enable
0: disable, 1: enable
*only supported by H/W prior to Cx
0x8290 RW software control register 1
bit0 0 RW absolute coordination mode
0: disable, 1: enable
*supported since Cx
bit1 0 RW gesture ID output
0: disable, 1: enable
*supported since Cx
bit2 0 RW two fingers' coordinates output
0: disable, 1: enable
*supported since Cx
bit3 0 RW finger up one packet output
0: disable, 1: enable
*supported since Cx
bit4 0 RW absolute coordination continuous mode
0: disable, 1: enable
*supported since Cx
bit6~bit5 00 RW gesture group selection
00: basic
01: suite
10: suite pro
11: advanced
*supported since Cx
bit7 0 RW Bx packet output compatible mode
0: disable, 1: enable *supported since Cx
*supported since Cx
0x833d RW on-pad command control 1
bit7 1 RW on-pad command detection enable
0: disable, 1: enable
*supported since Cx
0x833e RW on-pad command detection
bit7 0 RW on-pad command left button down tag
enable. Works only in H/W based PS/2
data packet mode.
0: disable, 1: enable
*supported since Cx

View File

@ -1,65 +0,0 @@
#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

View File

@ -0,0 +1,39 @@
<svg width="7.95in" height="3.70in" version="1.1" viewBox="1956 1041 9354.492 4306.001" xmlns="http://www.w3.org/2000/svg">
<polyline transform="translate(-121.88 -68.4)" points="4200 3600 4200 3075 4950 2325 7425 2325 8250 3150 8250 3600" fill="none" stroke="#000" stroke-width="15"/>
<polyline transform="translate(-121.88 -68.4)" points="4200 3675 4200 5400" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="8250 3675 8250 5400" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="3675 3600 8700 3600" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="8775 3600 10200 3600" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="8325 3150 9075 3150" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="7500 2325 10200 2325" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="3600 3600 3e3 3600" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="4125 3075 3e3 3075" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="4217 5400 8158 5400" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="8053 5430 8173 5400 8053 5370" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="4322 5370 4202 5400 4322 5430" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="10125 2342 10125 3583" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="10095 3478 10125 3598 10155 3478" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="10155 2447 10125 2327 10095 2447" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="3e3 3167 3e3 3583" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="2970 3478 3e3 3598 3030 3478" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="3030 3272 3e3 3152 2970 3272" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="9075 3167 9075 3583" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="9045 3478 9075 3598 9105 3478" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="9105 3272 9075 3152 9045 3272" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="4950 2325 4950 1200" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="7425 2325 7425 1200" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="4200 3075 4200 2400 3600 1800 3600 1200" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="8250 3150 8250 2475 8775 1950 8775 1200" fill="none" stroke="#000" stroke-dasharray="40, 40" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="3617 1275 4933 1275" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="4828 1305 4948 1275 4828 1245" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="3722 1245 3602 1275 3722 1305" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="7442 1275 8683 1275" fill="none" stroke="#000" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="8578 1305 8698 1275 8578 1245" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<polyline transform="translate(-121.88 -68.4)" points="7547 1245 7427 1275 7547 1305" fill="none" stroke="#000" stroke-miterlimit="8" stroke-width="7"/>
<text x="5953.125" y="5256.6001" fill="#000000" font-family="sans-serif" font-size="144px" stroke-width=".025in" text-anchor="middle" xml:space="preserve">Effect duration</text>
<text x="10078.125" y="2931.5999" fill="#000000" font-family="sans-serif" font-size="144px" stroke-width=".025in" xml:space="preserve">Effect magnitude</text>
<text x="9028.125" y="3381.5999" fill="#000000" font-family="sans-serif" font-size="144px" stroke-width=".025in" xml:space="preserve">Fade level</text>
<text x="4153.125" y="1131.6" fill="#000000" font-family="sans-serif" font-size="144px" stroke-width=".025in" text-anchor="middle" xml:space="preserve">Attack length</text>
<text x="8053.125" y="1131.6" fill="#000000" font-family="sans-serif" font-size="144px" stroke-width=".025in" text-anchor="middle" xml:space="preserve">Fade length</text>
<text x="2803.125" y="3306.5999" fill="#000000" font-family="sans-serif" font-size="144px" stroke-width=".025in" text-anchor="end" xml:space="preserve">Attack level</text>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,245 @@
=============
uinput module
=============
Introduction
============
uinput is a kernel module that makes it possible to emulate input devices
from userspace. By writing to /dev/uinput (or /dev/input/uinput) device, a
process can create a virtual input device with specific capabilities. Once
this virtual device is created, the process can send events through it,
that will be delivered to userspace and in-kernel consumers.
Interface
=========
::
linux/uinput.h
The uinput header defines ioctls to create, set up, and destroy virtual
devices.
libevdev
========
libevdev is a wrapper library for evdev devices that provides interfaces to
create uinput devices and send events. libevdev is less error-prone than
accessing uinput directly, and should be considered for new software.
For examples and more information about libevdev:
https://www.freedesktop.org/software/libevdev/doc/latest/
Examples
========
Keyboard events
---------------
This first example shows how to create a new virtual device, and how to
send a key event. All default imports and error handlers were removed for
the sake of simplicity.
.. code-block:: c
#include <linux/uinput.h>
void emit(int fd, int type, int code, int val)
{
struct input_event ie;
ie.type = type;
ie.code = code;
ie.value = val;
/* timestamp values below are ignored */
ie.time.tv_sec = 0;
ie.time.tv_usec = 0;
write(fd, &ie, sizeof(ie));
}
int main(void)
{
struct uinput_setup usetup;
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
/*
* The ioctls below will enable the device that is about to be
* created, to pass key events, in this case the space key.
*/
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
memset(&usetup, 0, sizeof(usetup));
usetup.id.bustype = BUS_USB;
usetup.id.vendor = 0x1234; /* sample vendor */
usetup.id.product = 0x5678; /* sample product */
strcpy(usetup.name, "Example device");
ioctl(fd, UI_DEV_SETUP, &usetup);
ioctl(fd, UI_DEV_CREATE);
/*
* On UI_DEV_CREATE the kernel will create the device node for this
* device. We are inserting a pause here so that userspace has time
* to detect, initialize the new device, and can start listening to
* the event, otherwise it will not notice the event we are about
* to send. This pause is only needed in our example code!
*/
sleep(1);
/* Key press, report the event, send key release, and report again */
emit(fd, EV_KEY, KEY_SPACE, 1);
emit(fd, EV_SYN, SYN_REPORT, 0);
emit(fd, EV_KEY, KEY_SPACE, 0);
emit(fd, EV_SYN, SYN_REPORT, 0);
/*
* Give userspace some time to read the events before we destroy the
* device with UI_DEV_DESTOY.
*/
sleep(1);
ioctl(fd, UI_DEV_DESTROY);
close(fd);
return 0;
}
Mouse movements
---------------
This example shows how to create a virtual device that behaves like a physical
mouse.
.. code-block:: c
#include <linux/uinput.h>
/* emit function is identical to of the first example */
int main(void)
{
struct uinput_setup usetup;
int i = 50;
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
/* enable mouse button left and relative events */
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
ioctl(fd, UI_SET_EVBIT, EV_REL);
ioctl(fd, UI_SET_RELBIT, REL_X);
ioctl(fd, UI_SET_RELBIT, REL_Y);
memset(&usetup, 0, sizeof(usetup));
usetup.id.bustype = BUS_USB;
usetup.id.vendor = 0x1234; /* sample vendor */
usetup.id.product = 0x5678; /* sample product */
strcpy(usetup.name, "Example device");
ioctl(fd, UI_DEV_SETUP, &usetup);
ioctl(fd, UI_DEV_CREATE);
/*
* On UI_DEV_CREATE the kernel will create the device node for this
* device. We are inserting a pause here so that userspace has time
* to detect, initialize the new device, and can start listening to
* the event, otherwise it will not notice the event we are about
* to send. This pause is only needed in our example code!
*/
sleep(1);
/* Move the mouse diagonally, 5 units per axis */
while (i--) {
emit(fd, EV_REL, REL_X, 5);
emit(fd, EV_REL, REL_Y, 5);
emit(fd, EV_SYN, SYN_REPORT, 0);
usleep(15000);
}
/*
* Give userspace some time to read the events before we destroy the
* device with UI_DEV_DESTOY.
*/
sleep(1);
ioctl(fd, UI_DEV_DESTROY);
close(fd);
return 0;
}
uinput old interface
--------------------
Before uinput version 5, there wasn't a dedicated ioctl to set up a virtual
device. Programs supportinf older versions of uinput interface need to fill
a uinput_user_dev structure and write it to the uinput file descriptor to
configure the new uinput device. New code should not use the old interface
but interact with uinput via ioctl calls, or use libevdev.
.. code-block:: c
#include <linux/uinput.h>
/* emit function is identical to of the first example */
int main(void)
{
struct uinput_user_dev uud;
int version, rc, fd;
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
rc = ioctl(fd, UI_GET_VERSION, &version);
if (rc == 0 && version >= 5) {
/* use UI_DEV_SETUP */
return 0;
}
/*
* The ioctls below will enable the device that is about to be
* created, to pass key events, in this case the space key.
*/
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, KEY_SPACE);
memset(&uud, 0, sizeof(uud));
snprintf(uud.name, UINPUT_MAX_NAME_SIZE, "uinput old interface");
write(fd, &uud, sizeof(uud));
ioctl(fd, UI_DEV_CREATE);
/*
* On UI_DEV_CREATE the kernel will create the device node for this
* device. We are inserting a pause here so that userspace has time
* to detect, initialize the new device, and can start listening to
* the event, otherwise it will not notice the event we are about
* to send. This pause is only needed in our example code!
*/
sleep(1);
/* Key press, report the event, send key release, and report again */
emit(fd, EV_KEY, KEY_SPACE, 1);
emit(fd, EV_SYN, SYN_REPORT, 0);
emit(fd, EV_KEY, KEY_SPACE, 0);
emit(fd, EV_SYN, SYN_REPORT, 0);
/*
* Give userspace some time to read the events before we destroy the
* device with UI_DEV_DESTOY.
*/
sleep(1);
ioctl(fd, UI_DEV_DESTROY);
close(fd);
return 0;
}

View File

@ -1,37 +1,47 @@
The userio Protocol .. include:: <isonum.txt>
(c) 2015 Stephen Chandler Paul <thatslyude@gmail.com>
Sponsored by Red Hat
--------------------------------------------------------------------------------
1. Introduction ===================
~~~~~~~~~~~~~~~ The userio Protocol
This module is intended to try to make the lives of input driver developers ===================
:Copyright: |copy| 2015 Stephen Chandler Paul <thatslyude@gmail.com>
Sponsored by Red Hat
Introduction
=============
This module is intended to try to make the lives of input driver developers
easier by allowing them to test various serio devices (mainly the various easier by allowing them to test various serio devices (mainly the various
touchpads found on laptops) without having to have the physical device in front touchpads found on laptops) without having to have the physical device in front
of them. userio accomplishes this by allowing any privileged userspace program of them. userio accomplishes this by allowing any privileged userspace program
to directly interact with the kernel's serio driver and control a virtual serio to directly interact with the kernel's serio driver and control a virtual serio
port from there. port from there.
2. Usage overview Usage overview
~~~~~~~~~~~~~~~~~ ==============
In order to interact with the userio kernel module, one simply opens the
In order to interact with the userio kernel module, one simply opens the
/dev/userio character device in their applications. Commands are sent to the /dev/userio character device in their applications. Commands are sent to the
kernel module by writing to the device, and any data received from the serio kernel module by writing to the device, and any data received from the serio
driver is read as-is from the /dev/userio device. All of the structures and driver is read as-is from the /dev/userio device. All of the structures and
macros you need to interact with the device are defined in <linux/userio.h> and macros you need to interact with the device are defined in <linux/userio.h> and
<linux/serio.h>. <linux/serio.h>.
3. Command Structure Command Structure
~~~~~~~~~~~~~~~~~~~~ =================
The struct used for sending commands to /dev/userio is as follows:
The struct used for sending commands to /dev/userio is as follows::
struct userio_cmd { struct userio_cmd {
__u8 type; __u8 type;
__u8 data; __u8 data;
}; };
"type" describes the type of command that is being sent. This can be any one ``type`` describes the type of command that is being sent. This can be any one
of the USERIO_CMD macros defined in <linux/userio.h>. "data" is the argument of the USERIO_CMD macros defined in <linux/userio.h>. ``data`` is the argument
that goes along with the command. In the event that the command doesn't have an that goes along with the command. In the event that the command doesn't have an
argument, this field can be left untouched and will be ignored by the kernel. argument, this field can be left untouched and will be ignored by the kernel.
Each command should be sent by writing the struct directly to the character Each command should be sent by writing the struct directly to the character
@ -39,31 +49,36 @@ device. In the event that the command you send is invalid, an error will be
returned by the character device and a more descriptive error will be printed returned by the character device and a more descriptive error will be printed
to the kernel log. Only one command can be sent at a time, any additional data to the kernel log. Only one command can be sent at a time, any additional data
written to the character device after the initial command will be ignored. written to the character device after the initial command will be ignored.
To close the virtual serio port, just close /dev/userio.
4. Commands To close the virtual serio port, just close /dev/userio.
~~~~~~~~~~~
4.1 USERIO_CMD_REGISTER Commands
~~~~~~~~~~~~~~~~~~~~~~~ ========
Registers the port with the serio driver and begins transmitting data back and
USERIO_CMD_REGISTER
~~~~~~~~~~~~~~~~~~~
Registers the port with the serio driver and begins transmitting data back and
forth. Registration can only be performed once a port type is set with forth. Registration can only be performed once a port type is set with
USERIO_CMD_SET_PORT_TYPE. Has no argument. USERIO_CMD_SET_PORT_TYPE. Has no argument.
4.2 USERIO_CMD_SET_PORT_TYPE USERIO_CMD_SET_PORT_TYPE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
Sets the type of port we're emulating, where "data" is the port type being
Sets the type of port we're emulating, where ``data`` is the port type being
set. Can be any of the macros from <linux/serio.h>. For example: SERIO_8042 set. Can be any of the macros from <linux/serio.h>. For example: SERIO_8042
would set the port type to be a normal PS/2 port. would set the port type to be a normal PS/2 port.
4.3 USERIO_CMD_SEND_INTERRUPT USERIO_CMD_SEND_INTERRUPT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
Sends an interrupt through the virtual serio port to the serio driver, where
"data" is the interrupt data being sent.
5. Userspace tools Sends an interrupt through the virtual serio port to the serio driver, where
~~~~~~~~~~~~~~~~~~ ``data`` is the interrupt data being sent.
The userio userspace tools are able to record PS/2 devices using some of the
Userspace tools
===============
The userio userspace tools are able to record PS/2 devices using some of the
debugging information from i8042, and play back the devices on /dev/userio. The debugging information from i8042, and play back the devices on /dev/userio. The
latest version of these tools can be found at: latest version of these tools can be found at:

View File

@ -6551,7 +6551,7 @@ INPUT MULTITOUCH (MT) PROTOCOL
M: Henrik Rydberg <rydberg@bitmath.org> M: Henrik Rydberg <rydberg@bitmath.org>
L: linux-input@vger.kernel.org L: linux-input@vger.kernel.org
S: Odd fixes S: Odd fixes
F: Documentation/input/multi-touch-protocol.txt F: Documentation/input/multi-touch-protocol.rst
F: drivers/input/input-mt.c F: drivers/input/input-mt.c
K: \b(ABS|SYN)_MT_ K: \b(ABS|SYN)_MT_
@ -13963,7 +13963,7 @@ YEALINK PHONE DRIVER
M: Henk Vergonet <Henk.Vergonet@gmail.com> M: Henk Vergonet <Henk.Vergonet@gmail.com>
L: usbb2k-api-dev@nongnu.org L: usbb2k-api-dev@nongnu.org
S: Maintained S: Maintained
F: Documentation/input/yealink.txt F: Documentation/input/yealink.rst
F: drivers/input/misc/yealink.* F: drivers/input/misc/yealink.*
Z8530 DRIVER FOR AX.25 Z8530 DRIVER FOR AX.25

View File

@ -26,7 +26,6 @@
#include <linux/smsc911x.h> #include <linux/smsc911x.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/input/eeti_ts.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/w1-gpio.h> #include <linux/w1-gpio.h>
#include <linux/sched.h> #include <linux/sched.h>
@ -965,15 +964,28 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = {
.addr = 0x48, .addr = 0x48,
}; };
static struct eeti_ts_platform_data eeti_ts_pdata = { static struct gpiod_lookup_table raumfeld_controller_gpios_table = {
.irq_active_high = 1, .dev_id = "0-000a",
.irq_gpio = GPIO_TOUCH_IRQ, .table = {
GPIO_LOOKUP("gpio-pxa",
GPIO_TOUCH_IRQ, "attn", GPIO_ACTIVE_HIGH),
{ },
},
};
static const struct resource raumfeld_controller_resources[] __initconst = {
{
.start = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ),
.end = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ),
.flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
},
}; };
static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = { static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = {
.type = "eeti_ts", .type = "eeti_ts",
.addr = 0x0a, .addr = 0x0a,
.platform_data = &eeti_ts_pdata, .resources = raumfeld_controller_resources,
.num_resources = ARRAY_SIZE(raumfeld_controller_resources),
}; };
static struct platform_device *raumfeld_common_devices[] = { static struct platform_device *raumfeld_common_devices[] = {
@ -1064,6 +1076,8 @@ static void __init __maybe_unused raumfeld_controller_init(void)
platform_device_register(&rotary_encoder_device); platform_device_register(&rotary_encoder_device);
spi_register_board_info(ARRAY_AND_SIZE(controller_spi_devices)); spi_register_board_info(ARRAY_AND_SIZE(controller_spi_devices));
gpiod_add_lookup_table(&raumfeld_controller_gpios_table);
i2c_register_board_info(0, &raumfeld_controller_i2c_board_info, 1); i2c_register_board_info(0, &raumfeld_controller_i2c_board_info, 1);
ret = gpio_request(GPIO_SHUTDOWN_BATT, "battery shutdown"); ret = gpio_request(GPIO_SHUTDOWN_BATT, "battery shutdown");

View File

@ -15,6 +15,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/property.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -55,6 +56,7 @@ EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
* *
* The board info passed can safely be __initdata, but be careful of embedded * The board info passed can safely be __initdata, but be careful of embedded
* pointers (for platform_data, functions, etc) since that won't be copied. * pointers (for platform_data, functions, etc) since that won't be copied.
* Device properties are deep-copied though.
*/ */
int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len) int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
{ {
@ -78,6 +80,28 @@ int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsig
devinfo->busnum = busnum; devinfo->busnum = busnum;
devinfo->board_info = *info; devinfo->board_info = *info;
if (info->properties) {
devinfo->board_info.properties =
property_entries_dup(info->properties);
if (IS_ERR(devinfo->board_info.properties)) {
status = PTR_ERR(devinfo->board_info.properties);
break;
}
}
if (info->resources) {
devinfo->board_info.resources =
kmemdup(info->resources,
info->num_resources *
sizeof(*info->resources),
GFP_KERNEL);
if (!devinfo->board_info.resources) {
status = -ENOMEM;
break;
}
}
list_add_tail(&devinfo->list, &__i2c_board_list); list_add_tail(&devinfo->list, &__i2c_board_list);
} }

View File

@ -74,7 +74,6 @@
static DEFINE_MUTEX(core_lock); static DEFINE_MUTEX(core_lock);
static DEFINE_IDR(i2c_adapter_idr); static DEFINE_IDR(i2c_adapter_idr);
static struct device_type i2c_client_type;
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
static struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE; static struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE;
@ -1153,11 +1152,12 @@ struct bus_type i2c_bus_type = {
}; };
EXPORT_SYMBOL_GPL(i2c_bus_type); EXPORT_SYMBOL_GPL(i2c_bus_type);
static struct device_type i2c_client_type = { struct device_type i2c_client_type = {
.groups = i2c_dev_groups, .groups = i2c_dev_groups,
.uevent = i2c_device_uevent, .uevent = i2c_device_uevent,
.release = i2c_client_dev_release, .release = i2c_client_dev_release,
}; };
EXPORT_SYMBOL_GPL(i2c_client_type);
/** /**
@ -1334,6 +1334,32 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
i2c_encode_flags_to_addr(client)); i2c_encode_flags_to_addr(client));
} }
static int i2c_dev_irq_from_resources(const struct resource *resources,
unsigned int num_resources)
{
struct irq_data *irqd;
int i;
for (i = 0; i < num_resources; i++) {
const struct resource *r = &resources[i];
if (resource_type(r) != IORESOURCE_IRQ)
continue;
if (r->flags & IORESOURCE_BITS) {
irqd = irq_get_irq_data(r->start);
if (!irqd)
break;
irqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS);
}
return r->start;
}
return 0;
}
/** /**
* i2c_new_device - instantiate an i2c device * i2c_new_device - instantiate an i2c device
* @adap: the adapter managing the device * @adap: the adapter managing the device
@ -1369,7 +1395,11 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->flags = info->flags; client->flags = info->flags;
client->addr = info->addr; client->addr = info->addr;
client->irq = info->irq; client->irq = info->irq;
if (!client->irq)
client->irq = i2c_dev_irq_from_resources(info->resources,
info->num_resources);
strlcpy(client->name, info->type, sizeof(client->name)); strlcpy(client->name, info->type, sizeof(client->name));

View File

@ -385,8 +385,8 @@ static int gameport_queue_event(void *object, struct module *owner,
} }
if (!try_module_get(owner)) { if (!try_module_get(owner)) {
pr_warning("Can't get module reference, dropping event %d\n", pr_warn("Can't get module reference, dropping event %d\n",
event_type); event_type);
kfree(event); kfree(event);
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
@ -542,9 +542,8 @@ static void gameport_init_port(struct gameport *gameport)
INIT_LIST_HEAD(&gameport->node); INIT_LIST_HEAD(&gameport->node);
spin_lock_init(&gameport->timer_lock); spin_lock_init(&gameport->timer_lock);
init_timer(&gameport->poll_timer); setup_timer(&gameport->poll_timer, gameport_run_poll_handler,
gameport->poll_timer.function = gameport_run_poll_handler; (unsigned long)gameport);
gameport->poll_timer.data = (unsigned long)gameport;
} }
/* /*

View File

@ -609,9 +609,7 @@ static void db9_attach(struct parport *pp)
db9->pd = pd; db9->pd = pd;
db9->mode = mode; db9->mode = mode;
db9->parportno = pp->number; db9->parportno = pp->number;
init_timer(&db9->timer); setup_timer(&db9->timer, db9_timer, (long)db9);
db9->timer.data = (long) db9;
db9->timer.function = db9_timer;
for (i = 0; i < (min(db9_mode->n_pads, DB9_MAX_DEVICES)); i++) { for (i = 0; i < (min(db9_mode->n_pads, DB9_MAX_DEVICES)); i++) {

View File

@ -870,7 +870,8 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
err = gc_n64_init_ff(input_dev, idx); err = gc_n64_init_ff(input_dev, idx);
if (err) { if (err) {
pr_warning("Failed to initiate rumble for N64 device %d\n", idx); pr_warn("Failed to initiate rumble for N64 device %d\n",
idx);
goto err_free_dev; goto err_free_dev;
} }

View File

@ -200,9 +200,7 @@ static void tgfx_attach(struct parport *pp)
mutex_init(&tgfx->sem); mutex_init(&tgfx->sem);
tgfx->pd = pd; tgfx->pd = pd;
tgfx->parportno = pp->number; tgfx->parportno = pp->number;
init_timer(&tgfx->timer); setup_timer(&tgfx->timer, tgfx_timer, (long)tgfx);
tgfx->timer.data = (long) tgfx;
tgfx->timer.function = tgfx_timer;
for (i = 0; i < n_devs; i++) { for (i = 0; i < n_devs; i++) {
if (n_buttons[i] < 1) if (n_buttons[i] < 1)

View File

@ -339,6 +339,64 @@ static struct usb_device_id xpad_table[] = {
MODULE_DEVICE_TABLE(usb, xpad_table); MODULE_DEVICE_TABLE(usb, xpad_table);
struct xboxone_init_packet {
u16 idVendor;
u16 idProduct;
const u8 *data;
u8 len;
};
#define XBOXONE_INIT_PKT(_vid, _pid, _data) \
{ \
.idVendor = (_vid), \
.idProduct = (_pid), \
.data = (_data), \
.len = ARRAY_SIZE(_data), \
}
/*
* This packet is required for all Xbox One pads with 2015
* or later firmware installed (or present from the factory).
*/
static const u8 xboxone_fw2015_init[] = {
0x05, 0x20, 0x00, 0x01, 0x00
};
/*
* This packet is required for the Titanfall 2 Xbox One pads
* (0x0e6f:0x0165) to finish initialization and for Hori pads
* (0x0f0d:0x0067) to make the analog sticks work.
*/
static const u8 xboxone_hori_init[] = {
0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
0x00, 0x00, 0x00, 0x80, 0x00
};
/*
* A rumble packet is required for some PowerA pads to start
* sending input reports. One of those pads is (0x24c6:0x543a).
*/
static const u8 xboxone_zerorumble_init[] = {
0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00
};
/*
* This specifies the selection of init packets that a gamepad
* will be sent on init *and* the order in which they will be
* sent. The correct sequence number will be added when the
* packet is going to be sent.
*/
static const struct xboxone_init_packet xboxone_init_packets[] = {
XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init),
XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init),
XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_zerorumble_init),
XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_zerorumble_init),
XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_zerorumble_init),
};
struct xpad_output_packet { struct xpad_output_packet {
u8 data[XPAD_PKT_LEN]; u8 data[XPAD_PKT_LEN];
u8 len; u8 len;
@ -375,6 +433,7 @@ struct usb_xpad {
struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS]; struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS];
int last_out_packet; int last_out_packet;
int init_seq;
#if defined(CONFIG_JOYSTICK_XPAD_LEDS) #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
struct xpad_led *led; struct xpad_led *led;
@ -749,12 +808,48 @@ static void xpad_irq_in(struct urb *urb)
__func__, retval); __func__, retval);
} }
/* Callers must hold xpad->odata_lock spinlock */
static bool xpad_prepare_next_init_packet(struct usb_xpad *xpad)
{
const struct xboxone_init_packet *init_packet;
if (xpad->xtype != XTYPE_XBOXONE)
return false;
/* Perform initialization sequence for Xbox One pads that require it */
while (xpad->init_seq < ARRAY_SIZE(xboxone_init_packets)) {
init_packet = &xboxone_init_packets[xpad->init_seq++];
if (init_packet->idVendor != 0 &&
init_packet->idVendor != xpad->dev->id.vendor)
continue;
if (init_packet->idProduct != 0 &&
init_packet->idProduct != xpad->dev->id.product)
continue;
/* This packet applies to our device, so prepare to send it */
memcpy(xpad->odata, init_packet->data, init_packet->len);
xpad->irq_out->transfer_buffer_length = init_packet->len;
/* Update packet with current sequence number */
xpad->odata[2] = xpad->odata_serial++;
return true;
}
return false;
}
/* Callers must hold xpad->odata_lock spinlock */ /* Callers must hold xpad->odata_lock spinlock */
static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad) static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad)
{ {
struct xpad_output_packet *pkt, *packet = NULL; struct xpad_output_packet *pkt, *packet = NULL;
int i; int i;
/* We may have init packets to send before we can send user commands */
if (xpad_prepare_next_init_packet(xpad))
return true;
for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) { for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) {
if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS) if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS)
xpad->last_out_packet = 0; xpad->last_out_packet = 0;
@ -940,24 +1035,17 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad)
static int xpad_start_xbox_one(struct usb_xpad *xpad) static int xpad_start_xbox_one(struct usb_xpad *xpad)
{ {
struct xpad_output_packet *packet =
&xpad->out_packets[XPAD_OUT_CMD_IDX];
unsigned long flags; unsigned long flags;
int retval; int retval;
spin_lock_irqsave(&xpad->odata_lock, flags); spin_lock_irqsave(&xpad->odata_lock, flags);
/* Xbox one controller needs to be initialized. */ /*
packet->data[0] = 0x05; * Begin the init sequence by attempting to send a packet.
packet->data[1] = 0x20; * We will cycle through the init packet sequence before
packet->data[2] = xpad->odata_serial++; /* packet serial */ * sending any packets from the output ring.
packet->data[3] = 0x01; /* rumble bit enable? */ */
packet->data[4] = 0x00; xpad->init_seq = 0;
packet->len = 5;
packet->pending = true;
/* Reset the sequence so we send out start packet first */
xpad->last_out_packet = -1;
retval = xpad_try_sending_next_out_packet(xpad); retval = xpad_try_sending_next_out_packet(xpad);
spin_unlock_irqrestore(&xpad->odata_lock, flags); spin_unlock_irqrestore(&xpad->odata_lock, flags);

View File

@ -30,6 +30,7 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sysrq.h>
#include <linux/input/matrix_keypad.h> #include <linux/input/matrix_keypad.h>
#include <linux/mfd/cros_ec.h> #include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h> #include <linux/mfd/cros_ec_commands.h>
@ -260,6 +261,12 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
ckdev->ec->event_size); ckdev->ec->event_size);
break; break;
case EC_MKBP_EVENT_SYSRQ:
val = get_unaligned_le32(&ckdev->ec->event_data.data.sysrq);
dev_dbg(ckdev->dev, "sysrq code from EC: %#x\n", val);
handle_sysrq(val);
break;
case EC_MKBP_EVENT_BUTTON: case EC_MKBP_EVENT_BUTTON:
case EC_MKBP_EVENT_SWITCH: case EC_MKBP_EVENT_SWITCH:
/* /*

View File

@ -264,9 +264,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
spin_lock_init(&locomokbd->lock); spin_lock_init(&locomokbd->lock);
init_timer(&locomokbd->timer); setup_timer(&locomokbd->timer, locomokbd_timer_callback,
locomokbd->timer.function = locomokbd_timer_callback; (unsigned long)locomokbd);
locomokbd->timer.data = (unsigned long) locomokbd;
locomokbd->suspend_jiffies = jiffies; locomokbd->suspend_jiffies = jiffies;

View File

@ -42,9 +42,10 @@ struct matrix_keypad {
}; };
/* /*
* NOTE: normally the GPIO has to be put into HiZ when de-activated to cause * NOTE: If drive_inactive_cols is false, then the GPIO has to be put into
* minmal side effect when scanning other columns, here it is configured to * HiZ when de-activated to cause minmal side effect when scanning other
* be input, and it should work on most platforms. * columns. In that case it is configured here to be input, otherwise it is
* driven with the inactive value.
*/ */
static void __activate_col(const struct matrix_keypad_platform_data *pdata, static void __activate_col(const struct matrix_keypad_platform_data *pdata,
int col, bool on) int col, bool on)
@ -55,7 +56,8 @@ static void __activate_col(const struct matrix_keypad_platform_data *pdata,
gpio_direction_output(pdata->col_gpios[col], level_on); gpio_direction_output(pdata->col_gpios[col], level_on);
} else { } else {
gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
gpio_direction_input(pdata->col_gpios[col]); if (!pdata->drive_inactive_cols)
gpio_direction_input(pdata->col_gpios[col]);
} }
} }
@ -432,6 +434,9 @@ matrix_keypad_parse_dt(struct device *dev)
if (of_get_property(np, "gpio-activelow", NULL)) if (of_get_property(np, "gpio-activelow", NULL))
pdata->active_low = true; pdata->active_low = true;
pdata->drive_inactive_cols =
of_property_read_bool(np, "drive-inactive-cols");
of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms); of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms);
of_property_read_u32(np, "col-scan-delay-us", of_property_read_u32(np, "col-scan-delay-us",
&pdata->col_scan_delay_us); &pdata->col_scan_delay_us);

View File

@ -358,7 +358,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
"omap4-keypad", keypad_data); "omap4-keypad", keypad_data);
if (error) { if (error) {
dev_err(&pdev->dev, "failed to register interrupt\n"); dev_err(&pdev->dev, "failed to register interrupt\n");
goto err_free_input; goto err_free_keymap;
} }
device_init_wakeup(&pdev->dev, true); device_init_wakeup(&pdev->dev, true);

View File

@ -274,9 +274,18 @@ static const struct i2c_device_id qt1070_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, qt1070_id); MODULE_DEVICE_TABLE(i2c, qt1070_id);
#ifdef CONFIG_OF
static const struct of_device_id qt1070_of_match[] = {
{ .compatible = "qt1070", },
{ },
};
MODULE_DEVICE_TABLE(of, qt1070_of_match);
#endif
static struct i2c_driver qt1070_driver = { static struct i2c_driver qt1070_driver = {
.driver = { .driver = {
.name = "qt1070", .name = "qt1070",
.of_match_table = of_match_ptr(qt1070_of_match),
.pm = &qt1070_pm_ops, .pm = &qt1070_pm_ops,
}, },
.id_table = qt1070_id, .id_table = qt1070_id,

View File

@ -188,8 +188,6 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)
input_event(input, EV_MSC, MSC_SCAN, code); input_event(input, EV_MSC, MSC_SCAN, code);
input_report_key(input, keymap[code], state); input_report_key(input, keymap[code], state);
/* Read for next loop */
error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
} while (1); } while (1);
input_sync(input); input_sync(input);

View File

@ -143,7 +143,7 @@ config INPUT_PM8941_PWRKEY
config INPUT_PM8XXX_VIBRATOR config INPUT_PM8XXX_VIBRATOR
tristate "Qualcomm PM8XXX vibrator support" tristate "Qualcomm PM8XXX vibrator support"
depends on MFD_PM8XXX depends on MFD_PM8XXX || MFD_SPMI_PMIC
select INPUT_FF_MEMLESS select INPUT_FF_MEMLESS
help help
This option enables device driver support for the vibrator This option enables device driver support for the vibrator

View File

@ -314,7 +314,8 @@ static int __init apanel_init(void)
if (devno >= APANEL_DEV_MAX) if (devno >= APANEL_DEV_MAX)
pr_notice(APANEL ": unknown device %u found\n", devno); pr_notice(APANEL ": unknown device %u found\n", devno);
else if (device_chip[devno] != CHIP_NONE) else if (device_chip[devno] != CHIP_NONE)
pr_warning(APANEL ": duplicate entry for devno %u\n", devno); pr_warn(APANEL ": duplicate entry for devno %u\n",
devno);
else if (method != 1 && method != 2 && method != 4) { else if (method != 1 && method != 2 && method != 4) {
pr_notice(APANEL ": unknown method %u for devno %u\n", pr_notice(APANEL ": unknown method %u for devno %u\n",

View File

@ -13,6 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/acpi.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/init.h> #include <linux/init.h>
@ -188,21 +189,13 @@ static void axp20x_remove_sysfs_group(void *_data)
sysfs_remove_group(&dev->kobj, &axp20x_attribute_group); sysfs_remove_group(&dev->kobj, &axp20x_attribute_group);
} }
static int axp20x_pek_probe(struct platform_device *pdev) static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
struct platform_device *pdev)
{ {
struct axp20x_pek *axp20x_pek; struct axp20x_dev *axp20x = axp20x_pek->axp20x;
struct axp20x_dev *axp20x;
struct input_dev *idev; struct input_dev *idev;
int error; int error;
axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek),
GFP_KERNEL);
if (!axp20x_pek)
return -ENOMEM;
axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);
axp20x = axp20x_pek->axp20x;
axp20x_pek->irq_dbr = platform_get_irq_byname(pdev, "PEK_DBR"); axp20x_pek->irq_dbr = platform_get_irq_byname(pdev, "PEK_DBR");
if (axp20x_pek->irq_dbr < 0) { if (axp20x_pek->irq_dbr < 0) {
dev_err(&pdev->dev, "No IRQ for PEK_DBR, error=%d\n", dev_err(&pdev->dev, "No IRQ for PEK_DBR, error=%d\n",
@ -239,7 +232,7 @@ static int axp20x_pek_probe(struct platform_device *pdev)
axp20x_pek_irq, 0, axp20x_pek_irq, 0,
"axp20x-pek-dbr", idev); "axp20x-pek-dbr", idev);
if (error < 0) { if (error < 0) {
dev_err(axp20x->dev, "Failed to request dbr IRQ#%d: %d\n", dev_err(&pdev->dev, "Failed to request dbr IRQ#%d: %d\n",
axp20x_pek->irq_dbr, error); axp20x_pek->irq_dbr, error);
return error; return error;
} }
@ -248,14 +241,48 @@ static int axp20x_pek_probe(struct platform_device *pdev)
axp20x_pek_irq, 0, axp20x_pek_irq, 0,
"axp20x-pek-dbf", idev); "axp20x-pek-dbf", idev);
if (error < 0) { if (error < 0) {
dev_err(axp20x->dev, "Failed to request dbf IRQ#%d: %d\n", dev_err(&pdev->dev, "Failed to request dbf IRQ#%d: %d\n",
axp20x_pek->irq_dbf, error); axp20x_pek->irq_dbf, error);
return error; return error;
} }
error = input_register_device(idev);
if (error) {
dev_err(&pdev->dev, "Can't register input device: %d\n",
error);
return error;
}
return 0;
}
static int axp20x_pek_probe(struct platform_device *pdev)
{
struct axp20x_pek *axp20x_pek;
int error;
axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek),
GFP_KERNEL);
if (!axp20x_pek)
return -ENOMEM;
axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);
/*
* Do not register the input device if there is an "INTCFD9"
* gpio button ACPI device, that handles the power button too,
* and otherwise we end up reporting all presses twice.
*/
if (!acpi_dev_found("INTCFD9") ||
!IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY)) {
error = axp20x_pek_probe_input_device(axp20x_pek, pdev);
if (error)
return error;
}
error = sysfs_create_group(&pdev->dev.kobj, &axp20x_attribute_group); error = sysfs_create_group(&pdev->dev.kobj, &axp20x_attribute_group);
if (error) { if (error) {
dev_err(axp20x->dev, "Failed to create sysfs attributes: %d\n", dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n",
error); error);
return error; return error;
} }
@ -269,13 +296,6 @@ static int axp20x_pek_probe(struct platform_device *pdev)
return error; return error;
} }
error = input_register_device(idev);
if (error) {
dev_err(axp20x->dev, "Can't register input device: %d\n",
error);
return error;
}
platform_set_drvdata(pdev, axp20x_pek); platform_set_drvdata(pdev, axp20x_pek);
return 0; return 0;

View File

@ -70,7 +70,6 @@
#define BMA150_CFG_5_REG 0x11 #define BMA150_CFG_5_REG 0x11
#define BMA150_CHIP_ID 2 #define BMA150_CHIP_ID 2
#define BMA180_CHIP_ID 3
#define BMA150_CHIP_ID_REG BMA150_DATA_0_REG #define BMA150_CHIP_ID_REG BMA150_DATA_0_REG
#define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG #define BMA150_ACC_X_LSB_REG BMA150_DATA_2_REG
@ -538,13 +537,8 @@ static int bma150_probe(struct i2c_client *client,
return -EIO; return -EIO;
} }
/*
* Note if the IIO CONFIG_BMA180 driver is enabled we want to fail
* the probe for the bma180 as the iio driver is preferred.
*/
chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG); chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
if (chip_id != BMA150_CHIP_ID && if (chip_id != BMA150_CHIP_ID) {
(IS_ENABLED(CONFIG_BMA180) || chip_id != BMA180_CHIP_ID)) {
dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id); dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
return -EINVAL; return -EINVAL;
} }
@ -648,9 +642,6 @@ static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
static const struct i2c_device_id bma150_id[] = { static const struct i2c_device_id bma150_id[] = {
{ "bma150", 0 }, { "bma150", 0 },
#if !IS_ENABLED(CONFIG_BMA180)
{ "bma180", 0 },
#endif
{ "smb380", 0 }, { "smb380", 0 },
{ "bma023", 0 }, { "bma023", 0 },
{ } { }

View File

@ -32,7 +32,6 @@
struct dm355evm_keys { struct dm355evm_keys {
struct input_dev *input; struct input_dev *input;
struct device *dev; struct device *dev;
int irq;
}; };
/* These initial keycodes can be remapped */ /* These initial keycodes can be remapped */
@ -176,74 +175,49 @@ static int dm355evm_keys_probe(struct platform_device *pdev)
{ {
struct dm355evm_keys *keys; struct dm355evm_keys *keys;
struct input_dev *input; struct input_dev *input;
int status; int irq;
int error;
/* allocate instance struct and input dev */ keys = devm_kzalloc(&pdev->dev, sizeof (*keys), GFP_KERNEL);
keys = kzalloc(sizeof *keys, GFP_KERNEL); if (!keys)
input = input_allocate_device(); return -ENOMEM;
if (!keys || !input) {
status = -ENOMEM; input = devm_input_allocate_device(&pdev->dev);
goto fail1; if (!input)
} return -ENOMEM;
keys->dev = &pdev->dev; keys->dev = &pdev->dev;
keys->input = input; keys->input = input;
/* set up "threaded IRQ handler" */
status = platform_get_irq(pdev, 0);
if (status < 0)
goto fail1;
keys->irq = status;
input->name = "DM355 EVM Controls"; input->name = "DM355 EVM Controls";
input->phys = "dm355evm/input0"; input->phys = "dm355evm/input0";
input->dev.parent = &pdev->dev;
input->id.bustype = BUS_I2C; input->id.bustype = BUS_I2C;
input->id.product = 0x0355; input->id.product = 0x0355;
input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV); input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
status = sparse_keymap_setup(input, dm355evm_keys, NULL); error = sparse_keymap_setup(input, dm355evm_keys, NULL);
if (status) if (error)
goto fail1; return error;
/* REVISIT: flush the event queue? */ /* REVISIT: flush the event queue? */
status = request_threaded_irq(keys->irq, NULL, dm355evm_keys_irq, /* set up "threaded IRQ handler" */
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, irq = platform_get_irq(pdev, 0);
dev_name(&pdev->dev), keys); if (irq < 0)
if (status < 0) return irq;
goto fail2;
error = devm_request_threaded_irq(&pdev->dev, irq,
NULL, dm355evm_keys_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
dev_name(&pdev->dev), keys);
if (error)
return error;
/* register */ /* register */
status = input_register_device(input); error = input_register_device(input);
if (status < 0) if (error)
goto fail3; return error;
platform_set_drvdata(pdev, keys);
return 0;
fail3:
free_irq(keys->irq, keys);
fail2:
sparse_keymap_free(input);
fail1:
input_free_device(input);
kfree(keys);
dev_err(&pdev->dev, "can't register, err %d\n", status);
return status;
}
static int dm355evm_keys_remove(struct platform_device *pdev)
{
struct dm355evm_keys *keys = platform_get_drvdata(pdev);
free_irq(keys->irq, keys);
sparse_keymap_free(keys->input);
input_unregister_device(keys->input);
kfree(keys);
return 0; return 0;
} }
@ -259,7 +233,6 @@ static int dm355evm_keys_remove(struct platform_device *pdev)
*/ */
static struct platform_driver dm355evm_keys_driver = { static struct platform_driver dm355evm_keys_driver = {
.probe = dm355evm_keys_probe, .probe = dm355evm_keys_probe,
.remove = dm355evm_keys_remove,
.driver = { .driver = {
.name = "dm355evm_keys", .name = "dm355evm_keys",
}, },

View File

@ -652,7 +652,6 @@ static const struct i2c_device_id drv260x_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, drv260x_id); MODULE_DEVICE_TABLE(i2c, drv260x_id);
#ifdef CONFIG_OF
static const struct of_device_id drv260x_of_match[] = { static const struct of_device_id drv260x_of_match[] = {
{ .compatible = "ti,drv2604", }, { .compatible = "ti,drv2604", },
{ .compatible = "ti,drv2604l", }, { .compatible = "ti,drv2604l", },
@ -661,13 +660,12 @@ static const struct of_device_id drv260x_of_match[] = {
{ } { }
}; };
MODULE_DEVICE_TABLE(of, drv260x_of_match); MODULE_DEVICE_TABLE(of, drv260x_of_match);
#endif
static struct i2c_driver drv260x_driver = { static struct i2c_driver drv260x_driver = {
.probe = drv260x_probe, .probe = drv260x_probe,
.driver = { .driver = {
.name = "drv260x-haptics", .name = "drv260x-haptics",
.of_match_table = of_match_ptr(drv260x_of_match), .of_match_table = drv260x_of_match,
.pm = &drv260x_pm_ops, .pm = &drv260x_pm_ops,
}, },
.id_table = drv260x_id, .id_table = drv260x_id,

View File

@ -10,19 +10,15 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/slab.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h>
#define VIB_DRV 0x4A
#define VIB_DRV_SEL_MASK 0xf8
#define VIB_DRV_SEL_SHIFT 0x03
#define VIB_DRV_EN_MANUAL_MASK 0xfc
#define VIB_MAX_LEVEL_mV (3100) #define VIB_MAX_LEVEL_mV (3100)
#define VIB_MIN_LEVEL_mV (1200) #define VIB_MIN_LEVEL_mV (1200)
@ -30,20 +26,48 @@
#define MAX_FF_SPEED 0xff #define MAX_FF_SPEED 0xff
struct pm8xxx_regs {
unsigned int enable_addr;
unsigned int enable_mask;
unsigned int drv_addr;
unsigned int drv_mask;
unsigned int drv_shift;
unsigned int drv_en_manual_mask;
};
static const struct pm8xxx_regs pm8058_regs = {
.drv_addr = 0x4A,
.drv_mask = 0xf8,
.drv_shift = 3,
.drv_en_manual_mask = 0xfc,
};
static struct pm8xxx_regs pm8916_regs = {
.enable_addr = 0xc046,
.enable_mask = BIT(7),
.drv_addr = 0xc041,
.drv_mask = 0x1F,
.drv_shift = 0,
.drv_en_manual_mask = 0,
};
/** /**
* struct pm8xxx_vib - structure to hold vibrator data * struct pm8xxx_vib - structure to hold vibrator data
* @vib_input_dev: input device supporting force feedback * @vib_input_dev: input device supporting force feedback
* @work: work structure to set the vibration parameters * @work: work structure to set the vibration parameters
* @regmap: regmap for register read/write * @regmap: regmap for register read/write
* @regs: registers' info
* @speed: speed of vibration set from userland * @speed: speed of vibration set from userland
* @active: state of vibrator * @active: state of vibrator
* @level: level of vibration to set in the chip * @level: level of vibration to set in the chip
* @reg_vib_drv: VIB_DRV register value * @reg_vib_drv: regs->drv_addr register value
*/ */
struct pm8xxx_vib { struct pm8xxx_vib {
struct input_dev *vib_input_dev; struct input_dev *vib_input_dev;
struct work_struct work; struct work_struct work;
struct regmap *regmap; struct regmap *regmap;
const struct pm8xxx_regs *regs;
int speed; int speed;
int level; int level;
bool active; bool active;
@ -59,18 +83,24 @@ static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
{ {
int rc; int rc;
unsigned int val = vib->reg_vib_drv; unsigned int val = vib->reg_vib_drv;
const struct pm8xxx_regs *regs = vib->regs;
if (on) if (on)
val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK); val |= (vib->level << regs->drv_shift) & regs->drv_mask;
else else
val &= ~VIB_DRV_SEL_MASK; val &= ~regs->drv_mask;
rc = regmap_write(vib->regmap, VIB_DRV, val); rc = regmap_write(vib->regmap, regs->drv_addr, val);
if (rc < 0) if (rc < 0)
return rc; return rc;
vib->reg_vib_drv = val; vib->reg_vib_drv = val;
return 0;
if (regs->enable_mask)
rc = regmap_update_bits(vib->regmap, regs->enable_addr,
on ? regs->enable_mask : 0, val);
return rc;
} }
/** /**
@ -80,10 +110,11 @@ static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on)
static void pm8xxx_work_handler(struct work_struct *work) static void pm8xxx_work_handler(struct work_struct *work)
{ {
struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work); struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work);
const struct pm8xxx_regs *regs = vib->regs;
int rc; int rc;
unsigned int val; unsigned int val;
rc = regmap_read(vib->regmap, VIB_DRV, &val); rc = regmap_read(vib->regmap, regs->drv_addr, &val);
if (rc < 0) if (rc < 0)
return; return;
@ -147,6 +178,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
struct input_dev *input_dev; struct input_dev *input_dev;
int error; int error;
unsigned int val; unsigned int val;
const struct pm8xxx_regs *regs;
vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL); vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL);
if (!vib) if (!vib)
@ -163,16 +195,19 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
INIT_WORK(&vib->work, pm8xxx_work_handler); INIT_WORK(&vib->work, pm8xxx_work_handler);
vib->vib_input_dev = input_dev; vib->vib_input_dev = input_dev;
regs = of_device_get_match_data(&pdev->dev);
/* operate in manual mode */ /* operate in manual mode */
error = regmap_read(vib->regmap, VIB_DRV, &val); error = regmap_read(vib->regmap, regs->drv_addr, &val);
if (error < 0) if (error < 0)
return error; return error;
val &= ~VIB_DRV_EN_MANUAL_MASK; val &= regs->drv_en_manual_mask;
error = regmap_write(vib->regmap, VIB_DRV, val); error = regmap_write(vib->regmap, regs->drv_addr, val);
if (error < 0) if (error < 0)
return error; return error;
vib->regs = regs;
vib->reg_vib_drv = val; vib->reg_vib_drv = val;
input_dev->name = "pm8xxx_vib_ffmemless"; input_dev->name = "pm8xxx_vib_ffmemless";
@ -212,8 +247,9 @@ static int __maybe_unused pm8xxx_vib_suspend(struct device *dev)
static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
static const struct of_device_id pm8xxx_vib_id_table[] = { static const struct of_device_id pm8xxx_vib_id_table[] = {
{ .compatible = "qcom,pm8058-vib" }, { .compatible = "qcom,pm8058-vib", .data = &pm8058_regs },
{ .compatible = "qcom,pm8921-vib" }, { .compatible = "qcom,pm8921-vib", .data = &pm8058_regs },
{ .compatible = "qcom,pm8916-vib", .data = &pm8916_regs },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table); MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table);

View File

@ -19,6 +19,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/pwm.h> #include <linux/pwm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
@ -29,6 +30,7 @@ struct pwm_beeper {
struct regulator *amplifier; struct regulator *amplifier;
struct work_struct work; struct work_struct work;
unsigned long period; unsigned long period;
unsigned int bell_frequency;
bool suspended; bool suspended;
bool amplifier_on; bool amplifier_on;
}; };
@ -94,7 +96,7 @@ static int pwm_beeper_event(struct input_dev *input,
switch (code) { switch (code) {
case SND_BELL: case SND_BELL:
value = value ? 1000 : 0; value = value ? beeper->bell_frequency : 0;
break; break;
case SND_TONE: case SND_TONE:
break; break;
@ -131,6 +133,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct pwm_beeper *beeper; struct pwm_beeper *beeper;
struct pwm_state state; struct pwm_state state;
u32 bell_frequency;
int error; int error;
beeper = devm_kzalloc(dev, sizeof(*beeper), GFP_KERNEL); beeper = devm_kzalloc(dev, sizeof(*beeper), GFP_KERNEL);
@ -167,6 +170,16 @@ static int pwm_beeper_probe(struct platform_device *pdev)
INIT_WORK(&beeper->work, pwm_beeper_work); INIT_WORK(&beeper->work, pwm_beeper_work);
error = device_property_read_u32(dev, "beeper-hz", &bell_frequency);
if (error) {
bell_frequency = 1000;
dev_dbg(dev,
"failed to parse 'beeper-hz' property, using default: %uHz\n",
bell_frequency);
}
beeper->bell_frequency = bell_frequency;
beeper->input = devm_input_allocate_device(dev); beeper->input = devm_input_allocate_device(dev);
if (!beeper->input) { if (!beeper->input) {
dev_err(dev, "Failed to allocate input device\n"); dev_err(dev, "Failed to allocate input device\n");

View File

@ -20,13 +20,6 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
/*
* Definition of buttons on the tablet. The ACPI index of each button
* is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
* Platforms"
*/
#define MAX_NBUTTONS 5
struct soc_button_info { struct soc_button_info {
const char *name; const char *name;
int acpi_index; int acpi_index;
@ -55,7 +48,7 @@ static int soc_button_lookup_gpio(struct device *dev, int acpi_index)
struct gpio_desc *desc; struct gpio_desc *desc;
int gpio; int gpio;
desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index, GPIOD_ASIS); desc = gpiod_get_index(dev, NULL, acpi_index, GPIOD_ASIS);
if (IS_ERR(desc)) if (IS_ERR(desc))
return PTR_ERR(desc); return PTR_ERR(desc);
@ -79,14 +72,19 @@ soc_button_device_create(struct platform_device *pdev,
int gpio; int gpio;
int error; int error;
for (info = button_info; info->name; info++)
if (info->autorepeat == autorepeat)
n_buttons++;
gpio_keys_pdata = devm_kzalloc(&pdev->dev, gpio_keys_pdata = devm_kzalloc(&pdev->dev,
sizeof(*gpio_keys_pdata) + sizeof(*gpio_keys_pdata) +
sizeof(*gpio_keys) * MAX_NBUTTONS, sizeof(*gpio_keys) * n_buttons,
GFP_KERNEL); GFP_KERNEL);
if (!gpio_keys_pdata) if (!gpio_keys_pdata)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
gpio_keys = (void *)(gpio_keys_pdata + 1); gpio_keys = (void *)(gpio_keys_pdata + 1);
n_buttons = 0;
for (info = button_info; info->name; info++) { for (info = button_info; info->name; info++) {
if (info->autorepeat != autorepeat) if (info->autorepeat != autorepeat)
@ -140,6 +138,153 @@ soc_button_device_create(struct platform_device *pdev,
return ERR_PTR(error); return ERR_PTR(error);
} }
static int soc_button_get_acpi_object_int(const union acpi_object *obj)
{
if (obj->type != ACPI_TYPE_INTEGER)
return -1;
return obj->integer.value;
}
/* Parse a single ACPI0011 _DSD button descriptor */
static int soc_button_parse_btn_desc(struct device *dev,
const union acpi_object *desc,
int collection_uid,
struct soc_button_info *info)
{
int upage, usage;
if (desc->type != ACPI_TYPE_PACKAGE ||
desc->package.count != 5 ||
/* First byte should be 1 (control) */
soc_button_get_acpi_object_int(&desc->package.elements[0]) != 1 ||
/* Third byte should be collection uid */
soc_button_get_acpi_object_int(&desc->package.elements[2]) !=
collection_uid) {
dev_err(dev, "Invalid ACPI Button Descriptor\n");
return -ENODEV;
}
info->event_type = EV_KEY;
info->acpi_index =
soc_button_get_acpi_object_int(&desc->package.elements[1]);
upage = soc_button_get_acpi_object_int(&desc->package.elements[3]);
usage = soc_button_get_acpi_object_int(&desc->package.elements[4]);
/*
* The UUID: fa6bd625-9ce8-470d-a2c7-b3ca36c4282e descriptors use HID
* usage page and usage codes, but otherwise the device is not HID
* compliant: it uses one irq per button instead of generating HID
* input reports and some buttons should generate wakeups where as
* others should not, so we cannot use the HID subsystem.
*
* Luckily all devices only use a few usage page + usage combinations,
* so we can simply check for the known combinations here.
*/
if (upage == 0x01 && usage == 0x81) {
info->name = "power";
info->event_code = KEY_POWER;
info->wakeup = true;
} else if (upage == 0x07 && usage == 0xe3) {
info->name = "home";
info->event_code = KEY_LEFTMETA;
info->wakeup = true;
} else if (upage == 0x0c && usage == 0xe9) {
info->name = "volume_up";
info->event_code = KEY_VOLUMEUP;
info->autorepeat = true;
} else if (upage == 0x0c && usage == 0xea) {
info->name = "volume_down";
info->event_code = KEY_VOLUMEDOWN;
info->autorepeat = true;
} else {
dev_warn(dev, "Unknown button index %d upage %02x usage %02x, ignoring\n",
info->acpi_index, upage, usage);
info->name = "unknown";
info->event_code = KEY_RESERVED;
}
return 0;
}
/* ACPI0011 _DSD btns descriptors UUID: fa6bd625-9ce8-470d-a2c7-b3ca36c4282e */
static const u8 btns_desc_uuid[16] = {
0x25, 0xd6, 0x6b, 0xfa, 0xe8, 0x9c, 0x0d, 0x47,
0xa2, 0xc7, 0xb3, 0xca, 0x36, 0xc4, 0x28, 0x2e
};
/* Parse ACPI0011 _DSD button descriptors */
static struct soc_button_info *soc_button_get_button_info(struct device *dev)
{
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
const union acpi_object *desc, *el0, *uuid, *btns_desc = NULL;
struct soc_button_info *button_info;
acpi_status status;
int i, btn, collection_uid = -1;
status = acpi_evaluate_object_typed(ACPI_HANDLE(dev), "_DSD", NULL,
&buf, ACPI_TYPE_PACKAGE);
if (ACPI_FAILURE(status)) {
dev_err(dev, "ACPI _DSD object not found\n");
return ERR_PTR(-ENODEV);
}
/* Look for the Button Descriptors UUID */
desc = buf.pointer;
for (i = 0; (i + 1) < desc->package.count; i += 2) {
uuid = &desc->package.elements[i];
if (uuid->type != ACPI_TYPE_BUFFER ||
uuid->buffer.length != 16 ||
desc->package.elements[i + 1].type != ACPI_TYPE_PACKAGE) {
break;
}
if (memcmp(uuid->buffer.pointer, btns_desc_uuid, 16) == 0) {
btns_desc = &desc->package.elements[i + 1];
break;
}
}
if (!btns_desc) {
dev_err(dev, "ACPI Button Descriptors not found\n");
return ERR_PTR(-ENODEV);
}
/* The first package describes the collection */
el0 = &btns_desc->package.elements[0];
if (el0->type == ACPI_TYPE_PACKAGE &&
el0->package.count == 5 &&
/* First byte should be 0 (collection) */
soc_button_get_acpi_object_int(&el0->package.elements[0]) == 0 &&
/* Third byte should be 0 (top level collection) */
soc_button_get_acpi_object_int(&el0->package.elements[2]) == 0) {
collection_uid = soc_button_get_acpi_object_int(
&el0->package.elements[1]);
}
if (collection_uid == -1) {
dev_err(dev, "Invalid Button Collection Descriptor\n");
return ERR_PTR(-ENODEV);
}
/* There are package.count - 1 buttons + 1 terminating empty entry */
button_info = devm_kcalloc(dev, btns_desc->package.count,
sizeof(*button_info), GFP_KERNEL);
if (!button_info)
return ERR_PTR(-ENOMEM);
/* Parse the button descriptors */
for (i = 1, btn = 0; i < btns_desc->package.count; i++, btn++) {
if (soc_button_parse_btn_desc(dev,
&btns_desc->package.elements[i],
collection_uid,
&button_info[btn]))
return ERR_PTR(-ENODEV);
}
return button_info;
}
static int soc_button_remove(struct platform_device *pdev) static int soc_button_remove(struct platform_device *pdev)
{ {
struct soc_button_data *priv = platform_get_drvdata(pdev); struct soc_button_data *priv = platform_get_drvdata(pdev);
@ -167,9 +312,15 @@ static int soc_button_probe(struct platform_device *pdev)
if (!id) if (!id)
return -ENODEV; return -ENODEV;
button_info = (struct soc_button_info *)id->driver_data; if (!id->driver_data) {
button_info = soc_button_get_button_info(dev);
if (IS_ERR(button_info))
return PTR_ERR(button_info);
} else {
button_info = (struct soc_button_info *)id->driver_data;
}
if (gpiod_count(dev, KBUILD_MODNAME) <= 0) { if (gpiod_count(dev, NULL) <= 0) {
dev_dbg(dev, "no GPIO attached, ignoring...\n"); dev_dbg(dev, "no GPIO attached, ignoring...\n");
return -ENODEV; return -ENODEV;
} }
@ -197,9 +348,17 @@ static int soc_button_probe(struct platform_device *pdev)
if (!priv->children[0] && !priv->children[1]) if (!priv->children[0] && !priv->children[1])
return -ENODEV; return -ENODEV;
if (!id->driver_data)
devm_kfree(dev, button_info);
return 0; return 0;
} }
/*
* Definition of buttons on the tablet. The ACPI index of each button
* is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
* Platforms"
*/
static struct soc_button_info soc_button_PNP0C40[] = { static struct soc_button_info soc_button_PNP0C40[] = {
{ "power", 0, EV_KEY, KEY_POWER, false, true }, { "power", 0, EV_KEY, KEY_POWER, false, true },
{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true }, { "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
@ -211,6 +370,7 @@ static struct soc_button_info soc_button_PNP0C40[] = {
static const struct acpi_device_id soc_button_acpi_match[] = { static const struct acpi_device_id soc_button_acpi_match[] = {
{ "PNP0C40", (unsigned long)soc_button_PNP0C40 }, { "PNP0C40", (unsigned long)soc_button_PNP0C40 },
{ "ACPI0011", 0 },
{ } { }
}; };

View File

@ -64,13 +64,12 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
pwr->evbit[0] = BIT_MASK(EV_KEY); input_set_capability(pwr, EV_KEY, KEY_POWER);
pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
pwr->name = "twl4030_pwrbutton"; pwr->name = "twl4030_pwrbutton";
pwr->phys = "twl4030_pwrbutton/input0"; pwr->phys = "twl4030_pwrbutton/input0";
pwr->dev.parent = &pdev->dev; pwr->dev.parent = &pdev->dev;
err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq, err = devm_request_threaded_irq(&pdev->dev, irq, NULL, powerbutton_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
IRQF_ONESHOT, IRQF_ONESHOT,
"twl4030_pwrbutton", pwr); "twl4030_pwrbutton", pwr);

View File

@ -1243,12 +1243,10 @@ static int setup_input_dev(void)
error = input_register_polled_device(wistron_idev); error = input_register_polled_device(wistron_idev);
if (error) if (error)
goto err_free_keymap; goto err_free_dev;
return 0; return 0;
err_free_keymap:
sparse_keymap_free(input_dev);
err_free_dev: err_free_dev:
input_free_polled_device(wistron_idev); input_free_polled_device(wistron_idev);
return error; return error;
@ -1300,7 +1298,6 @@ static int wistron_remove(struct platform_device *dev)
{ {
wistron_led_remove(); wistron_led_remove();
input_unregister_polled_device(wistron_idev); input_unregister_polled_device(wistron_idev);
sparse_keymap_free(wistron_idev->input);
input_free_polled_device(wistron_idev); input_free_polled_device(wistron_idev);
bios_detach(); bios_detach();

View File

@ -41,6 +41,12 @@ struct xenkbd_info {
char phys[32]; char phys[32];
}; };
enum { KPARAM_X, KPARAM_Y, KPARAM_CNT };
static int ptr_size[KPARAM_CNT] = { XENFB_WIDTH, XENFB_HEIGHT };
module_param_array(ptr_size, int, NULL, 0444);
MODULE_PARM_DESC(ptr_size,
"Pointing device width, height in pixels (default 800,600)");
static int xenkbd_remove(struct xenbus_device *); static int xenkbd_remove(struct xenbus_device *);
static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *); static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
static void xenkbd_disconnect_backend(struct xenkbd_info *); static void xenkbd_disconnect_backend(struct xenkbd_info *);
@ -84,8 +90,8 @@ static irqreturn_t input_handler(int rq, void *dev_id)
input_report_key(dev, event->key.keycode, input_report_key(dev, event->key.keycode,
event->key.pressed); event->key.pressed);
else else
pr_warning("unhandled keycode 0x%x\n", pr_warn("unhandled keycode 0x%x\n",
event->key.keycode); event->key.keycode);
break; break;
case XENKBD_TYPE_POS: case XENKBD_TYPE_POS:
input_report_abs(dev, ABS_X, event->pos.abs_x); input_report_abs(dev, ABS_X, event->pos.abs_x);
@ -128,12 +134,17 @@ static int xenkbd_probe(struct xenbus_device *dev,
if (!info->page) if (!info->page)
goto error_nomem; goto error_nomem;
/* Set input abs params to match backend screen res */
abs = xenbus_read_unsigned(dev->otherend, "feature-abs-pointer", 0); abs = xenbus_read_unsigned(dev->otherend, "feature-abs-pointer", 0);
ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend, "width",
ptr_size[KPARAM_X]);
ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend, "height",
ptr_size[KPARAM_Y]);
if (abs) { if (abs) {
ret = xenbus_write(XBT_NIL, dev->nodename, ret = xenbus_write(XBT_NIL, dev->nodename,
"request-abs-pointer", "1"); "request-abs-pointer", "1");
if (ret) { if (ret) {
pr_warning("xenkbd: can't request abs-pointer"); pr_warn("xenkbd: can't request abs-pointer\n");
abs = 0; abs = 0;
} }
} }
@ -174,8 +185,8 @@ static int xenkbd_probe(struct xenbus_device *dev,
if (abs) { if (abs) {
__set_bit(EV_ABS, ptr->evbit); __set_bit(EV_ABS, ptr->evbit);
input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); input_set_abs_params(ptr, ABS_X, 0, ptr_size[KPARAM_X], 0, 0);
input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); input_set_abs_params(ptr, ABS_Y, 0, ptr_size[KPARAM_Y], 0, 0);
} else { } else {
input_set_capability(ptr, EV_REL, REL_X); input_set_capability(ptr, EV_REL, REL_X);
input_set_capability(ptr, EV_REL, REL_Y); input_set_capability(ptr, EV_REL, REL_Y);
@ -309,9 +320,6 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *info)
static void xenkbd_backend_changed(struct xenbus_device *dev, static void xenkbd_backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state) enum xenbus_state backend_state)
{ {
struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
int ret, val;
switch (backend_state) { switch (backend_state) {
case XenbusStateInitialising: case XenbusStateInitialising:
case XenbusStateInitialised: case XenbusStateInitialised:
@ -321,15 +329,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
break; break;
case XenbusStateInitWait: case XenbusStateInitWait:
InitWait:
if (xenbus_read_unsigned(info->xbdev->otherend,
"feature-abs-pointer", 0)) {
ret = xenbus_write(XBT_NIL, info->xbdev->nodename,
"request-abs-pointer", "1");
if (ret)
pr_warning("xenkbd: can't request abs-pointer");
}
xenbus_switch_state(dev, XenbusStateConnected); xenbus_switch_state(dev, XenbusStateConnected);
break; break;
@ -340,17 +339,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
* get Connected twice here. * get Connected twice here.
*/ */
if (dev->state != XenbusStateConnected) if (dev->state != XenbusStateConnected)
goto InitWait; /* no InitWait seen yet, fudge it */ xenbus_switch_state(dev, XenbusStateConnected);
/* Set input abs params to match backend screen res */
if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
"width", "%d", &val) > 0)
input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
"height", "%d", &val) > 0)
input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
break; break;
case XenbusStateClosed: case XenbusStateClosed:

View File

@ -28,7 +28,7 @@
struct yld_ctl_packet { struct yld_ctl_packet {
u8 cmd; /* command code, see below */ u8 cmd; /* command code, see below */
u8 size; /* 1-11, size of used data bytes. */ u8 size; /* 1-11, size of used data bytes. */
u16 offset; /* internal packet offset */ __be16 offset; /* internal packet offset */
u8 data[11]; u8 data[11];
s8 sum; /* negative sum of 15 preceding bytes */ s8 sum; /* negative sum of 15 preceding bytes */
} __attribute__ ((packed)); } __attribute__ ((packed));

View File

@ -78,6 +78,18 @@ config MOUSE_PS2_SYNAPTICS
If unsure, say Y. If unsure, say Y.
config MOUSE_PS2_SYNAPTICS_SMBUS
bool "Synaptics PS/2 SMbus companion" if EXPERT
default y
depends on MOUSE_PS2
depends on I2C=y || I2C=MOUSE_PS2
select MOUSE_PS2_SMBUS
help
Say Y here if you have a Synaptics RMI4 touchpad connected to
to an SMBus, but enumerated through PS/2.
If unsure, say Y.
config MOUSE_PS2_CYPRESS config MOUSE_PS2_CYPRESS
bool "Cypress PS/2 mouse protocol extension" if EXPERT bool "Cypress PS/2 mouse protocol extension" if EXPERT
default y default y
@ -171,6 +183,10 @@ config MOUSE_PS2_VMMOUSE
If unsure, say N. If unsure, say N.
config MOUSE_PS2_SMBUS
bool
depends on MOUSE_PS2
config MOUSE_SERIAL config MOUSE_SERIAL
tristate "Serial mouse" tristate "Serial mouse"
select SERIO select SERIO

View File

@ -39,6 +39,8 @@ psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o
psmouse-$(CONFIG_MOUSE_PS2_VMMOUSE) += vmmouse.o psmouse-$(CONFIG_MOUSE_PS2_VMMOUSE) += vmmouse.o
psmouse-$(CONFIG_MOUSE_PS2_SMBUS) += psmouse-smbus.o
elan_i2c-objs := elan_i2c_core.o elan_i2c-objs := elan_i2c_core.o
elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C) += elan_i2c_i2c.o elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C) += elan_i2c_i2c.o
elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_SMBUS) += elan_i2c_smbus.o elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_SMBUS) += elan_i2c_smbus.o

View File

@ -106,39 +106,36 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
#define ALPS_DUALPOINT_WITH_PRESSURE 0x400 /* device can report trackpoint pressure */ #define ALPS_DUALPOINT_WITH_PRESSURE 0x400 /* device can report trackpoint pressure */
static const struct alps_model_info alps_model_data[] = { static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */
{ { 0x33, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V1, 0x88, 0xf8, 0 } }, /* UMAX-530T */
{ { 0x53, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x53, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x60, 0x03, 0xc8 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } }, /* HP ze1115 */
{ { 0x63, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x02, 0x28 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Fujitsu Siemens S6010 */
{ { 0x63, 0x02, 0x3c }, 0x00, { ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL } }, /* Toshiba Satellite S2400-103 */
{ { 0x63, 0x02, 0x50 }, 0x00, { ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 } }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x03, 0xc8 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D800 */
{ { 0x73, 0x00, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT } }, /* ThinkPad R61 8918-5QG */
{ { 0x73, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x73, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Ahtec Laptop */
/* /*
* XXX This entry is suspicious. First byte has zero lower nibble, * XXX This entry is suspicious. First byte has zero lower nibble,
* which is what a normal mouse would report. Also, the value 0x0e * which is what a normal mouse would report. Also, the value 0x0e
* isn't valid per PS/2 spec. * isn't valid per PS/2 spec.
*/ */
{ { 0x20, 0x02, 0x0e }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, { { 0x20, 0x02, 0x0e }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
{ { 0x22, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, { { 0x22, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
{ { 0x22, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D600 */ { { 0x22, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D600 */
/* Dell Latitude E5500, E6400, E6500, Precision M4400 */ { { 0x32, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */
{ { 0x62, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xcf, 0xcf, { { 0x33, 0x02, 0x0a }, { ALPS_PROTO_V1, 0x88, 0xf8, 0 } }, /* UMAX-530T */
ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, { { 0x52, 0x01, 0x14 }, { ALPS_PROTO_V2, 0xff, 0xff,
{ { 0x73, 0x00, 0x14 }, 0x00, { ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT } }, /* Dell XT2 */
{ { 0x73, 0x02, 0x50 }, 0x00, { ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS } }, /* Dell Vostro 1400 */
{ { 0x52, 0x01, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xff, 0xff,
ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, /* Toshiba Tecra A11-11L */ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, /* Toshiba Tecra A11-11L */
{ { 0x73, 0x02, 0x64 }, 0x8a, { ALPS_PROTO_V4, 0x8f, 0x8f, 0 } }, { { 0x53, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x53, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x60, 0x03, 0xc8 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } }, /* HP ze1115 */
{ { 0x62, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xcf, 0xcf,
ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
{ { 0x63, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x02, 0x28 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Fujitsu Siemens S6010 */
{ { 0x63, 0x02, 0x3c }, { ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL } }, /* Toshiba Satellite S2400-103 */
{ { 0x63, 0x02, 0x50 }, { ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 } }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x63, 0x03, 0xc8 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D800 */
{ { 0x73, 0x00, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT } }, /* ThinkPad R61 8918-5QG */
{ { 0x73, 0x00, 0x14 }, { ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT } }, /* Dell XT2 */
{ { 0x73, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
{ { 0x73, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Ahtec Laptop */
{ { 0x73, 0x02, 0x50 }, { ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS } }, /* Dell Vostro 1400 */
}; };
static const struct alps_protocol_info alps_v3_protocol_data = { static const struct alps_protocol_info alps_v3_protocol_data = {
@ -149,6 +146,10 @@ static const struct alps_protocol_info alps_v3_rushmore_data = {
ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT
}; };
static const struct alps_protocol_info alps_v4_protocol_data = {
ALPS_PROTO_V4, 0x8f, 0x8f, 0
};
static const struct alps_protocol_info alps_v5_protocol_data = { static const struct alps_protocol_info alps_v5_protocol_data = {
ALPS_PROTO_V5, 0xc8, 0xd8, 0 ALPS_PROTO_V5, 0xc8, 0xd8, 0
}; };
@ -161,6 +162,10 @@ static const struct alps_protocol_info alps_v8_protocol_data = {
ALPS_PROTO_V8, 0x18, 0x18, 0 ALPS_PROTO_V8, 0x18, 0x18, 0
}; };
static const struct alps_protocol_info alps_v9_protocol_data = {
ALPS_PROTO_V9, 0xc8, 0xc8, 0
};
/* /*
* Some v2 models report the stick buttons in separate bits * Some v2 models report the stick buttons in separate bits
*/ */
@ -2806,12 +2811,8 @@ static const struct alps_protocol_info *alps_match_table(unsigned char *e7,
for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
model = &alps_model_data[i]; model = &alps_model_data[i];
if (!memcmp(e7, model->signature, sizeof(model->signature)) && if (!memcmp(e7, model->signature, sizeof(model->signature)))
(!model->command_mode_resp ||
model->command_mode_resp == ec[2])) {
return &model->protocol_info; return &model->protocol_info;
}
} }
return NULL; return NULL;
@ -2849,7 +2850,10 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
protocol = alps_match_table(e7, ec); protocol = alps_match_table(e7, ec);
if (!protocol) { if (!protocol) {
if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && if (e7[0] == 0x73 && e7[1] == 0x02 && e7[2] == 0x64 &&
ec[2] == 0x8a) {
protocol = &alps_v4_protocol_data;
} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) { ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) {
protocol = &alps_v5_protocol_data; protocol = &alps_v5_protocol_data;
} else if (ec[0] == 0x88 && } else if (ec[0] == 0x88 &&
@ -2863,6 +2867,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
} else if (e7[0] == 0x73 && e7[1] == 0x03 && } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
(e7[2] == 0x14 || e7[2] == 0x28)) { (e7[2] == 0x14 || e7[2] == 0x28)) {
protocol = &alps_v8_protocol_data; protocol = &alps_v8_protocol_data;
} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0xc8) {
protocol = &alps_v9_protocol_data;
psmouse_warn(psmouse,
"Unsupported ALPS V9 touchpad: E7=%3ph, EC=%3ph\n",
e7, ec);
return -EINVAL;
} else { } else {
psmouse_dbg(psmouse, psmouse_dbg(psmouse,
"Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);

View File

@ -23,6 +23,7 @@
#define ALPS_PROTO_V6 0x600 #define ALPS_PROTO_V6 0x600
#define ALPS_PROTO_V7 0x700 /* t3btl t4s */ #define ALPS_PROTO_V7 0x700 /* t3btl t4s */
#define ALPS_PROTO_V8 0x800 /* SS4btl SS4s */ #define ALPS_PROTO_V8 0x800 /* SS4btl SS4s */
#define ALPS_PROTO_V9 0x900 /* ss3btl */
#define MAX_TOUCHES 4 #define MAX_TOUCHES 4
@ -172,10 +173,6 @@ struct alps_protocol_info {
/** /**
* struct alps_model_info - touchpad ID table * struct alps_model_info - touchpad ID table
* @signature: E7 response string to match. * @signature: E7 response string to match.
* @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response
* (aka command mode response) identifies the firmware minor version. This
* can be used to distinguish different hardware models which are not
* uniquely identifiable through their E7 responses.
* @protocol_info: information about protocol used by the device. * @protocol_info: information about protocol used by the device.
* *
* Many (but not all) ALPS touchpads can be identified by looking at the * Many (but not all) ALPS touchpads can be identified by looking at the
@ -184,7 +181,6 @@ struct alps_protocol_info {
*/ */
struct alps_model_info { struct alps_model_info {
u8 signature[3]; u8 signature[3];
u8 command_mode_resp;
struct alps_protocol_info protocol_info; struct alps_protocol_info protocol_info;
}; };

View File

@ -116,17 +116,6 @@ static DEFINE_MUTEX(psmouse_mutex);
static struct workqueue_struct *kpsmoused_wq; static struct workqueue_struct *kpsmoused_wq;
struct psmouse_protocol {
enum psmouse_type type;
bool maxproto;
bool ignore_parity; /* Protocol should ignore parity errors from KBC */
bool try_passthru; /* Try protocol also on passthrough ports */
const char *name;
const char *alias;
int (*detect)(struct psmouse *, bool);
int (*init)(struct psmouse *);
};
static void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons) static void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
{ {
input_report_key(dev, BTN_LEFT, buttons & BIT(0)); input_report_key(dev, BTN_LEFT, buttons & BIT(0));
@ -148,7 +137,7 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
/* Full packet accumulated, process it */ /* Full packet accumulated, process it */
switch (psmouse->type) { switch (psmouse->protocol->type) {
case PSMOUSE_IMPS: case PSMOUSE_IMPS:
/* IntelliMouse has scroll wheel */ /* IntelliMouse has scroll wheel */
input_report_rel(dev, REL_WHEEL, -(signed char) packet[3]); input_report_rel(dev, REL_WHEEL, -(signed char) packet[3]);
@ -325,7 +314,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto out; goto out;
if (unlikely((flags & SERIO_TIMEOUT) || if (unlikely((flags & SERIO_TIMEOUT) ||
((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { ((flags & SERIO_PARITY) &&
!psmouse->protocol->ignore_parity))) {
if (psmouse->state == PSMOUSE_ACTIVATED) if (psmouse->state == PSMOUSE_ACTIVATED)
psmouse_warn(psmouse, psmouse_warn(psmouse,
@ -372,7 +362,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
} }
if (psmouse->packet[1] == PSMOUSE_RET_ID || if (psmouse->packet[1] == PSMOUSE_RET_ID ||
(psmouse->type == PSMOUSE_HGPK && (psmouse->protocol->type == PSMOUSE_HGPK &&
psmouse->packet[1] == PSMOUSE_RET_BAT)) { psmouse->packet[1] == PSMOUSE_RET_BAT)) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE); __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
serio_reconnect(serio); serio_reconnect(serio);
@ -783,7 +773,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.name = "SynPS/2", .name = "SynPS/2",
.alias = "synaptics", .alias = "synaptics",
.detect = synaptics_detect, .detect = synaptics_detect,
.init = synaptics_init, .init = synaptics_init_absolute,
}, },
{ {
.type = PSMOUSE_SYNAPTICS_RELATIVE, .type = PSMOUSE_SYNAPTICS_RELATIVE,
@ -793,6 +783,16 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.init = synaptics_init_relative, .init = synaptics_init_relative,
}, },
#endif #endif
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS
{
.type = PSMOUSE_SYNAPTICS_SMBUS,
.name = "SynSMBus",
.alias = "synaptics-smbus",
.detect = synaptics_detect,
.init = synaptics_init_smbus,
.smbus_companion = true,
},
#endif
#ifdef CONFIG_MOUSE_PS2_ALPS #ifdef CONFIG_MOUSE_PS2_ALPS
{ {
.type = PSMOUSE_ALPS, .type = PSMOUSE_ALPS,
@ -959,6 +959,8 @@ static void psmouse_apply_defaults(struct psmouse *psmouse)
__set_bit(INPUT_PROP_POINTER, input_dev->propbit); __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
psmouse->protocol = &psmouse_protocols[0];
psmouse->set_rate = psmouse_set_rate; psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution; psmouse->set_resolution = psmouse_set_resolution;
psmouse->set_scale = psmouse_set_scale; psmouse->set_scale = psmouse_set_scale;
@ -966,6 +968,7 @@ static void psmouse_apply_defaults(struct psmouse *psmouse)
psmouse->protocol_handler = psmouse_process_byte; psmouse->protocol_handler = psmouse_process_byte;
psmouse->pktsize = 3; psmouse->pktsize = 3;
psmouse->reconnect = NULL; psmouse->reconnect = NULL;
psmouse->fast_reconnect = NULL;
psmouse->disconnect = NULL; psmouse->disconnect = NULL;
psmouse->cleanup = NULL; psmouse->cleanup = NULL;
psmouse->pt_activate = NULL; psmouse->pt_activate = NULL;
@ -1018,6 +1021,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
unsigned int max_proto, bool set_properties) unsigned int max_proto, bool set_properties)
{ {
bool synaptics_hardware = false; bool synaptics_hardware = false;
int ret;
/* /*
* Always check for focaltech, this is safe as it uses pnp-id * Always check for focaltech, this is safe as it uses pnp-id
@ -1080,9 +1084,14 @@ static int psmouse_extensions(struct psmouse *psmouse,
* enabled first, since we try detecting Synaptics * enabled first, since we try detecting Synaptics
* even when protocol is disabled. * even when protocol is disabled.
*/ */
if (IS_ENABLED(CONFIG_MOUSE_PS2_SYNAPTICS) && if (IS_ENABLED(CONFIG_MOUSE_PS2_SYNAPTICS) ||
(!set_properties || synaptics_init(psmouse) == 0)) { IS_ENABLED(CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS)) {
return PSMOUSE_SYNAPTICS; if (!set_properties)
return PSMOUSE_SYNAPTICS;
ret = synaptics_init(psmouse);
if (ret >= 0)
return ret;
} }
/* /*
@ -1431,9 +1440,8 @@ static void psmouse_cleanup(struct serio *serio)
*/ */
static void psmouse_disconnect(struct serio *serio) static void psmouse_disconnect(struct serio *serio)
{ {
struct psmouse *psmouse, *parent = NULL; struct psmouse *psmouse = serio_get_drvdata(serio);
struct psmouse *parent = NULL;
psmouse = serio_get_drvdata(serio);
sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group); sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
@ -1461,7 +1469,10 @@ static void psmouse_disconnect(struct serio *serio)
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
input_unregister_device(psmouse->dev);
if (psmouse->dev)
input_unregister_device(psmouse->dev);
kfree(psmouse); kfree(psmouse);
if (parent) if (parent)
@ -1475,6 +1486,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
{ {
const struct psmouse_protocol *selected_proto; const struct psmouse_protocol *selected_proto;
struct input_dev *input_dev = psmouse->dev; struct input_dev *input_dev = psmouse->dev;
enum psmouse_type type;
input_dev->dev.parent = &psmouse->ps2dev.serio->dev; input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
@ -1487,15 +1499,13 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
if (proto->init && proto->init(psmouse) < 0) if (proto->init && proto->init(psmouse) < 0)
return -1; return -1;
psmouse->type = proto->type;
selected_proto = proto; selected_proto = proto;
} else { } else {
psmouse->type = psmouse_extensions(psmouse, type = psmouse_extensions(psmouse, psmouse_max_proto, true);
psmouse_max_proto, true); selected_proto = psmouse_protocol_by_type(type);
selected_proto = psmouse_protocol_by_type(psmouse->type);
} }
psmouse->ignore_parity = selected_proto->ignore_parity; psmouse->protocol = selected_proto;
/* /*
* If mouse's packet size is 3 there is no point in polling the * If mouse's packet size is 3 there is no point in polling the
@ -1521,7 +1531,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
input_dev->phys = psmouse->phys; input_dev->phys = psmouse->phys;
input_dev->id.bustype = BUS_I8042; input_dev->id.bustype = BUS_I8042;
input_dev->id.vendor = 0x0002; input_dev->id.vendor = 0x0002;
input_dev->id.product = psmouse->type; input_dev->id.product = psmouse->protocol->type;
input_dev->id.version = psmouse->model; input_dev->id.version = psmouse->model;
return 0; return 0;
@ -1583,12 +1593,18 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse_switch_protocol(psmouse, NULL); psmouse_switch_protocol(psmouse, NULL);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); if (!psmouse->protocol->smbus_companion) {
psmouse_initialize(psmouse); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
psmouse_initialize(psmouse);
error = input_register_device(psmouse->dev); error = input_register_device(input_dev);
if (error) if (error)
goto err_protocol_disconnect; goto err_protocol_disconnect;
} else {
/* Smbus companion will be reporting events, not us. */
input_free_device(input_dev);
psmouse->dev = input_dev = NULL;
}
if (parent && parent->pt_activate) if (parent && parent->pt_activate)
parent->pt_activate(parent); parent->pt_activate(parent);
@ -1597,7 +1613,12 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
if (error) if (error)
goto err_pt_deactivate; goto err_pt_deactivate;
psmouse_activate(psmouse); /*
* PS/2 devices having SMBus companions should stay disabled
* on PS/2 side, in order to have SMBus part operable.
*/
if (!psmouse->protocol->smbus_companion)
psmouse_activate(psmouse);
out: out:
/* If this is a pass-through port the parent needs to be re-activated */ /* If this is a pass-through port the parent needs to be re-activated */
@ -1610,8 +1631,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
err_pt_deactivate: err_pt_deactivate:
if (parent && parent->pt_deactivate) if (parent && parent->pt_deactivate)
parent->pt_deactivate(parent); parent->pt_deactivate(parent);
input_unregister_device(psmouse->dev); if (input_dev) {
input_dev = NULL; /* so we don't try to free it below */ input_unregister_device(input_dev);
input_dev = NULL; /* so we don't try to free it below */
}
err_protocol_disconnect: err_protocol_disconnect:
if (psmouse->disconnect) if (psmouse->disconnect)
psmouse->disconnect(psmouse); psmouse->disconnect(psmouse);
@ -1628,15 +1651,26 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
goto out; goto out;
} }
static int psmouse_reconnect(struct serio *serio) static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect)
{ {
struct psmouse *psmouse = serio_get_drvdata(serio); struct psmouse *psmouse = serio_get_drvdata(serio);
struct psmouse *parent = NULL; struct psmouse *parent = NULL;
unsigned char type; int (*reconnect_handler)(struct psmouse *);
enum psmouse_type type;
int rc = -1; int rc = -1;
mutex_lock(&psmouse_mutex); mutex_lock(&psmouse_mutex);
if (fast_reconnect) {
reconnect_handler = psmouse->fast_reconnect;
if (!reconnect_handler) {
rc = -ENOENT;
goto out_unlock;
}
} else {
reconnect_handler = psmouse->reconnect;
}
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent); parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent); psmouse_deactivate(parent);
@ -1644,8 +1678,8 @@ static int psmouse_reconnect(struct serio *serio)
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
if (psmouse->reconnect) { if (reconnect_handler) {
if (psmouse->reconnect(psmouse)) if (reconnect_handler(psmouse))
goto out; goto out;
} else { } else {
psmouse_reset(psmouse); psmouse_reset(psmouse);
@ -1654,7 +1688,7 @@ static int psmouse_reconnect(struct serio *serio)
goto out; goto out;
type = psmouse_extensions(psmouse, psmouse_max_proto, false); type = psmouse_extensions(psmouse, psmouse_max_proto, false);
if (psmouse->type != type) if (psmouse->protocol->type != type)
goto out; goto out;
} }
@ -1662,14 +1696,21 @@ static int psmouse_reconnect(struct serio *serio)
* OK, the device type (and capabilities) match the old one, * OK, the device type (and capabilities) match the old one,
* we can continue using it, complete initialization * we can continue using it, complete initialization
*/ */
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); if (!psmouse->protocol->smbus_companion) {
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
psmouse_initialize(psmouse); psmouse_initialize(psmouse);
}
if (parent && parent->pt_activate) if (parent && parent->pt_activate)
parent->pt_activate(parent); parent->pt_activate(parent);
psmouse_activate(psmouse); /*
* PS/2 devices having SMBus companions should stay disabled
* on PS/2 side, in order to have SMBus part operable.
*/
if (!psmouse->protocol->smbus_companion)
psmouse_activate(psmouse);
rc = 0; rc = 0;
out: out:
@ -1677,10 +1718,21 @@ static int psmouse_reconnect(struct serio *serio)
if (parent) if (parent)
psmouse_activate(parent); psmouse_activate(parent);
out_unlock:
mutex_unlock(&psmouse_mutex); mutex_unlock(&psmouse_mutex);
return rc; return rc;
} }
static int psmouse_reconnect(struct serio *serio)
{
return __psmouse_reconnect(serio, false);
}
static int psmouse_fast_reconnect(struct serio *serio)
{
return __psmouse_reconnect(serio, true);
}
static struct serio_device_id psmouse_serio_ids[] = { static struct serio_device_id psmouse_serio_ids[] = {
{ {
.type = SERIO_8042, .type = SERIO_8042,
@ -1708,6 +1760,7 @@ static struct serio_driver psmouse_drv = {
.interrupt = psmouse_interrupt, .interrupt = psmouse_interrupt,
.connect = psmouse_connect, .connect = psmouse_connect,
.reconnect = psmouse_reconnect, .reconnect = psmouse_reconnect,
.fast_reconnect = psmouse_fast_reconnect,
.disconnect = psmouse_disconnect, .disconnect = psmouse_disconnect,
.cleanup = psmouse_cleanup, .cleanup = psmouse_cleanup,
}; };
@ -1717,9 +1770,11 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de
{ {
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
struct psmouse_attribute *attr = to_psmouse_attr(devattr); struct psmouse_attribute *attr = to_psmouse_attr(devattr);
struct psmouse *psmouse; struct psmouse *psmouse = serio_get_drvdata(serio);
psmouse = serio_get_drvdata(serio); if (psmouse->protocol->smbus_companion &&
devattr != &psmouse_attr_protocol.dattr)
return -ENOENT;
return attr->show(psmouse, attr->data, buf); return attr->show(psmouse, attr->data, buf);
} }
@ -1738,6 +1793,12 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
psmouse = serio_get_drvdata(serio); psmouse = serio_get_drvdata(serio);
if (psmouse->protocol->smbus_companion &&
devattr != &psmouse_attr_protocol.dattr) {
retval = -ENOENT;
goto out_unlock;
}
if (attr->protect) { if (attr->protect) {
if (psmouse->state == PSMOUSE_IGNORE) { if (psmouse->state == PSMOUSE_IGNORE) {
retval = -ENODEV; retval = -ENODEV;
@ -1749,13 +1810,14 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
psmouse_deactivate(parent); psmouse_deactivate(parent);
} }
psmouse_deactivate(psmouse); if (!psmouse->protocol->smbus_companion)
psmouse_deactivate(psmouse);
} }
retval = attr->set(psmouse, attr->data, buf, count); retval = attr->set(psmouse, attr->data, buf, count);
if (attr->protect) { if (attr->protect) {
if (retval != -ENODEV) if (retval != -ENODEV && !psmouse->protocol->smbus_companion)
psmouse_activate(psmouse); psmouse_activate(psmouse);
if (parent) if (parent)
@ -1792,7 +1854,7 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const
static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf) static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf)
{ {
return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); return sprintf(buf, "%s\n", psmouse->protocol->name);
} }
static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count) static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count)
@ -1808,7 +1870,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
if (!proto) if (!proto)
return -EINVAL; return -EINVAL;
if (psmouse->type == proto->type) if (psmouse->protocol == proto)
return count; return count;
new_dev = input_allocate_device(); new_dev = input_allocate_device();
@ -1832,7 +1894,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
return -ENODEV; return -ENODEV;
} }
if (psmouse->type == proto->type) { if (psmouse->protocol == proto) {
input_free_device(new_dev); input_free_device(new_dev);
return count; /* switched by other thread */ return count; /* switched by other thread */
} }
@ -1845,7 +1907,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
} }
old_dev = psmouse->dev; old_dev = psmouse->dev;
old_proto = psmouse_protocol_by_type(psmouse->type); old_proto = psmouse->protocol;
if (psmouse->disconnect) if (psmouse->disconnect)
psmouse->disconnect(psmouse); psmouse->disconnect(psmouse);
@ -1864,23 +1926,29 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
psmouse_initialize(psmouse); psmouse_initialize(psmouse);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
error = input_register_device(psmouse->dev); if (psmouse->protocol->smbus_companion) {
if (error) { input_free_device(psmouse->dev);
if (psmouse->disconnect) psmouse->dev = NULL;
psmouse->disconnect(psmouse); } else {
error = input_register_device(psmouse->dev);
if (error) {
if (psmouse->disconnect)
psmouse->disconnect(psmouse);
psmouse_set_state(psmouse, PSMOUSE_IGNORE); psmouse_set_state(psmouse, PSMOUSE_IGNORE);
input_free_device(new_dev); input_free_device(new_dev);
psmouse->dev = old_dev; psmouse->dev = old_dev;
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
psmouse_switch_protocol(psmouse, old_proto); psmouse_switch_protocol(psmouse, old_proto);
psmouse_initialize(psmouse); psmouse_initialize(psmouse);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
return error; return error;
}
} }
input_unregister_device(old_dev); if (old_dev)
input_unregister_device(old_dev);
if (parent && parent->pt_activate) if (parent && parent->pt_activate)
parent->pt_activate(parent); parent->pt_activate(parent);
@ -1947,16 +2015,27 @@ static int __init psmouse_init(void)
synaptics_module_init(); synaptics_module_init();
hgpk_module_init(); hgpk_module_init();
err = psmouse_smbus_module_init();
if (err)
return err;
kpsmoused_wq = alloc_ordered_workqueue("kpsmoused", 0); kpsmoused_wq = alloc_ordered_workqueue("kpsmoused", 0);
if (!kpsmoused_wq) { if (!kpsmoused_wq) {
pr_err("failed to create kpsmoused workqueue\n"); pr_err("failed to create kpsmoused workqueue\n");
return -ENOMEM; err = -ENOMEM;
goto err_smbus_exit;
} }
err = serio_register_driver(&psmouse_drv); err = serio_register_driver(&psmouse_drv);
if (err) if (err)
destroy_workqueue(kpsmoused_wq); goto err_destroy_wq;
return 0;
err_destroy_wq:
destroy_workqueue(kpsmoused_wq);
err_smbus_exit:
psmouse_smbus_module_exit();
return err; return err;
} }
@ -1964,6 +2043,7 @@ static void __exit psmouse_exit(void)
{ {
serio_unregister_driver(&psmouse_drv); serio_unregister_driver(&psmouse_drv);
destroy_workqueue(kpsmoused_wq); destroy_workqueue(kpsmoused_wq);
psmouse_smbus_module_exit();
} }
module_init(psmouse_init); module_init(psmouse_init);

View File

@ -0,0 +1,302 @@
/*
* Copyright (c) 2017 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/libps2.h>
#include <linux/i2c.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include "psmouse.h"
struct psmouse_smbus_dev {
struct i2c_board_info board;
struct psmouse *psmouse;
struct i2c_client *client;
struct list_head node;
bool dead;
};
static LIST_HEAD(psmouse_smbus_list);
static DEFINE_MUTEX(psmouse_smbus_mutex);
static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
{
struct psmouse_smbus_dev *smbdev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY))
return;
mutex_lock(&psmouse_smbus_mutex);
list_for_each_entry(smbdev, &psmouse_smbus_list, node) {
if (smbdev->dead)
continue;
if (smbdev->client)
continue;
/*
* Here would be a good place to check if device is actually
* present, but it seems that SMBus will not respond unless we
* fully reset PS/2 connection. So cross our fingers, and try
* to switch over, hopefully our system will not have too many
* "host notify" I2C adapters.
*/
psmouse_dbg(smbdev->psmouse,
"SMBus candidate adapter appeared, triggering rescan\n");
serio_rescan(smbdev->psmouse->ps2dev.serio);
}
mutex_unlock(&psmouse_smbus_mutex);
}
static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
{
struct psmouse_smbus_dev *smbdev, *tmp;
mutex_lock(&psmouse_smbus_mutex);
list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
if (smbdev->client != client)
continue;
kfree(client->dev.platform_data);
client->dev.platform_data = NULL;
if (!smbdev->dead) {
psmouse_dbg(smbdev->psmouse,
"Marking SMBus companion %s as gone\n",
dev_name(&smbdev->client->dev));
smbdev->dead = true;
serio_rescan(smbdev->psmouse->ps2dev.serio);
} else {
list_del(&smbdev->node);
kfree(smbdev);
}
}
mutex_unlock(&psmouse_smbus_mutex);
}
static int psmouse_smbus_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
switch (action) {
case BUS_NOTIFY_ADD_DEVICE:
if (dev->type == &i2c_adapter_type)
psmouse_smbus_check_adapter(to_i2c_adapter(dev));
break;
case BUS_NOTIFY_REMOVED_DEVICE:
if (dev->type == &i2c_client_type)
psmouse_smbus_detach_i2c_client(to_i2c_client(dev));
break;
}
return 0;
}
static struct notifier_block psmouse_smbus_notifier = {
.notifier_call = psmouse_smbus_notifier_call,
};
static psmouse_ret_t psmouse_smbus_process_byte(struct psmouse *psmouse)
{
return PSMOUSE_FULL_PACKET;
}
static int psmouse_smbus_reconnect(struct psmouse *psmouse)
{
psmouse_deactivate(psmouse);
return 0;
}
struct psmouse_smbus_removal_work {
struct work_struct work;
struct i2c_client *client;
};
static void psmouse_smbus_remove_i2c_device(struct work_struct *work)
{
struct psmouse_smbus_removal_work *rwork =
container_of(work, struct psmouse_smbus_removal_work, work);
dev_dbg(&rwork->client->dev, "destroying SMBus companion device\n");
i2c_unregister_device(rwork->client);
kfree(rwork);
}
/*
* This schedules removal of SMBus companion device. We have to do
* it in a separate tread to avoid deadlocking on psmouse_mutex in
* case the device has a trackstick (which is also driven by psmouse).
*
* Note that this may be racing with i2c adapter removal, but we
* can't do anything about that: i2c automatically destroys clients
* attached to an adapter that is being removed. This has to be
* fixed in i2c core.
*/
static void psmouse_smbus_schedule_remove(struct i2c_client *client)
{
struct psmouse_smbus_removal_work *rwork;
rwork = kzalloc(sizeof(*rwork), GFP_KERNEL);
if (rwork) {
INIT_WORK(&rwork->work, psmouse_smbus_remove_i2c_device);
rwork->client = client;
schedule_work(&rwork->work);
}
}
static void psmouse_smbus_disconnect(struct psmouse *psmouse)
{
struct psmouse_smbus_dev *smbdev = psmouse->private;
mutex_lock(&psmouse_smbus_mutex);
if (smbdev->dead) {
list_del(&smbdev->node);
kfree(smbdev);
} else {
smbdev->dead = true;
psmouse_dbg(smbdev->psmouse,
"posting removal request for SMBus companion %s\n",
dev_name(&smbdev->client->dev));
psmouse_smbus_schedule_remove(smbdev->client);
}
mutex_unlock(&psmouse_smbus_mutex);
psmouse->private = NULL;
}
static int psmouse_smbus_create_companion(struct device *dev, void *data)
{
struct psmouse_smbus_dev *smbdev = data;
unsigned short addr_list[] = { smbdev->board.addr, I2C_CLIENT_END };
struct i2c_adapter *adapter;
adapter = i2c_verify_adapter(dev);
if (!adapter)
return 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY))
return 0;
smbdev->client = i2c_new_probed_device(adapter, &smbdev->board,
addr_list, NULL);
if (!smbdev->client)
return 0;
/* We have our(?) device, stop iterating i2c bus. */
return 1;
}
void psmouse_smbus_cleanup(struct psmouse *psmouse)
{
struct psmouse_smbus_dev *smbdev, *tmp;
mutex_lock(&psmouse_smbus_mutex);
list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
if (psmouse == smbdev->psmouse) {
list_del(&smbdev->node);
kfree(smbdev);
}
}
mutex_unlock(&psmouse_smbus_mutex);
}
int psmouse_smbus_init(struct psmouse *psmouse,
const struct i2c_board_info *board,
const void *pdata, size_t pdata_size,
bool leave_breadcrumbs)
{
struct psmouse_smbus_dev *smbdev;
int error;
smbdev = kzalloc(sizeof(*smbdev), GFP_KERNEL);
if (!smbdev)
return -ENOMEM;
smbdev->psmouse = psmouse;
smbdev->board = *board;
smbdev->board.platform_data = kmemdup(pdata, pdata_size, GFP_KERNEL);
if (!smbdev->board.platform_data) {
kfree(smbdev);
return -ENOMEM;
}
psmouse->private = smbdev;
psmouse->protocol_handler = psmouse_smbus_process_byte;
psmouse->reconnect = psmouse_smbus_reconnect;
psmouse->fast_reconnect = psmouse_smbus_reconnect;
psmouse->disconnect = psmouse_smbus_disconnect;
psmouse->resync_time = 0;
psmouse_deactivate(psmouse);
mutex_lock(&psmouse_smbus_mutex);
list_add_tail(&smbdev->node, &psmouse_smbus_list);
mutex_unlock(&psmouse_smbus_mutex);
/* Bind to already existing adapters right away */
error = i2c_for_each_dev(smbdev, psmouse_smbus_create_companion);
if (smbdev->client) {
/* We have our companion device */
return 0;
}
/*
* If we did not create i2c device we will not need platform
* data even if we are leaving breadcrumbs.
*/
kfree(smbdev->board.platform_data);
smbdev->board.platform_data = NULL;
if (error < 0 || !leave_breadcrumbs) {
mutex_lock(&psmouse_smbus_mutex);
list_del(&smbdev->node);
mutex_unlock(&psmouse_smbus_mutex);
kfree(smbdev);
}
return error < 0 ? error : -EAGAIN;
}
int __init psmouse_smbus_module_init(void)
{
int error;
error = bus_register_notifier(&i2c_bus_type, &psmouse_smbus_notifier);
if (error) {
pr_err("failed to register i2c bus notifier: %d\n", error);
return error;
}
return 0;
}
void psmouse_smbus_module_exit(void)
{
bus_unregister_notifier(&i2c_bus_type, &psmouse_smbus_notifier);
flush_scheduled_work();
}

View File

@ -44,50 +44,6 @@ enum psmouse_scale {
PSMOUSE_SCALE21 PSMOUSE_SCALE21
}; };
struct psmouse {
void *private;
struct input_dev *dev;
struct ps2dev ps2dev;
struct delayed_work resync_work;
char *vendor;
char *name;
unsigned char packet[8];
unsigned char badbyte;
unsigned char pktcnt;
unsigned char pktsize;
unsigned char type;
unsigned char oob_data_type;
unsigned char extra_buttons;
bool ignore_parity;
bool acks_disable_command;
unsigned int model;
unsigned long last;
unsigned long out_of_sync_cnt;
unsigned long num_resyncs;
enum psmouse_state state;
char devname[64];
char phys[32];
unsigned int rate;
unsigned int resolution;
unsigned int resetafter;
unsigned int resync_time;
bool smartscroll; /* Logitech only */
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse);
void (*set_rate)(struct psmouse *psmouse, unsigned int rate);
void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution);
void (*set_scale)(struct psmouse *psmouse, enum psmouse_scale scale);
int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse);
void (*cleanup)(struct psmouse *psmouse);
int (*poll)(struct psmouse *psmouse);
void (*pt_activate)(struct psmouse *psmouse);
void (*pt_deactivate)(struct psmouse *psmouse);
};
enum psmouse_type { enum psmouse_type {
PSMOUSE_NONE, PSMOUSE_NONE,
PSMOUSE_PS2, PSMOUSE_PS2,
@ -110,9 +66,68 @@ enum psmouse_type {
PSMOUSE_FOCALTECH, PSMOUSE_FOCALTECH,
PSMOUSE_VMMOUSE, PSMOUSE_VMMOUSE,
PSMOUSE_BYD, PSMOUSE_BYD,
PSMOUSE_SYNAPTICS_SMBUS,
PSMOUSE_AUTO /* This one should always be last */ PSMOUSE_AUTO /* This one should always be last */
}; };
struct psmouse;
struct psmouse_protocol {
enum psmouse_type type;
bool maxproto;
bool ignore_parity; /* Protocol should ignore parity errors from KBC */
bool try_passthru; /* Try protocol also on passthrough ports */
bool smbus_companion; /* "Protocol" is a stub, device is on SMBus */
const char *name;
const char *alias;
int (*detect)(struct psmouse *, bool);
int (*init)(struct psmouse *);
};
struct psmouse {
void *private;
struct input_dev *dev;
struct ps2dev ps2dev;
struct delayed_work resync_work;
const char *vendor;
const char *name;
const struct psmouse_protocol *protocol;
unsigned char packet[8];
unsigned char badbyte;
unsigned char pktcnt;
unsigned char pktsize;
unsigned char oob_data_type;
unsigned char extra_buttons;
bool acks_disable_command;
unsigned int model;
unsigned long last;
unsigned long out_of_sync_cnt;
unsigned long num_resyncs;
enum psmouse_state state;
char devname[64];
char phys[32];
unsigned int rate;
unsigned int resolution;
unsigned int resetafter;
unsigned int resync_time;
bool smartscroll; /* Logitech only */
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse);
void (*set_rate)(struct psmouse *psmouse, unsigned int rate);
void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution);
void (*set_scale)(struct psmouse *psmouse, enum psmouse_scale scale);
int (*reconnect)(struct psmouse *psmouse);
int (*fast_reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse);
void (*cleanup)(struct psmouse *psmouse);
int (*poll)(struct psmouse *psmouse);
void (*pt_activate)(struct psmouse *psmouse);
void (*pt_deactivate)(struct psmouse *psmouse);
};
void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
unsigned long delay); unsigned long delay);
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
@ -195,5 +210,34 @@ static struct psmouse_attribute psmouse_attr_##_name = { \
&(psmouse)->ps2dev.serio->dev, \ &(psmouse)->ps2dev.serio->dev, \
psmouse_fmt(format), ##__VA_ARGS__) psmouse_fmt(format), ##__VA_ARGS__)
#ifdef CONFIG_MOUSE_PS2_SMBUS
int psmouse_smbus_module_init(void);
void psmouse_smbus_module_exit(void);
struct i2c_board_info;
int psmouse_smbus_init(struct psmouse *psmouse,
const struct i2c_board_info *board,
const void *pdata, size_t pdata_size,
bool leave_breadcrumbs);
void psmouse_smbus_cleanup(struct psmouse *psmouse);
#else /* !CONFIG_MOUSE_PS2_SMBUS */
static inline int psmouse_smbus_module_init(void)
{
return 0;
}
static inline void psmouse_smbus_module_exit(void)
{
}
static inline void psmouse_smbus_cleanup(struct psmouse *psmouse)
{
}
#endif /* CONFIG_MOUSE_PS2_SMBUS */
#endif /* _PSMOUSE_H */ #endif /* _PSMOUSE_H */

File diff suppressed because it is too large Load Diff

View File

@ -25,36 +25,37 @@
#define SYN_QUE_MEXT_CAPAB_10 0x10 #define SYN_QUE_MEXT_CAPAB_10 0x10
/* synatics modes */ /* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7) #define SYN_BIT_ABSOLUTE_MODE BIT(7)
#define SYN_BIT_HIGH_RATE (1 << 6) #define SYN_BIT_HIGH_RATE BIT(6)
#define SYN_BIT_SLEEP_MODE (1 << 3) #define SYN_BIT_SLEEP_MODE BIT(3)
#define SYN_BIT_DISABLE_GESTURE (1 << 2) #define SYN_BIT_DISABLE_GESTURE BIT(2)
#define SYN_BIT_FOUR_BYTE_CLIENT (1 << 1) #define SYN_BIT_FOUR_BYTE_CLIENT BIT(1)
#define SYN_BIT_W_MODE (1 << 0) #define SYN_BIT_W_MODE BIT(0)
/* synaptics model ID bits */ /* synaptics model ID bits */
#define SYN_MODEL_ROT180(m) ((m) & (1 << 23)) #define SYN_MODEL_ROT180(m) ((m) & BIT(23))
#define SYN_MODEL_PORTRAIT(m) ((m) & (1 << 22)) #define SYN_MODEL_PORTRAIT(m) ((m) & BIT(22))
#define SYN_MODEL_SENSOR(m) (((m) >> 16) & 0x3f) #define SYN_MODEL_SENSOR(m) (((m) & GENMASK(21, 16)) >> 16)
#define SYN_MODEL_HARDWARE(m) (((m) >> 9) & 0x7f) #define SYN_MODEL_HARDWARE(m) (((m) & GENMASK(15, 9)) >> 9)
#define SYN_MODEL_NEWABS(m) ((m) & (1 << 7)) #define SYN_MODEL_NEWABS(m) ((m) & BIT(7))
#define SYN_MODEL_PEN(m) ((m) & (1 << 6)) #define SYN_MODEL_PEN(m) ((m) & BIT(6))
#define SYN_MODEL_SIMPLIC(m) ((m) & (1 << 5)) #define SYN_MODEL_SIMPLIC(m) ((m) & BIT(5))
#define SYN_MODEL_GEOMETRY(m) ((m) & 0x0f) #define SYN_MODEL_GEOMETRY(m) ((m) & GENMASK(3, 0))
/* synaptics capability bits */ /* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23)) #define SYN_CAP_EXTENDED(c) ((c) & BIT(23))
#define SYN_CAP_MIDDLE_BUTTON(c) ((c) & (1 << 18)) #define SYN_CAP_MIDDLE_BUTTON(c) ((c) & BIT(18))
#define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7)) #define SYN_CAP_PASS_THROUGH(c) ((c) & BIT(7))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4)) #define SYN_CAP_SLEEP(c) ((c) & BIT(4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3)) #define SYN_CAP_FOUR_BUTTON(c) ((c) & BIT(3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) #define SYN_CAP_MULTIFINGER(c) ((c) & BIT(1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) #define SYN_CAP_PALMDETECT(c) ((c) & BIT(0))
#define SYN_CAP_SUBMODEL_ID(c) (((c) & 0x00ff00) >> 8) #define SYN_CAP_SUBMODEL_ID(c) (((c) & GENMASK(15, 8)) >> 8)
#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) #define SYN_EXT_CAP_REQUESTS(c) (((c) & GENMASK(22, 20)) >> 20)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) #define SYN_CAP_MB_MASK GENMASK(15, 12)
#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & SYN_CAP_MB_MASK) >> 12)
#define SYN_MEXT_CAP_BIT(m) ((m) & (1 << 1)) #define SYN_CAP_PRODUCT_ID(ec) (((ec) & GENMASK(23, 16)) >> 16)
#define SYN_MEXT_CAP_BIT(m) ((m) & BIT(1))
/* /*
* The following describes response for the 0x0c query. * The following describes response for the 0x0c query.
@ -83,13 +84,14 @@
* hinged at the top. * hinged at the top.
* 2 0x20 report min query 0x0f gives min coord reported * 2 0x20 report min query 0x0f gives min coord reported
*/ */
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & BIT(20)) /* 1-button ClickPad */
#define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & BIT(8)) /* 2-button ClickPad */
#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & BIT(17))
#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000) #define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & BIT(13))
#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & BIT(19))
#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & BIT(10))
#define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & BIT(11))
#define SYN_CAP_INTERTOUCH(ex0c) ((ex0c) & BIT(14))
/* /*
* The following descibes response for the 0x10 query. * The following descibes response for the 0x10 query.
@ -108,42 +110,44 @@
* 3 0xff SecurePad height the height of the SecurePad fingerprint * 3 0xff SecurePad height the height of the SecurePad fingerprint
* reader. * reader.
*/ */
#define SYN_CAP_EXT_BUTTONS_STICK(ex10) ((ex10) & 0x010000) #define SYN_CAP_EXT_BUTTONS_STICK(ex10) ((ex10) & BIT(16))
#define SYN_CAP_SECUREPAD(ex10) ((ex10) & 0x020000) #define SYN_CAP_SECUREPAD(ex10) ((ex10) & BIT(17))
#define SYN_CAP_EXT_BUTTON_STICK_L(eb) (!!((eb) & 0x01)) #define SYN_EXT_BUTTON_STICK_L(eb) (((eb) & BIT(0)) >> 0)
#define SYN_CAP_EXT_BUTTON_STICK_M(eb) (!!((eb) & 0x02)) #define SYN_EXT_BUTTON_STICK_M(eb) (((eb) & BIT(1)) >> 1)
#define SYN_CAP_EXT_BUTTON_STICK_R(eb) (!!((eb) & 0x04)) #define SYN_EXT_BUTTON_STICK_R(eb) (((eb) & BIT(2)) >> 2)
/* synaptics modes query bits */ /* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) #define SYN_MODE_ABSOLUTE(m) ((m) & BIT(7))
#define SYN_MODE_RATE(m) ((m) & (1 << 6)) #define SYN_MODE_RATE(m) ((m) & BIT(6))
#define SYN_MODE_BAUD_SLEEP(m) ((m) & (1 << 3)) #define SYN_MODE_BAUD_SLEEP(m) ((m) & BIT(3))
#define SYN_MODE_DISABLE_GESTURE(m) ((m) & (1 << 2)) #define SYN_MODE_DISABLE_GESTURE(m) ((m) & BIT(2))
#define SYN_MODE_PACKSIZE(m) ((m) & (1 << 1)) #define SYN_MODE_PACKSIZE(m) ((m) & BIT(1))
#define SYN_MODE_WMODE(m) ((m) & (1 << 0)) #define SYN_MODE_WMODE(m) ((m) & BIT(0))
/* synaptics identify query bits */ /* synaptics identify query bits */
#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f) #define SYN_ID_MODEL(i) (((i) & GENMASK(7, 4)) >> 4)
#define SYN_ID_MAJOR(i) ((i) & 0x0f) #define SYN_ID_MAJOR(i) (((i) & GENMASK(3, 0)) >> 0)
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff) #define SYN_ID_MINOR(i) (((i) & GENMASK(23, 16)) >> 16)
#define SYN_ID_FULL(i) ((SYN_ID_MAJOR(i) << 8) | SYN_ID_MINOR(i)) #define SYN_ID_FULL(i) ((SYN_ID_MAJOR(i) << 8) | SYN_ID_MINOR(i))
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47) #define SYN_ID_IS_SYNAPTICS(i) (((i) & GENMASK(15, 8)) == 0x004700U)
#define SYN_ID_DISGEST_SUPPORTED(i) (SYN_ID_MAJOR(i) >= 4) #define SYN_ID_DISGEST_SUPPORTED(i) (SYN_ID_MAJOR(i) >= 4)
/* synaptics special commands */ /* synaptics special commands */
#define SYN_PS_SET_MODE2 0x14 #define SYN_PS_SET_MODE2 0x14
#define SYN_PS_CLIENT_CMD 0x28 #define SYN_PS_CLIENT_CMD 0x28
/* synaptics packet types */
#define SYN_NEWABS 0
#define SYN_NEWABS_STRICT 1
#define SYN_NEWABS_RELAXED 2
#define SYN_OLDABS 3
/* amount to fuzz position data when touchpad reports reduced filtering */ /* amount to fuzz position data when touchpad reports reduced filtering */
#define SYN_REDUCED_FILTER_FUZZ 8 #define SYN_REDUCED_FILTER_FUZZ 8
/* synaptics packet types */
enum synaptics_pkt_type {
SYN_NEWABS,
SYN_NEWABS_STRICT,
SYN_NEWABS_RELAXED,
SYN_OLDABS,
};
/* /*
* A structure to describe the state of the touchpad hardware (buttons and pad) * A structure to describe the state of the touchpad hardware (buttons and pad)
*/ */
@ -157,26 +161,30 @@ struct synaptics_hw_state {
unsigned int middle:1; unsigned int middle:1;
unsigned int up:1; unsigned int up:1;
unsigned int down:1; unsigned int down:1;
unsigned char ext_buttons; u8 ext_buttons;
signed char scroll; s8 scroll;
};
/* Data read from the touchpad */
struct synaptics_device_info {
u32 model_id; /* Model-ID */
u32 firmware_id; /* Firmware-ID */
u32 board_id; /* Board-ID */
u32 capabilities; /* Capabilities */
u32 ext_cap; /* Extended Capabilities */
u32 ext_cap_0c; /* Ext Caps from 0x0c query */
u32 ext_cap_10; /* Ext Caps from 0x10 query */
u32 identity; /* Identification */
u32 x_res, y_res; /* X/Y resolution in units/mm */
u32 x_max, y_max; /* Max coordinates (from FW) */
u32 x_min, y_min; /* Min coordinates (from FW) */
}; };
struct synaptics_data { struct synaptics_data {
/* Data read from the touchpad */ struct synaptics_device_info info;
unsigned long int model_id; /* Model-ID */
unsigned long int firmware_id; /* Firmware-ID */
unsigned long int board_id; /* Board-ID */
unsigned long int capabilities; /* Capabilities */
unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */
unsigned long int ext_cap_10; /* Ext Caps from 0x10 query */
unsigned long int identity; /* Identification */
unsigned int x_res, y_res; /* X/Y resolution in units/mm */
unsigned int x_max, y_max; /* Max coordinates (from FW) */
unsigned int x_min, y_min; /* Min coordinates (from FW) */
unsigned char pkt_type; /* packet type - old, new, etc */ enum synaptics_pkt_type pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */ u8 mode; /* current mode byte */
int scroll; int scroll;
bool absolute_mode; /* run in Absolute mode */ bool absolute_mode; /* run in Absolute mode */
@ -200,8 +208,10 @@ struct synaptics_data {
void synaptics_module_init(void); void synaptics_module_init(void);
int synaptics_detect(struct psmouse *psmouse, bool set_properties); int synaptics_detect(struct psmouse *psmouse, bool set_properties);
int synaptics_init(struct psmouse *psmouse); int synaptics_init_absolute(struct psmouse *psmouse);
int synaptics_init_relative(struct psmouse *psmouse); int synaptics_init_relative(struct psmouse *psmouse);
int synaptics_init_smbus(struct psmouse *psmouse);
int synaptics_init(struct psmouse *psmouse);
void synaptics_reset(struct psmouse *psmouse); void synaptics_reset(struct psmouse *psmouse);
#endif /* _SYNAPTICS_H */ #endif /* _SYNAPTICS_H */

View File

@ -652,9 +652,18 @@ static const struct i2c_device_id synaptics_i2c_id_table[] = {
}; };
MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table);
#ifdef CONFIG_OF
static const struct of_device_id synaptics_i2c_of_match[] = {
{ .compatible = "synaptics,synaptics_i2c", },
{ },
};
MODULE_DEVICE_TABLE(of, synaptics_i2c_of_match);
#endif
static struct i2c_driver synaptics_i2c_driver = { static struct i2c_driver synaptics_i2c_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.of_match_table = of_match_ptr(synaptics_i2c_of_match),
.pm = &synaptics_i2c_pm, .pm = &synaptics_i2c_pm,
}, },

View File

@ -251,7 +251,7 @@ static int rmi_irq_init(struct rmi_device *rmi_dev)
ret = devm_request_threaded_irq(&rmi_dev->dev, pdata->irq, NULL, ret = devm_request_threaded_irq(&rmi_dev->dev, pdata->irq, NULL,
rmi_irq_fn, irq_flags | IRQF_ONESHOT, rmi_irq_fn, irq_flags | IRQF_ONESHOT,
dev_name(rmi_dev->xport->dev), dev_driver_string(rmi_dev->xport->dev),
rmi_dev); rmi_dev);
if (ret < 0) { if (ret < 0) {
dev_err(&rmi_dev->dev, "Failed to register interrupt %d\n", dev_err(&rmi_dev->dev, "Failed to register interrupt %d\n",
@ -1234,16 +1234,21 @@ static int rmi_driver_probe(struct device *dev)
if (retval < 0) if (retval < 0)
goto err_destroy_functions; goto err_destroy_functions;
if (data->f01_container->dev.driver) if (data->f01_container->dev.driver) {
/* Driver already bound, so enable ATTN now. */ /* Driver already bound, so enable ATTN now. */
return rmi_enable_sensor(rmi_dev); retval = rmi_enable_sensor(rmi_dev);
if (retval)
goto err_disable_irq;
}
return 0; return 0;
err_disable_irq:
rmi_disable_irq(rmi_dev, false);
err_destroy_functions: err_destroy_functions:
rmi_free_function_list(rmi_dev); rmi_free_function_list(rmi_dev);
err: err:
return retval < 0 ? retval : 0; return retval;
} }
static struct rmi_driver rmi_physical_driver = { static struct rmi_driver rmi_physical_driver = {

View File

@ -113,20 +113,16 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
} }
if (rmi_register_desc_has_subpacket(item, 2)) { if (rmi_register_desc_has_subpacket(item, 2)) {
sensor->axis_align.clip_x_low = buf[offset]; /* Units 1/128 sensor pitch */
sensor->axis_align.clip_x_high = sensor->max_x rmi_dbg(RMI_DEBUG_FN, &fn->dev,
- buf[offset + 1]; "%s: Inactive Border xlo:%d xhi:%d ylo:%d yhi:%d\n",
sensor->axis_align.clip_y_low = buf[offset + 2]; __func__,
sensor->axis_align.clip_y_high = sensor->max_y buf[offset], buf[offset + 1],
- buf[offset + 3]; buf[offset + 2], buf[offset + 3]);
offset += 4; offset += 4;
} }
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x low: %d x high: %d y low: %d y high: %d\n",
__func__,
sensor->axis_align.clip_x_low, sensor->axis_align.clip_x_high,
sensor->axis_align.clip_y_low, sensor->axis_align.clip_y_high);
if (rmi_register_desc_has_subpacket(item, 3)) { if (rmi_register_desc_has_subpacket(item, 3)) {
rx_receivers = buf[offset]; rx_receivers = buf[offset];
tx_receivers = buf[offset + 1]; tx_receivers = buf[offset + 1];

View File

@ -105,16 +105,27 @@ static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
{ {
struct f34_data *f34 = dev_get_drvdata(&fn->dev); struct f34_data *f34 = dev_get_drvdata(&fn->dev);
int ret; int ret;
u8 status;
if (f34->bl_version != 5) if (f34->bl_version == 5) {
return 0; ret = rmi_read(f34->fn->rmi_dev, f34->v5.ctrl_address,
&status);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
__func__, status, ret);
ret = rmi_read(f34->fn->rmi_dev, f34->v5.ctrl_address, &f34->v5.status); if (!ret && !(status & 0x7f))
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n", complete(&f34->v5.cmd_done);
__func__, f34->v5.status, ret); } else {
ret = rmi_read_block(f34->fn->rmi_dev,
f34->fn->fd.data_base_addr +
f34->v7.off.flash_status,
&status, sizeof(status));
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
__func__, status, ret);
if (!ret && !(f34->v5.status & 0x7f)) if (!ret && !(status & 0x1f))
complete(&f34->v5.cmd_done); complete(&f34->v7.cmd_done);
}
return 0; return 0;
} }

View File

@ -30,6 +30,7 @@
#define F34_IDLE_WAIT_MS 500 #define F34_IDLE_WAIT_MS 500
#define F34_ENABLE_WAIT_MS 300 #define F34_ENABLE_WAIT_MS 300
#define F34_ERASE_WAIT_MS 5000 #define F34_ERASE_WAIT_MS 5000
#define F34_WRITE_WAIT_MS 3000
#define F34_BOOTLOADER_ID_LEN 2 #define F34_BOOTLOADER_ID_LEN 2
@ -47,11 +48,6 @@
#define CONFIG_ID_SIZE 32 #define CONFIG_ID_SIZE 32
#define PRODUCT_ID_SIZE 10 #define PRODUCT_ID_SIZE 10
#define ENABLE_WAIT_MS (1 * 1000)
#define WRITE_WAIT_MS (3 * 1000)
#define MIN_SLEEP_TIME_US 50
#define MAX_SLEEP_TIME_US 100
#define HAS_BSR BIT(5) #define HAS_BSR BIT(5)
#define HAS_CONFIG_ID BIT(3) #define HAS_CONFIG_ID BIT(3)
@ -292,6 +288,7 @@ struct f34v7_data {
const void *config_data; const void *config_data;
const void *image; const void *image;
struct completion cmd_done;
}; };
struct f34_data { struct f34_data {

View File

@ -15,6 +15,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/jiffies.h>
#include "rmi_driver.h" #include "rmi_driver.h"
#include "rmi_f34.h" #include "rmi_f34.h"
@ -31,7 +32,7 @@ static int rmi_f34v7_read_flash_status(struct f34_data *f34)
sizeof(status)); sizeof(status));
if (ret < 0) { if (ret < 0) {
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"%s: Failed to read flash status\n", __func__); "%s: Error %d reading flash status\n", __func__, ret);
return ret; return ret;
} }
@ -60,28 +61,17 @@ static int rmi_f34v7_read_flash_status(struct f34_data *f34)
static int rmi_f34v7_wait_for_idle(struct f34_data *f34, int timeout_ms) static int rmi_f34v7_wait_for_idle(struct f34_data *f34, int timeout_ms)
{ {
int count = 0; unsigned long timeout;
int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
do { timeout = msecs_to_jiffies(timeout_ms);
usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
count++; if (!wait_for_completion_timeout(&f34->v7.cmd_done, timeout)) {
dev_warn(&f34->fn->dev, "%s: Timed out waiting for idle status\n",
__func__);
return -ETIMEDOUT;
}
rmi_f34v7_read_flash_status(f34); return 0;
if ((f34->v7.command == v7_CMD_IDLE)
&& (f34->v7.flash_status == 0x00)) {
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"Idle status detected\n");
return 0;
}
} while (count < timeout_count);
dev_err(&f34->fn->dev,
"%s: Timed out waiting for idle status\n", __func__);
return -ETIMEDOUT;
} }
static int rmi_f34v7_write_command_single_transaction(struct f34_data *f34, static int rmi_f34v7_write_command_single_transaction(struct f34_data *f34,
@ -285,9 +275,10 @@ static int rmi_f34v7_write_partition_id(struct f34_data *f34, u8 cmd)
return 0; return 0;
} }
static int rmi_f34v7_read_f34v7_partition_table(struct f34_data *f34) static int rmi_f34v7_read_partition_table(struct f34_data *f34)
{ {
int ret; int ret;
unsigned long timeout;
u8 base; u8 base;
__le16 length; __le16 length;
u16 block_number = 0; u16 block_number = 0;
@ -320,6 +311,8 @@ static int rmi_f34v7_read_f34v7_partition_table(struct f34_data *f34)
return ret; return ret;
} }
init_completion(&f34->v7.cmd_done);
ret = rmi_f34v7_write_command(f34, v7_CMD_READ_CONFIG); ret = rmi_f34v7_write_command(f34, v7_CMD_READ_CONFIG);
if (ret < 0) { if (ret < 0) {
dev_err(&f34->fn->dev, "%s: Failed to write command\n", dev_err(&f34->fn->dev, "%s: Failed to write command\n",
@ -327,11 +320,15 @@ static int rmi_f34v7_read_f34v7_partition_table(struct f34_data *f34)
return ret; return ret;
} }
ret = rmi_f34v7_wait_for_idle(f34, WRITE_WAIT_MS); timeout = msecs_to_jiffies(F34_WRITE_WAIT_MS);
if (ret < 0) { while (time_before(jiffies, timeout)) {
dev_err(&f34->fn->dev, "%s: Failed to wait for idle status\n", usleep_range(5000, 6000);
__func__); rmi_f34v7_read_flash_status(f34);
return ret;
if (f34->v7.command == v7_CMD_IDLE &&
f34->v7.flash_status == 0x00) {
break;
}
} }
ret = rmi_read_block(f34->fn->rmi_dev, ret = rmi_read_block(f34->fn->rmi_dev,
@ -570,7 +567,7 @@ static int rmi_f34v7_read_queries(struct f34_data *f34)
f34->v7.read_config_buf_size = f34->v7.partition_table_bytes; f34->v7.read_config_buf_size = f34->v7.partition_table_bytes;
ptable = f34->v7.read_config_buf; ptable = f34->v7.read_config_buf;
ret = rmi_f34v7_read_f34v7_partition_table(f34); ret = rmi_f34v7_read_partition_table(f34);
if (ret < 0) { if (ret < 0) {
dev_err(&f34->fn->dev, "%s: Failed to read partition table\n", dev_err(&f34->fn->dev, "%s: Failed to read partition table\n",
__func__); __func__);
@ -666,6 +663,8 @@ static int rmi_f34v7_erase_config(struct f34_data *f34)
dev_info(&f34->fn->dev, "Erasing config...\n"); dev_info(&f34->fn->dev, "Erasing config...\n");
init_completion(&f34->v7.cmd_done);
switch (f34->v7.config_area) { switch (f34->v7.config_area) {
case v7_UI_CONFIG_AREA: case v7_UI_CONFIG_AREA:
ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_CONFIG); ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_CONFIG);
@ -684,11 +683,11 @@ static int rmi_f34v7_erase_config(struct f34_data *f34)
break; break;
} }
ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS); ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
if (ret < 0) if (ret < 0)
return ret; return ret;
return ret; return 0;
} }
static int rmi_f34v7_erase_guest_code(struct f34_data *f34) static int rmi_f34v7_erase_guest_code(struct f34_data *f34)
@ -697,11 +696,13 @@ static int rmi_f34v7_erase_guest_code(struct f34_data *f34)
dev_info(&f34->fn->dev, "Erasing guest code...\n"); dev_info(&f34->fn->dev, "Erasing guest code...\n");
init_completion(&f34->v7.cmd_done);
ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_GUEST_CODE); ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_GUEST_CODE);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS); ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -714,11 +715,13 @@ static int rmi_f34v7_erase_all(struct f34_data *f34)
dev_info(&f34->fn->dev, "Erasing firmware...\n"); dev_info(&f34->fn->dev, "Erasing firmware...\n");
init_completion(&f34->v7.cmd_done);
ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_FIRMWARE); ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_FIRMWARE);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS); ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -743,8 +746,8 @@ static int rmi_f34v7_erase_all(struct f34_data *f34)
return 0; return 0;
} }
static int rmi_f34v7_read_f34v7_blocks(struct f34_data *f34, u16 block_cnt, static int rmi_f34v7_read_blocks(struct f34_data *f34,
u8 command) u16 block_cnt, u8 command)
{ {
int ret; int ret;
u8 base; u8 base;
@ -787,17 +790,15 @@ static int rmi_f34v7_read_f34v7_blocks(struct f34_data *f34, u16 block_cnt,
return ret; return ret;
} }
init_completion(&f34->v7.cmd_done);
ret = rmi_f34v7_write_command(f34, command); ret = rmi_f34v7_write_command(f34, command);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS); ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
if (ret < 0) { if (ret < 0)
dev_err(&f34->fn->dev,
"%s: Wait for idle failed (%d blks remaining)\n",
__func__, remaining);
return ret; return ret;
}
ret = rmi_read_block(f34->fn->rmi_dev, ret = rmi_read_block(f34->fn->rmi_dev,
base + f34->v7.off.payload, base + f34->v7.off.payload,
@ -853,6 +854,8 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
transfer = min(remaining, max_transfer); transfer = min(remaining, max_transfer);
put_unaligned_le16(transfer, &length); put_unaligned_le16(transfer, &length);
init_completion(&f34->v7.cmd_done);
ret = rmi_write_block(f34->fn->rmi_dev, ret = rmi_write_block(f34->fn->rmi_dev,
base + f34->v7.off.transfer_length, base + f34->v7.off.transfer_length,
&length, sizeof(length)); &length, sizeof(length));
@ -877,13 +880,9 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
return ret; return ret;
} }
ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS); ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
if (ret < 0) { if (ret < 0)
dev_err(&f34->fn->dev,
"%s: Failed wait for idle (%d blks remaining)\n",
__func__, remaining);
return ret; return ret;
}
block_ptr += (transfer * f34->v7.block_size); block_ptr += (transfer * f34->v7.block_size);
remaining -= transfer; remaining -= transfer;
@ -945,6 +944,8 @@ static int rmi_f34v7_write_flash_config(struct f34_data *f34)
return -EINVAL; return -EINVAL;
} }
init_completion(&f34->v7.cmd_done);
ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_FLASH_CONFIG); ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_FLASH_CONFIG);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -952,7 +953,7 @@ static int rmi_f34v7_write_flash_config(struct f34_data *f34)
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"%s: Erase flash config command written\n", __func__); "%s: Erase flash config command written\n", __func__);
ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS); ret = rmi_f34v7_wait_for_idle(f34, F34_WRITE_WAIT_MS);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -981,7 +982,7 @@ static int rmi_f34v7_write_partition_table(struct f34_data *f34)
f34->v7.read_config_buf_size = f34->v7.config_size; f34->v7.read_config_buf_size = f34->v7.config_size;
ret = rmi_f34v7_read_f34v7_blocks(f34, block_count, v7_CMD_READ_CONFIG); ret = rmi_f34v7_read_blocks(f34, block_count, v7_CMD_READ_CONFIG);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1287,6 +1288,8 @@ static int rmi_f34v7_enter_flash_prog(struct f34_data *f34)
{ {
int ret; int ret;
f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, f34->fn->irq_mask);
ret = rmi_f34v7_read_flash_status(f34); ret = rmi_f34v7_read_flash_status(f34);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1294,19 +1297,16 @@ static int rmi_f34v7_enter_flash_prog(struct f34_data *f34)
if (f34->v7.in_bl_mode) if (f34->v7.in_bl_mode)
return 0; return 0;
init_completion(&f34->v7.cmd_done);
ret = rmi_f34v7_write_command(f34, v7_CMD_ENABLE_FLASH_PROG); ret = rmi_f34v7_write_command(f34, v7_CMD_ENABLE_FLASH_PROG);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS); ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!f34->v7.in_bl_mode) {
dev_err(&f34->fn->dev, "%s: BL mode not entered\n", __func__);
return -EINVAL;
}
return 0; return 0;
} }
@ -1314,6 +1314,8 @@ int rmi_f34v7_start_reflash(struct f34_data *f34, const struct firmware *fw)
{ {
int ret = 0; int ret = 0;
f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, f34->fn->irq_mask);
f34->v7.config_area = v7_UI_CONFIG_AREA; f34->v7.config_area = v7_UI_CONFIG_AREA;
f34->v7.image = fw->data; f34->v7.image = fw->data;
@ -1376,8 +1378,13 @@ int rmi_f34v7_probe(struct f34_data *f34)
memset(&f34->v7.blkcount, 0x00, sizeof(f34->v7.blkcount)); memset(&f34->v7.blkcount, 0x00, sizeof(f34->v7.blkcount));
memset(&f34->v7.phyaddr, 0x00, sizeof(f34->v7.phyaddr)); memset(&f34->v7.phyaddr, 0x00, sizeof(f34->v7.phyaddr));
rmi_f34v7_read_queries(f34);
f34->v7.force_update = false; init_completion(&f34->v7.cmd_done);
ret = rmi_f34v7_read_queries(f34);
if (ret < 0)
return ret;
f34->v7.force_update = true;
return 0; return 0;
} }

Some files were not shown because too many files have changed in this diff Show More