You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

204 lines
5.4 KiB

#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include "Grove_LCD_rgb_V2.0.h"
// ADD device i2c
// echo grove_lcd 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
// echo grove_rgb 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
// Delete i2c device
// echo 0x3e | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device
// echo 0x62 | sudo tee /sys/class/i2c-adapter/i2c-1/delete_device
// Test i2c
// i2cdetect -y 1
struct i2c_client *i2c_client_lcd;
struct i2c_client *i2c_client_rgb;
#define DEVICE_NAME "grove_lcd"
#define CLASS_NAME "grove_lcd_lcd"
static int majorNumber;
static struct class* grove_lcd_class = NULL;
static struct device* grove_lcd_device = NULL;
static int is_device_open = 0;
// --- Driver for display (grove_lcd) ----------------------------
static const struct i2c_device_id grove_lcd_id[] = {
{ "grove_lcd", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, grove_lcd_id);
static int grove_lcd_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
i2c_client_lcd = client;
return 0;
}
static int grove_lcd_remove(struct i2c_client *client)
{
return 0;
}
static struct i2c_driver grove_lcd_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "grove_lcd",
},
.probe = grove_lcd_probe,
.remove = grove_lcd_remove,
.id_table = grove_lcd_id,
};
// --- Driver for LED (grove_rgb) --------------------------------
static const struct i2c_device_id grove_rgb_id[] = {
{ "grove_rgb", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, grove_rgb_id);
static int grove_rgb_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
i2c_client_rgb = client;
lcd_begin();
lcd_print("Grove_LCD start!");
return 0;
}
static int grove_rgb_remove(struct i2c_client *client)
{
return 0;
}
static struct i2c_driver grove_rgb_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "grove_rgb",
},
.probe = grove_rgb_probe,
.remove = grove_rgb_remove,
.id_table = grove_rgb_id,
};
// --- Device ----------------------------------------------------
static int device_open( struct inode *inode, struct file *file )
{
if ( is_device_open ) return -EBUSY;
is_device_open++;
return 0;
}
static int device_release( struct inode *inode, struct file *file )
{
is_device_open--;
return 0;
}
static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * offset)
{
int i;
if (buff[0] == '@')
{
if (buff[1] == 'A') lcd_setColor(AQUA);
if (buff[1] == 'B') lcd_setColor(BLUE);
if (buff[1] == 'P') lcd_setColor(PURPLE);
if (buff[1] == 'G') lcd_setColor(GREEN);
if (buff[1] == 'R') lcd_setColor(RED);
if (buff[1] == 'W') lcd_setColor(WHITE);
if (buff[1] == 'Y') lcd_setColor(YELLOW);
if (buff[1] == 'L')
{
if (buff[1] == '1') lcd_setCursor(0,1);
if (buff[1] == '0') lcd_setCursor(0,0);
}
if (buff[1] == 'H') lcd_home();
if (buff[1] == 'C') lcd_clear();
return len;
}
for (i=0; i<len-1; i++)
{
lcd_write(buff[i]);
}
//printk(" --- buf: %s", buff);
return len;
}
static ssize_t device_read( struct file *filp, char *buffer, size_t length, loff_t * offset )
{
char ch[] = "Grove-LCD: Pleas print IN display.\n";
printk (ch);
//copy_to_user(buffer, ch, sizeof(ch));
return 0;
}
static struct file_operations fops =
{
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
// --- Init module -----------------------------------------------
static int __init grove_lcd_init(void) {
printk("Grove-LCD: display modele - start.\n");
majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
if (majorNumber<0){
printk(KERN_ALERT "Grove-LCD: failed to register a major number\n");
return majorNumber;
}
printk(KERN_INFO "Grove-LCD: registered correctly with major number %d\n", majorNumber);
grove_lcd_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(grove_lcd_class)){
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Grove-LCD: Failed to register device class\n");
return PTR_ERR(grove_lcd_class);
}
printk(KERN_INFO "Grove-LCD: device class registered correctly\n");
grove_lcd_device = device_create(grove_lcd_class, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
if (IS_ERR(grove_lcd_device)){
class_destroy(grove_lcd_class);
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_ALERT "Grove-LCD: Failed to create the device\n");
return PTR_ERR(grove_lcd_device);
}
printk("Grove-LCD: device class created correctly\n");
i2c_add_driver(&grove_lcd_driver);
i2c_add_driver(&grove_rgb_driver);
return 0;
}
static void __exit grove_lcd_exit(void) {
device_destroy(grove_lcd_class, MKDEV(majorNumber, 0));
class_unregister(grove_lcd_class);
class_destroy(grove_lcd_class);
unregister_chrdev(majorNumber, DEVICE_NAME);
i2c_del_driver(&grove_lcd_driver);
i2c_del_driver(&grove_rgb_driver);
printk("Grove-LCD: display modele - kill.\n");
}
module_init(grove_lcd_init);
module_exit(grove_lcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZEN");