前言
Ubuntu系统版本:12.04
Android源码文件夹名:aosp
Goldfish内核文件夹名:goldfish
项目工程名:Tslights
本项目使用多寄存器变量存取
程序运行效果:
1.1 底层驱动程序代码编写
文件结构
~/goldfish2.6.29/drivers
-----tslights.h
-----tslights.c
-----Kconfig
-----Makefile
tslights.h
#ifndef _FAKE_REG_H_
#define _FAKE_REG_H_
#include <linux/cdev.h>
#include <linux/semaphore.h>
#define TSLIGHTS_DEVICE_NODE_NAME "tslights"
#define TSLIGHTS_DEVICE_FILE_NAME "tslights"
#define TSLIGHTS_DEVICE_PROC_NAME "tslights"
#define TSLIGHTS_DEVICE_CLASS_NAME "tslights"
struct tslights_dev {
int red_init;//红灯状态值
int red_time;//红灯时间
int green_init;
int green_time;
int yellow_init;
int yellow_time;
};
#endif
tslights.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 "tslights.h"
static int tslights_major = 0;
static int tslights_minor = 0;
static struct cdev rdev; // 定义字符设备
static struct class* tslights_class = NULL;
static struct tslights_dev* tslightsdev = NULL;
static char tslights_buff[256];
static ssize_t tslights_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {
copy_to_user((struct tslights_dev __user *)buf, tslightsdev, sizeof(struct tslights_dev));
return 0;
}
static ssize_t tslights_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {
copy_from_user(tslightsdev, (struct tslights_dev __user *)buf, count);
return 0;
}
static struct file_operations tslights_ops = {
.owner = THIS_MODULE,
.read = tslights_read,
.write = tslights_write,
};
static ssize_t tslights_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data) {
if(off > 0) {
*eof = 1;
return 0;
}
int len;
int* red_init = (int*)kmalloc(64, GFP_KERNEL);
int* red_time = (int*)kmalloc(64, GFP_KERNEL);
int* green_init = (int*)kmalloc(64, GFP_KERNEL);
int* green_time = (int*)kmalloc(64, GFP_KERNEL);
int* yellow_init = (int*)kmalloc(64, GFP_KERNEL);
int* yellow_time = (int*)kmalloc(64, GFP_KERNEL);
sprintf(red_init, "%d", tslightsdev->red_init);
sprintf(red_time, "%d", tslightsdev->red_time);
sprintf(green_init, "%d", tslightsdev->green_init);
sprintf(green_time, "%d", tslightsdev->green_time);
sprintf(yellow_init, "%d", tslightsdev->yellow_init);
sprintf(yellow_time, "%d", tslightsdev->yellow_time);
memset(tslights_buff, 0, 256);
strcat(tslights_buff,"red state:");
strcat(tslights_buff,red_init);
strcat(tslights_buff," red time:");
strcat(tslights_buff,red_time);
strcat(tslights_buff,"green state:");
strcat(tslights_buff,green_init);
strcat(tslights_buff," green time:");
strcat(tslights_buff,green_time);
strcat(tslights_buff,"yellow state:");
strcat(tslights_buff,yellow_init);
strcat(tslights_buff," yellow time:");
strcat(tslights_buff,yellow_time);
kfree(red_init);
kfree(red_time);
kfree(green_init);
kfree(green_time);
kfree(yellow_init);
kfree(yellow_time);
len=sprintf(page,tslights_buff);
return len;
}
static ssize_t tslights_proc_write(struct file* filp, const char __user *buff, unsigned long len, void* data) {
return 0;
}
static void tslights_create_proc(void) {
struct proc_dir_entry* entry;
entry = create_proc_entry(TSLIGHTS_DEVICE_PROC_NAME, 0, NULL);
if(entry) {
entry->owner = THIS_MODULE;
entry->read_proc = tslights_proc_read;
entry->write_proc = tslights_proc_write;
}
}
static void tslights_remove_proc(void) {
remove_proc_entry(TSLIGHTS_DEVICE_PROC_NAME, NULL);
}
// 初始化模块时操作
static int __init tslights_init(void)
{
int result;
dev_t dev = 0;
tslightsdev = (struct tslights_dev*) kmalloc(sizeof(struct tslights_dev), GFP_KERNEL);
alloc_chrdev_region(&dev, 0, 1, TSLIGHTS_DEVICE_NODE_NAME);
tslights_major = MAJOR(dev);
tslights_minor = MINOR(dev);
cdev_init(&rdev, &tslights_ops);
result = cdev_add(&rdev, dev, 1);
tslights_create_proc();
tslightsdev->green_init=1;
tslightsdev->yellow_init=0;
tslightsdev->red_init = 0;
tslightsdev->green_time=10;
tslightsdev->yellow_time=3;
tslightsdev->red_time=8;
tslights_class = class_create(THIS_MODULE, TSLIGHTS_DEVICE_CLASS_NAME);
struct device* RCtemp = device_create(tslights_class, NULL, dev, "%s", TSLIGHTS_DEVICE_FILE_NAME); // 创建一个字符结点文件
if (result < 0) goto add_err;
return 0;
add_err:
unregister_chrdev_region(dev, 1);
return -1;
}
// 卸载模块时操作
static void __exit tslights_exit(void)
{
dev_t dev = MKDEV(tslights_major, tslights_minor);
tslights_remove_proc();
cdev_del(&rdev);
kfree(tslightsdev);
unregister_chrdev_region(dev, 1);
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("TSLights Register Driver");
module_init(tslights_init);
module_exit(tslights_exit);
Kconfig
config TSLIGHTS
tristate "Tslights Register Driver"
default n
help
This is the tslights driver for android system.
Makefile
obj-$(CONFIG_TSLIGHTS) += tslights.o
1.2 修改内核Kconfig文件
打开arch/arm/Kconfig文件
在这两行之间
menu "Device Drivers"
.....
endmenu
插入 source "drivers/tslgihts/Kconfig"
1.3 修改内核Makefile文件
打开drivers/Makefile文件,在里面添加以下一行内容:
......
obj-$(CONFIG_TSLIGHTS)+=tslights/
1.4 编译内核驱动程序模块
在goldfish目录下执行 make menuconfig命令来配置它的编译方式
选择 "Device Drivers" 回车
选择 Fake Register Driver项按Y键
配置完成后保存编译配置,退出make menuconfig命令。
接着执行 ./build_kernel.sh命令
1.5 编写硬件抽象层模块接口
文件结构:
~/aosp/hardware/libhardware
-----include/hardware
tslights.h
-----modules/tslights
tslights.cpp
android.mk
tslights.h
#ifndef ANDROID_TSLIGHTS_INTERFACE_H
#define ANDROID_TSLIGHTS_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS
/**
* The id of this module
*/
#define TSLIGHTS_HARDWARE_MODULE_ID "tslights"