- #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");

