root/trunk/drv_G15.c

Revision 840, 13.2 kB (checked in by michael, 15 months ago)

email address changed

  • Property svn:keywords set to Id URL Rev
Line 
1/* $Id$
2 * $URL$
3 *
4 * Driver for Logitech G-15 keyboard LCD screen
5 *
6 * Copyright (C) 2006 Dave Ingram <dave@partis-project.net>
7 * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
8 * Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
9 *
10 * This file is part of LCD4Linux.
11 *
12 * LCD4Linux is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
16 *
17 * LCD4Linux is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 */
27
28/*
29 *
30 * exported fuctions:
31 *
32 * struct DRIVER drv_G15
33 *
34 */
35
36#include "config.h"
37
38#include <stdlib.h>
39#include <stdio.h>
40#include <string.h>
41#include <errno.h>
42
43#include <usb.h>
44#include <fcntl.h>
45#include <linux/input.h>
46#include <linux/uinput.h>
47
48#include "debug.h"
49#include "cfg.h"
50#include "qprintf.h"
51#include "udelay.h"
52#include "plugin.h"
53#include "drv.h"
54#include "drv_generic_graphic.h"
55#include "thread.h"
56
57#define G15_VENDOR 0x046d
58#define G15_DEVICE 0xc222
59
60#if 0
61#define DEBUG(x) debug("%s(): %s", __FUNCTION__, x);
62#else
63#define DEBUG(x)
64#endif
65
66#define KB_UPDOWN_PRESS
67
68static char Name[] = "G-15";
69
70static usb_dev_handle *g15_lcd;
71
72static unsigned char *g15_image;
73
74unsigned char g_key_states[18];
75unsigned char m_key_states[4];
76unsigned char l_key_states[5];
77
78static int uinput_fd;
79static int kb_mutex;
80static int kb_thread_pid;
81static int kb_single_keypress = 0;
82
83
84/****************************************/
85/***  hardware dependant functions    ***/
86/****************************************/
87
88
89void drv_G15_keyDown(unsigned char scancode)
90{
91    struct input_event event;
92    memset(&event, 0, sizeof(event));
93
94    event.type = EV_KEY;
95    event.code = scancode;
96    event.value = 1;
97    write(uinput_fd, &event, sizeof(event));
98}
99
100void drv_G15_keyUp(unsigned char scancode)
101{
102    struct input_event event;
103    memset(&event, 0, sizeof(event));
104
105    event.type = EV_KEY;
106    event.code = scancode;
107    event.value = 0;
108    write(uinput_fd, &event, sizeof(event));
109}
110
111void drv_G15_keyDownUp(unsigned char scancode)
112{
113    drv_G15_keyDown(scancode);
114    drv_G15_keyUp(scancode);
115
116}
117
118inline unsigned char drv_G15_evalScanCode(int key)
119{
120    /* first 12 G keys produce F1 - F12, thats 0x3a + key */
121    if (key < 12) {
122  return 0x3a + key;
123    }
124
125    /* the other keys produce Key '1' (above letters) + key, thats 0x1e + key */
126    else {
127  return 0x1e + key - 12; /* sigh, half an hour to find  -12 .... */
128    }
129}
130
131void drv_G15_processKeyEvent(unsigned char *buffer)
132{
133    const int g_scancode_offset = 167;
134    const int m_scancode_offset = 187;
135    const int l_scancode_offset = 191;
136    int i;
137    int is_set;
138    unsigned char m_key_new_states[4];
139    unsigned char l_key_new_states[5];
140    unsigned char orig_scancode;
141
142#if 0
143    printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx \n\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
144     buffer[5], buffer[6], buffer[7], buffer[8]);
145    usleep(100);
146#endif
147
148    if (buffer[0] == 0x01) {
149  DEBUG("Checking keys: ");
150
151  for (i = 0; i < 18; ++i) {
152      orig_scancode = drv_G15_evalScanCode(i);
153      is_set = 0;
154
155      if (buffer[1] == orig_scancode || buffer[2] == orig_scancode || buffer[3] == orig_scancode ||
156    buffer[4] == orig_scancode || buffer[5] == orig_scancode)
157    is_set = 1;
158
159      if (!is_set && g_key_states[i] != 0) {
160    /* key was pressed but is no more */
161    if (!kb_single_keypress)
162        drv_G15_keyUp(g_scancode_offset + i);
163    g_key_states[i] = 0;
164    debug("G%d going up", (i + 1));
165      } else if (is_set && g_key_states[i] == 0) {
166    if (!kb_single_keypress)
167        drv_G15_keyDown(g_scancode_offset + i);
168    else
169        drv_G15_keyDownUp(g_scancode_offset + i);
170
171    g_key_states[i] = 1;
172    debug("G%d going down", (i + 1));
173      }
174  }
175    } else {
176  if (buffer[0] == 0x02) {
177      memset(m_key_new_states, 0, sizeof(m_key_new_states));
178
179      if (buffer[6] & 0x01)
180    m_key_new_states[0] = 1;
181      if (buffer[7] & 0x02)
182    m_key_new_states[1] = 1;
183      if (buffer[8] & 0x04)
184    m_key_new_states[2] = 1;
185      if (buffer[7] & 0x40)
186    m_key_new_states[3] = 1;
187
188      for (i = 0; i < 4; ++i) {
189    if (!m_key_new_states[i] && m_key_states[i] != 0) {
190        /* key was pressed but is no more */
191        if (!kb_single_keypress)
192      drv_G15_keyUp(m_scancode_offset + i);
193        m_key_states[i] = 0;
194        debug("M%d going up", (i + 1));
195    } else if (m_key_new_states[i] && m_key_states[i] == 0) {
196        if (!kb_single_keypress)
197      drv_G15_keyDown(m_scancode_offset + i);
198        else
199      drv_G15_keyDownUp(m_scancode_offset + i);
200        m_key_states[i] = 1;
201        debug("M%d going down", (i + 1));
202    }
203      }
204
205      memset(l_key_new_states, 0, sizeof(l_key_new_states));
206      if (buffer[8] & 0x80)
207    l_key_new_states[0] = 1;
208      if (buffer[2] & 0x80)
209    l_key_new_states[1] = 1;
210      if (buffer[3] & 0x80)
211    l_key_new_states[2] = 1;
212      if (buffer[4] & 0x80)
213    l_key_new_states[3] = 1;
214      if (buffer[5] & 0x80)
215    l_key_new_states[4] = 1;
216
217      for (i = 0; i < 5; ++i) {
218    if (!l_key_new_states[i] && l_key_states[i] != 0) {
219        /* key was pressed but is no more */
220        if (!kb_single_keypress)
221      drv_G15_keyUp(l_scancode_offset + i);
222        l_key_states[i] = 0;
223        debug("L%d going up", (i + 1));
224    } else if (l_key_new_states[i] && l_key_states[i] == 0) {
225        if (!kb_single_keypress)
226      drv_G15_keyDown(l_scancode_offset + i);
227        else
228      drv_G15_keyDownUp(l_scancode_offset + i);
229        l_key_states[i] = 1;
230        debug("L%d going down", (i + 1));
231    }
232      }
233
234  }
235    }
236}
237
238void drv_G15_closeUIDevice()
239{
240    DEBUG("closing device");
241    ioctl(uinput_fd, UI_DEV_DESTROY);
242    close(uinput_fd);
243}
244
245
246void drv_G15_initKeyHandling(char *device_filename)
247{
248    struct uinput_user_dev device;
249    int i;
250    DEBUG("Key Handling init")
251  uinput_fd = open(device_filename, O_RDWR);
252
253    if (uinput_fd < 0) {
254  info("Error, could not open the uinput device");
255  info("Compile your kernel for uinput, calling it a day now");
256  info("mknod uinput c 10 223");
257  abort();
258    }
259    memset(&device, 0, sizeof(device));
260    strncpy(device.name, "G15 Keys", UINPUT_MAX_NAME_SIZE);
261    device.id.bustype = BUS_USB;
262    device.id.version = 4;
263
264    ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY);
265
266    for (i = 0; i < 256; ++i)
267  ioctl(uinput_fd, UI_SET_KEYBIT, i);
268
269    write(uinput_fd, &device, sizeof(device));
270
271    if (ioctl(uinput_fd, UI_DEV_CREATE)) {
272  info("Failed to create input device");
273  abort();
274    }
275
276/*  atexit(&closeDevice); */
277
278    memset(g_key_states, 0, sizeof(g_key_states));
279    memset(m_key_states, 0, sizeof(m_key_states));
280    memset(l_key_states, 0, sizeof(l_key_states));
281}
282
283
284static void drv_G15_KBThread(void __attribute__ ((unused)) * notused)
285{
286    unsigned char buffer[9];
287    int ret;
288    while (1) {
289  mutex_lock(kb_mutex);
290  ret = usb_bulk_read(g15_lcd, 0x81, (char *) buffer, 9, 10);
291/*      ret = usb_interrupt_read(g15_lcd, 0x81, (char*)buffer, 9, 10); */
292  mutex_unlock(kb_mutex);
293  if (ret == 9) {
294      drv_G15_processKeyEvent(buffer);
295  }
296    }
297}
298
299static int drv_G15_open()
300{
301    struct usb_bus *bus;
302    struct usb_device *dev;
303    char dname[32] = { 0 };
304
305    g15_lcd = NULL;
306
307    info("%s: Scanning USB for G-15 keyboard...", Name);
308
309    usb_init();
310    usb_set_debug(0);
311    usb_find_busses();
312    usb_find_devices();
313
314    for (bus = usb_get_busses(); bus; bus = bus->next) {
315  for (dev = bus->devices; dev; dev = dev->next) {
316      if ((g15_lcd = usb_open(dev))) {
317    if ((dev->descriptor.idVendor == G15_VENDOR) && (dev->descriptor.idProduct == G15_DEVICE)) {
318
319        /* detach from the kernel if we need to */
320        int retval = usb_get_driver_np(g15_lcd, 0, dname, 31);
321        if (retval == 0 && strcmp(dname, "usbhid") == 0) {
322      usb_detach_kernel_driver_np(g15_lcd, 0);
323        }
324        usb_set_configuration(g15_lcd, 1);
325        usleep(100);
326        usb_claim_interface(g15_lcd, 0);
327        return 0;
328    } else {
329        usb_close(g15_lcd);
330    }
331      }
332  }
333    }
334
335    return -1;
336}
337
338
339static int drv_G15_close(void)
340{
341    usb_release_interface(g15_lcd, 0);
342    if (g15_lcd)
343  usb_close(g15_lcd);
344
345    return 0;
346}
347
348
349static void drv_G15_update_img()
350{
351    int i, j, k;
352    unsigned char *output = malloc(160 * 43 * sizeof(unsigned char));
353
354    DEBUG("entered");
355    if (!output)
356  return;
357
358    DEBUG("memory allocated");
359    memset(output, 0, 160 * 43);
360    DEBUG("memory set");
361    output[0] = 0x03;
362    DEBUG("first output set");
363
364    for (k = 0; k < 6; k++) {
365  for (i = 0; i < 160; i++) {
366      int maxj = (k == 5) ? 3 : 8;
367      for (j = 0; j < maxj; j++) {
368    if (g15_image[(k * 1280) + i + (j * 160)])
369        output[32 + i + (k * 160)] |= (1 << j);
370      }
371  }
372    }
373
374    DEBUG("output array prepared");
375    mutex_lock(kb_mutex);
376    usb_interrupt_write(g15_lcd, 0x02, (char *) output, 992, 1000);
377    mutex_unlock(kb_mutex);
378    usleep(300);
379
380    DEBUG("data written to LCD");
381
382    free(output);
383
384    DEBUG("memory freed");
385    DEBUG("left");
386}
387
388
389
390/* for graphic displays only */
391static void drv_G15_blit(const int row, const int col, const int height, const int width)
392{
393    int r, c;
394
395    DEBUG("entered");
396
397    for (r = row; r < row + height; r++) {
398  for (c = col; c < col + width; c++) {
399      g15_image[r * 160 + c] = drv_generic_graphic_black(r, c);
400  }
401    }
402
403    DEBUG("updating image");
404
405    drv_G15_update_img();
406
407    DEBUG("left");
408}
409
410
411/* start graphic display */
412static int drv_G15_start(const char *section)
413{
414    char *s;
415
416    DEBUG("entered");
417
418    /* read display size from config */
419    DROWS = 43;
420    DCOLS = 160;
421
422    DEBUG("display size set");
423
424    s = cfg_get(section, "Font", "6x8");
425    if (s == NULL || *s == '\0') {
426  error("%s: no '%s.Font' entry from %s", Name, section, cfg_source());
427  return -1;
428    }
429
430    XRES = -1;
431    YRES = -1;
432    if (sscanf(s, "%dx%d", &XRES, &YRES) != 2 || XRES < 1 || YRES < 1) {
433  error("%s: bad Font '%s' from %s", Name, s, cfg_source());
434  return -1;
435    }
436
437    /* Fixme: provider other fonts someday... */
438    if (XRES != 6 && YRES != 8) {
439  error("%s: bad Font '%s' from %s (only 6x8 at the moment)", Name, s, cfg_source());
440  return -1;
441    }
442
443    DEBUG("Finished config stuff");
444
445    DEBUG("allocating image buffer");
446    /* you surely want to allocate a framebuffer or something... */
447    g15_image = malloc(160 * 43 * sizeof(unsigned char));
448    if (!g15_image)
449  return -1;
450    DEBUG("allocated");
451    memset(g15_image, 0, 160 * 43);
452    DEBUG("zeroed");
453
454    /* open communication with the display */
455    DEBUG("opening display...");
456    if (drv_G15_open() < 0) {
457  DEBUG("opening failed");
458  return -1;
459    }
460    DEBUG("display open");
461
462    /* reset & initialize display */
463    DEBUG("clearing display");
464    drv_G15_update_img();
465    DEBUG("done");
466
467    /*
468       if (cfg_number(section, "Contrast", 0, 0, 255, &contrast) > 0) {
469       drv_G15_contrast(contrast);
470       }
471     */
472    s = cfg_get(section, "Uinput", "");
473    if (s != NULL && *s != '\0') {
474  cfg_number(section, "SingleKeyPress", 0, 0, 1, &kb_single_keypress);
475  drv_G15_initKeyHandling(s);
476
477  DEBUG("creating thread for keyboard");
478  kb_mutex = mutex_create();
479  kb_thread_pid = thread_create("G15_KBThread", drv_G15_KBThread, NULL);
480
481  DEBUG("done");
482    }
483    DEBUG("left");
484
485    return 0;
486}
487
488
489/****************************************/
490/***            plugins               ***/
491/****************************************/
492
493/* none */
494
495
496/****************************************/
497/***        exported functions        ***/
498/****************************************/
499
500
501/* list models */
502int drv_G15_list(void)
503{
504    printf("generic");
505    return 0;
506}
507
508
509/* initialize driver & display */
510int drv_G15_init(const char *section, const int quiet)
511{
512    int ret;
513
514    info("%s: %s", Name, "$Rev$");
515
516    DEBUG("entered");
517
518    /* real worker functions */
519    drv_generic_graphic_real_blit = drv_G15_blit;
520
521    /* start display */
522    if ((ret = drv_G15_start(section)) != 0)
523  return ret;
524
525    /* initialize generic graphic driver */
526    if ((ret = drv_generic_graphic_init(section, Name)) != 0)
527  return ret;
528
529    if (!quiet) {
530  char buffer[40];
531
532  qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
533  if (drv_generic_graphic_greet(buffer, NULL)) {
534      sleep(3);
535      drv_generic_graphic_clear();
536  }
537    }
538
539    /* register plugins */
540    /* none at the moment... */
541
542
543    DEBUG("left");
544
545    return 0;
546}
547
548
549
550/* close driver & display */
551int drv_G15_quit(const int quiet)
552{
553    info("%s: shutting down.", Name);
554
555    DEBUG("clearing display");
556    /* clear display */
557    drv_generic_graphic_clear();
558
559    DEBUG("saying goodbye");
560    /* say goodbye... */
561    if (!quiet) {
562  drv_generic_graphic_greet("goodbye!", NULL);
563    }
564
565    DEBUG("generic_graphic_quit()");
566    drv_generic_graphic_quit();
567
568    mutex_destroy(kb_mutex);
569    usleep(10 * 1000);
570    thread_destroy(kb_thread_pid);
571
572    drv_G15_closeUIDevice();
573    DEBUG("closing UInputDev");
574
575
576    DEBUG("closing connection");
577    drv_G15_close();
578
579    DEBUG("freeing image alloc");
580    free(g15_image);
581
582    return (0);
583}
584
585
586DRIVER drv_G15 = {
587    .name = Name,
588    .list = drv_G15_list,
589    .init = drv_G15_init,
590    .quit = drv_G15_quit,
591};
Note: See TracBrowser for help on using the browser.