功能: 通过一个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");
test_led.c
#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;
}