drivers/input
subdirectory
include/linux/input.h
include/linux/input.h
),
time
of the event;type
, the type of the event;code
,
the code of the event (a sort of subtype);value
, a value number assigend to the event.input_dev
, which represents an input device;input_handler
, which represents an input handler;input_handle
, which represents a connection between an
input device and an input handler.input_dev
contains several fields. In particular
private
, a pointer to private data;name
, a string identifying the device;idbus
, bus identifier;idvendor
, idproduct
, and idversion
(in 2.5 these, together with idbus
, are packed in an
id
structure);evbit
, keybit
, etc.;timer
;open
, close
, event
, upload_effect
and erase_effect
;handle
, a pointer to an input_handle;next
, a pointer to the next input_dev since the input devices
are linked in a list.input_handler
data structure contains
private
data;event
, connect
and disconnect
,
as well as a pointer to file_operations;handle
, a pointer to an input_handle
;next
, for the linked list of input_handler's.input_handle
contains
private
data;open
;dev
, a pointer to an input_dev;handler
, a pointer to an input_handler;dnext
and hnext
, for the linked
lists of input_handle's attached to a input_dev, and to a
input_handler, respectively.input_event( dev, type, code, value )
reports events.
It returns immediately if the device has not set the bit for the
type
.
The it switches on the event type
.
Each event is handled only if the corresponding bit of the proper
device bitset is set.
Key events ...
For absolute motion events the code
entry of the device
abs[]
array is modified (with some fuzziness) before handling
them.
Relative motion events are skipped if the value
is 0.
LED and sound events toggle the device led
and
snd
, respectively, and call the device event()
function if it exists defore handling.
Repeat events set the code
entry of the device
rep[]
array to value
before handling.
After these controls and preliminary things it dispatches the event
to the list of handles attaches to the device: traversing the
list dnext
it calls the event()
method
for each open handle.
input_repeat_key( dev )
invokes the input_event()
method with the device
dev
, a "key" event type, the code of the device
repaet_key
, and value 2
input_open_device( handle )
is called when a handle' device is opened.
It invokes the open
method of the handle's device
and increases the handle open
counter.
input_close_device( handle )
is called when the handle' device is closed.
It invokes the close
method of the handle's device
and decreases the open counter.
input_link_handle( handle )
inserts handle in the first position of both the device list
(of the handle's dev)
and the handler list (of the handle's handler).
input_unlink_handle( handle )
remove the handle from both the device list and the handler list
input_register_device( dev )
is called by an input device that wants to register with the
input core.
It initializes the device repeat timer to default values (in particular
the timer function is input_repeat_key
).
Then it assignes the device number (the first free number).
Finally it scans the list of input_handler trying to connect each
handler with the device: if it succeeds it inserts the newly created
handle. It increases input_number
.
input_unregister_device( dev )
is called by a device that drops from the input core.
It deletes the repeat timer.
For each handle in the device list of dev
it unlinks the
handle and disconnect it from the associated handler.
Finally it removes the device and decreases input_number
.
input_register_handler( handler )
is called by an input handler that wants to register with the
input core.
It adds the handler to the list input_handler
and add it
to the input_table
.
Then it adds a handle for each device that can be connected to the handler.
input_unregister_handler( handler )
is called by a handler to unregister from the input core.
It disconnects the handler from all the devices to which it is connected.
Then it removes the handler from the list input_handler
and remove it from the input_table
.
input_open_file( inode, file )
.
This is the only file operation of the input core driver.
[ STILL TO DO ]
evdev.c
.
Two data structures are used to store event device and event informations:
evdev
, which contains, besides other things,
an input_handle, a wait_queue_head,
and a pointer to an evdev_list;evdev_list
, with a buffer of input_event's,
a fasync_struct pointer, a pointer to its evdev, and the next evdev_list
pointer.evdev_table
;
evdev_fasync( fd, file, on )
.
It gets the evdev_list
stored in the file
's
private_data
, and invokes the the fasync_helper with
the evdev_list
's fasync
function [FIXME],
evdev_open( inode, file )
.
The inode
's minor specifes which evdev to open.
A new evdev_list structure is allocated and linked into the evdev's
evdev_list, and the file
private_data
is made to
point to the newly created evdev_list,
input_open_device
is invoked with the
evdev's handle
.
evdev_release( inode, file )
.
This does the opposite operations of the open method:
if this was the last list of the evdev, the evdev is closed with the
input_core (and possibly unregistered and deallocated if its
exist
flag is not set).
Finally the evdev_list is freed.
buffer
.
The user buffer
must contain one or more
struct input_event
. count
is the number of bytes
used in the user buffer
.
evdev_read( file, buffer, count, ppos )
.
Reading is the reverse operation: events are copied from the evdev's
buffer
to the user buffer
.
There is one catch. If the evdev's buffer
is empty the
process is put to sleep.
evdev_poll( file, wait ).
evdev_ioctl( inode, file, cmd, arg ).
evdev_event
:
given an input_handle, retrieves the associated evdev (contained in the
private
field), and its list of evdev_list's.
Then for each evdev_list in the list, the event informations (time, type,
code and value) are put on the next free slot of the buffer
,
and the fasync
is signalled [FIXME].
Finally the processes on the evdev
's wait_queue are waken up.
evdev_connect( handler, dev )
.
Finds the first unused entry in the evdev_table, and allocates a new
evdev for it. Initialize its wait_queue, its handle
evdev_disconnect( handle )
.
The evdev is contained in the handle's private
field.
If the evdev is open it is closed and the processes on its wait_queue
are waken up. Otherwise it is unregistered, dropped from the
evdev_table, and deallocated.
evdev_init
: register with the input_core;evdev_exit
: unregister with the input_core.
Exercise 1
ledbit
.
Give it a try before looking at a solution,
Exercise 2