22071.11.24

#ifndef __LED_H__
#define __LED_H__
#define LED_ON _IOW('a',1,int)
#define LED_OFF _IOW('a',0,int)
typedef enum 
{
    LED1,
    LED2,
    LED3,
    LED4,
    LED5,
    LED6
}led_t;
 
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "led.h"
 
int main(int argc, char const *argv[])
{
    int fd1 = -1;
    int fd2 = -1;
    int fd3 = -1;
    int fd4 = -1;
    int fd5 = -1;
    int fd6 = -1;
    int whitch;
    //打开6个led设备文件
    fd1 = open("/dev/myled0",O_RDWR);
    if(-1==fd1)
    {
        perror("open fd1 is error");
        exit(1);
    }
    fd2 = open("/dev/myled1",O_RDWR);
    if(-1==fd2)
    {
        perror("open fd2 is error");
        exit(1);
    }
    fd3 = open("/dev/myled2",O_RDWR);
    if(-1==fd3)
    {
        perror("open fd3 is error");
        exit(1);
    }
    fd4 = open("/dev/myled3",O_RDWR);
    if(-1==fd4)
    {
        perror("open fd4 is error");
        exit(1);
    }
    fd5 = open("/dev/myled4",O_RDWR);
    if(-1==fd5)
    {
        perror("open fd5 is error");
        exit(1);
    }
    fd6 = open("/dev/myled5",O_RDWR);
    if(-1==fd6)
    {
        perror("open fd6 is error");
        exit(1);
    }
    while(1)
    {
        whitch=LED1;
        ioctl(fd1,LED_ON,&whitch);
        sleep(1);
        ioctl(fd1,LED_OFF,&whitch);
        sleep(1);
 
        whitch=LED2;
        ioctl(fd2,LED_ON,&whitch);
        sleep(1);
        ioctl(fd2,LED_OFF,&whitch);
        sleep(1);
 
        whitch=LED3;
        ioctl(fd3,LED_ON,&whitch);
        sleep(1);
        ioctl(fd3,LED_OFF,&whitch);
        sleep(1);
 
        whitch=LED4;
        ioctl(fd4,LED_ON,&whitch);
        sleep(1);
        ioctl(fd4,LED_OFF,&whitch);
        sleep(1);
 
        whitch=LED5;
        ioctl(fd5,LED_ON,&whitch);
        sleep(1);
        ioctl(fd5,LED_OFF,&whitch);
        sleep(1);
 
        whitch=LED6;
        ioctl(fd6,LED_ON,&whitch);
        sleep(1);
        ioctl(fd6,LED_OFF,&whitch);
        sleep(1);
    }
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd5);
    close(fd6);
    return 0;
}

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h> 
#include <linux/slab.h>
#include "led.h"
#define CNAME "myled"

