⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drv.c

📁 s3c2410的很多驱动实验
💻 C
字号:
/****************************************** *  这是一段含有基本功能的字符设备的驱动程序 *	$$$$  运行在内核空间 *	其中调用ioctl()将会点亮或熄灭LED灯 * *****************************************/#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/errno.h> 	/* for -EBUSY */#include <linux/ioport.h>	/* for verify_area */#include <linux/init.h>		/* for module_init */#include <asm/uaccess.h>  	/* 在/home/cvtech/jx2410/linux/include 							下可以找到 put[get]_user()及copy_to[from]_user() */#include <asm/io.h>  	    /* 输入输出口的地址映射 */#include <asm-arm/arch-s3c2410/S3C2410.h>#include "drv.h"#define 	BUF_LEN 		4#define 	DEVICE_NAME 	"char_dev"static int  Device_Open = 0;static int trans = 0;	//一个全局变量:用于read()和write()交换信息volatile unsigned long *led_addr;	//ioremap()需要这样定义int device_ioctl(struct inode *,struct file *,unsigned int ,unsigned long ); 	/**************************************   *	当一个过程要打开设备文件总是要调用这个函数 *	(对应于用户层的open()函数) * *************************************/static int device_open(struct inode *inode, struct file *file){	led_addr = ioremap(0x10000000,4);	//将物理地址映射到led_addr		printk("the address of led_addr is: 0x%p\n",led_addr);		//看看地址为多少	printk("Device Open!\n");		//打印一句信息	if (Device_Open) return -EBUSY;	//此语句是为了防止重复进入本子程序	Device_Open++;		return 0;}/**************************************   *	当一个过程要关闭设备文件就一定会调用本函数 *	该函数无返回值,因为它不能失败 *	(对应于用户层的close()函数) * *************************************/static int device_release(struct inode *inode, struct file *file){	printk(("Device released\n"));	Device_Open --;		// 准备下一次调用		iounmap( (void *)led_addr);	//释放用过的空间		return 0;}/**************************************   *	当一个过程要从一个已经打开的设备文件读取 *	就一定会调用本函数 * *************************************/static ssize_t device_read(struct file *file,	char *buffer,		// 数据缓冲变量	size_t length,     	// 缓冲变量的字节数	loff_t *offset) 	// 设备文件的offset {		printk("Device read %d\n", trans);	//put_user(trans, buffer);  				// 该函数的功能:把内核空间的数据放到用户空间	copy_to_user(buffer, &trans, sizeof trans);	// 该函数的功能:把内核空间的数据放到用户空间   	return 4;}/**************************************   *	当一个过程要对一个已经打开的设备文件进行写 *	就一定会调用本函数 * *************************************/static ssize_t device_write(struct file *file,    const char *buffer,		// 数据缓冲变量	size_t length,     		// 缓冲变量的字节数	loff_t *offset) 		// 设备文件的offset{		//get_user(trans, buffer);						// 该函数的功能:把用户空间的数据放到内核空间		copy_from_user(&trans,buffer, sizeof trans);	// 该函数的功能:把用户空间的数据放到内核空间		printk("Device write %d\n", trans);	return 4;};/********************************************** *	当一个过程要对一个已经打开的设备文件进行I/o控制 *	就一定会调用本函数. *	 *********************************************/int device_ioctl(    struct inode *inode,    struct file *file,    unsigned int ioctl_num,		// ioctl的功能参数,在用户层指定    unsigned long ioctl_param)	// 用户传过来的数{	int *data;	//定义一个指针	printk(("Device_\n"));  	switch(ioctl_num) 	{		case IOCTL_SET_MSG:	//接收到一个信息指针(在用户空间)用于对设备进行设置      		data = (int *)ioctl_param;	//只能以这种方式获取用户传来的数据  		printk("Device ioctl SET_MSG %d\n",*data );		*led_addr = (*data)<<4;//输出到led灯				break;				case IOCTL_GET_MSG:						printk(("Device_ioctl PUT_MSG\n"));		break;	}		return 0;};/**************************************   *	模块声明:需要用到的函数的指针 *	 *************************************/struct file_operations Fops = {	.read 		= device_read, 	.write 		= device_write,	.open 		= device_open,	.release 	= device_release,	.ioctl		= device_ioctl	};// 初始化模块: 注册字符设备static int __init led_module_init( void ){	int ret_val;  	// 注册字符设备	ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);	// 若值为负则表示错误	if (ret_val < 0) 	{    	printk ("%s failed with %d\n",            "Sorry, registering the character device ",            ret_val);    	return ret_val;	}  	printk ("%s The major device number is %d.\n",          "Registeration is a success",           MAJOR_NUM);            	printk ("If you want to talk to the device driver,\n");  	printk ("you'll have to create a device file. \n");  	printk ("We suggest you use:\n");  	printk ("mknod /dev/%s c %d 0\n", DEVICE_FILE_NAME,MAJOR_NUM);  	printk ("The device file name is important, because\n");  	printk ("the ioctl program assumes that's the\n");  	printk ("file you'll use.\n");	return 0;};// 卸载字符设备: rmmod命令将会调用本函数static void __exit led_module_cleanup(void){	int ret;			//  release_region(LED_BASE, 12);	// 注销字符设备	ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME); 	//  如果有错则报告	if (ret < 0)		printk("Error in module_unregister_chrdev: %d\n", ret);	else		printk("Close the char device OK!\n");};module_init(led_module_init);		//insmod命令调用module_exit(led_module_cleanup);	//rmmod命令调用MODULE_LICENSE("GPL");MODULE_AUTHOR("Cvtech Co., Ltd <http://www.cvtech.com.cn>");MODULE_DESCRIPTION("LED char driver");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -