驱动文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
unsigned int major = 0;
unsigned int minor = 0;
struct gpio_desc *gpioDesc;
struct class *clz;
struct device *dev;
unsigned int condition;
int number;
wait_queue_head_t wq_head;
ssize_t myDev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{
if (file->f_flags & O_NONBLOCK)
{
return -ENXIO;
}
else
{
wait_event_interruptible(wq_head, condition);
}
condition = 0;
int ret;
ret = copy_to_user(ubuf, (void *)&number, size);
if (ret)
{
printk("copy_to_user failed!\n");
return ret;
}
return 0;
}
struct file_operations fop = {
.read = myDev_read};
irqreturn_t my_handler(int irq, void *dev)
{
gpiod_set_value(gpioDesc, !gpiod_get_value(gpioDesc));
condition = 1;
wake_up_interruptible(&wq_head);
number = number == 0 ? 1 : 0;
return IRQ_HANDLED;
}
int drv_probe(struct platform_device *d)
{
printk("%s,%s,%d\n", __FILE__, __func__, __LINE__);
init_waitqueue_head(&wq_head);
major = register_chrdev(major, "myDev", &fop);
if (major < 0)
{
printk("注册字符设备失败\n");
goto OUT1;
}
printk("注册字符设备成功\n");
clz = class_create(THIS_MODULE, "myDev");
if (IS_ERR(clz))
{
printk("向上提交目录失败\n");
goto OUT2;
}
printk("向上提交目录成功\n");
dev = device_create(clz, NULL, MKDEV(major, minor), NULL, "myDev");
if (IS_ERR(dev))
{
printk("向上提交设备节点信息失败\n");
goto OUT3;
}
printk("向上提交设备节点信息成功\n");
struct resource *res = platform_get_resource(d, IORESOURCE_MEM, 0);
if (res == NULL)
{
printk("获取设备资源失败\n");
goto OUT4;
}
printk("获取设备资源成功\n");
int irqNo = platform_get_irq(d, 0);
if (irqNo < 0)
{
printk("获取软中断号失败\n");
goto OUT4;
}
printk("获取软中断号成功\n");
gpioDesc = gpiod_get_from_of_node(d->dev.of_node, "led1_gpio", 0, GPIOD_OUT_LOW, NULL);
if (gpioDesc == NULL)
{
printk("解析gpio节点失败\n");
goto OUT4;
}
printk("解析gpio节点成功\n");
int ret = request_irq(irqNo, my_handler, IRQF_TRIGGER_FALLING, "key1", NULL);
if (ret < 0)
{
printk("申请软中断号失败!\n");
goto OUT5;
}
printk("申请软中断号成功!\n");
return 0;
OUT5:
gpiod_put(gpioDesc);
OUT4:
device_destroy(clz, MKDEV(major, minor));
OUT3:
class_destroy(clz);
OUT2:
unregister_chrdev(MKDEV(major, minor), "myDev");
OUT1:
return -1;
}
int drv_remove(struct platform_device *d)
{
printk("%s,%s,%d\n", __FILE__, __func__, __LINE__);
gpiod_set_value(gpioDesc, 0);
gpiod_put(gpioDesc);
device_destroy(clz, MKDEV(major, minor));
class_destroy(clz);
unregister_chrdev(major, "myDev");
return 0;
}
struct of_device_id idtable[] = {
{
.compatible = "hqyj,myplatform",
},
{
.compatible = "hqyj,myplatform1",
},
{
.compatible = "hqyj,myplatform2",
},
{}};
struct platform_driver pdrv = {
.probe = drv_probe,
.remove = drv_remove,
.driver = {
.name = "aaaa",
.of_match_table = idtable},
};
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");
测试文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "head.h"
int main()
{
int number;
int fd = open("/dev/myDev", O_RDWR);
if (fd < 0)
{
perror("open failed!\n");
exit(-1);
}
while(1) {
read(fd,&number,sizeof(number));
printf("%d\n",number);
}
close(fd);
return 0;
}