diff options
-rw-r--r-- | drv_G15.c | 281 | ||||
-rw-r--r-- | lcd4linux.conf.sample | 10 | ||||
-rw-r--r-- | plugin_exec.c | 8 |
3 files changed, 288 insertions, 11 deletions
@@ -1,4 +1,4 @@ -/* $Id: drv_G15.c,v 1.6 2006/02/27 06:14:46 reinelt Exp $ +/* $Id: drv_G15.c,v 1.7 2006/07/12 20:45:30 reinelt Exp $ * * Driver for Logitech G-15 keyboard LCD screen * @@ -24,6 +24,9 @@ * * * $Log: drv_G15.c,v $ + * Revision 1.7 2006/07/12 20:45:30 reinelt + * G15 and thread patch by Anton + * * Revision 1.6 2006/02/27 06:14:46 reinelt * graphic bug resulting in all black pixels solved * @@ -60,6 +63,10 @@ #include <errno.h> #include <usb.h> +#include <fcntl.h> +#include <linux/input.h> +#include <linux/uinput.h> +#include <signal.h> #include "debug.h" #include "cfg.h" @@ -68,6 +75,7 @@ #include "plugin.h" #include "drv.h" #include "drv_generic_graphic.h" +#include "thread.h" #define G15_VENDOR 0x046d #define G15_DEVICE 0xc222 @@ -78,16 +86,252 @@ #define DEBUG(x) #endif +#define KB_UPDOWN_PRESS + static char Name[] = "G-15"; static usb_dev_handle *g15_lcd; static unsigned char *g15_image; +unsigned char g_key_states[18]; +unsigned char m_key_states[4]; +unsigned char l_key_states[5]; + +static int uinput_fd; +static int kb_mutex; +static int kb_thread_pid; +static int kb_single_keypress=0; + + /****************************************/ /*** hardware dependant functions ***/ /****************************************/ + +void drv_G15_keyDown(unsigned char scancode) +{ + struct input_event event; + memset(&event, 0, sizeof(event)); + + event.type = EV_KEY; + event.code = scancode; + event.value = 1; + write (uinput_fd, &event, sizeof(event)); +} +void drv_G15_keyUp(unsigned char scancode) +{ + struct input_event event; + memset(&event, 0, sizeof(event)); + + event.type = EV_KEY; + event.code = scancode; + event.value = 0; + write (uinput_fd, &event, sizeof(event)); +} +void drv_G15_keyDownUp(unsigned char scancode) +{ + drv_G15_keyDown(scancode); + drv_G15_keyUp(scancode); + +} +inline unsigned char drv_G15_evalScanCode(int key) +{ + // first 12 G keys produce F1 - F12, thats 0x3a + key + if (key < 12) + { + return 0x3a + key; + } + // the other keys produce Key '1' (above letters) + key, thats 0x1e + key + else + { + return 0x1e + key - 12; // sigh, half an hour to find -12 .... + } +} + +void drv_G15_processKeyEvent(unsigned char *buffer) +{ + const int g_scancode_offset = 167; + const int m_scancode_offset = 187; + const int l_scancode_offset = 191; + int i; + int is_set; + unsigned char m_key_new_states[4]; + unsigned char l_key_new_states[5]; + unsigned char orig_scancode; +// printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx \n\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],buffer[8]); +// usleep(100); + if (buffer[0] == 0x01) + { + DEBUG("Checking keys: "); + + + for (i=0;i<18;++i) + { + orig_scancode = drv_G15_evalScanCode(i); + is_set = 0; + + if (buffer[1] == orig_scancode || buffer[2] == orig_scancode || buffer[3] == orig_scancode || + buffer[4] == orig_scancode || buffer[5] == orig_scancode) + is_set = 1; + + if (!is_set && g_key_states[i] != 0) + { + // key was pressed but is no more + if (!kb_single_keypress) + drv_G15_keyUp( g_scancode_offset + i); + g_key_states[i] = 0; + debug("G%d going up",(i+1)); + } + else if (is_set && g_key_states[i] == 0) + { + if (!kb_single_keypress) + drv_G15_keyDown ( g_scancode_offset + i); + else + drv_G15_keyDownUp ( g_scancode_offset + i); + + g_key_states[i] = 1; + debug("G%d going down",(i+1)); + } + } + } + else + { + if (buffer[0] == 0x02) + { + memset(m_key_new_states,0,sizeof(m_key_new_states)); + + if (buffer[6]&0x01) + m_key_new_states[0] = 1; + if (buffer[7]&0x02) + m_key_new_states[1] = 1; + if (buffer[8]&0x04) + m_key_new_states[2] = 1; + if (buffer[7]&0x40) + m_key_new_states[3] = 1; + + for (i=0;i<4;++i) + { + if (!m_key_new_states[i] && m_key_states[i] != 0) + { + // key was pressed but is no more + if (!kb_single_keypress) + drv_G15_keyUp( m_scancode_offset + i); + m_key_states[i] = 0; + debug("M%d going up",(i+1)); + } + else if (m_key_new_states[i] && m_key_states[i] == 0) + { + if (!kb_single_keypress) + drv_G15_keyDown ( m_scancode_offset + i); + else + drv_G15_keyDownUp ( m_scancode_offset + i); + m_key_states[i] = 1; + debug("M%d going down",(i+1)); + } + } + + memset(l_key_new_states,0,sizeof(l_key_new_states)); + if (buffer[8]&0x80) + l_key_new_states[0] = 1; + if (buffer[2]&0x80) + l_key_new_states[1] = 1; + if (buffer[3]&0x80) + l_key_new_states[2] = 1; + if (buffer[4]&0x80) + l_key_new_states[3] = 1; + if (buffer[5]&0x80) + l_key_new_states[4] = 1; + + for (i=0;i<5;++i) + { + if (!l_key_new_states[i] && l_key_states[i] != 0) + { + // key was pressed but is no more + if (!kb_single_keypress) + drv_G15_keyUp( l_scancode_offset + i); + l_key_states[i] = 0; + debug("L%d going up",(i+1)); + } + else if (l_key_new_states[i] && l_key_states[i] == 0) + { + if (!kb_single_keypress) + drv_G15_keyDown ( l_scancode_offset + i); + else + drv_G15_keyDownUp ( l_scancode_offset + i); + l_key_states[i] = 1; + debug("L%d going down",(i+1)); + } + } + + } + } +} + +void drv_G15_closeUIDevice() +{ + DEBUG("closing device"); + ioctl(uinput_fd, UI_DEV_DESTROY); + close(uinput_fd); +} + + +void drv_G15_initKeyHandling(char *device_filename) +{ + struct uinput_user_dev device; + int i; + DEBUG("Key Handling init") + uinput_fd = open(device_filename, O_RDWR); + + if (uinput_fd < 0) + { + info("Error, could not open the uinput device"); + info("Compile your kernel for uinput, calling it a day now"); + info("mknod uinput c 10 223"); + abort(); + } + memset(&device,0,sizeof(device)); + strncpy(device.name, "G15 Keys", UINPUT_MAX_NAME_SIZE); + device.id.bustype = BUS_USB; + device.id.version = 4; + + ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY); + + for (i=0;i<256;++i) + ioctl(uinput_fd, UI_SET_KEYBIT, i); + + write(uinput_fd, &device, sizeof(device)); + + if (ioctl(uinput_fd, UI_DEV_CREATE)) + { + info("Failed to create input device"); + abort(); + } +// atexit(&closeDevice); + + memset(g_key_states, 0, sizeof(g_key_states)); + memset(m_key_states, 0, sizeof(m_key_states)); + memset(l_key_states, 0, sizeof(l_key_states)); +} + + +static void drv_G15_KBThread(void __attribute__ ((unused)) * notused) +{ + unsigned char buffer[9]; + int ret; + while (1) + { + mutex_lock(kb_mutex); + ret = usb_bulk_read(g15_lcd, 0x81, (char*)buffer, 9, 10); +// ret = usb_interrupt_read(g15_lcd, 0x81, (char*)buffer, 9, 10); + mutex_unlock(kb_mutex); + if (ret == 9) + { + drv_G15_processKeyEvent(buffer); + } + } +} + static int drv_G15_open() { struct usb_bus *bus; @@ -164,8 +408,9 @@ static void drv_G15_update_img() } DEBUG("output array prepared"); - - usb_bulk_write(g15_lcd, 0x02, (char *) output, 992, 1000); + mutex_lock(kb_mutex); + usb_interrupt_write(g15_lcd, 0x02, (char *) output, 992, 1000); + mutex_unlock(kb_mutex); usleep(300); DEBUG("data written to LCD"); @@ -185,8 +430,8 @@ static void drv_G15_blit(const int row, const int col, const int height, const i DEBUG("entered"); - for (r = row; r < row + height; r++) { - for (c = col; c < col + width; c++) { + for (r = row; r < row + height && r < DROWS; r++) { + for (c = col; c < col + width && c < DCOLS; c++) { g15_image[r * 160 + c] = drv_generic_graphic_black(r, c); } } @@ -207,8 +452,8 @@ static int drv_G15_start(const char *section) DEBUG("entered"); /* read display size from config */ - DROWS = 160; - DCOLS = 43; + DROWS = 43; + DCOLS = 160; DEBUG("display size set"); @@ -260,7 +505,17 @@ static int drv_G15_start(const char *section) drv_G15_contrast(contrast); } */ - + s = cfg_get(section, "Uinput", ""); + if (s!=NULL && *s!='\0' ){ + cfg_number(section, "SingleKeyPress", 0, 0, 1, &kb_single_keypress); + drv_G15_initKeyHandling(s); + + DEBUG("creating thread for keyboard"); + kb_mutex=mutex_create(); + kb_thread_pid=thread_create("G15_KBThread", drv_G15_KBThread, NULL); + + DEBUG("done"); + } DEBUG("left"); return 0; @@ -292,7 +547,7 @@ int drv_G15_init(const char *section, const int quiet) { int ret; - info("%s: %s", Name, "$Revision: 1.6 $"); + info("%s: %s", Name, "$Revision: 1.7 $"); DEBUG("entered"); @@ -346,6 +601,14 @@ int drv_G15_quit(const int quiet) DEBUG("generic_graphic_quit()"); drv_generic_graphic_quit(); + mutex_destroy(kb_mutex); + usleep(10*1000); + kill(kb_thread_pid,SIGKILL); + + drv_G15_closeUIDevice(); + DEBUG("closing UInputDev"); + + DEBUG("closing connection"); drv_G15_close(); diff --git a/lcd4linux.conf.sample b/lcd4linux.conf.sample index 78538f8..123a14d 100644 --- a/lcd4linux.conf.sample +++ b/lcd4linux.conf.sample @@ -4,6 +4,16 @@ Variables { minute 60000 } +Display G15 { + Driver 'G-15' + Font '6x8' + Contrast 10 + Inverted 0 + UInput '/dev/input/uinput' + SingleKeyPress 1 +} + + Display SerDispLib { Driver 'serdisplib' Port 'PAR:/dev/parports/0' diff --git a/plugin_exec.c b/plugin_exec.c index f9576e2..ec7806d 100644 --- a/plugin_exec.c +++ b/plugin_exec.c @@ -1,4 +1,4 @@ -/* $Id: plugin_exec.c,v 1.9 2005/05/08 04:32:44 reinelt Exp $ +/* $Id: plugin_exec.c,v 1.10 2006/07/12 20:45:30 reinelt Exp $ * * plugin for external processes * @@ -27,6 +27,9 @@ * * * $Log: plugin_exec.c,v $ + * Revision 1.10 2006/07/12 20:45:30 reinelt + * G15 and thread patch by Anton + * * Revision 1.9 2005/05/08 04:32:44 reinelt * CodingStyle added and applied * @@ -80,6 +83,7 @@ #include <unistd.h> #include <string.h> #include <errno.h> +#include <signal.h> #include "debug.h" #include "plugin.h" @@ -182,7 +186,7 @@ static void destroy_exec_thread(const int n) free(Thread[n].key); if (Thread[n].ret) shm_destroy(Thread[n].shmid, Thread[n].ret); - + kill(Thread[n].pid,SIGKILL); Thread[n].delay = 0; Thread[n].mutex = 0; Thread[n].pid = 0; |