Platform bus realizes LED lights turning on and off

head File

#ifndef __HEAD_H__
#define __HEAD_H__

#define LED_ON _IO('l', 1)
#define LED_OFF _IO('l', 0)
#endif

application code

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "head.h"

int main(int argc, char const *argv[])
{
    int fd = open("/dev/myled0", O_RDWR);
    if(fd < 0)
    {
        printf("Failed to open device file\
");
        return -1;
    }
    int a;
    while(1)
    {
        printf("Please choose to turn the lights on or off (0, turn off the lights) (1, turn the lights on)");
        scanf("%d", & amp;a);
        switch (a)
        {
        case 0:
            ioctl(fd, LED_OFF);
            break;
        case 1:
            ioctl(fd, LED_ON);
            break;
        default:
            break;
        }
    }
    return 0;
}

driver code

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include "head.h"

//Define variables, device driver objects
struct cdev *cdev;
//Define variables, major device number, minor device number, device number
unsigned int major = 0;
unsigned int minor = 0;
//Define variables to save the object pointer for submitting directory information upwards
struct class *cls;
//Define variables and submit the object pointer of device node information upwards
struct device *dev;
dev_t devno;
//Define variables, GOIO objects
struct gpio_desc *gpiono[3];

//Encapsulate the open method
int mycdev_open(struct inode *inode, struct file *file)
{
    return 0;
}
//Encapsulate close method
int mycdev_close(struct inode *inode, struct file *file)
{
   
    return 0;
}
//Encapsulate ioctl method
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
     switch(cmd)
    {
        int i;
        case LED_ON:
            for(i=0; i<3; i + + )
            {
                gpiod_set_value(gpiono[i], 1);
            }
            break;
        case LED_OFF:
            for(i=0; i<3; i + + )
            {
                gpiod_set_value(gpiono[i], 0);
            }
            break;

    }
    return 0;
}
//Encapsulation operation method structure
struct file_operations fop={
    .open = mycdev_open,
    .release = mycdev_close,
    .unlocked_ioctl = mycdev_ioctl,
};

 //Distribute registration device driver and create device file function statement
 int __register_file(void);
//Encapsulate the probe function, and the device information and driver information are matched successfully.
int platform_probe(struct platform_device *pdev)
{
    //Distribute registered device drivers and create device files
    __register_file();
    //Parse the GPIO node and parse the GPIO object
    int i;
    for(i=0; i<3; i + + )
    {
        gpiono[i] = gpiod_get_from_of_node(pdev->dev.of_node, "led-gpios", i, GPIOD_OUT_LOW, NULL);
        if(IS_ERR(gpiono[i]))
        {
            printk("Failed to parse GPIO object\
");
            return -PTR_ERR(gpiono[i]);
        }
    }
    return 0;
}
//Repackage remove function, executed when device information and driver information are separated
int platform_remove(struct platform_device *pdev)
{
    //Release the GPIO object
    int i;
    //Destroy device node
    for(i=0; i<3; i + + )
    {
        gpiod_put(gpiono[i]);
        device_destroy(cls, MKDEV(major, i));
    }
    //Destroy device directory
    class_destroy(cls);
    //Unregister the character device driver
    cdev_del(cdev);
    //Release device number
    unregister_chrdev_region(MKDEV(major, minor), 3);
    //Release device driver object space
    kfree(cdev);
    return 0;
}
// struct platform_driver {
// int (*probe)(struct platform_device *);
// int (*remove)(struct platform_device *);
// void (*shutdown)(struct platform_device *);
// int (*suspend)(struct platform_device *, pm_message_t state);
// int (*resume)(struct platform_device *);
// struct device_driver driver;
// const struct platform_device_id *id_table;
// bool prevent_deferred_probe;
// };
// struct of_device_id {
//char name[32];
//char type[32];
//char compatible[128];
// const void *data;
// };
//Build device tree matching table
struct of_device_id oftable[]={
    {.compatible = "hqyj,myplatform"},
    {.compatible = "hqyj,myplatform1"},
};
//Allocate driver information object and initialize it
struct platform_driver pdrv={
    .probe = platform_probe,
    .remove = platform_remove,
    .driver={
        .name = "myplatform",
        .of_match_table = oftable,
    },
};

// static int __init mycdev_init(void)
// {
// //Register driver information object
// platform_register_drivers( & amp;pdrv);
// return 0;
// }
// static void __exit mycdev_exit(void)
// {
// //Unregister the driver information object
// platform_unregister_drivers( & amp;pdrv);

// }
//Register macro with one click
module_platform_driver(pdrv);
//Distribute registration device driver and create device file function statement
 int __register_file(void)
 {
    //1. Apply for device driver object
    cdev = cdev_alloc();
    if(NULL == cdev)
    {
        printk("Failed to apply for device driver object\
");
        goto out1;
    }
    printk("Applying for device driver object successfully\
");
    //2.Initialize the device driver object
    cdev_init(cdev, & amp;fop);
    //3. Apply for device number
    if(0 == major)
    {
        int ret = alloc_chrdev_region( & amp;devno, 0, 3, "mychrdev");
        if(ret)
        {
            printk("Dynamic application for device number failed");
            goto out2;
        }
        major = MAJOR(devno);
        minor = MINOR(devno);
        printk("Dynamic application for device number successful\
");
    }
    else
    {
        int ret = register_chrdev_region(MKDEV(major, minor), 3, "mychrdev");
        if(ret)
        {
            printk("Static specification of device number failed\
");
            goto out2;
        }
        printk("Static device number specified successfully\
");
    }
    //4. Register character device driver
    int ret =cdev_add(cdev, MKDEV(major, minor), 3);
    if(ret)
    {
        printk("Failed to register character device driver\
");
        goto out3;
    }
    printk("Registration of character device driver successful\
");
    //5. Submit directory upwards
    cls = class_create(THIS_MODULE, "mychrdev");
    if(IS_ERR(cls))
    {
        printk("Failed to submit directory upward\
");
        goto out4;
    }
    printk("Submit directory upward successfully\
");
    //6. Submit the device node upwards
    int i;
    for(i=0; i<3; i + + )
    {
        dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
        if(IS_ERR(dev))
        {
            printk("Failed to submit device node upward");
            goto out5;
        }
    }
    printk("Submit device node upward successfully\
");
    return 0;
    out5:
        //Destroy device node
        for(--i; i>=0; i + + )
        {
            device_destroy(cls, MKDEV(major, i));
        }
        //Destroy device directory
        class_destroy(cls);
    out4:
        //Unregister the character device driver
        cdev_del(cdev);
    out3:
        //Release device number
        unregister_chrdev_region(MKDEV(major, minor), 3);
    out2:
        //Release device driver object space
        kfree(cdev);
    out1:
        return -1;
 }
//
//module_init(mycdev_init);
//module_exit(mycdev_exit);
MODULE_LICENSE("GPL");