android hal 学习——编写android内核驱动
来源:互联网 发布:淘宝代发网 编辑:程序博客网 时间:2024/05/22 03:39
参考:http://blog.csdn.net/liuhaoyutz/article/details/9147877
1、代码准备
在下载的android内核的drivers目录下新建了example目录:
代码是拷贝参考文章里的。。。只是去掉了锁相关的内容:
exampe.h内容:
#ifndef _EXAMPLE_H_#define _EXAMPLE_H_#include <linux/cdev.h>#include <linux/semaphore.h>#define EXAMPLE_DEVICE_NODE_NAME "example"#define EXAMPLE_DEVICE_FILE_NAME "example"#define EXAMPLE_DEVICE_PROC_NAME "example"#define EXAMPLE_DEVICE_CLASS_NAME "example"#define EXAMPLE_MAJOR 0struct example_dev{ struct semaphore sem; struct cdev cdev; int val;};#endif
exampe.c内容:
#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 "example.h"static int example_major=EXAMPLE_MAJOR;static int example_minor=0;static struct class* example_class=NULL;static struct example_dev* example_dev=NULL;module_param(example_major,int,S_IRUGO);module_param(example_minor,int,S_IRUGO);static int example_open(struct inode* inode,struct file* filp){ struct example_dev* dev; dev=container_of(inode->i_cdev,struct example_dev,cdev); filp->private_data=dev; return 0;}static int example_release(struct inode* inode,struct file* filp){ return 0;}static ssize_t example_read(struct file* filp,char __user *buf,size_t count,loff_t * f_pos){ struct example_dev* dev = filp->private_data; ssize_t retval = 0; /* * 加锁 */ //if(down_interruptible(&(dev->sem))) // return -ERESTARTSYS; if(count < sizeof(dev->val)) goto out; /* * 读寄存器的值到用户空间。 */ if(copy_to_user(buf, &(dev->val), sizeof(dev->val))) { retval = -EFAULT; goto out; } retval = sizeof(dev->val); out: /* * 解锁 */ // up(&(dev->sem)); return retval; }static ssize_t example_write(struct file* filp,const char __user *buf,size_t count,loff_t* f_pos){struct example_dev* dev = filp->private_data; ssize_t retval = 0; /* * 加锁 */ //if(down_interruptible(&(dev->sem))) // return -ERESTARTSYS; if(count != sizeof(dev->val)) goto out; /* * 从用户空间读取并给寄存器赋值。 */ if(copy_from_user(&(dev->val), buf, count)) { retval = -EFAULT; goto out; } retval = sizeof(dev->val); out: /* * 解锁 */ // up(&(dev->sem)); return retval; }static struct file_operations example_fops={ .owner=THIS_MODULE, .open=example_open, .release=example_release, .read=example_read, .write=example_write};static ssize_t __example_get_val(struct example_dev* dev,char* buf){ int val=0;// if(down_interruptible(&(dev->sem))){// return -ERESTARTSYS;// } val=dev->val;// up(&(dev->sem)); return snprintf(buf,30,"%d\n",val);}static ssize_t __example_set_val(struct example_dev* dev,const char* buf,size_t count){ int val=0; val=(int)simple_strtol(buf,NULL,10);// if(down_interruptible(&(dev->sem)))// return -ERESTARTSYS; dev->val=val;// up(&(dev->sem)); return count;}static ssize_t example_val_show(struct device* dev,struct device_attribute* attr,char* buf){ struct example_dev* hdev = (struct example_dev*)dev_get_drvdata(dev); return __example_get_val(hdev, buf);}static ssize_t example_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) { struct example_dev* hdev = (struct example_dev*)dev_get_drvdata(dev); return __example_set_val(hdev, buf, count); } static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, example_val_show, example_val_store);static ssize_t example_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data) { if(off > 0) { *eof = 1; return 0; } return __example_get_val(example_dev, page); } /* * /proc节点的写操作函数。 */ static ssize_t example_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; } if(copy_from_user(page, buff, len)) { printk("Failed to copy buff from user.\n"); err = -EFAULT; goto out; } err = __example_set_val(example_dev, page, len); out: free_page((unsigned long)page); return err; }/* * 创建/proc节点 */ static void example_create_proc(void) { struct proc_dir_entry* entry; entry = create_proc_entry(EXAMPLE_DEVICE_PROC_NAME, 0, NULL); if(entry) { //entry->owner = THIS_MODULE; entry->read_proc = example_proc_read; entry->write_proc = example_proc_write; } } /* * 删除/proc节点 */ static void example_remove_proc(void) { remove_proc_entry(EXAMPLE_DEVICE_PROC_NAME, NULL); }static int __example_setup_dev(struct example_dev* dev){ int retval; dev_t devno=MKDEV(example_major,example_minor); memset(dev,0,sizeof(struct example_dev)); cdev_init(&(dev->cdev),&example_fops); dev->cdev.owner=THIS_MODULE; dev->cdev.ops=&example_fops; retval=cdev_add(&(dev->cdev),devno,1); if(retval){ return retval; } //sem_init(&(dev->sem), pshared, value); //init_MUTEX(&(dev->sem)); dev->val=0; return 0;}static int __init example_init(void){ int retval=-1; dev_t dev=0; struct device* device=NULL; printk("Initializing example device.\n"); if(example_major){ dev=MKDEV(example_major,example_minor); retval=register_chrdev_region(dev,1,EXAMPLE_DEVICE_NODE_NAME); }else{ retval = alloc_chrdev_region(&dev, example_minor, 1, EXAMPLE_DEVICE_NODE_NAME); } if(retval<0){ printk("can't get example major %d\n",example_major); goto fail; }/* * 取得主设备号和次设备号 */ example_major = MAJOR(dev); example_minor = MINOR(dev); /* * 为设备结构体example_dev动态分配内存空间。 */ example_dev = kmalloc(sizeof(struct example_dev), GFP_KERNEL); if(!example_dev) { retval = -ENOMEM; printk(KERN_ALERT"Failed to alloc example_dev.\n"); goto unregister; } /* * 调用__example_setup_dev函数对example_dev结构体进行初始化。 */ retval = __example_setup_dev(example_dev); if(retval) { printk(KERN_ALERT"Failed to setup dev: %d.\n", retval); goto cleanup; } /* * 创建类example,class_create函数执行成功后,在/sys/class目录下 * 就会出现一个名为example的目录。 */ example_class = class_create(THIS_MODULE, EXAMPLE_DEVICE_CLASS_NAME); if(IS_ERR(example_class)) { retval = PTR_ERR(example_class); printk(KERN_ALERT"Failed to create example class.\n"); goto destroy_cdev; } /* * 创建设备,device_create函数执行成功后,会生成/dev/example文件 * 和/sys/class/example/example目录及相关文件。 * 注意device的类型是struct device,代表一个设备。 */ device = device_create(example_class, NULL, dev, "%s", EXAMPLE_DEVICE_FILE_NAME); if(IS_ERR(device)) { retval = PTR_ERR(device); printk(KERN_ALERT"Failed to create example device."); goto destroy_class; } /* * 创建属性文件,对应的属性操作函数由dev_attr_val指定。 */ retval = device_create_file(device, &dev_attr_val); if(retval < 0) { printk(KERN_ALERT"Failed to create attribute val."); goto destroy_device; } /* * 将example_dev保存在设备私有数据区中。 */ dev_set_drvdata(device, example_dev); /* * 创建proc节点。 */ example_create_proc(); printk(KERN_ALERT"Succedded to initialize example device.\n"); return 0; destroy_device: device_destroy(example_class, dev); destroy_class: class_destroy(example_class); destroy_cdev: cdev_del(&(example_dev->cdev)); cleanup: kfree(example_dev); unregister: unregister_chrdev_region(MKDEV(example_major, example_minor), 1); fail: return retval; } /* * 模块清理函数。 */ static void __exit example_exit(void) { dev_t dev = MKDEV(example_major, example_minor); printk(KERN_ALERT"Destroy example device.\n"); example_remove_proc(); if(example_class) { device_destroy(example_class, MKDEV(example_major, example_minor)); class_destroy(example_class); } if(example_dev) { cdev_del(&(example_dev->cdev)); kfree(example_dev); } unregister_chrdev_region(dev, 1); } MODULE_LICENSE("GPL"); module_init(example_init); module_exit(example_exit);
Makefile内容:
obj-y +=example.o
在drivers下的Makefile下也增加一行:
obj-y +=example/
2、编译
[zzz@localhost goldfish]$ make ARCH=arm CROSS_COMPILE=/home/zzz/opensource/android-src/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h’ is up to date.
CALL scripts/checksyscalls.sh
CHK include/generated/compile.h
CHK kernel/config_data.h
CC drivers/example/example.o
LD drivers/example/built-in.o
LD drivers/built-in.o
LD vmlinux.o
…
SYSMAP System.map
SYSMAP .tmp_System.map
OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
GZIP arch/arm/boot/compressed/piggy.gzip
AS arch/arm/boot/compressed/piggy.gzip.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
后面再继续测试了。
- android hal 学习——编写android内核驱动
- HAL(1) -- 编写android内核驱动
- android hal学习——编写hal代码
- android hal学习——编写hal代码【转】
- android hal学习——aidl,java service,jni编写
- android HAL访问linux内核驱动
- Android—GSensor驱动与HAL/Framework
- Android底层HAL驱动开发学习笔记
- 编写android HAL代码
- Android HAL驱动开发
- HAL(2) -- 编写android C可执行文件调用驱动
- android hal学习——aidl,java service,jni编写【转】
- android hal 学习——数据结构整理
- Android GPS学习笔记—HAL实现
- 为android编写linux内核驱动
- 编写android HAL举例: lights
- Android深度探索:HAL与驱动开发学习笔记--中断
- android hal学习
- C语言中typedef 与结构体
- 字符串之字符串平移(java实现)
- UVa1935
- Intent 初步认识【1】
- Xdebug
- android hal 学习——编写android内核驱动
- Git上手(2)安装Git
- laravel_db_operation
- 快排
- 1006. Sign In and Sign Out (25)
- C++ typedef用法小结 (※不能不看※)
- SortedSet 接口 源代码
- 2015年11月13日
- char 与 unsigned char的本质区别