diff options
Diffstat (limited to 'oncology/dpfhack_display/lcd4linux/.svn/text-base/drv_GLCD2USB.c.svn-base')
| -rw-r--r-- | oncology/dpfhack_display/lcd4linux/.svn/text-base/drv_GLCD2USB.c.svn-base | 641 |
1 files changed, 0 insertions, 641 deletions
diff --git a/oncology/dpfhack_display/lcd4linux/.svn/text-base/drv_GLCD2USB.c.svn-base b/oncology/dpfhack_display/lcd4linux/.svn/text-base/drv_GLCD2USB.c.svn-base deleted file mode 100644 index 25048007..00000000 --- a/oncology/dpfhack_display/lcd4linux/.svn/text-base/drv_GLCD2USB.c.svn-base +++ /dev/null @@ -1,641 +0,0 @@ -/* $Id$ - * $URL$ - * - * GLCD2USB driver for LCD4Linux - * (see http://www.harbaum.org/till/glcd2usb for hardware) - * - * Copyright (C) 2007 Till Harbaum <till@harbaum.org> - * - * This file is part of LCD4Linux. - * - * LCD4Linux is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * LCD4Linux is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * - * exported fuctions: - * - * struct DRIVER drv_GLCD2USB - * - */ - -/* - * Options: - */ - -#include "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <termios.h> -#include <fcntl.h> -#include <sys/time.h> -#include <usb.h> - -#include "debug.h" -#include "cfg.h" -#include "timer.h" -#include "qprintf.h" -#include "plugin.h" -#include "widget.h" -#include "widget_text.h" -#include "widget_icon.h" -#include "widget_bar.h" -#include "widget_keypad.h" -#include "drv.h" -#include "drv_generic_graphic.h" -#include "drv_generic_keypad.h" - -/* Numeric constants for 'reportType' parameters */ -#define USB_HID_REPORT_TYPE_INPUT 1 -#define USB_HID_REPORT_TYPE_OUTPUT 2 -#define USB_HID_REPORT_TYPE_FEATURE 3 - -/* These are the error codes which can be returned by functions of this - * module. - */ -#define USB_ERROR_NONE 0 -#define USB_ERROR_ACCESS 1 -#define USB_ERROR_NOTFOUND 2 -#define USB_ERROR_BUSY 16 -#define USB_ERROR_IO 5 - -/* ------------------------------------------------------------------------ */ - -#include "glcd2usb.h" - -/* ------------------------------------------------------------------------- */ - -#define USBRQ_HID_GET_REPORT 0x01 -#define USBRQ_HID_SET_REPORT 0x09 - -usb_dev_handle *dev = NULL; - -/* USB message buffer */ -static union { - unsigned char bytes[132]; - display_info_t display_info; -} buffer; - -/* ------------------------------------------------------------------------- */ - - -#define IDENT_VENDOR_NUM 0x1c40 -#define IDENT_VENDOR_STRING "www.harbaum.org/till/glcd2usb" -#define IDENT_PRODUCT_NUM 0x0525 -#define IDENT_PRODUCT_STRING "GLCD2USB" - -/* early versions used the ftdi vendor id */ -#define IDENT_VENDOR_NUM_OLD 0x0403 -#define IDENT_PRODUCT_NUM_OLD 0xc634 - -static char Name[] = IDENT_PRODUCT_STRING; - -/* ------------------------------------------------------------------------- */ - -static int usbGetString(usb_dev_handle * dev, int index, char *buf, int buflen) -{ - char buffer[256]; - int rval, i; - - if ((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, - (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 1000)) < 0) - return rval; - - /* not a string */ - if (buffer[1] != USB_DT_STRING) - return 0; - - /* string would have been longer than buffer is */ - if ((unsigned char) buffer[0] < rval) - rval = (unsigned char) buffer[0]; - - /* 16 bit unicode -> 8 bit ascii */ - rval /= 2; - - /* lossy conversion to ISO Latin1 */ - for (i = 1; i < rval; i++) { - if (i > buflen) /* destination buffer overflow */ - break; - - buf[i - 1] = buffer[2 * i]; - - if (buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */ - buf[i - 1] = '?'; - } - - /* terminate string */ - buf[i - 1] = 0; - - return i - 1; -} - -/* ------------------------------------------------------------------------- */ - -int usbOpenDevice(usb_dev_handle ** device, int vendor, char *vendorName, int product, char *productName) -{ - struct usb_bus *bus; - struct usb_device *dev; - usb_dev_handle *handle = NULL; - int errorCode = USB_ERROR_NOTFOUND; - static int didUsbInit = 0; - - if (!didUsbInit) { - usb_init(); - didUsbInit = 1; - } - - usb_find_busses(); - usb_find_devices(); - - for (bus = usb_get_busses(); bus; bus = bus->next) { - for (dev = bus->devices; dev; dev = dev->next) { - if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) { - char string[256]; - int len; - handle = usb_open(dev); /* we need to open the device in order to query strings */ - if (!handle) { - errorCode = USB_ERROR_ACCESS; - error("%s Warning: cannot open USB device: %s", Name, usb_strerror()); - continue; - } - if (vendorName == NULL && productName == NULL) { /* name does not matter */ - break; - } - /* now check whether the names match: */ - len = usbGetString(handle, dev->descriptor.iManufacturer, string, sizeof(string)); - if (len < 0) { - errorCode = USB_ERROR_IO; - error("%s: Cannot query manufacturer for device: %s", Name, usb_strerror()); - } else { - errorCode = USB_ERROR_NOTFOUND; - if (strcmp(string, vendorName) == 0) { - len = usbGetString(handle, dev->descriptor.iProduct, string, sizeof(string)); - if (len < 0) { - errorCode = USB_ERROR_IO; - fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror()); - } else { - errorCode = USB_ERROR_NOTFOUND; - if (strcmp(string, productName) == 0) - break; - } - } - } - usb_close(handle); - handle = NULL; - } - } - if (handle) - break; - } - - if (handle != NULL) { - int rval, retries = 3; - if (usb_set_configuration(handle, 1)) { - fprintf(stderr, "Warning: could not set configuration: %s\n", usb_strerror()); - } - /* now try to claim the interface and detach the kernel HID driver on - * linux and other operating systems which support the call. - */ - while ((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0) { -#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP - if (usb_detach_kernel_driver_np(handle, 0) < 0) { - fprintf(stderr, "Warning: could not detach kernel HID driver: %s\n", usb_strerror()); - } -#endif - } -#ifndef __APPLE__ - if (rval != 0) - fprintf(stderr, "Warning: could not claim interface\n"); -#endif - /* Continue anyway, even if we could not claim the interface. Control transfers - * should still work. - */ - errorCode = 0; - *device = handle; - } - return errorCode; -} - -/* ------------------------------------------------------------------------- */ - -void usbCloseDevice(usb_dev_handle * device) -{ - if (device != NULL) - usb_close(device); -} - -/* ------------------------------------------------------------------------- */ - -int usbSetReport(usb_dev_handle * device, int reportType, unsigned char *buffer, int len) -{ - int bytesSent; - - /* the write command needs some tweaking regarding allowed report lengths */ - if (buffer[0] == GLCD2USB_RID_WRITE) { - int i = 0, allowed_lengths[] = { 4 + 4, 8 + 4, 16 + 4, 32 + 4, 64 + 4, 128 + 4 }; - - if (len > 128 + 4) - error("%s: %d bytes usb report is too long \n", Name, len); - - while (allowed_lengths[i] != (128 + 4) && allowed_lengths[i] < len) - i++; - - len = allowed_lengths[i]; - buffer[0] = GLCD2USB_RID_WRITE + i; - } - - bytesSent = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | - USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, - reportType << 8 | buffer[0], 0, (char *) buffer, len, 1000); - if (bytesSent != len) { - if (bytesSent < 0) - error("%s: Error sending message: %s", Name, usb_strerror()); - return USB_ERROR_IO; - } - return 0; -} - -/* ------------------------------------------------------------------------- */ - -int usbGetReport(usb_dev_handle * device, int reportType, int reportNumber, unsigned char *buffer, int *len) -{ - *len = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | - USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, - reportType << 8 | reportNumber, 0, (char *) buffer, *len, 1000); - if (*len < 0) { - error("%s: Error sending message: %s", Name, usb_strerror()); - return USB_ERROR_IO; - } - return 0; -} - -char *usbErrorMessage(int errCode) -{ - static char buffer[80]; - - switch (errCode) { - case USB_ERROR_ACCESS: - return "Access to device denied"; - case USB_ERROR_NOTFOUND: - return "The specified device was not found"; - case USB_ERROR_BUSY: - return "The device is used by another application"; - case USB_ERROR_IO: - return "Communication error with device"; - default: - sprintf(buffer, "Unknown USB error %d", errCode); - return buffer; - } - return NULL; /* not reached */ -} - -static char *video_buffer = NULL; -static char *dirty_buffer = NULL; - -static void drv_GLCD2USB_blit(const int row, const int col, const int height, const int width) -{ - int r, c, err, i, j; - - /* update offscreen buffer */ - for (r = row; r < row + height; r++) { - for (c = col; c < col + width; c++) { - int x, y, bit; - - /* these assignments are display layout dependent */ - x = c; - y = r / 8; - bit = r % 8; - - i = video_buffer[x + DCOLS * y]; - - if (drv_generic_graphic_black(r, c)) - video_buffer[x + DCOLS * y] |= 1 << bit; - else - video_buffer[x + DCOLS * y] &= ~(1 << bit); - - if (video_buffer[x + DCOLS * y] != i) - dirty_buffer[x + DCOLS * y] |= 1 << bit; - } - } - -#if 0 - /* display what's in the buffer (for debugging) */ - for (r = 0; r < DROWS; r++) { - for (c = 0; c < DCOLS; c++) { - if (video_buffer[c + DCOLS * (r / 8)] & (1 << (r % 8))) - putchar('#'); - else - putchar(' '); - } - putchar('\n'); - } -#endif - - /* short gaps of unchanged bytes in fact increase the communication */ - /* overhead. so we eliminate them here */ - for (j = -1, i = 0; i < DROWS * DCOLS / 8; i++) { - if (dirty_buffer[i] && j >= 0 && i - j <= 4) { - /* found a clean gap <= 4 bytes: mark it dirty */ - for (r = j; r < i; r++) - dirty_buffer[r] = 1; - } - - /* if this is dirty, drop the saved position */ - if (dirty_buffer[i]) - j = -1; - - /* save position of this clean entry if there's no position saved yet */ - if (!dirty_buffer[i] && j < 0) - j = i; - } - - /* and do the actual data transmission */ - buffer.bytes[0] = 0; - for (i = 0; i < DROWS * DCOLS / 8; i++) { - if (dirty_buffer[i]) { - /* starting a new run? */ - if (!buffer.bytes[0]) { - buffer.bytes[0] = GLCD2USB_RID_WRITE; - buffer.bytes[1] = i % 256; // offset - buffer.bytes[2] = i / 256; - buffer.bytes[3] = 0; // length - } - buffer.bytes[4 + buffer.bytes[3]++] = video_buffer[i]; - } - - /* this part of the buffer is not dirty or we are at end */ - /* of buffer or the buffer is fill: send data then */ - if ((!dirty_buffer[i]) || (i == DROWS * DCOLS / 8 - 1) || (buffer.bytes[3] == 128)) { - /* is there data to be sent in the buffer? */ - if (buffer.bytes[0] && buffer.bytes[3]) { - if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, buffer.bytes[3] + 4)) != 0) - error("%s: Error sending display contents: %s", Name, usbErrorMessage(err)); - - buffer.bytes[0] = 0; - } - } - - /* this entry isn't dirty anymore */ - dirty_buffer[i] = 0; - } -} - -static int drv_GLCD2USB_brightness(int brightness) -{ - int err = 0; - - printf("setting bright to %d\n", brightness); - - if (brightness < 0) - brightness = 0; - if (brightness > 255) - brightness = 255; - - buffer.bytes[0] = GLCD2USB_RID_SET_BL; - buffer.bytes[1] = brightness; - if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, 2)) != 0) { - error("%s: Error freeing display: %s\n", Name, usbErrorMessage(err)); - usbCloseDevice(dev); - return -1; - } - - return brightness; -} - -static void drv_GLCD2USB_timer(void __attribute__ ((unused)) * notused) -{ - /* request button state */ - static unsigned int last_but = 0; - int err = 0, len = 2; - - if ((err = usbGetReport(dev, USB_HID_REPORT_TYPE_FEATURE, GLCD2USB_RID_GET_BUTTONS, buffer.bytes, &len)) != 0) { - fprintf(stderr, "Error getting button state: %s\n", usbErrorMessage(err)); - return; - } - - int i; - - /* check if button state changed */ - if (buffer.bytes[1] ^ last_but) { - - /* send single keypad events for all changed buttons */ - for (i = 0; i < 4; i++) - if ((buffer.bytes[1] & (1 << i)) ^ (last_but & (1 << i))) - drv_generic_keypad_press(((buffer.bytes[1] & (1 << i)) ? 0x80 : 0) | i); - } - - last_but = buffer.bytes[1]; -} - -static int drv_GLCD2USB_start(const char *section) -{ - int brightness; - char *s; - int err = 0, len; - - if (sscanf(s = cfg_get(section, "font", "6x8"), "%dx%d", &XRES, &YRES) != 2 || XRES < 1 || YRES < 1) { - error("%s: bad %s.Font '%s' from %s", Name, section, s, cfg_source()); - free(s); - return -1; - } - free(s); - - if ((err = usbOpenDevice(&dev, IDENT_VENDOR_NUM, IDENT_VENDOR_STRING, - IDENT_PRODUCT_NUM, IDENT_PRODUCT_STRING)) != 0) { - if ((err = usbOpenDevice(&dev, IDENT_VENDOR_NUM_OLD, IDENT_VENDOR_STRING, - IDENT_PRODUCT_NUM_OLD, IDENT_PRODUCT_STRING)) != 0) { - error("%s: opening GLCD2USB device: %s", Name, usbErrorMessage(err)); - return -1; - } - } - - info("%s: Found device", Name); - - /* query display parameters */ - memset(&buffer, 0, sizeof(buffer)); - - len = sizeof(display_info_t); - if ((err = usbGetReport(dev, USB_HID_REPORT_TYPE_FEATURE, GLCD2USB_RID_GET_INFO, buffer.bytes, &len)) != 0) { - - error("%s: query display parameters: %s", Name, usbErrorMessage(err)); - usbCloseDevice(dev); - return -1; - } - - if (len < (int) sizeof(buffer.display_info)) { - error("%s: Not enough bytes in display info report (%d instead of %d)", - Name, len, (int) sizeof(buffer.display_info)); - usbCloseDevice(dev); - return -1; - } - - info("%s: display name = %s", Name, buffer.display_info.name); - info("%s: display resolution = %d * %d", Name, buffer.display_info.width, buffer.display_info.height); - info("%s: display flags: %x", Name, buffer.display_info.flags); - - /* TODO: check for supported features */ - - - /* save display size */ - DCOLS = buffer.display_info.width; - DROWS = buffer.display_info.height; - - /* allocate a offscreen buffer */ - video_buffer = malloc(DCOLS * DROWS / 8); - dirty_buffer = malloc(DCOLS * DROWS / 8); - memset(video_buffer, 0, DCOLS * DROWS / 8); - memset(dirty_buffer, 0, DCOLS * DROWS / 8); - - /* get access to display */ - buffer.bytes[0] = GLCD2USB_RID_SET_ALLOC; - buffer.bytes[1] = 1; /* 1=alloc, 0=free */ - if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, 2)) != 0) { - error("%s: Error allocating display: %s", Name, usbErrorMessage(err)); - usbCloseDevice(dev); - return -1; - } - - /* regularly request key state. can be quite slow since the device */ - /* buffers button presses internally */ - timer_add(drv_GLCD2USB_timer, NULL, 100, 0); - - if (cfg_number(section, "Brightness", 0, 0, 255, &brightness) > 0) { - drv_GLCD2USB_brightness(brightness); - } - - return 0; -} - - - -/****************************************/ -/*** plugins ***/ -/****************************************/ - -static void plugin_brightness(RESULT * result, RESULT * arg1) -{ - double brightness; - - brightness = drv_GLCD2USB_brightness(R2N(arg1)); - SetResult(&result, R_NUMBER, &brightness); -} - -/****************************************/ -/*** widget callbacks ***/ -/****************************************/ - - -/* using drv_generic_graphic_draw(W) */ -/* using drv_generic_graphic_icon_draw(W) */ -/* using drv_generic_graphic_bar_draw(W) */ - - -/****************************************/ -/*** exported functions ***/ -/****************************************/ - - -/* list models */ -int drv_GLCD2USB_list(void) -{ - printf("GLCD2USB homebrew USB interface for graphic displays"); - return 0; -} - -static int drv_GLCD2USB_keypad(const int num) -{ - const int keys[] = { WIDGET_KEY_LEFT, WIDGET_KEY_RIGHT, - WIDGET_KEY_CONFIRM, WIDGET_KEY_CANCEL - }; - - int val; - - /* check for key press event */ - if (num & 0x80) - val = WIDGET_KEY_PRESSED; - else - val = WIDGET_KEY_RELEASED; - - return val | keys[num & 0x03]; -} - -/* initialize driver & display */ -int drv_GLCD2USB_init(const char *section, const __attribute__ ((unused)) - int quiet) -{ - int ret; - - info("%s: %s", Name, "$Rev$"); - - /* real worker functions */ - drv_generic_graphic_real_blit = drv_GLCD2USB_blit; - drv_generic_keypad_real_press = drv_GLCD2USB_keypad; - - /* start display */ - if ((ret = drv_GLCD2USB_start(section)) != 0) - return ret; - - /* initialize generic graphic driver */ - if ((ret = drv_generic_graphic_init(section, Name)) != 0) - return ret; - - /* register plugins */ - AddFunction("LCD::brightness", 1, plugin_brightness); - - return 0; -} - - -/* close driver & display */ -int drv_GLCD2USB_quit(const __attribute__ ((unused)) - int quiet) -{ - int err; - - info("%s: shutting down.", Name); - drv_generic_graphic_quit(); - - /* release access to display */ - - buffer.bytes[0] = GLCD2USB_RID_SET_ALLOC; - buffer.bytes[1] = 0; /* 1=alloc, 0=free */ - if ((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, 2)) != 0) { - error("%s Error freeing display: %s", Name, usbErrorMessage(err)); - } - - /* clean up */ - if (dev != NULL) - usbCloseDevice(dev); - - if (video_buffer != NULL) { - free(video_buffer); - free(dirty_buffer); - } - - return (0); -} - - -DRIVER drv_GLCD2USB = { - .name = Name, - .list = drv_GLCD2USB_list, - .init = drv_GLCD2USB_init, - .quit = drv_GLCD2USB_quit, -}; |
