~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to drv_GLCD2USB.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:28:49 UTC
  • mfrom: (0.1.1 upstream)
  • Revision ID: siretart@tauware.de-20110427172849-mj5cj5a0igpcc9fn
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: drv_GLCD2USB.c 1134 2010-11-20 20:22:05Z mzuther $
 
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_GLCD2USB.c $
 
3
 *
 
4
 * GLCD2USB driver for LCD4Linux 
 
5
 * (see http://www.harbaum.org/till/glcd2usb for hardware)
 
6
 *
 
7
 * Copyright (C) 2007 Till Harbaum <till@harbaum.org>
 
8
 *
 
9
 * This file is part of LCD4Linux.
 
10
 *
 
11
 * LCD4Linux is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2, or (at your option)
 
14
 * any later version.
 
15
 *
 
16
 * LCD4Linux is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
24
 *
 
25
 */
 
26
 
 
27
/* 
 
28
 *
 
29
 * exported fuctions:
 
30
 *
 
31
 * struct DRIVER drv_GLCD2USB
 
32
 *
 
33
 */
 
34
 
 
35
/*
 
36
 * Options:
 
37
 */
 
38
 
 
39
#include "config.h"
 
40
 
 
41
#include <stdlib.h>
 
42
#include <stdio.h>
 
43
#include <string.h>
 
44
#include <errno.h>
 
45
#include <unistd.h>
 
46
#include <termios.h>
 
47
#include <fcntl.h>
 
48
#include <sys/time.h>
 
49
#include <usb.h>
 
50
 
 
51
#include "debug.h"
 
52
#include "cfg.h"
 
53
#include "timer.h"
 
54
#include "qprintf.h"
 
55
#include "plugin.h"
 
56
#include "widget.h"
 
57
#include "widget_text.h"
 
58
#include "widget_icon.h"
 
59
#include "widget_bar.h"
 
60
#include "widget_keypad.h"
 
61
#include "drv.h"
 
62
#include "drv_generic_graphic.h"
 
63
#include "drv_generic_keypad.h"
 
64
 
 
65
/* Numeric constants for 'reportType' parameters */
 
66
#define USB_HID_REPORT_TYPE_INPUT   1
 
67
#define USB_HID_REPORT_TYPE_OUTPUT  2
 
68
#define USB_HID_REPORT_TYPE_FEATURE 3
 
69
 
 
70
/* These are the error codes which can be returned by functions of this
 
71
 * module.
 
72
 */
 
73
#define USB_ERROR_NONE      0
 
74
#define USB_ERROR_ACCESS    1
 
75
#define USB_ERROR_NOTFOUND  2
 
76
#define USB_ERROR_BUSY      16
 
77
#define USB_ERROR_IO        5
 
78
 
 
79
/* ------------------------------------------------------------------------ */
 
80
 
 
81
#include "glcd2usb.h"
 
82
 
 
83
/* ------------------------------------------------------------------------- */
 
84
 
 
85
#define USBRQ_HID_GET_REPORT    0x01
 
86
#define USBRQ_HID_SET_REPORT    0x09
 
87
 
 
88
usb_dev_handle *dev = NULL;
 
89
 
 
90
/* USB message buffer */
 
91
static union {
 
92
    unsigned char bytes[132];
 
93
    display_info_t display_info;
 
94
} buffer;
 
95
 
 
96
/* ------------------------------------------------------------------------- */
 
97
 
 
98
 
 
99
#define IDENT_VENDOR_NUM        0x1c40
 
100
#define IDENT_VENDOR_STRING     "www.harbaum.org/till/glcd2usb"
 
101
#define IDENT_PRODUCT_NUM       0x0525
 
102
#define IDENT_PRODUCT_STRING    "GLCD2USB"
 
103
 
 
104
/* early versions used the ftdi vendor id */
 
105
#define IDENT_VENDOR_NUM_OLD    0x0403
 
106
#define IDENT_PRODUCT_NUM_OLD   0xc634
 
107
 
 
108
static char Name[] = IDENT_PRODUCT_STRING;
 
109
 
 
110
/* ------------------------------------------------------------------------- */
 
111
 
 
112
static int usbGetString(usb_dev_handle * dev, int index, char *buf, int buflen)
 
113
{
 
114
    char buffer[256];
 
115
    int rval, i;
 
116
 
 
117
    if ((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
 
118
                                (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 1000)) < 0)
 
119
        return rval;
 
120
 
 
121
    /* not a string */
 
122
    if (buffer[1] != USB_DT_STRING)
 
123
        return 0;
 
124
 
 
125
    /* string would have been longer than buffer is */
 
126
    if ((unsigned char) buffer[0] < rval)
 
127
        rval = (unsigned char) buffer[0];
 
128
 
 
129
    /* 16 bit unicode -> 8 bit ascii */
 
130
    rval /= 2;
 
131
 
 
132
    /* lossy conversion to ISO Latin1 */
 
133
    for (i = 1; i < rval; i++) {
 
134
        if (i > buflen)         /* destination buffer overflow */
 
135
            break;
 
136
 
 
137
        buf[i - 1] = buffer[2 * i];
 
138
 
 
139
        if (buffer[2 * i + 1] != 0)     /* outside of ISO Latin1 range */
 
140
            buf[i - 1] = '?';
 
141
    }
 
142
 
 
143
    /* terminate string */
 
144
    buf[i - 1] = 0;
 
145
 
 
146
    return i - 1;
 
147
}
 
148
 
 
149
/* ------------------------------------------------------------------------- */
 
150
 
 
151
int usbOpenDevice(usb_dev_handle ** device, int vendor, char *vendorName, int product, char *productName)
 
152
{
 
153
    struct usb_bus *bus;
 
154
    struct usb_device *dev;
 
155
    usb_dev_handle *handle = NULL;
 
156
    int errorCode = USB_ERROR_NOTFOUND;
 
157
    static int didUsbInit = 0;
 
158
 
 
159
    if (!didUsbInit) {
 
160
        usb_init();
 
161
        didUsbInit = 1;
 
162
    }
 
163
 
 
164
    usb_find_busses();
 
165
    usb_find_devices();
 
166
 
 
167
    for (bus = usb_get_busses(); bus; bus = bus->next) {
 
168
        for (dev = bus->devices; dev; dev = dev->next) {
 
169
            if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
 
170
                char string[256];
 
171
                int len;
 
172
                handle = usb_open(dev); /* we need to open the device in order to query strings */
 
173
                if (!handle) {
 
174
                    errorCode = USB_ERROR_ACCESS;
 
175
                    error("%s Warning: cannot open USB device: %s", Name, usb_strerror());
 
176
                    continue;
 
177
                }
 
178
                if (vendorName == NULL && productName == NULL) {        /* name does not matter */
 
179
                    break;
 
180
                }
 
181
                /* now check whether the names match: */
 
182
                len = usbGetString(handle, dev->descriptor.iManufacturer, string, sizeof(string));
 
183
                if (len < 0) {
 
184
                    errorCode = USB_ERROR_IO;
 
185
                    error("%s: Cannot query manufacturer for device: %s", Name, usb_strerror());
 
186
                } else {
 
187
                    errorCode = USB_ERROR_NOTFOUND;
 
188
                    if (strcmp(string, vendorName) == 0) {
 
189
                        len = usbGetString(handle, dev->descriptor.iProduct, string, sizeof(string));
 
190
                        if (len < 0) {
 
191
                            errorCode = USB_ERROR_IO;
 
192
                            fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
 
193
                        } else {
 
194
                            errorCode = USB_ERROR_NOTFOUND;
 
195
                            if (strcmp(string, productName) == 0)
 
196
                                break;
 
197
                        }
 
198
                    }
 
199
                }
 
200
                usb_close(handle);
 
201
                handle = NULL;
 
202
            }
 
203
        }
 
204
        if (handle)
 
205
            break;
 
206
    }
 
207
 
 
208
    if (handle != NULL) {
 
209
        int rval, retries = 3;
 
210
        if (usb_set_configuration(handle, 1)) {
 
211
            fprintf(stderr, "Warning: could not set configuration: %s\n", usb_strerror());
 
212
        }
 
213
        /* now try to claim the interface and detach the kernel HID driver on
 
214
         * linux and other operating systems which support the call.
 
215
         */
 
216
        while ((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0) {
 
217
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
 
218
            if (usb_detach_kernel_driver_np(handle, 0) < 0) {
 
219
                fprintf(stderr, "Warning: could not detach kernel HID driver: %s\n", usb_strerror());
 
220
            }
 
221
#endif
 
222
        }
 
223
#ifndef __APPLE__
 
224
        if (rval != 0)
 
225
            fprintf(stderr, "Warning: could not claim interface\n");
 
226
#endif
 
227
        /* Continue anyway, even if we could not claim the interface. Control transfers
 
228
         * should still work.
 
229
         */
 
230
        errorCode = 0;
 
231
        *device = handle;
 
232
    }
 
233
    return errorCode;
 
234
}
 
235
 
 
236
/* ------------------------------------------------------------------------- */
 
237
 
 
238
void usbCloseDevice(usb_dev_handle * device)
 
239
{
 
240
    if (device != NULL)
 
241
        usb_close(device);
 
242
}
 
243
 
 
244
/* ------------------------------------------------------------------------- */
 
245
 
 
246
int usbSetReport(usb_dev_handle * device, int reportType, unsigned char *buffer, int len)
 
247
{
 
248
    int bytesSent;
 
249
 
 
250
    /* the write command needs some tweaking regarding allowed report lengths */
 
251
    if (buffer[0] == GLCD2USB_RID_WRITE) {
 
252
        int i = 0, allowed_lengths[] = { 4 + 4, 8 + 4, 16 + 4, 32 + 4, 64 + 4, 128 + 4 };
 
253
 
 
254
        if (len > 128 + 4)
 
255
            error("%s: %d bytes usb report is too long \n", Name, len);
 
256
 
 
257
        while (allowed_lengths[i] != (128 + 4) && allowed_lengths[i] < len)
 
258
            i++;
 
259
 
 
260
        len = allowed_lengths[i];
 
261
        buffer[0] = GLCD2USB_RID_WRITE + i;
 
262
    }
 
263
 
 
264
    bytesSent = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE |
 
265
                                USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT,
 
266
                                reportType << 8 | buffer[0], 0, (char *) buffer, len, 1000);
 
267
    if (bytesSent != len) {
 
268
        if (bytesSent < 0)
 
269
            error("%s: Error sending message: %s", Name, usb_strerror());
 
270
        return USB_ERROR_IO;
 
271
    }
 
272
    return 0;
 
273
}
 