struct device_node *node;
struct gpio_desc *gpio1;
struct gpio_desc *gpio2;
struct gpio_desc *gpio3;
struct gpio_desc *gpio4;
struct gpio_desc *gpio5;
struct gpio_desc *gpio6;
int ret;
struct cdev* cdev; //字符设备结构体指针
dev_t devno;
struct class* cls;
struct device* devt;
#if 1
unsigned int major = 0; //动态申请设备号
#else
unsigned int major = 500;
#endif
int minor = 0;
const int count = 6;
int mycdev_open(struct inode *inode,struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
long mycdev_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{
    int ret;
    int whitch;
    switch(cmd)
    {
    case LED_ON:
        ret = copy_from_user(&whitch,(void*)arg,sizeof(int));
        if(ret)
        {
            printk("copy from user led on...");
            return -EIO;
        }
        switch(whitch)
        {
            case LED1:
            gpiod_set_value(gpio1,1);
            break;
            case LED2:
            gpiod_set_value(gpio2,1);
            break;
            case LED3:
            gpiod_set_value(gpio3,1);
            break;
            case LED4:
            gpiod_set_value(gpio4,1);
            break;
            case LED5:
            gpiod_set_value(gpio5,1);
            break;
            case LED6:
            gpiod_set_value(gpio6,1);
            break;
        }
    break;
    case LED_OFF:
        ret = copy_from_user(&whitch,(void*)arg,sizeof(int));
        if(ret)
        {
            printk("copy from user led off...");
            return -EIO;
        }
        switch(whitch)
        {
            case LED1:
            gpiod_set_value(gpio1,0);
            break;
            case LED2:
            gpiod_set_value(gpio2,0);
            break;
            case LED3:
            gpiod_set_value(gpio3,0);
            break;
            case LED4:
            gpiod_set_value(gpio4,0);
            break;
            case LED5:
            gpiod_set_value(gpio5,0);
            break;
            case LED6:
            gpiod_set_value(gpio6,0);
            break;
        }
    break;
    }
    return 0;
}
int mycdev_close(struct inode *inode,struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}
const struct file_operations fops = {
        .open = mycdev_open,
        .unlocked_ioctl = mycdev_ioctl,
        .release = mycdev_close,
};
//进出口
static int __init mycdev_init(void)
{ 
    int i;
    int error;  
    cdev = cdev_alloc();
    if(NULL==cdev)
    {
        printk("cdev alloc is error...\n");
        error = -EIO;
        goto ERR1;
    }
    cdev_init(cdev,&fops);
    if(major>0)
    {
        //静态指定设备号
        error = register_chrdev_region(MKDEV(major,minor),count,CNAME);
        if(error)
        {
            printk("register chrdev region is error ...\n");
            error = -ENOMEM;
            goto ERR2;
        }
    }
    else
    {
        //动态申请设备号
        error = alloc_chrdev_region(&devno,0,count,CNAME);
        if(error)
        {
            printk("alloc chadev region is error ...\n");
            error = -ENOMEM;
            goto ERR2;
        }
        major = MAJOR(devno);
        minor = MINOR(devno); 
    }
    error = cdev_add(cdev,MKDEV(major,minor),count);
    if(error)
    {
        printk("cdev add is error...\n");
        error = -EIO;
        goto ERR3;
    }
    //自动创建设备节点
    cls = class_create(THIS_MODULE,CNAME);
    if(IS_ERR(cls))
    {
        printk("class create is error ...\n");
        error = PTR_ERR(cls);
        goto ERR4;
    }
    for(i=0;i<count;i++)
    {
        devt = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);
        if(IS_ERR(devt))
        {
            printk("device create is error ...\n");
            error = PTR_ERR(devt);
            goto ERR5;
        }
    }
    node=of_find_node_by_name(NULL,"myleds");
    if(node==NULL)
    {
        printk("find node error\n");
        return -EFAULT;
    }
    printk("find node success\n");
    //获取并申请gpio编号
    gpio1 = gpiod_get_from_of_node(node,"myled1",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpio1))
    {
        printk("get gpio1 error\n");
        return PTR_ERR(gpio1);
    }
    gpiod_direction_output(gpio1,0);

    gpio2 = gpiod_get_from_of_node(node,"myled2",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpio2))
    {
        printk("get gpio2 error\n");
        return PTR_ERR(gpio2);
    }
    gpiod_direction_output(gpio2,0);

    gpio3 = gpiod_get_from_of_node(node,"myled3",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpio3))
    {
        printk("get gpio3 error\n");
        return PTR_ERR(gpio3);
    }
    gpiod_direction_output(gpio3,0);
    
    gpio4 = gpiod_get_from_of_node(node,"myled4",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpio4))
    {
        printk("get gpio4 error\n");
        return PTR_ERR(gpio4);
    }
    gpiod_direction_output(gpio4,0);

    gpio5 = gpiod_get_from_of_node(node,"myled5",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpio5))
    {
        printk("get gpio5 error\n");
        return PTR_ERR(gpio5);
    }
    gpiod_direction_output(gpio5,0);

    gpio6 = gpiod_get_from_of_node(node,"myled6",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpio6))
    {
        printk("get gpio6 error\n");
        return PTR_ERR(gpio6);
    }
    gpiod_direction_output(gpio6,0);
    return 0;
//跳转接口
ERR5:
    for(--i;i>=0;i--)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    class_destroy(cls);
ERR4:
    cdev_del(cdev);
ERR3:
    unregister_chrdev_region(MKDEV(major,minor),count);
ERR2:
    kfree(cdev);
ERR1:
    return -EIO;
}
static void __exit mycdev_exit(void)
{
    int i;
    //注销
    gpiod_set_value(gpio1,0);
    gpiod_set_value(gpio2,0);
    gpiod_set_value(gpio3,0);
    gpiod_set_value(gpio4,0);
    gpiod_set_value(gpio5,0);
    gpiod_set_value(gpio6,0);
    gpiod_put(gpio1);
    gpiod_put(gpio2);
    gpiod_put(gpio3);
    gpiod_put(gpio4);
    gpiod_put(gpio5);
    gpiod_put(gpio6);
 
    //1。销毁设备节点信息
    for(i=0;i<count;i++)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    //2.销毁目录信息
    class_destroy(cls);
    //3.驱动的注销
    cdev_del(cdev);
    //4.销毁设备号
    unregister_chrdev_region(MKDEV(major,minor),count);
    //5.释放cdev结构体
    kfree(cdev);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值