#include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/fcntl.h> #include <linux/cdev.h> #include <asm/system.h> #include <asm/uaccess.h>
int scull_major = 0; int scull_minor = 0; int scull_num = 1;
module_param(scull_major, int , S_IRUGO); module_param(scull_minor, int , S_IRUGO); module_param(scull_num, int, S_IRUGO);
MODULE_LICENSE("Dual BSD/GPL");
struct scull_dev{ struct cdev cdev; struct semaphore sem; };
struct scull_dev *scull_devices;
static int scull_init_module(void); ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); ssize_t scull_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); int scull_open(struct inode *inode, struct file *filp); int scull_release(struct inode *inode, struct file *filp); static void scull_setup_cdev(struct scull_dev *dev, int index);
struct file_operations scull_fops = { .owner = THIS_MODULE, .read = scull_read, .write = scull_write, .open = scull_open, .release = scull_release, };
static int scull_init_module(void) { int result, i; //int err;
//int devt = MKDEV(scull_major, scull_minor);
dev_t dev = 0; printk(KERN_ALERT "init\n");
if(scull_major) { dev = MKDEV(scull_major, scull_minor); result = register_chrdev_region(dev, scull_num, "scull"); } else { result = alloc_chrdev_region(&dev, scull_minor, scull_num, "scull"); scull_major = MAJOR(dev); }
if(result < 0) { printk(KERN_ALERT "scull: can't get major d\n", scull_major); return result; }
scull_devices = kmalloc(sizeof(struct scull_dev), GFP_KERNEL); if(!scull_devices) { result = -ENOMEM; goto fail; }
memset(scull_devices, 0, sizeof(struct scull_dev));
scull_setup_cdev(scull_devices, 0); //cdev_init(&(scull_devices->cdev), &scull_fops);
//scull_devices->cdev.owner = THIS_MODULE;
//scull_devices->cdev.ops = &scull_fops;
//err = cdev_add(&(scull_devices->cdev), devt, 1);
//printk(KERN_ALERT "add\n");
//if(err)
//{
// printk(KERN_ALERT "add failed\n");
//}
return 0;
fail: return result;
}
static void scull_setup_cdev(struct scull_dev *dev, int index) { int err, devno = MKDEV(scull_major, scull_minor+index); cdev_init(&dev->cdev, &scull_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &scull_fops; err = cdev_add(&dev->cdev, devno, 1);
if(err) {printk(KERN_ALERT "Error adding scull\n");} }
static void scull_cleanup_module(void) {
dev_t devno = MKDEV(scull_major, scull_minor);
printk(KERN_ALERT "clean\n");
if(scull_devices) { cdev_del(&(scull_devices->cdev)); } kfree(scull_devices);
unregister_chrdev_region(devno, 1); }
int scull_open(struct inode *inode, struct file *filp) { struct scull_dev *dev; printk(KERN_ALERT "opne1\n");
dev = container_of(inode->i_cdev, struct scull_dev, cdev); filp->private_data = dev;
printk(KERN_ALERT "open\n");
if((filp->f_flags & O_ACCMODE) == O_WRONLY) { printk(KERN_ALERT "write only\n"); }
return 0; }
int scull_release(struct inode *inode, struct file *filp) { printk(KERN_ALERT "release\n"); return 0; }
ssize_t scull_read(struct file *filp, char __user *data, size_t total, loff_t *f_pos) { ssize_t retval = 10; struct scull_dev *dev = filp->private_data; printk(KERN_ALERT "read\n");
return retval; }
ssize_t scull_write(struct file *filp, char __user *data, size_t total, loff_t *f_pos) { struct scull_dev *dev = filp->private_data; ssize_t retval = 40; printk(KERN_ALERT "write\n");
return retval; }
module_init(scull_init_module); module_exit(scull_cleanup_module);
|