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
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");
|