您的位置:首页 > 移动开发 > Android开发

HAL(1) -- 编写android内核驱动

2013-08-27 10:02 204 查看

一. 进入到kernel/drivers目录,新建zhx_print目录:  





  $ cd ics/kernel/drivers

  $ mkdir zhx_print
  二. 在zhx_print目录中增加zhx_print.h文件:



#ifndef _PRINT_H_
#define _PRINT_H_
 
#include <linux/cdev.h>
 
#define PRINT_NAME "zhx_print"
 
struct print_reg_dev
{
    struct cdev print_cdev;
    int val;
};
 
#endif

   这个头文件定义了一些字符串常量宏,在后面我们要用到!。此外,还定义了一个字符设备结构体print_dev,这个就是我们虚拟的硬件设备了,val成员变量就代表设备里面的寄存器,它的类型为int。

  三.在zhx_print目录中增加print.c文件

这是驱动程序的实现部分。驱动程序的功能主要是向上层提供访问设备的寄存器的值,包括读和写。

这里,为了让程序看起来简单明了,我们只实现普遍的字符串驱动模式。 

首先是包含必要的头文件和定义三种访问设备的方法:





#[b]include<linux/module.h>

#include
<linux/init.h>

#include
<linux/kernel.h>

#include
<linux/fs.h>

#include
<asm/uaccess.h>

#include
<linux/device.h>

#include
<linux/types.h>

#include
<linux/proc_fs.h>

#include
<linux/errno.h>

#include
"print.h"
/*device major and minor*/
static
int major_number =
0;
static
int minor_number =
0;

static
struct print_reg_dev *print_dev= NULL;
static
struct class*print_class= NULL;

/*function*/
static
int print_open(struct inode*inodep,struct file*filep);
static
int print_close(struct inode*inodep,struct file*filep);
static ssize_t print_read([b]struct file*filep,char __user*buf,size_t
count,loff_t *ppos);
static ssize_t print_write(struct file*filep,constchar
__user *buf,size_t count,loff_t
*ppos)
[/b]

四:实现各个函数的功能

主要有 print_open,print_close ,print_read,print_write等



/*打开函数*/
static
int print_open(struct inode*inodep,struct file*filep)

{

    struct print_reg_dev
*dev = NULL;

    dev = container_of(inodep->i_cdev,struct print_reg_dev,print_cdev);

    if(dev
== NULL)

    {

        printk("print_open is error.\n");

        return
-1;

    }

    filep->private_data= (void*)dev;

    

    return
0;

}

/*关闭*/
static
int print_close(struct inode*inodep,struct file*filep)

{

    return
0;

}

/*读取*/
static ssize_t print_read(struct file*filep,char __user*buff,

        size_t count,loff_t *ppos)

{

    /*定义自己定义的结构体函数*/

    struct print_reg_dev
*dev = (struct print_reg_dev*)filep->private_data;

    /*返回值*/

    int ret
= 0;

    printk(KERN_INFO"print_read : you read value\n");

    if(count
!= sizeof(dev->val))    

    {

        printk("print_read : sorry error\n");

        return
0;

    }

    if(copy_to_user(buff,&(dev->val),sizeof(dev->val)))

    {

        ret =  -EFAULT;

    }

    else

    {

        ret = sizeof(dev->val);

    }    

    return ret;

}

/*写入*/
static ssize_t print_write(struct file*filep,constchar
__user *buf,

        size_t count,loff_t *ppos)

{

    struct print_reg_dev
*dev = filep->private_data;

    int ret
= 0;

    printk(KERN_INFO"print_write:yout write value\n");

    

    if(count
!= sizeof(dev->val))

    {

        printk("print_write : sorry error\n");

        return
0;

    }

    if(copy_from_user((void*)&dev->val,(void*)buf,sizeof(dev->val)))

    {

        ret = -EFAULT;

    }

    else

    {

        ret = sizeof(dev->val);

    }

    return ret;

}

五:定义字符驱动函数结构体
 



staticstruct file_operations print_fops=

{

    .owner = THIS_MODULE,

    .open = print_open,

    .release = print_close,

    .read = print_read,

    .write = print_write,

}


 
六:实现初始化init函数
 


staticint __init print_init(void)

