Task: Complete the writing of the LED driver based on the platform driver model to realize the lighting of three lamps
Application layer program
#include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #define LED_ON _IOW('l',1,int) #define LED_OFF _IOW('l',0,int) int main(int argc, char const *argv[]) { //Open the first device file int fd1 = open("/dev/myled0", O_RDWR); if (fd1 < 0) { printf("Failed to open device file\ "); exit(-1); } //Open the second device file int fd2 = open("/dev/myled1", O_RDWR); if (fd2 < 0) { printf("Failed to open device file\ "); exit(-1); } //Open the third device file int fd3 = open("/dev/myled2", O_RDWR); if (fd3 < 0) { printf("Failed to open device file\ "); exit(-1); } while (1) { int a, b; //Read from terminal printf("Please enter characters\ "); printf("First character: 1(LED1) 2(LED2) 3(LED3)\ "); scanf("%d", & amp;a); printf("Second character: 0 (lights off) 1 (lights on)\ "); printf("Please enter >"); scanf("%d", & amp;b); //Write to device file switch (b) { case 1: switch (a) { case 1: //LED1 printf("LED1_ON\ "); ioctl(fd1, LED_ON, & amp;a); break; case 2: //LED2 printf("LED2_ON\ "); ioctl(fd2, LED_ON, & amp;a); break; case 3: //LED3 printf("LED3_ON\ "); ioctl(fd3, LED_ON, & amp;a); break; } break; case 0: switch (a) { case 1: //LED1 printf("LED1_OFF\ "); ioctl(fd1, LED_OFF, & amp;a); break; case 2: //LED2 printf("LED2_OFF\ "); ioctl(fd2, LED_OFF, & amp;a); break; case 3: //LED3 printf("LED3_OFF\ "); ioctl(fd3, LED_OFF, & amp;a); break; } break; } } close(fd1); close(fd2); close(fd3); return 0; }
driver code
#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/gpio.h> #include <linux/io.h> #include <linux/fs.h> #include <linux/device.h> #define LED_ON _IOW('l',1,int) #define LED_OFF _IOW('l',0,int) struct resource *res; int irqnum; struct gpio_desc *gpionum1; struct gpio_desc *gpionum2; struct gpio_desc *gpionum3; struct device *dev; int major; struct class *cls; struct of_device_id of_tab[] = { { .compatible = "hqyj,myplatform", }, { .compatible = "hqyj,myplatform1", }, {}, }; //Open file function int myopen(struct inode *inode, struct file *file) { return 0; } //Close file function int myclose(struct inode *inode, struct file *file) { int i; for(i = 0;i < 3;i + + ) { device_destroy(cls,MKDEV(major,i)); } class_destroy(cls); unregister_chrdev(major,"mychrdev"); return 0; } // io control function long myioctl(struct file *file, unsigned int cmd, unsigned long arg) { printk("__ioctrl__"); int which; int ret = copy_from_user( & amp;which, (void *)arg, 4); if (ret) { printk("copy_from_user failed\ "); return -EIO; } printk("copy_from_user success : [%d]\ ",which); switch(cmd) { case LED_ON: switch (which) { case 1: printk("[1] : LED_ON\ "); gpiod_set_value(gpionum1, 1); break; case 2: printk("[2] : LED_ON\ "); gpiod_set_value(gpionum2, 1); break; case 3: printk("[3] : LED_ON\ "); gpiod_set_value(gpionum3, 1); break; } break; case LED_OFF: switch (which) { case 1: printk("[1] : LED_OFF\ "); gpiod_set_value(gpionum1, 0); break; case 2: printk("[2] : LED_OFF\ "); gpiod_set_value(gpionum2, 0); break; case 3: printk("[3] : LED_OFF\ "); gpiod_set_value(gpionum3, 0); break; } break; } return 0; } // Operation method structure struct file_operations fops = { .open = myopen, .unlocked_ioctl = myioctl, .release = myclose, }; //Matching success function int pdri_probe(struct platform_device *pdev) { printk("%s : %s : %d\ ", __FILE__, __func__, __LINE__); //Character device registration major = register_chrdev(0, "mychrdev", & amp;fops); if (major < 0) { printk("register_chrdev failed\ "); return -1; } printk("register_chrdev success\ "); //Submit the superior directory cls = class_create(THIS_MODULE, "mychrdev"); if (IS_ERR(cls)) { printk("class_create failed\ "); return -PTR_ERR(cls); } printk("class_create success\ "); // Submit node information upward three times 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("[%d] : device_create failed\ ", i); return -PTR_ERR(dev); } } printk("device_create success\ "); // Get device information res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { printk("MEM : platform_get_resource failed\ "); return -1; } printk("MEN : %x\ ", res->start); // Get interrupt number information irqnum = platform_get_irq(pdev, 0); if (irqnum < 0) { printk("IRQ : platform_get_irq failed\ "); return -1; } printk("IRQ : %d\ ", irqnum); // Get LED1gpio information gpionum1 = gpiod_get_from_of_node(pdev->dev.of_node, "led1-gpioe", 0, GPIOD_OUT_LOW, NULL); if (IS_ERR(gpionum1)) { printk("gpiod_get_from_of_node failed\ "); return PTR_ERR(gpionum1); } printk("gpiod_get_from_of_node success\ "); // Get LED2gpio information gpionum2 = gpiod_get_from_of_node(pdev->dev.of_node, "led2-gpiof", 0, GPIOD_OUT_LOW, NULL); if (IS_ERR(gpionum2)) { printk("gpiod_get_from_of_node failed\ "); return PTR_ERR(gpionum2); } printk("gpiod_get_from_of_node success\ "); // Get LED3gpio information gpionum3 = gpiod_get_from_of_node(pdev->dev.of_node, "led3-gpioe", 0, GPIOD_OUT_LOW, NULL); if (IS_ERR(gpionum3)) { printk("gpiod_get_from_of_node failed\ "); return PTR_ERR(gpionum3); } printk("gpiod_get_from_of_node success\ "); return 0; } // separate function int pdri_remove(struct platform_device *pdev) { gpiod_set_value(gpionum1, 0); gpiod_set_value(gpionum2, 0); gpiod_set_value(gpionum3, 0); gpiod_put(gpionum1); gpiod_put(gpionum2); gpiod_put(gpionum3); printk("%s : %s : %d\ ", __FILE__, __func__, __LINE__); return 0; } // Allocate space to the driver object struct platform_driver pdri = { .probe = pdri_probe, .remove = pdri_remove, .driver.name = "a", .driver.of_match_table = of_tab, }; module_platform_driver(pdri); MODULE_LICENSE("GPL");