应用层代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
int x = 0;
char buf[128]={0};
int fd = open("/dev/mycdev", O_RDWR);
if (fd < 0)
{
printf("创建设备文件失败\n");
return -1;
}
printf("创建设备文件成功\n");
while (1)
{
memset(buf,0,sizeof(buf));//清空
printf("请输入1关灯,2开灯,3退出\n");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';
printf("输入的数据长度:%d\n",strlen(buf));
switch (buf[0])
{
case '1':
printf("进入case1\n");
x = write(fd,buf,sizeof(buf));
if (x<0)
{
printf("写入设备文件失败\n");
return -1;
}
break;
case '2':
printf("进入case2\n");
x = write(fd,buf,sizeof(buf));
if (x<0)
{
printf("写入设备文件失败\n");
return -1;
}
break;
case '3':
printf("进入case3\n");
goto OUT;
break;
default:
printf("进入case4\n");
printf("请输入正确内容\n");
break;
}
}
OUT:
close(fd);
return 0;
}
驱动层代码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/wait.h>
#include <linux/device.h>
char kbuf[128] = {0};
struct resource *res = NULL;
int res1 = -1;
struct gpio_desc *gpiono;
unsigned int major;
struct class *cls;
struct device *dev;
//open函数
int mycdev_open(struct inode*inode,struct file*file)
{
printk("驱动文件创立成功\n");
return 0;
}
//write函数
ssize_t mycdev_write(struct file* file,const char *ubuf,size_t size,loff_t* loff)
{
int ret;
ret=copy_from_user(kbuf,ubuf,size);
if(ret)
{
printk("驱动从用户获取信息失败\n");
return -EIO;
}
printk("驱动获取用户信息成功\n");
if('1'==kbuf[0])
gpiod_set_value(gpiono,0);
else if('2'==kbuf[0])
gpiod_set_value(gpiono,1);
return 0;
}
//close函数
int mycdev_close(struct inode* inode, struct file* file)
{
printk("设备文件已被关闭\n");
return 0;
}
//定义操作方法结构体
struct file_operations fops={
.open=mycdev_open,
.write=mycdev_write,
.release=mycdev_close,
};
// 定义相关成员函数
// 匹配完成后需要执行的函数
int pdrv_probe(struct platform_device *pdev)
{
// 匹配完成后需要获取设备的资源结构体
printk("%d\n", __LINE__);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (NULL == res)
{
printk("获取设备文件结构体失败\n");
return -ENOMEM; //???
}
printk("获取设备结构体文件成功\n");
printk("%d\n", __LINE__);
// 获取设备的中断资源结构体
res1 = platform_get_irq(pdev, 0);
if (res1 < 0)
{
printk("获取中断信息结构体失败\n");
return -ENOMEM;
}
printk("获取终端信息结构体成功\n");
// 解析gpio编号
printk("%d\n", __LINE__);
gpiono = gpiod_get_from_of_node(pdev->dev.of_node, "led1", 0, GPIOD_OUT_LOW, NULL);
if (IS_ERR(gpiono))
{
printk("gpio设备解析失败\n");
return -PTR_ERR(gpiono);
}
gpiod_set_value(gpiono, 0);
printk("gpio信息解释成功\n");
printk("设备匹配完成%d\n", __LINE__);
return 0;
}
// 在驱动中创建一个用于设备树匹配的表
struct of_device_id oftable[] = {
{.compatible = "hqyj,myplatform"},
{.compatible = "hqyj,myplatform1"},
{.compatible = "hqyj,myplatform2"},
{},
};
// remove用于设备分离时执行
int pdrv_remove(struct platform_device *pdev)
{
// 关灯
gpiod_set_value(gpiono, 0);
// 释放设备驱动文件
gpiod_put(gpiono);
printk("驱动文件移除完毕\n");
return 0;
}
// 分配对象并初始化
struct platform_driver pdrv = {
.probe = pdrv_probe,
.remove = pdrv_remove,
.driver = {
.name = "name",
.of_match_table = oftable,
},
};
static int __init mycdev_init(void)
{
major=register_chrdev(0,"mycdev",&fops);
if(major<0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功\n");
//向上提交目录
cls=class_create(THIS_MODULE,"mycdev");
if(IS_ERR(cls))
{
printk("向上提交目录失败\n");
return -PTR_ERR(cls);
}
printk("向上提交目录成功\n");
//向上提交设备节点信息
dev=device_create(cls,NULL,MKDEV(major,0),NULL,"mycdev");
if(IS_ERR(dev))
{
printk("向上提交设备节点失败\n");
return -PTR_ERR(dev);
}
printk("向上提交设备节点成功\n");
platform_driver_register(&pdrv);//对象的注册
return 0;
}
static void __exit mycdev_exit(void)
{
//销毁设备节点信息
device_destroy(cls,MKDEV(major,0));
//销毁目录空间
class_destroy(cls);
//字符设备驱动的注销
unregister_chrdev(major,"mycdev");
platform_driver_unregister(&pdrv);//对象的注销
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");