{

    int err
= 0;

    dev_t devno =
0;

    printk(KERN_ALERT"Initializing print device\n");

    

    //1.动态分配主从设备号,并且注册驱动

    err = alloc_chrdev_region(&devno,0,1,"zhx_print");

    if(err
< 0)

    {

        printk(KERN_ALERT"Failed to alloc char dev region.\n");

        return err;

    }

    printk(KERN_INFO"print_init : alloc_chrdev_region sucessfully\n");

    //2.分配结构体内存空间

    print_dev = kmalloc(sizeof(struct print_reg_dev),GFP_KERNEL);

    if(print_dev
== NULL)

    {

        printk(KERN_ALERT"Failed to kmalloc print_dev");

        err = -ENOMEM;

    }

    major_number = MAJOR(devno);

    minor_number = MINOR(devno);

    printk(KERN_INFO"print_init : kmalloc print_dev sucessfully\n");

    //3.初始化和注册cdev

    memset(print_dev,0,sizeof(struct print_reg_dev));//结构体初始化

    cdev_init(&(print_dev->print_cdev),&print_fops);//cdev初始化

    print_dev->print_cdev.owner= THIS_MODULE;

    print_dev->print_cdev.ops=&print_fops;

    err = cdev_add(&print_dev->print_cdev,devno,1);//注册cdev

    if(err)

        return err;

    print_dev->val=0;

    printk(KERN_INFO"print_init : cdev_init -- cdev_add sucessfully\n");

    //4.创建设备节点,就是在/dev/目录下创建zhx_print

    print_class = class_create(THIS_MODULE,"zhx_print");

    if(IS_ERR(print_class))    

    {

        err = PTR_ERR(print_class);

        printk(KERN_ALERT"Failed to create print device class.\n");

        cdev_del(&(print_dev->print_cdev));

        unregister_chrdev_region(devno,1);

        kfree(print_dev);

        return err;

    }

    device_create(print_class,NULL,devno,"%s","zhx_print");//创建zhx_print

    printk(KERN_INFO" init sucessfully!!!!!\n");

    return
0;

}

 
七:实现卸载函数
 


staticvoid __exit print_exit(void)

{

    //1.卸载设备节点

    device_destroy(print_class,MKDEV(major_number,minor_number));

    //2.卸载cdev

    if(print_dev)    

    {

        cdev_del(&(print_dev->print_cdev));

        kfree(print_dev);

    }

    //3.卸载

    unregister_chrdev_region(MKDEV(major_number,minor_number),1);

}

 
八:添加模块协议和指定模块初始化和卸载函数



MODULE_LICENSE("GPL");

module_init(print_init);

module_exit(print_exit);

 
九:在zhx_print目录下添加Kconfig文件,文件内容:



config ZHX_PRINT

    tristate "zhx write driver"

    default n

    help

    this is the driver

 
十:在zhx_print目录下添加Makefile文件,文件内容:



obj-$(CONFIG_ZHX_PRINT)+= print.o
 
十一:在ics/kernel/drivers目录上的Kconfig 中添加粗体红色语句:



...

source "drivers/i-tv/Kconfig"

source "drivers/gps/Kconfig"

source "drivers/zhx_print/Kconfig"
endmenu
 
十二:在ics/kernel/drivers/目录下的Makefile中添加以下语句:



obj-$(CONFIG_ZHX_PRINT)+= zhx_print/
 
十三:在ics/kernel/目录下,敲入以下命令:

 


ics/kernle$  make menuconfig
 
到这里会弹出内核配置菜单,这里配置如下:

 


Device Drivers --->

                [*]zhx write driver

 
然后重新编译内核!

 


ics/kernle$  make-j4
 
到这里,zhx_print的驱动就添加进入内核里面了!!!  

 
十四:处理硬件设备访问权限问题

 
在硬件抽象层中,我们调用open函数来打开对应内核设备时:

 


if((dev->fd= open(DEVICE_NAME,O_RDWR))==
-1)

{

   LOGE("Failed to open device file /dev/zhx_print");

   free(dev);

   return
-EFAULT;

}

 
如果没有修改设备节点/dev/zhx_print权限,那么,就会提示:

 


Failed to open device file
/dev/zhx_print  

 
 
这表明当前用户没有权限打开设备文件/dev/zhx_print,解决方法如下:

 在板子的命令行中 执行以下命令:

board@Ubuntu:$ chmod 777 /dev/zhx_print                                                                                                                              
                                    

然后就可以操作啦!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android hal 内核
相关文章推荐