274
 
 
275
/* ------------------------------------------------------------------------- */
 
276
 
 
277
int usbGetReport(usb_dev_handle * device, int reportType, int reportNumber, unsigned char *buffer, int *len)
 
278
{
 
279
    *len = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE |
 
280
                           USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT,
 
281
                           reportType << 8 | reportNumber, 0, (char *) buffer, *len, 1000);
 
282
    if (*len < 0) {
 
283
        error("%s: Error sending message: %s", Name, usb_strerror());
 
284
        return USB_ERROR_IO;
 
285
    }
 
286
    return 0;
 
287
}
 
288
 
 
289
char *usbErrorMessage(int errCode)
 
290
{
 
291
    static char buffer[80];
 
292
 
 
293
    switch (errCode) {
 
294
    case USB_ERROR_ACCESS:
 
295
        return "Access to device denied";
 
296
    case USB_ERROR_NOTFOUND:
 
297
        return "The specified device was not found";
 
298
    case USB_ERROR_BUSY:
 
299
        return "The device is used by another application";
 
300
    case USB_ERROR_IO:
 
301
        return "Communication error with device";
 
302
    default:
 
303
        sprintf(buffer, "Unknown USB error %d", errCode);
 
304
        return buffer;
 
305
    }
 
306
    return NULL;                /* not reached */
 
307
}
 
