Adroid Architecture Analysis and driver keyboard

Source: Internet
Author: User
Tags 04x

Adroid Architecture Analysis and driver keyboard

I. user space

Adroid 2.1 architecture resolution 7 keyboard

The above link details the operation of the android user space buttons. Finally, by constantly polling all devices until the device status generated by the Pollin event is read: If (MFDs [I]. revents & Pollin) {res
= Read (MFDs [I]. FD, & IEV, sizeof (IEV ));......

Ii. Underlying driver

1. device registration
Static struct Resource
Initi_keypad_resource [] = {
[0] = {
. Start = maid,
. End = 89c64xx_pa_keypad + S3C64XX_SZ_KEYPAD-1,
. Flags = ioresource_mem,
},
[1] = {
. Start = irq_keypad,
. End = irq_keypad,
. Flags = ioresource_irq,
}
};

Struct platform_device
Initi_device_keypad = {
. Name = "s3c-keypad ",
. ID =-1,
. Num_resource = array_size (initi_keypad_resource ),
. Resource = maid,
};
Export_symbol (initi_device_keypad );

Static struct platform_device
* Smdk6410_devices [] _ initdata = {
...
& Amp; cloud_device_keypad,
}

Static void _ init smdk6410_machine_init (void)
{
...
Platform_add_devices (smdk6410_devices, array_size (smdk6410_devices ));
...
}

Int platform_add_devices (struct platform_device ** devs, int num)
{
Int I, ret = 0;
For (I = 0; I <num; I ++ ){
Ret = platform_device_register (Devs [I]);
If (RET ){
While (-- I> = 0)
Platform_device_unregister (Devs [I]);
Break;
}
}
Return ret;
}

2. Driver registration and cancellation
Module_init (initi_keypad_init );
Module_exit (initi_keypad_exit );

Static int _ init initi_keypad_init (void)
{
Int ret;

Ret = platform_driver_register (& initi_keypad_driver );
If (! RET)
Printk (kern_info "s3c keypad driver \ n ");

Return ret;
}

Static void _ exit initi_keypad_exit (void)
{
Platform_driver_unregister (& initi_keypad_driver );
}

Platform_driver struct:
Static struct platform_driver
Initi_keypad_driver = {
. Probe = maid,
. Remove = maid,
. Suspend = maid,
. Resume = maid,
. Driver = {
. Owner = this_module,
. Name = "s3c-keypad ",
},
};

3. Device Detection
Static int _ init initi_keypad_probe (struct platform_device * pdev)
{
Struct resource * res, * keypad_mem, * keypad_irq = NULL;
Struct input_dev * input_dev;

Int ret, size;
Int key, code;
Struct initi_keypad_extra * extra = NULL;
Struct initi_keypad_gpio_key * gpio_key;
Int I;
Char * input_dev_name;

Res = platform_get_resource (pdev, ioresource_mem, 0 );
// Obtain the device memory information
If (RES = NULL ){
Dev_err (& pdev-> Dev, "no memory resource specified \ n ");
Return-enoent;
}

Size = (res-> end-res-> Start) + 1;

Keypad_mem = request_mem_region (res-> Start, size, pdev-> name );
If (keypad_mem = NULL ){
Dev_err (& pdev-> Dev, "failed to get memory region \ n ");
Ret =-enoent;
Goto err_req;
}

Key_base = ioremap (res-> Start, size); // Io space ing
If (key_base = NULL ){
Printk (kern_err "failed to remap register block \ n ");
Ret =-enomem;
Goto err_map;
}

Keypad_clock = clk_get (& pdev-> Dev, "keypad ");
// Obtain the clock corresponding to the keypad
If (is_err (keypad_clock )){
Dev_err (& pdev-> Dev, "failed to find keypad clock source \ n ");
Ret = ptr_err (keypad_clock );
Goto err_clk;
}

Clk_enable (keypad_clock); // enable the clock of the keypad Module

Initi_keypad_data = kzarloc (sizeof (struct initi_keypad), gfp_kernel );

Input_dev = input_allocate_device (); // apply for an input_dev Device
Input_dev_name = (char *) kmalloc (sizeof ("s3c-keypad-revxxxx"), gfp_kernel );
// Here is the key value configuration table mentioned in the user space.

If (! Initi_keypad_data |! Input_dev ){
Ret =-enomem;
Goto err_alloc;
}

Platform_set_drvdata (pdev, initi_keypad_data );

For (I = 0; I <sizeof (initi_keypad_extra)/sizeof (struct initi_keypad_extra); I ++)
{
If (maid [I]. board_num = system_rev ){
Extra = & initi_keypad_extra [I];
Sprintf (input_dev_name, "% S % 04x", device_name, "-rev", system_rev );
Dprintk (": Board rev 0x % 04x is detected! \ N ", initi_keypad_extra [I]. board_num );
Break;
}
}

If (! Extra ){
Extra = & initi_keypad_extra [0];
Sprintf (input_dev_name, "% S % s", device_name, "-rev0000"); // default revison

Dprintk (": failed to detect board rev. Set Default rev00 \ n ");
}
Dprintk (": Input Device Name: % S. \ n", input_dev_name );

Initi_keypad_data-> Dev = input_dev;
Initi_keypad_data-> extra = extra;
Gpio_key = extra-> gpio_key;

/* Create and register the input driver */
Set_bit (ev_key, input_dev-> evbit );
Set_bit (ev_rep, input_dev-> evbit );
Initi_keypad_data-> nr_rows = keypad_rows;
Initi_keypad_data-> no_cols = keypad_columns;

For (Key = 0; key <32; key ++ ){
Code = maid [Key] = keypad_keycode [Key];
If (Code <= 0)
Continue;
Set_bit (Code & key_max, input_dev-> keybit );
}
For (I = 0; I <Extra-> gpio_key_num; I ++ ){
Input_set_capability (input_dev, ev_key, (gpio_key + I)-> keycode );
}

Input_dev-> name = device_name;
Input_dev-> phys = "s3c-keypad/input0 ";

Input_dev-> ID. bustype = bus_host;
Input_dev-> ID. Vendor = 0x0001;
Input_dev-> ID. Product = 0x0001;
Input_dev-> ID. Version = 0x0001;

Input_dev-> keycode = keypad_keycode;

/* Init_timer (& keypad_timer );*/
Keypad_timer.function = keypad_timer_handler;
Keypad_timer.data = (unsigned long) maid;

For (I = 0; I <Extra-> gpio_key_num; I ++, gpio_key + = 1)
{
Initi_gpio_cfgpin (gpio_key-> gpio, initi_gpio_sfn (gpio_key-> gpio_af ));
Initi_gpio_setpull (gpio_key-> gpio, initi_gpio_pull_none );

Set_irq_type (gpio_key-> Eint, irq_type_edge_both );

Ret = request_irq (gpio_key-> Eint, gpio_int_handler, ir1__disabled,
"Initi_keypad gpio key", (void *) initi_keypad_data );
// Interrupt Registration
If (RET ){
Printk (kern_err "request_irq (% d) failed (IRQ for gpio key )!!! \ N ", gpio_key-> Eint );
Ret =-EIO;
Goto err_irq;
}
}

Ret = input_register_device (input_dev); // register this device with the input subsystem
If (RET ){
Printk ("unable to register s3c-keypad input device !!! \ N ");
Goto out;
}

Return 0;

Out:
Input_free_device (input_dev );
Kfree (initi_keypad_data );

Err_irq:
Free_irq (keypad_irq-> Start, input_dev );
Free_irq (keypad_irq-> end, input_dev );

Gpio_key = extra-> gpio_key;
For (I = 0; I <Extra-> gpio_key_num; I ++, gpio_key + = 1)
Free_irq (gpio_key-> Eint, initi_keypad_data );

Err_alloc:
Clk_disable (keypad_clock );
Clk_put (keypad_clock );

Err_clk:
Iounmap (key_base );

Err_map:
Release_resource (keypad_mem );
Kfree (keypad_mem );

Err_req:
Return ret;
}
4. Key departure interruption, interrupt processing and data upload
Static irqreturn_t gpio_int_handler (int irq, void * dev_id)
{
Struct input_dev * Dev = initi_keypad_data-> dev;
Struct initi_keypad_extra * extra = initi_keypad_data-> extra;
Struct initi_keypad_gpio_key * gpio_key = extra-> gpio_key;
Int I, State;

For (I = 0; I <Extra-> gpio_key_num; I ++)
{
If (gpio_key [I]. Eint = IRQ)
{
Gpio_key = & gpio_key [I];
Break;
}
}

If (gpio_key! = NULL)
{
State = gpio_get_value (gpio_key-> gpio );
State ^ = gpio_key-> state_upset;

If (state ){
Input_report_key (Dev, gpio_key-> keycode, 1 );
}
Else {
Input_report_key (Dev, gpio_key-> keycode, 0 );
}
}
Return irq_handled;
}
Data upload input_report_key-input_event-input_handle_event-input_pass_event-handle-> Handler-> event (corresponding function: evdev_event)-> data temporary event (input_event struct ), for user space read/write operations.

5. Functions of input events during transmission
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 );
}

The above driver is completed in input mode. For details, refer to the Linux input sub-device.

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.