added write functionality
This commit is contained in:
parent
ac91c5cb2b
commit
7fd5e0fffc
67
src/io.c
67
src/io.c
|
@ -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
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
||||
}
|
Loading…
Reference in a new issue