308
 
 
309
static char *video_buffer = NULL;
 
310
static char *dirty_buffer = NULL;
 
311
 
 
312
static void drv_GLCD2USB_blit(const int row, const int col, const int height, const int width)
 
313
{
 
314
    int r, c, err, i, j;
 
315
 
 
316
    /* update offscreen buffer */
 
317
    for (r = row; r < row + height; r++) {
 
318
        for (c = col; c < col + width; c++) {
 
319
            int x, y, bit;
 
320
 
 
321
            /* these assignments are display layout dependent */
 
322
            x = c;
 
323
            y = r / 8;
 
324
            bit = r % 8;
 
325
 
 
326
            i = video_buffer[x + DCOLS * y];
 
327
 
 
328
            if (drv_generic_graphic_black(r, c))
 
329
                video_buffer[x + DCOLS * y] |= 1 << bit;
 
330
            else
 
331
                video_buffer[x + DCOLS * y] &= ~(1 << bit);
 
332
 
 
333
            if (video_buffer[x + DCOLS * y] != i)
 
334
                dirty_buffer[x + DCOLS * y] |= 1 << bit;
 
335
        }
 
336
    }
 
337
 
 
338
#if 0
 
339
    /* display what's in the buffer (for debugging) */
 
340
    for (r = 0; r < DROWS; r++) {
 
341
        for (c = 0; c < DCOLS; c++) {
 
342
            if (video_buffer[c + DCOLS * (r / 8)] & (1 << (r % 8)))
 
343
                putchar('#');
 
344
            else
 
345
                putchar(' ');
 
346
        }
 
347
        putchar('\n');
 
348
    }
 
349
#endif
 
350
 
 
351
    /* short gaps of unchanged bytes in fact increase the communication */
 
352
    /* overhead. so we eliminate them here */
 
353
    for (j = -1, i = 0; i < DROWS * DCOLS / 8; i++) {
 
354
        if (dirty_buffer[i] && j >= 0 && i - j <= 4) {
 
355
            /* found a clean gap <= 4 bytes: mark it dirty */
 
356
            for (r = j; r < i; r++)
 
357
                dirty_buffer[r] = 1;
 
358
        }
 
359
 
 
360
        /* if this is dirty, drop the saved position */
 
361
        if (dirty_buffer[i])
 
362
            j = -1;
 
363
 
 
364
        /* save position of this clean entry if there's no position saved yet */
 
365
        if (!dirty_buffer[i] && j < 0)
 
366
            j = i;
 
367
    }
 
368
 
 
369
    /* and do the actual data transmission */
 
370
    buffer.bytes[0] = 0;
 
371
    for (i = 0; i < DROWS * DCOLS / 8; i++) {
 
372
        if (dirty_buffer[i]) {
 
373
            /* starting a new run? */
 
374
            if (!buffer.bytes[0]) {
 
375
                buffer.bytes[0] = GLCD2USB_RID_WRITE;
 
376
                buffer.bytes[1] = i % 256;      // offset
 
377
                buffer.bytes[2] = i / 256;
 
378
                buffer.bytes[3] = 0;    // length
 
379
            }
 
380
            buffer.bytes[4 + buffer.bytes[3]++] = video_buffer[i];
 
381
        }
 
382
 
 
383
        /* this part of the buffer is not dirty or we are at end */
 
384
        /* of buffer or the buffer is fill: send data then */
 
385
        if ((!dirty_buffer[i]) || (i == DROWS * DCOLS / 8 - 1) || (buffer.bytes[3] == 128)) {
 
386
            /* is there data to be sent in the buffer? */
 
387
            if (buffer.bytes[0] && buffer.bytes[3]) {
 
388
                if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, buffer.bytes[3] + 4)) != 0)
 
389
                    error("%s: Error sending display contents: %s", Name, usbErrorMessage(err));
 
390
 
 
391
                buffer.bytes[0] = 0;
 
392
            }
 
