aboutsummaryrefslogtreecommitdiffstats
path: root/drv_G15.c
diff options
context:
space:
mode:
authorreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>2006-07-12 20:45:30 +0000
committerreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>2006-07-12 20:45:30 +0000
commit0c45f59043d0403274fcd6c2b3f9c70b412377e6 (patch)
treee7fbe8657b72c97d7cd14545e049519263c9bc6f /drv_G15.c
parenta2bb31e88bf20d30d1a3e3d50fba774c2a438b49 (diff)
downloadlcd4linux-0c45f59043d0403274fcd6c2b3f9c70b412377e6.tar.gz
[lcd4linux @ 2006-07-12 20:45:30 by reinelt]
G15 and thread patch by Anton git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@667 3ae390bd-cb1e-0410-b409-cd5a39f66f1f
Diffstat (limited to 'drv_G15.c')
-rw-r--r--drv_G15.c281
1 files changed, 272 insertions, 9 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();