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");