/* char.c *字符设备驱动模板,用于快速建立驱动框架 */ #include <linux/module.h> /*__init, __exit, module_init*/ #include <linux/types.h> /* size_t */ #include <linux/fs.h> /*file_operations*/ #include <linux/cdev.h> /*stuct cdev*/
#include "char.h" static int xxx_major = 0; static int xxx_minor = 0;
struct xxx_devt { struct cdev cdev; //....
}xxx_dev; static ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct xxx_devt *dev=filp->private_data;/*读取私有数据*/ //... copy_to_user();/*设备到用户空间*/ //...
} static ssize_t xxx_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct xxx_devt *dev=filp->private_data;/*读取私有数据*/ //... copy_from_user();/*用户空间到设备*/ //...
} static int xxx_open(struct inode *inode, struct file *filp) { filp->private_data = &xxx_dev;/*私有数据指针传递数据*/ //... } static int xxx_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd, unsigned long arg) { int err = 0; int retval; int tmp; /* don't even decode wrong cmds: better returning ENOTTY than EFAULT */ if (_IOC_TYPE(cmd) != XXX_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > XXX_IOC_MAXNR) return -ENOTTY; switch(cmd) { case XXX_IOCRESET: reset(); break; case XXX_IOCGQUANTUM: retval = __put_user(tmp, (int __user *)arg);/*把数据从驱动传到用户空间*/ break; case XXX_IOCSQSET: if (! capable (CAP_SYS_ADMIN)) return -EPERM; retval = __get_user(tmp, (int __user *)arg);/*把数据从用户空间传到驱动*/ break; case XXX_IOCXQSET: if (! capable (CAP_SYS_ADMIN)) return -EPERM; retval = __get_user(tmp, (int __user *)arg); if(retval == 0) retval = __put_user(tmp, (int __user *)arg); break; default: return -ENOTTY; } } static struct file_operations xxx_fops = { .owner =THIS_MODULE, .read =xxx_read, .write =xxx_write, .open =xxx_open, .ioctl =xxx_ioctl, // .close =xxx_close,
}; static int __init xxx_init(void) { int rt; int count=1; dev_t dev; if(xxx_major) /*获取设备号*/ { dev = MKDEV(xxx_major,xxx_minor); rt = register_chrdev_region(dev, count, "xxx"); } else { rt = alloc_chrdev_region(&dev, xxx_minor, count, "xxx"); xxx_major = MAJOR(dev); } if(rt < 0) printk(KERN_WARNING"Major Error!\n");
dev = MKDEV(xxx_major, 0); cdev_init(&xxx_dev.cdev, &xxx_fops); xxx_dev.cdev.owner = THIS_MODULE; xxx_dev.cdev.ops = &xxx_fops; rt = cdev_add(&xxx_dev.cdev, dev, count); if( rt ) { printk(KERN_WARNING"Cdev Add Error!\n"); cdev_del(&xxx_dev.cdev); return -1; } return 0; }
static void __exit xxx_exit(void) { cdev_del(&xxx_dev.cdev); unregister_chrdev_region(MKDEV (xxx_major, xxx_minor), 1); }
module_init(xxx_init); module_exit(xxx_exit);
MODULE_AUTHOR("gfy @ CQUPT"); MODULE_DESCRIPTION("Character Driver Model"); MODULE_LICENSE("GPL");
|