393
        }
 
394
 
 
395
        /* this entry isn't dirty anymore */
 
396
        dirty_buffer[i] = 0;
 
397
    }
 
398
}
 
399
 
 
400
static int drv_GLCD2USB_brightness(int brightness)
 
401
{
 
402
    int err = 0;
 
403
 
 
404
    printf("setting bright to %d\n", brightness);
 
405
 
 
406
    if (brightness < 0)
 
407
        brightness = 0;
 
408
    if (brightness > 255)
 
409
        brightness = 255;
 
410
 
 
411
    buffer.bytes[0] = GLCD2USB_RID_SET_BL;
 
412
    buffer.bytes[1] = brightness;
 
413
    if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, 2)) != 0) {
 
414
        error("%s: Error freeing display: %s\n", Name, usbErrorMessage(err));
 
415
        usbCloseDevice(dev);
 
416
        return -1;
 
417
    }
 
418
 
 
419
    return brightness;
 
420
}
 
421
 
 
422
static void drv_GLCD2USB_timer(void __attribute__ ((unused)) * notused)
 
423
{
 
424
    /* request button state */
 
425
    static unsigned int last_but = 0;
 
426
    int err = 0, len = 2;
 
427
 
 
428
    if ((err = usbGetReport(dev, USB_HID_REPORT_TYPE_FEATURE, GLCD2USB_RID_GET_BUTTONS, buffer.bytes, &len)) != 0) {
 
429
        fprintf(stderr, "Error getting button state: %s\n", usbErrorMessage(err));
 
430
        return;
 
431
    }
 
432
 
 
433
    int i;
 
434
 
 
435
    /* check if button state changed */
 
436
    if (buffer.bytes[1] ^ last_but) {
 
437
 
 
438
        /* send single keypad events for all changed buttons */
 
439
        for (i = 0; i < 4; i++)
 
440
            if ((buffer.bytes[1] & (1 << i)) ^ (last_but & (1 << i)))
 
441
                drv_generic_keypad_press(((buffer.bytes[1] & (1 << i)) ? 0x80 : 0) | i);
 
442
    }
 
443
 
 
444
    last_but = buffer.bytes[1];
 
445
}
 
