NIOS2 uCLinux-mmu驱动之LED

功能: 通过一个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;
}




你可能感兴趣的:(NIOS2 uCLinux-mmu驱动之LED)