?? sbc2410_leds.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 "cyc_io"static int Device_Open = 0;static int trans = 0; //一個全局變量:用于read()和write()交換信息volatile unsigned long *led_addr; //ioremap()需要這樣定義volatile unsigned long *led_con;volatile unsigned long *led_up;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(0x56000014,4); //將物理地址映射到led_addr led_con = ioremap(0x56000010,4); led_up = ioremap(0x56000018,4); *led_con = 0X15400; *led_up = 0; 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)<<7);//輸出到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 + -