446
 
 
447
static int drv_GLCD2USB_start(const char *section)
 
448
{
 
449
    int brightness;
 
450
    char *s;
 
451
    int err = 0, len;
 
452
 
 
453
    if (sscanf(s = cfg_get(section, "font", "6x8"), "%dx%d", &XRES, &YRES) != 2 || XRES < 1 || YRES < 1) {
 
454
        error("%s: bad %s.Font '%s' from %s", Name, section, s, cfg_source());
 
455
        free(s);
 
456
        return -1;
 
457
    }
 
458
    free(s);
 
459
 
 
460
    if ((err = usbOpenDevice(&dev, IDENT_VENDOR_NUM, IDENT_VENDOR_STRING,
 
461
                             IDENT_PRODUCT_NUM, IDENT_PRODUCT_STRING)) != 0) {
 
462
        if ((err = usbOpenDevice(&dev, IDENT_VENDOR_NUM_OLD, IDENT_VENDOR_STRING,
 
463
                                 IDENT_PRODUCT_NUM_OLD, IDENT_PRODUCT_STRING)) != 0) {
 
464
            error("%s: opening GLCD2USB device: %s", Name, usbErrorMessage(err));
 
465
            return -1;
 
466
        }
 
467
    }
 
468
 
 
469
    info("%s: Found device", Name);
 
470
 
 
471
    /* query display parameters */
 
472
    memset(&buffer, 0, sizeof(buffer));
 
473
 
 
474
    len = sizeof(display_info_t);
 
475
    if ((err = usbGetReport(dev, USB_HID_REPORT_TYPE_FEATURE, GLCD2USB_RID_GET_INFO, buffer.bytes, &len)) != 0) {
 
476
 
 
477
        error("%s: query display parameters: %s", Name, usbErrorMessage(err));
 
478
        usbCloseDevice(dev);
 
479
        return -1;
 
480
    }
 
481
 
 
482
    if (len < (int) sizeof(buffer.display_info)) {
 
483
        error("%s: Not enough bytes in display info report (%d instead of %d)",
 
484
              Name, len, (int) sizeof(buffer.display_info));
 
485
        usbCloseDevice(dev);
 
486
        return -1;
 
487
    }
 
488
 
 
489
    info("%s: display name = %s", Name, buffer.display_info.name);
 
490
    info("%s: display resolution = %d * %d", Name, buffer.display_info.width, buffer.display_info.height);
 
491
    info("%s: display flags: %x", Name, buffer.display_info.flags);
 
492
 
 
493
    /* TODO: check for supported features */
 
494
 
 
495
 
 
496
    /* save display size */
 
497
    DCOLS = buffer.display_info.width;
 
498
    DROWS = buffer.display_info.height;
 
499
 
 
500
    /* allocate a offscreen buffer */
 
501
    video_buffer = malloc(DCOLS * DROWS / 8);
 
502
    dirty_buffer = malloc(DCOLS * DROWS / 8);
 
503
    memset(video_buffer, 0, DCOLS * DROWS / 8);
 
504
    memset(dirty_buffer, 0, DCOLS * DROWS / 8);
 
505
 
 
506
    /* get access to display */
 
507
    buffer.bytes[0] = GLCD2USB_RID_SET_ALLOC;
 
508
    buffer.bytes[1] = 1;        /* 1=alloc, 0=free */
 
509
    if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, 2)) != 0) {
 
510
        error("%s: Error allocating display: %s", Name, usbErrorMessage(err));
 
511
        usbCloseDevice(dev);
 
512
        return -1;
 
513
    }
 
514
 
 
515
    /* regularly request key state. can be quite slow since the device */
 
516
    /* buffers button presses internally */
 
517
    timer_add(drv_GLCD2USB_timer, NULL, 100, 0);
 
