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