How to register a keyboard device in Linux

Source: Internet
Author: User

How to register a keyboard device in Linux

[Implementation of the mouse driver in Linux]
Input_init () =>
=>
Class_register (& input_class); registers the input class
Input_proc_init (); create directories and files under proc
Register_chrdev (input_major, "input", & input_fops); register the driver to the cdev_map to be driven.

Drivers/input/keyboard/pxa3xx_keypad.c is our Keyboard device,
Pxa3xx_keypad_probe =>
Request_irq (irq_enhrot, & enhanced_rotary_interrupt,
Irced _disabled, "enhanced rotary", (void *) keypad); Registration shortcut key interruption
Request_irq (irq_keypad, pxa3xx_keypad_interrupt, ir1__disabled, pdev-> name, keypad); Registration interrupted
Static irqreturn_t pxa3xx_keypad_interrupt (int irq, void * dev_id)
{
Struct pxa3xx_keypad * keypad = dev_id;
Uint32_t KPC = keypad_readl (KPC );

If (KPC & kpc_mi)
Pxa3xx_keypad_scan_matrix (keypad );

If (KPC & kpc_di)
Pxa3xx_keypad_scan_direct (keypad );

Return irq_handled;
}
If the key is read in IRQ
Input_report_key (keypad-> input_dev, lookup_matrix_keycode (keypad, row, col ),
New_state [col] & (1 <row ));
Static inline unsigned int lookup_matrix_keycode (
Struct pxa3xx_keypad * keypad, int row, int col)
{
Return keypad-> matrix_keycodes [(row <3) + Col];
}
Input_report_key (struct input_dev * Dev, unsigned int code, int value)
Dev is an input_dev device. Our 4*4 keyboard
The Code is the standard PC keyboard code.
Value indicates the key action. If the value is 1, the keyboard is pressed. If the value is 0, the key is lifted.
Static inline void input_report_key (struct input_dev * Dev, unsigned int code, int value)
{
Input_event (Dev, ev_key, code ,!! Value );
}
Void input_event (struct input_dev * Dev,
Unsigned int type, unsigned int code, int value)
{
Unsigned long flags;

If (is_event_supported (type, Dev-> evbit, ev_max )){
Spin_lock_irqsave (& Dev-> event_lock, flags );
Add_input_randomness (type, code, value); // keys are a good source of random numbers.
Input_handle_event (Dev, type, code, value );
Spin_unlock_irqrestore (& Dev-> event_lock, flags );
}
}
Static void input_handle_event (struct input_dev * Dev,
Unsigned int type, unsigned int code, int value)
{
...
Case ev_key:
If (is_event_supported (Code, Dev-> keybit, key_max )&&
!! Test_bit (Code, Dev-> key )! = Value) {// whether this time is a new key value

If (value! = 2 ){
_ Change_bit (Code, Dev-> key); // The bitmap corresponding to the code is reversed through an exception or ^ operation. If the value is equal to 2, this button is ignored.
If (value)
Input_start_autorepeat (Dev, Code); // press the keyboard to enable timed detection. This allows continuous input.
}

Disposition = input_pass_to_handlers;
}
Break;
...
}
Static void input_start_autorepeat (struct input_dev * Dev, int code)
{
If (test_bit (ev_rep, Dev-> evbit )&&
Dev-> rep [rep_period] & Dev-> rep [rep_delay] &
Dev-> timer. Data ){
Dev-> repeat_key = code;
Mod_timer (& Dev-> timer, // restart the timer input_repeat_key, interval msecs_to_jiffies (Dev-> rep [rep_delay])
Jiffies + msecs_to_jiffies (Dev-> rep [rep_delay]);
}
}

Static void input_repeat_key (unsigned long data)
{
Struct input_dev * Dev = (void *) data;
Unsigned long flags;

Spin_lock_irqsave (& Dev-> event_lock, flags );

If (test_bit (Dev-> repeat_key, Dev-> key )&&
Is_event_supported (Dev-> repeat_key, Dev-> keybit, key_max )){

Input_pass_event (Dev, ev_key, Dev-> repeat_key, 2); // hand it over to the processing Button Function

If (Dev-> sync ){
/*
* Only send syn_report if we are not in a middle
* Of driver parsing a new hardware packet.
* Otherwise assume that the driver will send...
* Syn_report once it's done.
*/
Input_pass_event (Dev, ev_syn, syn_report, 1 );
}

If (Dev-> rep [rep_period])
Mod_timer (& Dev-> timer, jiffies +
Msecs_to_jiffies (Dev-> rep [rep_period]);
}

Spin_unlock_irqrestore (& Dev-> event_lock, flags );
}

Input_pass_event =>
Handle-> Handler-> event (handle, type, code, value );
Kbd_event => kbd_keycode =>
Atomic_notifier_call_chain (& keyboard_notifier_list, kbd_unicode, & PARAM)
All applications that are waiting for keyboard input on the keyboard chain are notified,
You can use the register_keyboard_notifier () function to register it with the keyboard chain [gliethttp. Leith ],

Input_dev = input_allocate_device (); apply for an input device space
Input_dev-> open = pxa3xx_keypad_open; fill in the space
Input_dev-> close = pxa3xx_keypad_close;
Input_dev-> private = keypad;
Set_bit (ev_key, input_dev-> evbit); // press the key
Set_bit (ev_rel, input_dev-> evbit); // key release
Pxa3xx_keypad_build_keycode (keypad); // The device keyboard ing code.
This function performs key-encryption settings based on the matrix_key_map in the pxa3xx_device_keypad device,
Pxa_set_keypad_info (& jades_keypad_info) => Register jades_keypad_info as pdata;
# Define max_matrix_key_num (8*8)
Matrix_keycodes [max_matrix_key_num]; 8x8 keyboard
Keypad-> matrix_keycodes [(row <3) + Col] = Code; indicates pressing the key in the col column of the row, representing the code encoding value, which is used internally.
Set_bit (Code, input_dev-> keybit); // set the code to the available keyboard value of our keyboard for the operating system
If (pdata-> direct_key_num ){
For (I = 0; I <pdata-> direct_key_num; I ++ ){
Set_bit (pdata-> direct_key_map [I], input_dev-> keybit); // shortcut key unit
}
}
Set_bit (key_power, input_dev-> keybit); // register the power button as the system visible button
Input_register_device (input_dev); => // register and set this backup devices_subsys Bus
Int input_register_device (struct input_dev * Dev)
{
Static atomic_t input_no = atomic_init (0 );
Struct input_handler * Handler;
Const char * path;
Int error;

_ Set_bit (ev_syn, Dev-> evbit );

/*
* If delay and period are pre-set by the driver, then autorepeating
* Is handled by the driver itself and we don't do it in input. C.
*/

Init_timer (& Dev-> timer );
If (! Dev-> rep [rep_delay] &! Dev-> rep [rep_period]) {
Dev-> timer. Data = (long) Dev;
Dev-> timer. Function = input_repeat_key; // The deshake processing function, which uses the delayed deshake function.
Dev-> rep [rep_delay] = 500; // 250;
Dev-> rep [rep_period] = 66; // 33;
}

If (! Dev-> getkeycode)
Dev-> getkeycode = input_default_getkeycode;

If (! Dev-> setkeycode)
Dev-> setkeycode = input_default_setkeycode;
// Create an input device named input0 and input1 under/sys/class/Input
Snprintf (Dev-> Dev. bus_id, sizeof (Dev-> Dev. bus_id ),
"Input % lD", (unsigned long) atomic_inc_return (& input_no)-1 );

If (Dev-> cdev. Dev)
Dev-> Dev. Parent = Dev-> cdev. Dev;

Error = device_add (& Dev-> Dev); // register the device to the device bus and then present it as a directory and file
If (error)
Return Error;

Path = kobject_get_path (& Dev-> Dev. kobj, gfp_kernel );
Printk (kern_info "input: % s as % s/n ",
Dev-> name? Dev-> name: "unspecified device", path? Path: "N/");
Kfree (PATH );

Error = mutex_lock_interruptible (& input_mutex );
If (error ){
Device_del (& Dev-> Dev );
Return Error;
}

List_add_tail (& Dev-> node, & input_dev_list );
// Put the device on the input linked list, which stores all input-type Dev Device objects [gliethttp. Leith]
List_for_each_entry (handler, & input_handler_list, node)
Input_attach_handler (Dev, Handler );
// From the input_handler_list drive chain table, try to match whether there is a driver driving the dev device. If so, bind the matched driver to the dev device to drive the dev.
Input_wakeup_procfs_readers ();

Mutex_unlock (& input_mutex );

Return 0;
}

Drivers/Char/keyboard. c
Kbd_init () =>
Input_register_handler (& kbd_handler); register the keyboard driver to the input_handler_list linked list.

Static int input_attach_handler (struct input_dev * Dev, struct input_handler * Handler)
{
Const struct input_device_id * ID;
Int error;
// Check whether this is in the blacklist. If so, byebye [gliethttp. Leith]
If (Handler-> blacklist & input_match_device (Handler-> blacklist, Dev ))
Return-enodev;

Id = input_match_device (Handler-> id_table, Dev );
If (! ID)
Return-enodev;

Error = Handler-> connect (handler, Dev, ID); // OK, find the driver driving the dev, then try to connect
If (error & error! =-Enodev)
Printk (kern_err
"Input: failed to attach handler % s to device % s ,"
"Error: % d/N ",
Handler-> name, kobject_name (& Dev-> Dev. kobj), error );

Return Error;
}

Kbd_connect => input_register_handle => input_open_device => pxa3xx_keypad_open configure the keyboard IO port

 

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/zpf1217/archive/2009/10/16/4679731.aspx

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.