记smarthome驱动,包括测试程序
来源:互联网 发布:blingbelle 知乎 编辑:程序博客网 时间:2024/06/08 13:30
//Environment : ubuntu 10.04
//tool : gcc
//platform : i386 machine
//smarthome.c
// ====================================================#include<linux/module.h>#include<linux/init.h>#include<linux/types.h>#include<linux/fs.h>#include<linux/seq_file.h>#include<linux/proc_fs.h>#include<linux/errno.h>#include<linux/mm.h>#include<linux/sched.h>#include<linux/init.h>#include<linux/cdev.h>#include<asm/io.h>#include<asm/system.h>#include<asm/uaccess.h>#define DEV_ON 1#define DEV_OFF 0#define LIGHTNUM 6#define TVNUM 1#define AIRCONDNUM 4#define HUGNUM 10#define DEV_SUM LIGHTNUM + TVNUM + AIRCONDNUM + HUGNUM#define MEM_CLEAR 0x01#define SMARHOMEDEV_MAJOR 0//using dynamic majorstatic int SmartHomeDevice_major = SMARHOMEDEV_MAJOR;int SmartHomeDevice_nr_devs =1;typedef struct _tagSmartHomeDevice{struct cdev cdev; char lightsSwitch[LIGHTNUM]; char TVSwitch[TVNUM]; char AirCondSwitch[AIRCONDNUM]; char Hug[HUGNUM];}SmartHomeDevice;SmartHomeDevice *pSmartHomeDev;static loff_t SmartHomeDevice_llseek(struct file *filp,loff_t offset,int orig);static void SmartHomeDevice_setup_cdev(SmartHomeDevice *dev,int index);static ssize_t SmartHomeDevice_read(struct file * flip, char __user* buf,size_t count,loff_t *ppos);static ssize_t SmartHomeDevice_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos);static int SmartHomeDevice_ioctl(struct inode *inodep, struct file *filp,unsigned int cmd, unsigned long arg);static int SmartHomeDevice_open(struct inode *inode, struct file *filp);static const struct file_operations SmartHomeDevice_fops = { .owner = THIS_MODULE,.open = SmartHomeDevice_open, .llseek = SmartHomeDevice_llseek, .read = SmartHomeDevice_read, .write = SmartHomeDevice_write, .ioctl = SmartHomeDevice_ioctl};static int SmartHomeDevice_open(struct inode *inode, struct file *filp){ filp->private_data = pSmartHomeDev; return 0;} static int SmartHomeDevice_ioctl(struct inode *inodep, struct file *filp,unsigned int cmd, unsigned long arg){ //SmartHomeDevice *dev = filp->private_data; switch(cmd){ case MEM_CLEAR: //memset(dev->mem,0,GLOBALMEM_SIZE); printk(KERN_INFO "SmartHomeDevice is set to zero \n"); break; default: return -EINVAL; } return 0;} static void SmartHomeDevice_setup_cdev(SmartHomeDevice* dev , int index){ int err,devno=MKDEV(SmartHomeDevice_major,index); cdev_init(&dev->cdev,&SmartHomeDevice_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops= &SmartHomeDevice_fops; err= cdev_add(&dev->cdev,devno,1); if(err) printk(KERN_NOTICE "ERROR %d adding SmartHomeDevice",err);} static ssize_t SmartHomeDevice_read(struct file * filp, char __user* buf,size_t count,loff_t *ppos){unsigned long p = *ppos; int ret =0;SmartHomeDevice *dev = filp->private_data; if(p >= DEV_SUM) return count? -ENXIO : 0; if(p >= DEV_SUM- p){ count = DEV_SUM-p; } if(copy_to_user(buf,(void*)(dev->lightsSwitch+ p),count)){ret= -EFAULT;} else{ *ppos += count; ret = count; } return ret;} static ssize_t SmartHomeDevice_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos){unsigned long p = *ppos;char* pChar= 0; int ret = 0 ,i =0; SmartHomeDevice *dev = filp->private_data;if(dev == NULL){return 0;} if(p >= DEV_SUM){ return count? -ENXIO :0; } if(count > DEV_SUM - p){ count = DEV_SUM - p; }if(copy_from_user(dev->lightsSwitch + p,buf,count)){ ret = -EFAULT; } else{ *ppos =+ count; ret = count; printk(KERN_INFO "written %d bytes from %ld \n", count ,p);pChar = dev->lightsSwitch;for(i=0;((i<count) && (pChar != NULL));i++,pChar++){switch(*pChar){case DEV_OFF: printk("write OFF data \n");break;case DEV_ON: printk("write ON data \n");break;default: printk("write error data \n"); break;}} }return ret;} static loff_t SmartHomeDevice_llseek(struct file *filp,loff_t offset,int orig){ loff_t ret = 0; switch(orig) { case 0: if(offset <0 ){ ret = -EINVAL; break; } if((unsigned int )offset > DEV_SUM){ ret = - EINVAL; break; } filp->f_pos = (unsigned int)offset; ret = filp->f_pos; break; case 1: if((filp->f_pos+ offset) > DEV_SUM){ ret = -EINVAL; break; } if((filp->f_pos+ offset)<0) { ret = -EINVAL; break; } filp->f_pos += offset; ret = filp->f_pos; break; default: ret = -EINVAL; break; }return ret;} int SmartHomeDevice_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data) {//int i, j, len = 0;//int limit = count - 80; /* Don't print more than this *///struct SmartHomeDevice_dev *d = pSmartHomeDev;//*eof = 1;return 0;} /* * Here are our sequence iteration methods. Our "position" is * simply the device number. */ static void *SmartHomeDevice_seq_start(struct seq_file *s, loff_t *pos) {if (*pos >= SmartHomeDevice_nr_devs)return NULL; /* No more to read */return pSmartHomeDev + *pos; } static void *SmartHomeDevice_seq_next(struct seq_file *s, void *v, loff_t *pos){(*pos)++;if (*pos >= SmartHomeDevice_nr_devs)return NULL;return pSmartHomeDev + *pos;}static void SmartHomeDevice_seq_stop(struct seq_file *s, void *v){/* Actually, there's nothing to do here */}static int SmartHomeDevice_seq_show(struct seq_file *s, void *v){//struct SmartHomeDevice_dev *dev = (struct SmartHomeDevice_dev *) v;//struct SmartHomeDevice_qset *d;//int i;//seq_printf(s, "\nDevice %i: qset %i, q %i, sz %li\n",// 1000, 800,// 120, 110);return 0;} /* * Tie the sequence operators up. */ static struct seq_operations SmartHomeDevice_seq_ops = { .start = SmartHomeDevice_seq_start, .next = SmartHomeDevice_seq_next, .stop = SmartHomeDevice_seq_stop, .show = SmartHomeDevice_seq_show }; /* * Now to implement the /proc file we need only make an open * method which sets up the sequence operators. */ static int SmartHomeDevice_proc_open(struct inode *inode, struct file *file) {return seq_open(file, &SmartHomeDevice_seq_ops); } /* * Create a set of file operations for our proc file. */ static struct file_operations SmartHomeDevice_proc_ops = {.owner = THIS_MODULE,.open = SmartHomeDevice_proc_open,.read = seq_read,.llseek = seq_lseek,.release = seq_release }; //===========Create proc file ===========static void SmartHomeDevice_create_proc(void){struct proc_dir_entry *entry;entry = create_proc_read_entry("SmartHomeDevice", 0 /* default mode */,NULL /* parent dir */, SmartHomeDevice_read_procmem,NULL /* client data */);if (entry)entry->proc_fops = &SmartHomeDevice_proc_ops;}//================================int SmartHomeDevice_init(void){int result;dev_t devno = MKDEV(SmartHomeDevice_major,0);if(SmartHomeDevice_major){result = register_chrdev_region(devno,1,"smarthome");}else{result = alloc_chrdev_region(&devno,0,1,"smarthome"); SmartHomeDevice_major = MAJOR(devno);} if(result<0){ return result; }pSmartHomeDev = kmalloc(sizeof(SmartHomeDevice), GFP_KERNEL);if (!pSmartHomeDev){ result = -ENOMEM;goto fail_malloc;}memset(pSmartHomeDev,0,sizeof(SmartHomeDevice));SmartHomeDevice_setup_cdev(pSmartHomeDev,0);//SmartHomeDevice_create_proc(); //we don't need proc debugreturn 0;fail_malloc:unregister_chrdev_region(devno, 1); return result;}void SmartHomeDevice_exit(void){ cdev_del(&pSmartHomeDev->cdev);kfree(pSmartHomeDev); unregister_chrdev_region(MKDEV(SmartHomeDevice_major,0),1);}MODULE_AUTHOR("NOBODY");MODULE_LICENSE("GPL");module_param(SmartHomeDevice_major,int,S_IRUGO);module_init(SmartHomeDevice_init);module_exit(SmartHomeDevice_exit);
//================makefile=========================
KERN_DIR := /lib/modules/$(shell uname -r)/buildOBJ := smarthome.oall:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m += $(OBJ)
//======================testFile.c==================#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#define LIGHTNUM 6#define TVNUM 1#define AIRCONDNUM 4#define HUGNUM 10#define DEV_SUM LIGHTNUM + TVNUM + AIRCONDNUM + HUGNUM/* * testfile <dev> <on|off> */void print_usage(char *file){ printf("Usage:\n"); printf("%s <dev> <device nmae> <number> <on|off>\n",file); printf("device name is :light/TV/air-condtion/hug"); printf("eg. \n"); printf("%s /dev/smarthome light 0 on\n", file); printf("%s /dev/smarthome TV 0 on\n", file); printf("%s /dev/smarthome air-condition 0 on\n", file); printf("%s /dev/smarthome hug 0 on\n", file);}int main(int argc, char **argv){ int fd;char* filename;char lightsSwitch[LIGHTNUM]={0,0,0,0,0,0};char TVSwitch[TVNUM]={0};char AirCondSwitch[AIRCONDNUM]={0,0,0,0};char HugSwitch[HUGNUM]={0,0,0,0,0,0};int num,i; if (argc != 5) { print_usage(argv[0]); return 0; } filename = argv[1]; fd = open(filename, O_RDWR); if (fd < 0) { printf("error, can't open %s\n", filename); return 0; } if (!strcmp("light", argv[2])) { num=atoi(argv[3]);if(!strcmp("on", argv[4])){lightsSwitch[num] = 1;}else lightsSwitch[num] = 0;for(i=0;i<LIGHTNUM;i++){printf("lightswtich[%d] = %d \n " , i , lightsSwitch[i]);} write(fd, lightsSwitch, LIGHTNUM,0); } else if (!strcmp("TV", argv[2])) { num=atoi(argv[3]); if(!strcmp("on", argv[4])){TVSwitch[num] = 1;}else TVSwitch[num] = 0; write(fd, TVSwitch, TVNUM,LIGHTNUM); } else if (!strcmp("air-condition", argv[2])) { num=atoi(argv[3]); if(!strcmp("on", argv[4])){AirCondSwitch[num] = 1;}else AirCondSwitch[num] = 0; write(fd, AirCondSwitch, AIRCONDNUM,TVNUM+LIGHTNUM); } else if (!strcmp("hug", argv[2])) { num=atoi(argv[3]); if(!strcmp("on", argv[4])){HugSwitch[num] = 1;}else HugSwitch[num] = 0; write(fd, HugSwitch, AIRCONDNUM,TVNUM+LIGHTNUM+AIRCONDNUM); } return 0;}//====================编译驱动文件============================$ make$ sudo insmod smarthome.ko$ cat /proc/devices250 smarthome//创建 dev 节点$ sudo mknod /dev/smarthome c 250 0//=====================编译testFile.c============================$ gcc -c testFile.c$ gcc -o testFile testFile.o//============================运行测试程序======================//使用root权限运行$ sudo ./testFile /dev/smarthome air-condition 3 on//==============查看打印信息===================================/使用root权限$ cd /var/logroot@ubuntu:/var/log# echo > kern.log root@ubuntu:/var/log# cat kern.log Oct 15 01:31:58 ubuntu kernel: [27769.446685] written 4 bytes from 0 Oct 15 01:31:58 ubuntu kernel: [27769.446692] write OFF data //0Oct 15 01:31:58 ubuntu kernel: [27769.446694] write OFF data //1Oct 15 01:31:58 ubuntu kernel: [27769.446696] write OFF data //2Oct 15 01:31:58 ubuntu kernel: [27769.446697] write ON data // 3 this is on PS:BUG:我们看到写入的位置都是0开始的,所以write的最后一个参数根本没用,写不了指定的位置,于是查看write的原型:定义函数 ssize_t write (int fd,const void * buf,size_t count); ssize_t write (int fd,const void * buf,size_t count);故第四个参数根本没用,在查询,发现还有pwrite的这个函数:原型ssize_t pwrite(unsigned int fd, const char __user *buf,size_t count, loff_t pos)我编译出来的ARM版本的是这样子的:// linux/fs/read_write.cwrite:内核实现asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count){struct file *file;ssize_t ret = -EBADF;int fput_needed;file = fget_light(fd, &fput_needed);if (file) {loff_t pos = file_pos_read(file);ret = vfs_write(file, buf, count, &pos);file_pos_write(file, pos);fput_light(file, fput_needed);}return ret;}pwrite:内核实现asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf, size_t count, loff_t pos){struct file *file;ssize_t ret = -EBADF;int fput_needed;if (pos < 0)return -EINVAL;file = fget_light(fd, &fput_needed);if (file) {ret = -ESPIPE;if (file->f_mode & FMODE_PWRITE) ret = vfs_write(file, buf, count, &pos);fput_light(file, fput_needed);}return ret;}
// linux/include/asm-arm/unistd.h
//系统调用确实这样子调用,这些函数都是有固定位置的
#define __NR_restart_syscall(__NR_SYSCALL_BASE+ 0)
#define __NR_exit (__NR_SYSCALL_BASE+ 1)
#define __NR_fork (__NR_SYSCALL_BASE+ 2)
#define __NR_read (__NR_SYSCALL_BASE+ 3)
#define __NR_write (__NR_SYSCALL_BASE+ 4)
#define __NR_open (__NR_SYSCALL_BASE+ 5)
#define __NR_close (__NR_SYSCALL_BASE+ 6)
#define __NR_exit (__NR_SYSCALL_BASE+ 1)
#define __NR_fork (__NR_SYSCALL_BASE+ 2)
#define __NR_read (__NR_SYSCALL_BASE+ 3)
#define __NR_write (__NR_SYSCALL_BASE+ 4)
#define __NR_open (__NR_SYSCALL_BASE+ 5)
#define __NR_close (__NR_SYSCALL_BASE+ 6)
具体不做讨论!
可以看到pwrite是带文件位置的访问,所以只要把测试代码中的write改为pwrite即可指定四个参数的文件对应位置写入数据了!
编译测试:
root@ubuntu:/home/liqinghan/workspace/smartHome# ./testFile /dev/smarthome air-condition 2 on
root@ubuntu:/home/liqinghan/workspace/smartHome# tail /var/log/kern.log
Oct 15 20:22:21 ubuntu kernel: [ 6881.225695] written 4 bytes from 7
Oct 15 20:22:21 ubuntu kernel: [ 6881.225701] write OFF data
Oct 15 20:22:21 ubuntu kernel: [ 6881.225704] write OFF data
Oct 15 20:22:21 ubuntu kernel: [ 6881.225705] write ON data
Oct 15 20:22:21 ubuntu kernel: [ 6881.225707] write OFF data
//
0 0
- 记smarthome驱动,包括测试程序
- SmartHome
- SmartHome
- ds18b20 驱动测试程序
- UVC驱动测试程序
- Watchdog驱动测试程序
- 按键驱动测试程序
- led驱动测试程序
- Android环境 驱动测试程序
- 驱动测试程序的编写
- Linux触摸屏驱动测试程序
- Android环境下直接测试驱动 | 链接的目录视图包括很多嵌入式驱动技术 | 不错
- mini2440的ds18b20驱动和测试程序
- Linux: 输入设备驱动测试程序
- V4L2 camera 驱动 capture测试程序
- mini2440的ds18b20驱动和测试程序
- linxu s3c2440 LCD驱动 测试程序
- Android S5PV210 camera驱动测试程序
- ant简介
- 距离才是最美的风景
- C++调用约定和名字约定
- 微软封杀泄露密钥 YouTube视频遭误删
- C语言的inline关键字
- 记smarthome驱动,包括测试程序
- Tomcat配置solr
- android4.4以上版本获取图片的uri
- 从USB获得高效的双轨电源
- 为数据表对象(NSManagedObject)添加排序
- linux命令的使用
- google code 多用户下提交代码
- solr解析请求
- js 分页技术