perled.c
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #define DEVICE_NAME "myled" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */ static struct class *leds_class; static struct class *led_dev_class; int major; /* 应用程序对设备文件/dev/leds执行open(...)时, * 就会调用s3c24xx_leds_open函数 */ static int led_open (struct inode *inode, struct file *filep) { // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能 s3c2410_gpio_cfgpin( S3C2410_GPF6, S3C2410_GPF5_OUTP); return 0; } static ssize_t led_write(struct file *file, const char __user *data, size_t len, loff_t * ppos) { int val; copy_from_user(&val, data, 1); // copy_to_user(); s3c2410_gpio_setpin(S3C2410_GPF5, (val & 0x1));//避免使用if语句 return 1; } /* 这个结构是字符设备驱动程序的核心 * 当应用程序操作设备文件时所调用的open、read、write等函数, * 最终会调用这个结构中指定的对应函数 */ static struct file_operations led_ops= { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = led_open, .write = led_write, }; /* * 执行insmod命令时就会调用这个函数 */ static int led_init(void) { int ret; /* 注册字符设备 * 参数为主设备号、设备名字、file_operations结构; * 这样,主设备号就和具体的file_operations结构联系起来了, * 操作主设备为LED_MAJOR的设备文件时,就会调用s3c24xx_leds_fops中的相关成员函数 * LED_MAJOR可以设为0,表示由内核自动分配主设备号 */ major = register_chrdev(0, DEVICE_NAME, &led_ops); if (major < 0) { printk(DEVICE_NAME " can't register major number number::%d\n",major); return ret; } printk(DEVICE_NAME " initialized1\n"); leds_class = class_create(THIS_MODULE, "leds"); if (IS_ERR(leds_class)) return PTR_ERR(leds_class); led_dev_class = class_device_create(leds_class, NULL, MKDEV(major, 0), NULL, "perled"); /* /dev/leds */ return 0; } /* * 执行rmmod命令时就会调用这个函数 */ static void led_exit(void) { class_device_unregister(led_dev_class, MKDEV(major, 0)); class_destroy(leds_class); /* 卸载驱动程序 */ unregister_chrdev(major, DEVICE_NAME); } module_init(led_init); module_exit(led_exit); MODULE_AUTHOR("http://www.100ask.net"); MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver"); MODULE_LICENSE("GPL");
test.c
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <sys/ioctl.h> /* * ledtest <dev> <on|off> */ void print_usage(char *file) { printf("Usage:\n"); printf("%s <dev> <on|off>\n",file); printf("eg. \n"); printf("%s /dev/leds on\n", file); printf("%s /dev/leds off\n", file); printf("%s /dev/led1 on\n", file); printf("%s /dev/led1 off\n", file); } int main(int argc,char**argv) { int fd; int ret; int num=1; char val; if(argc!=2) { printf("error USAGE\n"); exit(1); } //1、打开设备 fd = open("/dev/perled",O_RDWR); if(fd<0) { perror("open fail \n"); return -1; } if (!strcmp("on", argv[1])) { // 亮灯 val = 0; write(fd, &val, 1); } else if (!strcmp("off", argv[1])) { // 灭灯 val = 1; write(fd, &val, 1); } else { print_usage(argv[0]); return 0; } close(fd); return 0; }