Linux input subsystem: input device programming guide-input-programming.txt

Source: Internet
Author: User

Programming input drivers)

~~~~~~~~~~~~~~~~~~~~~~~~~

1. Create an input device driverProgram

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.0 The simplest example

~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This article by droidphone Translation: http://blog.csdn.net/droidphone
Kernel version: v3.4.10
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Below is a very simple input device driver. The device only has one button, which is accessed through the I/O port button_port. When you press or release the button, button_irq is interrupted and the driver looks like this:

# Include <Linux/input. h> # include <Linux/module. h> # include <Linux/init. h> # include <ASM/IRQ. h> # include <ASM/Io. h> static struct input_dev * button_dev; static vertex evaluate (int irq, void * dummy) {input_report_key (button_dev, btn_0, INB (button_port) & 1); input_sync (button_dev ); return irq_handled;} static int _ init button_init (void) {int error; If (request_irq (button_irq, button_interrupt, 0, "Button", null) {printk (kern_err "button. c: Can't allocate IRQ % d \ n ", button_irq); Return-ebusy;} button_dev = input_allocate_device (); If (! Button_dev) {printk (kern_err "button. c: not enough memory \ n "); error =-enomem; goto err_free_irq;} button_dev-> evbit [0] = bit_mask (ev_key ); button_dev-> keybit [bit_word (btn_0)] = bit_mask (btn_0); error = input_register_device (button_dev); If (error) {printk (kern_err "button. c: failed to register device \ n "); goto err_free_dev;} return 0; err_free_dev: input_free_device (button_dev); err_free_irq: free_irq (button_irq, response); Return Error ;} static void _ exit button_exit (void) {response (button_dev); free_irq (button_irq, button_interrupt);} module_init (button_init); module_exit (button_exit );

1.1 example-driven work process

~~~~~~~~~~~~~~~~~~~~~~~~~

First, it must contain the header file <Linux/input. h>. It is the interface of the input subsystem and provides all necessary definition information.

The _ init initialization function can be loaded through modules or compiled into the kernel. It collects the resources required by the device (and checks whether the device exists ).

Next, it allocates an input device structure with input_allocate_device () and sets its bitfields. the device driver notifies other parts of the input subsystem through this method: what events does it generate or accept. In our example, the device can only generate ev_key events, and only send btn_0 Event code. In this way, we only need to set these two bits. We can also use

 
Set_bit (ev_key, button_dev.evbit); set_bit (btn_0, button_dev.keybit );

But the above exampleCodeYou can set more bits at a time.

Then, the example driver registers the input device structure with the following function:

 
Input_register_device (& button_dev );

This adds the button_dev structure to the global linked list of the input driver, and calls the _ connect function in the device handler module to notify him of a new device. Input_register_device () may sleep, so it cannot be used when it is interrupted or holding a spinlock.

Function, the driver only uses the function:

 
Button_interrupt ()

During each interruption, check the button status and report the status using the following functions:

 
Input_report_key ()

This function enters the input subsystem. The interrupted service program does not have to check whether it will report duplicate value events to the input subsystem (for example, press or press ). This is because the input_report _ * function will check this by itself.

Then, call:

 
Input_sync ()

This function tells the receiver that we have sent a complete report. This is not very important for a device with only one button, but in some cases it is very important. For example, when the mouse moves, you do not want the values X and Y to be explained separately, because it will be interpreted as two moves.

1.2 Dev-> open () and Dev-> close ()

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When the driver does not provide the Interrupt Capability, it needs to constantly query the status of the device, but it is a waste of time to continue this query. Sometimes the device needs to use some valuable resources (such as interruptions ). In this case, we can use the open and close callback functions to dynamically stop the query and release the interrupt, and determine when to resume the query and obtain the interrupt again. To implement this function, we need to add the following code to the example DRIVER:

 
Static int button_open (struct input_dev * Dev) {If (request_irq (button_irq, button_interrupt, 0, "button", null) {printk (kern_err "button. c: Can't allocate IRQ % d \ n ", button_irq); Return-ebusy;} return 0;} static void button_close (struct input_dev * Dev) {free_irq (irq_amiga_vertb, button_interrupt);} static int _ init button_init (void ){... button_dev-> open = button_open; button_dev-> close = button_close ;...}

Note that the input core keeps the device count to ensure that Dev-> open () is called only when the first user connects to the device, dev-> close () is called only when the last user is disconnected from the device. Calls to both Callbacks are serialized.

When the call is successful, the open () callback returns 0. If the return value is not 0, an error occurs. The close () callback of the return type void must be successful all the time.

1.3 Basic Event Type (types)

~~~~~~~~~~~~~~~~~~~~~

The simplest event type is ev_key, which is used for keyboards and buttons. It is reported to the input subsystem through the following functions:

 
Input_report_key (struct input_dev * Dev, int code, int value)

Linux/input. h defines available values and code for this type (from 0 to key_max ). Value is interpreted as a false value, that is, any non-0 value means that the key is pressed, and 0 means that the key is released. The code of the input subsystem generates an event only when the value and the previous value are different.

In addition to ev_key, there are two basic event types: ev_rel and ev_abs. They are used to provide relative and absolute values of devices. Moving the mouse is a relative value. The relative difference between the mouse and the previous position is reported because it works in no absolute coordinate system. Absolute Value events are useful for game joystick and digital devices that work in an absolute coordinate system.

Reporting ev_rel by devices is as simple as ev_key. You only need to set the corresponding bit and then call the following function:

 
Input_report_rel (struct input_dev * Dev, int code, int value)

An event is generated only when the value is not 0.

However, ev_abs requires a little special processing. Before calling input_register_device, you need to fill in additional fields for the Axis supported by your device in the input_dev structure. Assume that our button device has the abs_x axis:

Button_dev.absmin [abs_x] = 0; button_dev.absmax [abs_x] = 255; button_dev.absfuzz [abs_x] = 4; button_dev.absflat [abs_x] = 8;

Or, you only need:

 
Input_set_abs_params (button_dev, abs_x, 0,255, 4, 8 );

The preceding settings are suitable for a game joystick device that has an X axis, with a minimum value of 0 and a maximum value of 255 (which indicates that it must provide a range, occasionally, reporting beyond this range does not cause problems, but it must be up to the maximum and minimum values)

The noise range is +-4, and there is a center point of 8.

If you do not need absfuzz or absflat, you can set them to 0, which means it is absolutely accurate and always returns the center position (if any ).

1.4 bits_to_longs (), bit_word (), bit_mask ()

~~~~~~~~~~~~~~~~~~~~~~~~~~

These three macros are from bitops. H, which facilitates bit domain computing:

    • Bits_to_longs (x)-returns the number of long fields required for the array of the X-bit bitwise fields.
    • Bit_word (x)-returns the index in long units corresponding to the X-th digit in the array of bit fields.
    • Bit_mask (x)-returns the long-type mask value corresponding to bit X.

1.5 The ID * and name fields

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The Dev-> Name field should be set before the driver registers the input device. It is a user-friendly device name string such as 'generic button device '.

The ID * field contains the bus ID (PCI, USB...), Vendor ID, and device ID. Bus IDs are defined in input. h. The vendor and device IDs are defined in pci_ids.h, usb_ids.h, and similar header files. These fields should also be set before the device is registered.

The idtype field can be used as the private information of the input device.

These ID and name fields can be passed to the user space through the evdev interface.

1.6 keycode, keycodemax, keycodesize Field

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~

The three fields are used for the input device that requires key-value ing. keycode is an array used to convert the scan code to the key value of the input system. keycodemax is the size of the array, keycodesize indicates the size of each element in the array (in bytes)

You can use eviocgkeycode and eviocskeycode IOCTLs through the corresponding evdev interface to query and modify the ing table from the current scan code to the key value. When the device is filled with three of the above fields, the driver can set and query the key-value ing table based on the default Implementation of the kernel.

1.7 Dev-> getkeycode () and Dev-> setkeycode ()

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~

The getkeycode () and setkeycode () callbacks allow the driver to override the default ing mechanism for keycode, keycodemax, and keycodesize provided by the input core code, so as to implement sparse ing.

1.8 button autorepeat

~~~~~~~~~~~~~~~~~~

... It is very simple. It is processed by the input. c module. Hardware autorepeat is not used, because many devices do not have this function, and even if it exists, it is sometimes abnormal (for example, the keyboard in toshba notebook ). To enable the autorepeat function of your device, you only need to set the ev_rep bit in Dev-> evbit. Other tasks are handled by the input subsystem.

1.9 other event types, output event processing

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~

So far, other event types include:

    • Ev_led-the LEDs lamp used as the keyboard.
    • Ev_snd-buzzer for keyboard.

They are similar to Keyboard Events, but they move in another direction-from the system to the input device driver. If your driver can handle these events, you must set the corresponding bits in the evbit and implement a callback function:

 
Button_dev-> event = button_event; int button_event (struct input_dev * Dev, unsigned int type, unsigned int code, int value ); {If (type = ev_snd & code = snd_bell) {outb (value, button_bell); Return 0 ;}return-1 ;}

This callback can be called in the interrupt context or BH context, so it cannot sleep and should not be processed for too long.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.