added write functionality

This commit is contained in:
Lauchmelder 2022-06-07 18:44:32 +02:00
parent ac91c5cb2b
commit 7fd5e0fffc
3 changed files with 68 additions and 9 deletions

View file

@ -5,6 +5,8 @@
#include <linux/gpio.h>
#include "lcd.h"
static bool advance_ptr(const char* base, ssize_t size, char** ptr);
loff_t lcd_llseek(struct file* filp, loff_t where, int whence)
{
return 0;
@ -17,7 +19,54 @@ ssize_t lcd_read(struct file* filp, char __user* buf, size_t count, loff_t* off)
ssize_t lcd_write(struct file* filp, const char __user* buf, size_t count, loff_t* off)
{
return count;
struct lcd_dev* dev = (struct lcd_dev*)filp->private_data;
char* kern_buf = NULL;
char* cmd_start = NULL;
char* cmd_end = NULL;
ssize_t retval = 0;
if(down_interruptible(&dev->sem))
return retval;
kern_buf = (char*)kmalloc(count, GFP_KERNEL);
if(kern_buf == NULL)
{
printk(KERN_ERR "%s: Failed to allocate buffer (%d bytes), aborting write.\n", THIS_MODULE->name, count);
retval = -ENOMEM;
goto out;
}
if(copy_from_user(kern_buf, buf, count))
{
printk(KERN_ERR "%s: Failed to copy data from user, aborting write.\n", THIS_MODULE->name);
retval = -EFAULT;
kfree(kern_buf);
goto out;
}
cmd_start = kern_buf;
cmd_end = kern_buf;
while(advance_ptr(kern_buf, count, &cmd_end))
{
*cmd_end = '\0';
if(strcmp(cmd_start, "0") == 0)
gpio_set_value(dev->gpio, 0);
else if(strcmp(cmd_start, "1") == 0)
gpio_set_value(dev->gpio, 1);
else
printk(KERN_WARNING "%s: Unrecognized command \"%s\"\n", THIS_MODULE->name, cmd_start);
cmd_start = cmd_end + 1;
}
retval = count;
kfree(kern_buf);
out:
up(&dev->sem);
return retval;
}
long lcd_ioctl(struct file* filp, unsigned int cmd, unsigned long arg)
@ -31,9 +80,7 @@ int lcd_open(struct inode* inode, struct file* filp)
dev = container_of(inode->i_cdev, struct lcd_dev, dev);
filp->private_data = (void*)dev;
gpio_set_value(dev->gpio, 1);
printk(KERN_INFO "%s: Opened device\n", THIS_MODULE->name);
printk(KERN_DEBUG "%s: Opened device\n", THIS_MODULE->name);
return 0;
}
@ -41,9 +88,17 @@ int lcd_release(struct inode* inode, struct file* filp)
{
struct lcd_dev* dev;
dev = (struct lcd_dev*)filp->private_data;
gpio_set_value(dev->gpio, 0);
printk(KERN_INFO "%s: Released device\n", THIS_MODULE->name);
printk(KERN_DEBUG "%s: Released device\n", THIS_MODULE->name);
return 0;
}
static bool advance_ptr(const char* base, ssize_t size, char** ptr)
{
while(*ptr - base < size && **ptr != '\n')
(*ptr)++;
return *ptr - base < size;
}
#endif

View file

@ -10,9 +10,11 @@ MODULE_LICENSE("GPL");
int lcd_major = LCD_MAJOR;
int lcd_minor = LCD_MINOR;
int lcd_gpio = LCD_GPIO;
module_param(lcd_major, int, S_IRUGO);
module_param(lcd_minor, int, S_IRUGO);
module_param(lcd_gpio, int, S_IRUGO);
static struct lcd_dev lcddev = { 0 };
static int __init lcd_init_cdev(void);
@ -60,6 +62,8 @@ static int __init lcd_init_module(void)
return result;
}
sema_init(&lcddev.sem, 1);
result = lcd_init_cdev();
if(result < 0)
return result;
@ -113,5 +117,5 @@ static int __init lcd_init_gpio(void)
static void __exit lcd_exit_gpio(void)
{
}

View file

@ -7,13 +7,13 @@
#define LCD_MAJOR 0
#define LCD_MINOR 0
extern int lcd_major;
extern int lcd_minor;
#define LCD_GPIO 18
struct lcd_dev
{
dev_t devno;
struct cdev dev;
struct semaphore sem;
int gpio;
};