平台:
全志A20
Android4.2.2 Linux3.4
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //定义virt_to_phys接口
#include //remap_pfn_range
#define FIFO_SIZE 128
static int DEV_MAJOR = 1222;
static int DEV_MINOR = 0;
static struct class *cdrv_class;
static struct device *cdrv_class_dev;
static struct cdev *c_cdev;
static char *buff;
#if 0
typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) c_fifo;
static c_fifo cdrv_fifo;
#else
struct kfifo_rec_ptr_1 cdrv_fifo;
#endif
static const char *expected_buff1[] = {
"aaaaaaaaaa",
"bbbbbbbbbb",
"cccccccccc",
"dddddddddd",
"eeeeeeeeee",
"ffffffffff",
"gggggggggg",
"hhhhhhhhhh",
};
static const char *expected_buff2[] = {
"iiiiiiiiii",
"jjjjjjjjjj",
"kkkkkkkkkk",
"llllllllll",
"mmmmmmmmmm",
"nnnnnnnnnn",
"oooooooooo",
"pppppppppp",
};
static const char *expected_buff3 = "abcdefghijk";
static const char *expected_buff4 = "lmnopqrstuvwxyz";
#define pagesSIZE 4096
static wait_queue_head_t creadq;
static int flag = 0;
static int wakeMe = 0;
static struct task_struct *tsk;
static int c_open(struct inode *inode,struct file *filp){
//filp->private_data = buff;
buff = (char *)kmalloc(pagesSIZE,GFP_KERNEL);
if(!buff){
printk("kmalloc err \n");
return -1;
}
memset(buff,'\0',pagesSIZE);
return 0;
}
static int c_release(struct inode *inode,struct file *filp){
if(buff){
kfree(buff);
}
return 0;
}
static ssize_t c_read(struct file *filp,char *buf,size_t len,loff_t *off){
#if 0
if(copy_to_user(buf,filp->private_data,strlen(filp->private_data))){
return -EFAULT;
}
#else
int ret;
unsigned int copied;
ret = kfifo_to_user(&cdrv_fifo,buf,len,&copied);
return sizeof(filp->private_data);
#endif
return ret?ret:copied;
}
static ssize_t c_write(struct file *filp,const char *buf,size_t len,loff_t *off){
#if 0
memset(filp->private_data,0,strlen(filp->private_data));
if(copy_from_user(filp->private_data,buf,strlen(buf))){
return -EFAULT;
}
return sizeof(buf);
#else
int ret;
unsigned int copied;
ret = kfifo_from_user(&cdrv_fifo,buf,len,&copied);
return ret?ret:copied;
#endif
}
#if 0
static int fifo_handler(void){
int i;
for(i=0;ivm_flags |= VM_IO;
vma->vm_flags |= VM_RESERVED;
if(remap_pfn_range(vma,//虚拟内存区域,即设备地址将要映射到这里
vma->vm_start,//虚拟空间的起始地址
virt_to_phys(buff)>>PAGE_SHIFT,//与物理内存对应的页帧号,物理地址右移12位
vma->vm_end - vma->vm_start,//映射区域大小,一般是页大小的整数倍
vma->vm_page_prot))//保护属性,
{
return -EAGAIN;
}
//memcpy((void *)buff,"dddddd8",8);
return 0;
}
static int isReadyToWakeup(void *data){
int i,ret;
printk("kthread is in \n");
for(i=0;iops = &c_fops;
c_cdev->owner = THIS_MODULE;
err = cdev_add(c_cdev,devno,1);
if(err<0){
printk("cdev_add err \n");
goto cdev_add_err;
}
cdrv_class = class_create(THIS_MODULE,"c_drv");
cdrv_class_dev = device_create(cdrv_class,NULL,MKDEV(DEV_MAJOR,DEV_MINOR),NULL,"cdrv-%d",0);
if(!cdrv_class_dev){
printk("device create err \n");
goto device_create_err;
}
init_waitqueue_head(&creadq);
#if 0
INIT_KFIFO(cdrv_fifo);
#else
err = kfifo_alloc(&cdrv_fifo, FIFO_SIZE, GFP_KERNEL);
if (ret) {
printk(KERN_ERR "error kfifo_alloc\n");
goto kfifo_alloc_err;
}
#endif
#if 0
err = fifo_handler();
if(err){
printk("fifo_handler err \n");
return err;
}
#endif
tsk = kthread_run(isReadyToWakeup,NULL,"thread_isReadyToWakeup");
if(NULL == tsk){
printk("kthread created failed \n");
goto kthread_run_err;
}
printk("init is ok \n\n");
return 0;
kthread_run_err:
kfifo_free(&cdrv_fifo);
kfifo_alloc_err:
device_unregister(cdrv_class_dev);
device_create_err:
class_destroy(cdrv_class);
cdev_del(c_cdev);
cdev_add_err:
kfree(c_cdev);
cdev_alloc_err:
unregister_chrdev_region(devno,1);
return err;
}
static void __exit c_exit(void){
dev_t devno = MKDEV(DEV_MAJOR,DEV_MINOR);
if(tsk){
kthread_stop(tsk);
}
kfifo_free(&cdrv_fifo);
device_unregister(cdrv_class_dev);
class_destroy(cdrv_class);
cdev_del(c_cdev);
kfree(c_cdev);
unregister_chrdev_region(devno,1);
}
module_init(c_init);
module_exit(c_exit);
MODULE_LICENSE("GPL");
用户测设程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MBUFF_SIZE 20
int main()
{
char *mbuff;
int fd,i;
fd_set rfds;
struct timeval tv;
fd=open("/dev/cdrv-0",O_RDWR,S_IRUSR | S_IWUSR);
if(fd == -1){
perror("open");
return -1;
}
mbuff = mmap(NULL,MBUFF_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(mbuff != NULL){
printf("mbuff: %p \n",mbuff);
//puts(mbuff);
}
else{
puts("mbuff: err");
return -1;
}
while(1){
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
tv.tv_sec = 5;
tv.tv_usec = 0;
select(fd+1,&rfds,NULL,NULL,&tv);//最后一个参数设为NULL,将会永远等待,即阻塞!
if(FD_ISSET(fd,&rfds)){
puts("The new data is:");
puts(mbuff);
// memset(mbuff,'\0',MBUFF_SIZE);
}else{
printf("No data within 5s,please wait.. \n",&tv.tv_sec);
}
sleep(3);
}
munmap(mbuff,MBUFF_SIZE);
close(fd);
return 0;
}
测试截图: