added checks to pin configuration

This commit is contained in:
Lauchmelder 2022-06-10 22:02:28 +02:00
parent 15a4f817f2
commit 060ffddcf1
5 changed files with 82 additions and 13 deletions

View file

@ -1,5 +1,5 @@
obj-m = lcd.o obj-m = lcd.o
lcd-y = src/lcd.o src/io.o lcd-y = src/lcd.o src/io.o src/checks.o
KVERSION = $(shell uname -r) KVERSION = $(shell uname -r)

37
src/checks.c Normal file
View file

@ -0,0 +1,37 @@
#include "checks.h"
#include <linux/module.h>
#include "lcd.h"
#define LCD_MIN_GPIO 2
#define LCD_MAX_GPIO 27
static int sub_pin = LCD_MIN_GPIO;
int lcd_is_valid_gpio(int pin)
{
return (LCD_MIN_GPIO <= pin && pin <= LCD_MAX_GPIO);
}
int lcd_assign_gpio(int pin)
{
if(lcd_is_valid_gpio(pin))
return pin;
printk(KERN_WARNING "%s: GPIO pin %d is invalid. Using %d instead\n", THIS_MODULE->name, pin, sub_pin);
return sub_pin++;
}
int lcd_check_duplicates(const int* used_pins)
{
int i, j;
for(i = 0; i < 7; i++)
for(j = i + 1; j < 8; j++)
if(used_pins[i] == used_pins[j])
return -EFAULT;
return 0;
}

11
src/checks.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef _LCD_CHECKS_H
#define _LCD_CHECKS_H
struct lcd_gpio_config;
int lcd_is_valid_gpio(int pin);
int lcd_assign_gpio(int pin);
int lcd_check_duplicates(const int* config);
#endif

View file

@ -5,6 +5,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include "lcd.h" #include "lcd.h"
#include "checks.h"
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@ -85,7 +86,10 @@ static int __init lcd_init_module(void)
result = lcd_init_gpio(); result = lcd_init_gpio();
if(result < 0) if(result < 0)
{
printk(KERN_ERR "%s: Failed to configure GPIO pins\n", THIS_MODULE->name);
return result; return result;
}
printk(KERN_INFO "%s: Module loaded!\n", THIS_MODULE->name); printk(KERN_INFO "%s: Module loaded!\n", THIS_MODULE->name);
return result; return result;
@ -120,26 +124,41 @@ static int __init lcd_init_cdev(void)
static int __init lcd_init_gpio(void) static int __init lcd_init_gpio(void)
{ {
lcd_validate_gpio(); int result, i;
result = lcd_validate_gpio();
if(result < 0)
return result;
for(i = 0; i < 8; i++)
gpio_direction_output(lcddev.used_pins[i], 0);
// gpio_direction_output(lcddev.gpio, 0); return result;
return 0;
} }
static int __init lcd_validate_gpio(void) static int __init lcd_validate_gpio(void)
{ {
int result = 0;
struct lcd_gpio_config* config = &lcddev.config; struct lcd_gpio_config* config = &lcddev.config;
lcddev.used_pins = (int*)config;
config->power = pin_power; config->power = lcd_assign_gpio(pin_power);
config->rs = pin_rs; config->rs = lcd_assign_gpio(pin_rs);
config->rw = pin_rw; config->rw = lcd_assign_gpio(pin_rw);
config->enable = pin_enable; config->enable = lcd_assign_gpio(pin_enable);
memcpy(config->data, pin_data, 4 * sizeof(int)); config->data[0] = lcd_assign_gpio(pin_data[0]);
config->data[1] = lcd_assign_gpio(pin_data[1]);
config->data[2] = lcd_assign_gpio(pin_data[2]);
config->data[3] = lcd_assign_gpio(pin_data[3]);
// TODO: Check if pin configuration is valid result = lcd_check_duplicates(lcddev.used_pins);
// - no duplicate pins? if(result < 0)
// - all pin numbers in range? {
printk(KERN_ERR "%s: Invalid pin configuration (duplicate pin usage)\n", THIS_MODULE->name);
return result;
}
return 0; return 0;
} }

View file

@ -3,6 +3,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/semaphore.h>
#define LCD_MAJOR 0 #define LCD_MAJOR 0
#define LCD_MINOR 0 #define LCD_MINOR 0
@ -18,7 +19,7 @@ struct lcd_gpio_config
int power; int power;
int rs, rw, enable; int rs, rw, enable;
int data[4]; int data[4];
}; } __attribute__((packed));
struct lcd_dev struct lcd_dev
{ {
@ -26,6 +27,7 @@ struct lcd_dev
struct cdev dev; struct cdev dev;
struct semaphore sem; struct semaphore sem;
struct lcd_gpio_config config; struct lcd_gpio_config config;
int* used_pins;
}; };
#endif #endif