#include <linux/module.h>
#include <linux/of.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "myled.h"
#define CNAME "myled"
int gpiono1;
int gpiono2;
int gpiono3;
int gpiono4;
int gpiono5;
int gpiono6;
char kbuf[128]={};
unsigned int major;
struct class *cls;//句柄
struct device *dev;
struct device_node *node;
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 whitch;
int ret;
// 1.判断命令码
switch (cmd)
{
case LED_ON:
// 2.将用户空间的数据传递给内核空间
ret = copy_from_user(&whitch, (void *)arg, sizeof(int));
if (ret)
{
printk("copy from user led on!!!!\n");
return -EIO;
}
switch (whitch) // 3.判断whitch的值
{
case LED1:
gpio_set_value(gpiono1, 1); // PE10点亮
break;
case LED2:
gpio_set_value(gpiono2, 1); // PE10点亮
break;
case LED3:
gpio_set_value(gpiono3, 1); // PE8点亮
break;
case LED4:
gpio_set_value(gpiono4, 1); // PZ5
break;
case LED5:
gpio_set_value(gpiono5, 1); // PZ6
break;
case LED6:
gpio_set_value(gpiono6, 1); // PZ7
break;
}
break;
case LED_OFF:
ret = copy_from_user(&whitch, (void *)arg, sizeof(int));
if (ret)
{
printk("copy from user led off!!!!\n");
return -EIO;
}
switch (whitch) // 3.判断whitch的值
{
case LED1:
gpio_set_value(gpiono1, 0); // PE10熄灭
break;
case LED2:
gpio_set_value(gpiono2, 0); // PE10熄灭
break;
case LED3:
gpio_set_value(gpiono3, 0); // PE8熄灭
break;
case LED4:
gpio_set_value(gpiono4, 0); // PZ5
break;
case LED5:
gpio_set_value(gpiono5, 0);// PZ6
break;
case LED6:
gpio_set_value(gpiono6, 0);// PZ7
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 demo_init(void)
{
int ret;
//动态注册字符设备驱动
major=register_chrdev(0,CNAME,&fops);
if(major<0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功major=%d\n",major);
//向上提交节点目录
cls=class_create(THIS_MODULE,"LED");
if(IS_ERR(cls))
{
printk("向上提交目录失败\n");
return PTR_ERR(cls);
}
printk("向上提交目录成功\n");
//创建设备节点
dev=device_create(cls,NULL,MKDEV(major,0),NULL,"myled");
if(IS_ERR(dev))
{
printk("创建节点失败\n");
return PTR_ERR(dev);
}
printk("创建节点成功\n");
node = of_find_node_by_path("/myleds");
if (NULL == node)
{
printk("获取节点设备失败\n");
return ENODATA;
}
printk("获取节点信息成功\n");
//led1
//获取GPIO编号
gpiono1 = of_get_named_gpio(node,"led1",0);
if(gpiono1<0)
{
printk("获取GPIO编号失败\n");
return ENODATA;
}
printk("获取GPIO编号成功\n");
//申请GPIO编号
ret = gpio_request(gpiono1,NULL);
if(ret<0)
{
printk("申请GPIO编号失败\n");
return ENODATA;
}
printk("申请GPIO编号成功\n");
//led2
//获取GPIO编号
gpiono2 = of_get_named_gpio(node,"led2",0);
if(gpiono2<0)
{
printk("获取GPIO编号失败\n");
return ENODATA;
}
printk("获取GPIO编号成功\n");
//申请GPIO编号
ret = gpio_request(gpiono2,NULL);
if(ret<0)
{
printk("申请GPIO编号失败\n");
return ENODATA;
}
printk("申请GPIO编号成功\n");
//led3
//获取GPIO编号
gpiono3 = of_get_named_gpio(node,"led3",0);
if(gpiono3<0)
{
printk("获取GPIO编号失败\n");
return ENODATA;
}
printk("获取GPIO编号成功\n");
//申请GPIO编号
ret = gpio_request(gpiono3,NULL);
if(ret<0)
{
printk("申请GPIO编号失败\n");
return ENODATA;
}
printk("申请GPIO编号成功\n");
//led4
//获取GPIO编号
gpiono4 = of_get_named_gpio(node,"led4",0);
if(gpiono4<0)
{
printk("获取GPIO编号失败\n");
return ENODATA;
}
printk("获取GPIO编号成功\n");
//申请GPIO编号
ret = gpio_request(gpiono4,NULL);
if(ret<0)
{
printk("申请GPIO编号失败\n");
return ENODATA;
}
printk("申请GPIO编号成功\n");
//led5
//获取GPIO编号
gpiono5 = of_get_named_gpio(node,"led5",0);
if(gpiono5<0)
{
printk("获取GPIO编号失败\n");
return ENODATA;
}
printk("获取GPIO编号成功\n");
//申请GPIO编号
ret = gpio_request(gpiono5,NULL);
if(ret<0)
{
printk("申请GPIO编号失败\n");
return ENODATA;
}
printk("申请GPIO编号成功\n");
//led6
//获取GPIO编号
gpiono6 = of_get_named_gpio(node,"led6",0);
if(gpiono6<0)
{
printk("获取GPIO编号失败\n");
return ENODATA;
}
printk("获取GPIO编号成功\n");
//申请GPIO编号
ret = gpio_request(gpiono6,NULL);
if(ret<0)
{
printk("申请GPIO编号失败\n");
return ENODATA;
}
printk("申请GPIO编号成功\n");
//设置输出方式
gpio_direction_output(gpiono1,0);
gpio_direction_output(gpiono2,0);
gpio_direction_output(gpiono3,0);
gpio_direction_output(gpiono4,0);
gpio_direction_output(gpiono5,0);
gpio_direction_output(gpiono6,0);
return 0;
}
//出口
static void __exit demo_exit(void)
{
//释放GPIO编号
gpio_free(gpiono1);
gpio_free(gpiono2);
gpio_free(gpiono3);
gpio_free(gpiono4);
gpio_free(gpiono5);
gpio_free(gpiono6);
//销毁节点
device_destroy(cls,MKDEV(major,0));
//销毁目录
class_destroy(cls);
//注销字符设备驱动
unregister_chrdev(major,CNAME);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");