/* $Id$ * $URL$ * * GLCD2USB driver for LCD4Linux * (see http://www.harbaum.org/till/glcd2usb for hardware) * * Copyright (C) 2007 Till Harbaum * * 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 #include #include #include #include #include #include #include #include #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
/* $Id$
 * $URL$
 *
 * generic driver helper for keypads
 *
 * Copyright (C) 2006 Chris Maj <cmaj@freedomcorpse.com>
 * Copyright (C) 2006 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 *
 * This program 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.
 *
 * This program 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.
 *
 */

#ifndef _DRV_GENERIC_KEYPAD_H_
#define _DRV_GENERIC_KEYPAD_H_

#include "widget.h"

/* these functions must be implemented by the real driver */
extern int (*drv_generic_keypad_real_press) (const int num);

/* generic functions and widget callbacks */
int drv_generic_keypad_init(const char *section, const char *driver);
int drv_generic_keypad_press(const int num);
int drv_generic_keypad_quit(void);

#endif
tes[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, };