linux设备驱动——一个驱动如何管理多个设备

来源:互联网 发布:windows下打tar包 编辑:程序博客网 时间:2024/05/20 10:15
/* * 说明:用于演示一个驱动如何管理多个设备。 */#include <linux/init.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/cdev.h>#include <linux/slab.h>#include <linux/uaccess.h>#include "ioctl.h"#define FSDEV_MAJOR250#defineFSDEV_MINOR0#define FSDEV_NR2#define FSDEV_NAME"fsdev"struct fsdev {struct cdev cdev;unsigned char buf[256];};static struct fsdev *fsdev[FSDEV_NR];static int fschr_open(struct inode *inode, struct file *filp){struct fsdev *fsdev;/* 根据保存在inode节点中的cdev指针,反向查询到包含该cdev的结构体, * 将该结构体指针保存在打开的文件结构体的私有数据中,可以在之后 * 的read、write以及ioctl当中通过file结构体指针顺利获得反查得到的 * 结构体指针,这是实现一个驱动管理多个设备的关键 */fsdev = container_of(inode->i_cdev, struct fsdev, cdev);filp->private_data = fsdev;return 0;}static int fschr_close(struct inode *inode, struct file *filp){return 0;}static ssize_t fschr_read(struct file *filp, char __user *buf, size_t count, loff_t *fops){int len;int ret;struct fsdev *fsdev = filp->private_data;//通过filp的private_data得到是哪一个设备的操作len = count > 256 ? 256 : count;ret = copy_to_user(buf, fsdev->buf, len);return len - ret;}static ssize_t fschr_write(struct file *filp, const char __user *buf, size_t count, loff_t *fops){int len;int ret;struct fsdev *fsdev = filp->private_data;len = count > 256 ? 256 : count;ret = copy_from_user(fsdev->buf, buf, len);return len - ret;}static int fschr_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){int ret = 0;struct fsdev *fsdev = filp->private_data;if (_IOC_TYPE(cmd) != FS_IOC_MAGIC)return -ENOTTY;if (_IOC_NR(cmd) > FS_IOC_MAXNR)return -ENOTTY;if (_IOC_DIR(cmd) & _IOC_READ)ret = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));else if (_IOC_DIR(cmd) & _IOC_WRITE)ret =  !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));if (ret)return -EFAULT;switch (cmd) {case FS_IOC_SET_BUF:memset(fsdev->buf, *(char *)arg, sizeof(fsdev->buf));break;}return 0;}static struct file_operations fsfops = {.owner = THIS_MODULE,.open = fschr_open,.release = fschr_close,.read = fschr_read,.write = fschr_write,.ioctl = fschr_ioctl};static int __init fschr_init(void){int i;int ret;int alloc_num = 0;int add_num = 0;dev_t devno;devno = MKDEV(FSDEV_MAJOR, FSDEV_MINOR);ret = register_chrdev_region(devno, FSDEV_NR, FSDEV_NAME);if (ret) {printk(KERN_ERR "fschr: register chrdev region failed\n");goto reg_err;}for (i = 0; i < FSDEV_NR; i++){fsdev[i] = (struct fsdev *)kzalloc(sizeof(struct fsdev), GFP_KERNEL);if (!fsdev[i]) {printk(KERN_ERR "fschr: kzalloc failure\n");alloc_num = i;ret = -ENOMEM;goto alloc_err;}}alloc_num = FSDEV_NR;for (i = 0; i < FSDEV_NR; i++) {cdev_init(&fsdev[i]->cdev, &fsfops);fsdev[i]->cdev.owner = THIS_MODULE;ret = cdev_add(&fsdev[i]->cdev, devno + i, 1);if (ret) {printk(KERN_ERR "fschr: add cdev failed");add_num = i;goto add_err;}}return 0;add_err:for (i = 0; i < add_num; i++)cdev_del(&fsdev[i]->cdev);alloc_err:for (i = 0; i < alloc_num; i++)kfree(fsdev[i]);unregister_chrdev_region(devno, FSDEV_NR);reg_err:return ret;}static void __exit fschr_exit(void){int i;dev_t devno;devno = MKDEV(FSDEV_MAJOR, FSDEV_MINOR);for (i = 0; i < FSDEV_NR; i++)cdev_del(&fsdev[i]->cdev);for (i = 0; i < FSDEV_NR; i++)kfree(fsdev[i]);unregister_chrdev_region(devno, FSDEV_NR);}module_init(fschr_init);module_exit(fschr_exit);MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("xxxx<xxxx@xxxx.com>");MODULE_DESCRIPTION("Character device driver example for FSC100 development board");

ioctl.h

#ifndef __IOCTL__#define __IOCTL__#define FS_IOC_MAGIC'f'#define FS_IOC_MAXNR1#defineFS_IOC_SET_BUF_IOW(FS_IOC_MAGIC, 1, char)#endif



4 0
原创粉丝点击