On A20, we will demonstrate the overview and learning plan of Oracle's Android hardware abstraction layer (HAL) 2-about the kernel section.

Source: Internet
Author: User
Tags access properties

Generally, the fully-recorded code is changed to the compiling method that we think is logical, for example, we think that the lichee of quanzhi includes the code of the packaging tool kernel and uboot, which should be placed in the android directory. So we made changes, so the kernel code path is as follows: vendor/softwinner/linux-3.4/Drivers/input/keyboard/the Hello old man. C and hello. the H file is stored in the keyboard directory, because the driver he wrote may be in the old version, so it may be slightly changed when the kernel is 3.4. If you want to demonstrate it yourself, you will not compile it into KO. You can directly compile it into the kernel:

Diff -- git a/Drivers/input/keyboard/makefile B/Drivers/input/keyboard/makefile
Index 6fbeff6 .. af0262a 100644
--- A/Drivers/input/keyboard/makefile
++ B/Drivers/input/keyboard/makefile
@-4, 6 + 4, 7 @@
 
# Each configuration option enables a list of files.
 
+ Obj-y + = Hello. o
OBJ-$ (config_keyboard_adp5520) + = adp5520-keys.o
OBJ-$ (config_keyboard_adp5588) + = adp5588-keys.o
OBJ-$ (config_keyboard_adp5589) + = adp5589-keys.o

----------------------------------------- The above is the modified makefile, and the following code is used:

The code for the hello. h header file is as follows:

# Ifndef _ hello_android_h _
# DEFINE _ hello_android_h _

# Include <Linux/cdev. h>
# Include <Linux/semaphore. h>

# Define hello_device_node_name "hello"
# Define hello_device_file_name "hello"
# Define hello_device_proc_name "hello"
# Define hello_device_class_name "hello"

Struct hello_android_dev {
Int val;
Struct semaphore SEM;
Struct cdev dev;
};

# Endif

The Hello. C code is as follows:

# Include <Linux/init. h>
# Include <Linux/module. h>
# Include <Linux/types. h>
# Include <Linux/fs. h>
# Include <Linux/proc_fs.h>
# Include <Linux/device. h>
# Include <ASM/uaccess. h>

# Include "Hello. H"

/* Main device and slave device number variable */
Static int hello_major = 0;
Static int hello_minor = 0;

/* Device category and device variable */
Static struct class * hello_class = NULL;
Static struct hello_android_dev * hello_dev = NULL;

/* Traditional Device File Operations */
Static int hello_open (struct inode * inode, struct file * filp );
Static int hello_release (struct inode * inode, struct file * filp );
Static ssize_t hello_read (struct file * filp, char _ User * Buf, size_t count, loff_t * f_pos );
Static ssize_t hello_write (struct file * filp, const char _ User * Buf, size_t count, loff_t * f_pos );

/* Operation method table of Device Files */
Static struct file_operations hello_fops = {
. Owner = this_module,
. Open = hello_open,
. Release = hello_release,
. Read = hello_read,
. Write = hello_write,
};

/* Method for setting access properties */
Static ssize_t hello_val_show (struct device * Dev, struct device_attribute * ATTR, char * BUF );
Static ssize_t hello_val_store (struct device * Dev, struct device_attribute * ATTR, const char * Buf, size_t count );

/* Define device properties */
Static device_attr (Val, s_irugo | s_iwusr, hello_val_show, hello_val_store );

Static int hello_open (struct inode * inode, struct file * filp ){
Struct hello_android_dev * dev;

/* Save the custom device struct in the private data field of the file pointer for use when accessing the device */
Dev = container_of (inode-> I _cdev, struct hello_android_dev, Dev );
Filp-> private_data = dev;
Return 0;
}

/* Called when the device file is released, empty implement */
Static int hello_release (struct inode * inode, struct file * filp ){
Return 0;
}

/* Read the Val value of the device's register */
Static ssize_t hello_read (struct file * filp, char _ User * Buf, size_t count, loff_t * f_pos ){
Ssize_t err = 0;
Struct hello_android_dev * Dev = filp-> private_data;

/* Synchronous access */
If (down_interruptible (& (Dev-> SEM ))){
Return-erestartsys;
}

If (count <sizeof (Dev-> Val )){
Goto out;
}

/* Copy the Val value of the Register to the buffer zone provided by the user */
If (copy_to_user (BUF, & (Dev-> Val), sizeof (Dev-> Val ))){
Err =-efault;
Goto out;
}
Err = sizeof (Dev-> Val );
Out:
Up (& (Dev-> SEM ));
Return err;
}

/* Write the device register value Val */
Static ssize_t hello_write (struct file * filp, const char _ User * Buf, size_t count, loff_t * f_pos ){
Struct hello_android_dev * Dev = filp-> private_data;
Ssize_t err = 0;

/* Synchronous access */
If (down_interruptible (& (Dev-> SEM ))){
Return-erestartsys;
}

If (count! = Sizeof (Dev-> Val )){
Goto out;
}

/* Write the value of the buffer provided by the user to the device register */
If (copy_from_user (& (Dev-> Val), Buf, count )){
Err =-efault;
Goto out;
}

Err = sizeof (Dev-> Val );

Out:
Up (& (Dev-> SEM ));
Return err;
}

/* Read the Val value of the Register to the buffer Buf and use it internally */
Static ssize_t _ hello_get_val (struct hello_android_dev * Dev, char * BUF ){
Int val = 0;

/* Synchronous access */
If (down_interruptible (& (Dev-> SEM ))){
Return-erestartsys;
}

Val = Dev-> val;
Up (& (Dev-> SEM ));

Return snprintf (BUF, page_size, "% d \ n", Val );
}

/* Write the buffer Buf value to the device register Val and use it internally */
Static ssize_t _ hello_set_val (struct hello_android_dev * Dev, const char * Buf, size_t count ){
Int val = 0;

/* Convert a string to a number */
Val = simple_strtol (BUF, null, 10 );

/* Synchronous access */
If (down_interruptible (& (Dev-> SEM ))){
Return-erestartsys;
}

Dev-> val = val;
Up (& (Dev-> SEM ));

Return count;
}

/* Read the device property val */
Static ssize_t hello_val_show (struct device * Dev, struct device_attribute * ATTR, char * BUF ){
Struct hello_android_dev * hdev = (struct hello_android_dev *) dev_get_drvdata (Dev );

Return _ hello_get_val (hdev, Buf );
}

/* Write the device property val */
Static ssize_t hello_val_store (struct device * Dev, struct device_attribute * ATTR, const char * Buf, size_t count ){
Struct hello_android_dev * hdev = (struct hello_android_dev *) dev_get_drvdata (Dev );

Return _ hello_set_val (hdev, Buf, count );
}

/* Read the Val value of the device register and save it in the page buffer */
Static ssize_t hello_proc_read (char * Page, char ** start, off_t off, int count, int * EOF, void * Data ){

If (Off> 0)
{
* EOF = 1;
Return 0;
}

Return _ hello_get_val (hello_dev, page );
}

/* Save the buffer value buff to the device register Val */
Static ssize_t hello_proc_write (struct file * filp, const char _ User * buff, unsigned long Len, void * Data ){
Int err = 0;
Char * page = NULL;

If (LEN> page_size ){
Printk (kern_alert "The buff is too large: % lu. \ n", Len );
Return-efault;
}

Page = (char *) _ get_free_page (gfp_kernel );
If (! Page ){
Printk (kern_alert "failed to alloc page. \ n ");
Return-enomem;
}

/* First copy the buffer value provided by the user to the kernel buffer */
If (copy_from_user (page, buff, Len )){
Printk (kern_alert "failed to copy Buff from user. \ n ");
Err =-efault;
Goto out;
}

Err = _ hello_set_val (hello_dev, page, Len );

Out:
Free_page (unsigned long) page );
Return err;
}

/* Create/proc/Hello file */
Static void hello_create_proc (void ){
Struct proc_dir_entry * entry;

Entry = create_proc_entry (hello_device_proc_name, 0, null );
If (entry ){
// Entry-> owner = this_module;
Entry-> read_proc = hello_proc_read;
Entry-> write_proc = hello_proc_write;
}
}

