嵌入式Linux的gpio做dido输入输出驱动

分享份关于Linux的dido驱动

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/gpio.h>

////////////////////////////////////////////////////////////////////////////////
#define di1 32
#define di2 33
#define di3 34
#define di4 35
#define do1 64
#define do2 65
#define do3 66
#define do4 67

static struct class *shaohuawlw_dido;
static struct device *di_device;
static struct device *do_device;

////////////////////////////////////////////////////////////////////////////////
// di1
static ssize_t get_di1(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(di1);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_di1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(di1, value);
    return count;
}
static DEVICE_ATTR(di1, 0664, get_di1, set_di1);

// di2
static ssize_t get_di2(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(di2);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_di2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(di2, value);
    return count;
}
static DEVICE_ATTR(di2, 0664, get_di2, set_di2);

// di3
static ssize_t get_di3(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(di3);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_di3(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(di3, value);
    return count;
}
static DEVICE_ATTR(di3, 0664, get_di3, set_di3);

// di4
static ssize_t get_di4(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(di4);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_di4(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(di4, value);
    return count;
}
static DEVICE_ATTR(di4, 0664, get_di4, set_di4);

////////////////////////////////////////////////////////////////////////////////
// do1
static ssize_t get_do1(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(do1);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_do1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(do1, value);
    return count;
}
static DEVICE_ATTR(do1, 0664, get_do1, set_do1);

// do2
static ssize_t get_do2(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(do2);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_do2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(do2, value);
    return count;
}
static DEVICE_ATTR(do2, 0664, get_do2, set_do2);

// do3
static ssize_t get_do3(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(do3);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_do3(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(do3, value);
    return count;
}
static DEVICE_ATTR(do3, 0664, get_do3, set_do3);

// do4
static ssize_t get_do4(struct device *dev, struct device_attribute *attr, char *buf)
{
    int value = gpio_get_value(do4);
    return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
static ssize_t set_do4(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int value;
    sscanf(buf, "%d", &value);
    gpio_set_value(do4, value);
    return count;
}
static DEVICE_ATTR(do4, 0664, get_do4, set_do4);

static int __init dido_init(void)
{
    // 创建设备类
    shaohuawlw_dido = class_create(THIS_MODULE, "dido"); // CLASS_NAME
    if (IS_ERR(shaohuawlw_dido))
	{
        printk(KERN_ALERT "===== DIDO Failed to create class\n");
        return PTR_ERR(shaohuawlw_dido);
    }

    // 创建设备节点
    di_device = device_create(shaohuawlw_dido, NULL, MKDEV(0, 0), NULL, "di"); // DEVICE_NAME
    do_device = device_create(shaohuawlw_dido, NULL, MKDEV(0, 0), NULL, "do"); // DEVICE_NAME
    if (IS_ERR(di_device))
	{
        printk(KERN_ALERT "===== DIDO Failed to create device\n");
        class_destroy(shaohuawlw_dido);
        return PTR_ERR(di_device);
    }
    if (IS_ERR(do_device))
	{
        printk(KERN_ALERT "===== DIDO Failed to create device\n");
        class_destroy(shaohuawlw_dido);
        return PTR_ERR(do_device);
    }
	
    // 添加设备属性
	// di
	device_create_file(di_device, &dev_attr_di1);
	device_create_file(di_device, &dev_attr_di2);
	device_create_file(di_device, &dev_attr_di3);
	device_create_file(di_device, &dev_attr_di4);
	//do
	device_create_file(do_device, &dev_attr_do1);
	device_create_file(do_device, &dev_attr_do2);
	device_create_file(do_device, &dev_attr_do3);
	device_create_file(do_device, &dev_attr_do4);
	/*
    if (device_create_file(di_device, &dev_attr_do1) < 0)
	{
        printk(KERN_ALERT "===== DIDO Failed to create device attribute\n");
        device_destroy(shaohuawlw_dido, MKDEV(0, 0));
        class_destroy(shaohuawlw_dido);
        return -ENOMEM;
    }
    if (device_create_file(do_device, &dev_attr_do1) < 0)
	{
        printk(KERN_ALERT "===== DIDO Failed to create device attribute\n");
        device_destroy(shaohuawlw_dido, MKDEV(0, 0));
        class_destroy(shaohuawlw_dido);
        return -ENOMEM;
    }
	*/
	
    // 初始化 GPIO 端口
	//di
	gpio_request(di1, "di1");
	gpio_request(di2, "di2");
	gpio_request(di3, "di3");
	gpio_request(di4, "di4");
	gpio_direction_input(di1);
	gpio_direction_input(di2);
	gpio_direction_input(di3);
	gpio_direction_input(di4);
	// do
	gpio_request(do1, "do1");
	gpio_request(do2, "do2");
	gpio_request(do3, "do3");
	gpio_request(do4, "do4");
	gpio_direction_output(do1, 0);
	gpio_direction_output(do2, 0);
	gpio_direction_output(do3, 0);
	gpio_direction_output(do4, 0);
	/*
    if (gpio_request(di1, "my_gpio") < 0)
	{
        printk(KERN_ALERT "===== DIDO Failed to request GPIO pin\n");
        device_remove_file(shaohuawlw_dido, &dev_attr_do1_state);
        device_destroy(shaohuawlw_dido, MKDEV(0, 0));
        class_destroy(shaohuawlw_dido);
        return -ENODEV;
    }
	*/
	
    printk(KERN_INFO "===== DIDO Device created\n");
    return 0;
}

static void __exit dido_exit(void)
{
    // 释放 GPIO 端口
    gpio_free(di1);
    gpio_free(di2);
    gpio_free(di3);
    gpio_free(di4);
    gpio_free(do1);
    gpio_free(do2);
    gpio_free(do3);
    gpio_free(do4);

    // 移除设备属性
	// di
    device_remove_file(di_device, &dev_attr_di1);
    device_remove_file(di_device, &dev_attr_di2);
    device_remove_file(di_device, &dev_attr_di3);
    device_remove_file(di_device, &dev_attr_di4);
	// do
    device_remove_file(do_device, &dev_attr_do1);
    device_remove_file(do_device, &dev_attr_do2);
    device_remove_file(do_device, &dev_attr_do3);
    device_remove_file(do_device, &dev_attr_do4);
	
    // 销毁设备节点
    device_destroy(shaohuawlw_dido, MKDEV(0, 0));

    // 销毁设备类
    class_destroy(shaohuawlw_dido);

    printk(KERN_INFO "===== DIDO Device destroyed\n");
}

module_init(dido_init);
module_exit(dido_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("shaohuawlw");
MODULE_DESCRIPTION("shaohuawlw-dido device driver");

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