518
 
 
519
    if (cfg_number(section, "Brightness", 0, 0, 255, &brightness) > 0) {
 
520
        drv_GLCD2USB_brightness(brightness);
 
521
    }
 
522
 
 
523
    return 0;
 
524
}
 
525
 
 
526
 
 
527
 
 
528
/****************************************/
 
529
/***            plugins               ***/
 
530
/****************************************/
 
531
 
 
532
static void plugin_brightness(RESULT * result, RESULT * arg1)
 
533
{
 
534
    double brightness;
 
535
 
 
536
    brightness = drv_GLCD2USB_brightness(R2N(arg1));
 
537
    SetResult(&result, R_NUMBER, &brightness);
 
538
}
 
539
 
 
540
/****************************************/
 
541
/***        widget callbacks          ***/
 
542
/****************************************/
 
543
 
 
544
 
 
545
/* using drv_generic_graphic_draw(W) */
 
546
/* using drv_generic_graphic_icon_draw(W) */
 
547
/* using drv_generic_graphic_bar_draw(W) */
 
548
 
 
549
 
 
550
/****************************************/
 
551
/***        exported functions        ***/
 
552
/****************************************/
 
553
 
 
554
 
 
555
/* list models */
 
556
int drv_GLCD2USB_list(void)
 
557
{
 
558
    printf("GLCD2USB homebrew USB interface for graphic displays");
 
559
    return 0;
 
560
}
 
561
 
 
562
static int drv_GLCD2USB_keypad(const int num)
 
563
{
 
564
    const int keys[] = { WIDGET_KEY_LEFT, WIDGET_KEY_RIGHT,
 
565
        WIDGET_KEY_CONFIRM, WIDGET_KEY_CANCEL
 
566
    };
 
567
 
 
568
    int val;
 
569
 
 
570
    /* check for key press event */
 
571
    if (num & 0x80)
 
572
        val = WIDGET_KEY_PRESSED;
 
573
    else
 
574
        val = WIDGET_KEY_RELEASED;
 
575
 
 
576
    return val | keys[num & 0x03];
 
577
}
 
578
 
 
579
/* initialize driver & display */
 
580
int drv_GLCD2USB_init(const char *section, const __attribute__ ((unused))
 
581
                      int quiet)
 
582
{
 
583
    int ret;
 
584
 
 
585
    info("%s: %s", Name, "$Rev: 1134 $");
 
586
 
 
587
    /* real worker functions */
 
588
    drv_generic_graphic_real_blit = drv_GLCD2USB_blit;
 
589
    drv_generic_keypad_real_press = drv_GLCD2USB_keypad;
 
590
 
 
591
    /* start display */
 
592
    if ((ret = drv_GLCD2USB_start(section)) != 0)
 
593
        return ret;
 
594
 
 
595
    /* initialize generic graphic driver */
 
596
    if ((ret = drv_generic_graphic_init(section, Name)) != 0)
 
597
        return ret;
 
598
 
 
599
    /* register plugins */
 
600
    AddFunction("LCD::brightness", 1, plugin_brightness);
 
601
 
 
602
    return 0;
 
603
}
 
604
 
 
605
 
 
606
/* close driver & display */
 
607
int drv_GLCD2USB_quit(const __attribute__ ((unused))
 
608
                      int quiet)
 
609
{
 
610
    int err;
 
611
 
 
612
    info("%s: shutting down.", Name);
 
613
    drv_generic_graphic_quit();
 
614
 
 
615
    /* release access to display */
 
616
 
 
617
    buffer.bytes[0] = GLCD2USB_RID_SET_ALLOC;
 
618
    buffer.bytes[1] = 0;        /* 1=alloc, 0=free */
 
619
    if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, 2)) != 0) {
 
620
        error("%s Error freeing display: %s", Name, usbErrorMessage(err));
 
621
    }
 
622
 
 
623
    /* clean up */
 
624
    if (dev != NULL)
 
625
        usbCloseDevice(dev);
 
626
 
 
627
    if (video_buffer != NULL) {
 
628
        free(video_buffer);
 
629
        free(dirty_buffer);
 
630
    }
 
631
 
 
632
    return (0);
 
633
}
 
634
 
 
635
 
 
636
DRIVER drv_GLCD2USB = {
 
637
    .name = Name,
 
638
    .list = drv_GLCD2USB_list,
 
639
    .init = drv_GLCD2USB_init,
 
640
    .quit = drv_GLCD2USB_quit,
 
641
};