字符驱动框架

发布时间 2023-12-19 20:48:27作者: zxz-FINE

Hello World

/*字符驱动框架*/
//*****************相关的头文件和宏定义*******************
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/version.h>

#define CLASS_NAME "char_cdev_class" /* 定义类名称 */
#define DEVICE_NAME "char_cdev"		 /* 定义设备名称 */

static int major = 232; /* 静态设备号方式的默认值 */
static int minor = 0;	/* 静态设备号方式的默认值 */
static dev_t devno;		/* 设备编号 */
static struct class *char_cdev_class;
module_param(major, int, S_IRUGO);
module_param(minor, int, S_IRUGO);

//*********** 文件操作接口函数定义 *********
398 static int char_cdev_open(struct inode *inode, struct file *filp)
{
	// 打开设备操作
	try_module_get(THIS_MODULE);
	printk(KERN_INFO DEVICE_NAME " opened!\n");
	return 0;
}

static int char_cdev_release(struct inode *inode, struct file *filp)
{
	// 关闭设备操作
	printk(KERN_INFO DEVICE_NAME " closed!\n");
	module_put(THIS_MODULE);
	return 0;
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
static long char_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	// 设备 I/O 控制
	printk(KERN_INFO DEVICE_NAME " ioctl method!\n");
	return 0;
}
#else
static int char_cdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	// 设备 I/O 控制
	printk(KERN_INFO DEVICE_NAME " ioctl method!\n");
	return 0;
}
#endif

static ssize_t char_cdev_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
	// 设备读操作
	printk(KERN_INFO DEVICE_NAME " read method!\n");
	return count;
}

static ssize_t char_cdev_write(struct file *filp, const char *buffer, size_t count, loff_t *ppos)
{
	// 设备写操作
	printk(KERN_INFO DEVICE_NAME " write method!\n");
	399 return count;
}

//*********** fops 文件操作结构体 *********
static struct file_operations char_cdev_fops = {
	.owner = THIS_MODULE,
	.open = char_cdev_open,
	.release = char_cdev_release,
	.read = char_cdev_read,
	.write = char_cdev_write,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
	.unlocked_ioctl = char_cdev_ioctl,
#else
	.ioctl = char_cdev_ioctl,
#endif
};

//**********设备驱动模块加载函数***********
static int char_cdev_init(void)
{
	int ret;
	/* 动态或静态申请设备号和注册设备 */
	ret = register_chrdev(major, DEVICE_NAME, &char_cdev_fops);
	if (major > 0) /* major=232,静态设备号 */
	{
		if (ret < 0) /* 申请、注册设备失败 */
		{
			printk(KERN_INFO " Can't get major number!\n");
			return ret;
		}
	}
	else /* major=0,动态设备号 */
	{
		printk(KERN_INFO " ret is %d\n", ret);
		major = ret; /* 保存动态获取到的主设备号 */
	}
	devno = MKDEV(major, minor);
	/* 在/sys/class/下创建 char_cdev_class 目录 */
	char_cdev_class = class_create(THIS_MODULE, CLASS_NAME);
	if (IS_ERR(char_cdev_class))
	{
		printk(KERN_INFO "create class error!\n");
		return -1;
	}
	400
		/* 将创建/dev/char_cdev 文件 */
		device_create(char_cdev_class, NULL, devno, NULL, DEVICE_NAME);
	printk(KERN_INFO "%s ok!\n", __func__);
	return ret;
}

//**********设备驱动模块卸载函数***********
static void char_cdev_exit(void)
{
	// 注销设备和释放设备号
	device_destroy(char_cdev_class, devno);
	class_destroy(char_cdev_class);
	unregister_chrdev(major, DEVICE_NAME);
	printk(KERN_INFO "%s\n", __func__);
}
module_init(char_cdev_init);
module_exit(char_cdev_exit);
//*********** 设备驱动许可证 ***********
MODULE_LICENSE("GPL");