/* Delete the/proc/Hello file */
Static void hello_remove_proc (void ){
Remove_proc_entry (hello_device_proc_name, null );
}

/* Initialize the device */
Static int _ hello_setup_dev (struct hello_android_dev * Dev ){
Int err;
Dev_t devno = mkdev (hello_major, hello_minor );

Memset (Dev, 0, sizeof (struct hello_android_dev ));

Cdev_init (& (Dev-> Dev), & hello_fops );
Dev-> Dev. Owner = this_module;
Dev-> Dev. Ops = & hello_fops;

/* Register a character device */
Err = cdev_add (& (Dev-> Dev), devno, 1 );
If (ERR ){
Return err;
}

/* Initialize the semaphore and register Val value */
// Init_mutex (& (Dev-> SEM ));
Sema_init (& (Dev-> SEM), 1 );
Dev-> val = 0;

Return 0;
}

/* Module Loading Method */
Static int _ init hello_init (void ){
Int err =-1;
Dev_t Dev = 0;
Struct device * temp = NULL;

Printk (kern_alert "Initializing Hello device. \ n ");

/* Dynamically allocate the master device and slave device Number */
Err = alloc_chrdev_region (& Dev, 0, 1, hello_device_node_name );
If (ERR <0 ){
Printk (kern_alert "failed to alloc char Dev region. \ n ");
Goto fail;
}

Hello_major = major (Dev );
Hello_minor = minor (Dev );

/* Allocate the helo device struct variable */
Hello_dev = kmalloc (sizeof (struct hello_android_dev), gfp_kernel );
If (! Hello_dev ){
Err =-enomem;
Printk (kern_alert "failed to alloc hello_dev. \ n ");
Goto unregister;
}

/* Initialize the device */
Err = _ hello_setup_dev (hello_dev );
If (ERR ){
Printk (kern_alert "failed to setup Dev: % d. \ n", err );
Goto cleanup;
}

/* Create the device category directory "hello" under the/sys/class/directory */
Hello_class = class_create (this_module, hello_device_class_name );
If (is_err (hello_class )){
Err = ptr_err (hello_class );
Printk (kern_alert "failed to create Hello class. \ n ");
Goto destroy_cdev;
}

/* Create the device file "hello */" in the/dev/directory and/sys/class/Hello directory respectively */
Temp = device_create (hello_class, null, Dev, "% s", hello_device_file_name );
If (is_err (temp )){
Err = ptr_err (temp );
Printk (kern_alert "failed to create Hello device .");
Goto destroy_class;
}

/* Create the attribute file Val in the/sys/class/Hello directory */
Err = device_create_file (temp, & dev_attr_val );
If (ERR <0 ){
Printk (kern_alert "failed to create Attribute Val .");
Goto destroy_device;
}

Dev_set_drvdata (temp, hello_dev );

/* Create/proc/Hello file */
Hello_create_proc ();

Printk (kern_alert "succedded to initialize Hello device. \ n ");
Return 0;

Destroy_device:
Device_destroy (hello_class, Dev );

Destroy_class:
Class_destroy (hello_class );

Destroy_cdev:
Cdev_del (& (hello_dev-> Dev ));

Cleanup:
Kfree (hello_dev );

Unregister:
Unregister_chrdev_region (mkdev (hello_major, hello_minor), 1 );

Fail:
Return err;
}

/* Module uninstallation Method */
Static void _ exit hello_exit (void ){
Dev_t devno = mkdev (hello_major, hello_minor );

Printk (kern_alert "Destroy Hello device. \ n ");

/* Delete the/proc/Hello file */
Hello_remove_proc ();

/* Destroy the device category and device */
If (hello_class ){
Device_destroy (hello_class, mkdev (hello_major, hello_minor ));
Class_destroy (hello_class );
}

/* Delete character devices and release device memory */
If (hello_dev ){
Cdev_del (& (hello_dev-> Dev ));
Kfree (hello_dev );
}

/* Release the device Number */
Unregister_chrdev_region (devno, 1 );
}

Module_license ("GPL ");
Module_description ("first Android driver ");

Module_init (hello_init );
Module_exit (hello_exit );

Related Article

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.