aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drv_G15.c281
-rw-r--r--lcd4linux.conf.sample10
-rw-r--r--plugin_exec.c8
3 files changed, 288 insertions, 11 deletions
diff --git a/drv_G15.c b/drv_G15.c
index ef7bbae..73bf033 100644
--- a/drv_G15.c
+++ b/drv_G15.c
@@ -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;