功能: 通过一个ioctl控制4个LED灯的开关
myled.c
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/fcntl.h> #include <asm/io.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/device.h> #include <asm/uaccess.h> #define LED_MAJOR 242 #define LED_MINOR 0 #define NUMBER_OF_DEVICE 2 #define PIO_LED 0x00401420|0xE0000000 //encode cmd #define LED_MAGIC 'x' #define LED_OP _IOW(LED_MAGIC,0,int) #define LED_MAX_NR 0 struct class *led_class; static struct cdev cdev; dev_t devno; static int led_ioctl(struct file *file,unsigned int cmd,unsigned long arg) { if(_IOC_TYPE(cmd)!=LED_MAGIC) return -EINVAL; //check cmd if(_IOC_NR(cmd)>LED_MAX_NR) return -EINVAL; switch(cmd){ case LED_OP: if(arg>15||arg<0){ printk("arg is %u, wrong! OUT OF RANGE!\n", arg); break; } writeb(arg, PIO_LED); break; default: return -EINVAL; } return 0; } static ssize_t led_open(struct inode *inode, struct file *file) { return 0; } static struct file_operations led_fops= { .owner=THIS_MODULE, .open = led_open, .unlocked_ioctl=led_ioctl, //important after kernel 2.6.36 }; static int led_init(void) { int ret; devno = MKDEV(LED_MAJOR,LED_MINOR); if(LED_MAJOR){ ret=register_chrdev_region(devno,NUMBER_OF_DEVICE,"leddev"); }else{ ret = alloc_chrdev_region(&devno,0, NUMBER_OF_DEVICE, "leddev"); } if(ret<0){ printk("%s",__func__); return ret; } led_class = class_create(THIS_MODULE,"led_char_class"); if(IS_ERR(led_class)){ printk("%s create class error\n",__func__); return -1; } device_create(led_class, NULL, devno, NULL, "leddev"); cdev_init(&cdev, &led_fops); cdev.owner = THIS_MODULE; cdev_add(&cdev, devno, NUMBER_OF_DEVICE); return 0; } static void led_exit(void) { printk("%s",__func__); cdev_del(&cdev); device_destroy(led_class,devno); class_destroy(led_class); unregister_chrdev_region(devno,NUMBER_OF_DEVICE); } module_init(led_init); module_exit(led_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kimi Shi");
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/ioctl.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #define LED_MAGIC 'x' #define LED_OP _IOW(LED_MAGIC,0,int) #define LED_MAX_NR 0 int main(int argc,char **argv) { int fd, LED_DATA; //Format: test_led LED_DATA if(argc!=2 || sscanf(argv[1],"%d",&LED_DATA)!=1 ||LED_DATA<0 ||LED_DATA>15){ //4-bit led printf("input is wrong!\n"); exit(1); } fd=open("/dev/leddev",O_WRONLY); //output only if(fd<0) { perror("open leds device"); exit(1); } if(ioctl(fd, LED_OP, LED_DATA)) printf("Call led_ioctl failed!"); close(fd); return 0; }