From 11fe5963519ab94c8edacd8abbd244f9cbfa0cb1 Mon Sep 17 00:00:00 2001 From: marschap Date: Sat, 9 Oct 2004 16:15:37 +0000 Subject: [PATCH] add ConnectionType sub-driver for BWCT USB devices to the HD44780 driver --- acinclude.m4 | 12 +- configure.in | 119 ++++++++++++- docs/lcdproc-user/drivers/hd44780.docbook | 20 +++ server/drivers/Makefile.am | 9 +- server/drivers/hd44780-bwct-usb.c | 202 ++++++++++++++++++++++ server/drivers/hd44780-bwct-usb.h | 22 +++ server/drivers/hd44780-drivers.h | 6 + server/drivers/hd44780.c | 14 ++ 8 files changed, 394 insertions(+), 10 deletions(-) create mode 100644 server/drivers/hd44780-bwct-usb.c create mode 100644 server/drivers/hd44780-bwct-usb.h diff --git a/acinclude.m4 b/acinclude.m4 index e5bb2a5..cbb1f8b 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -136,6 +136,9 @@ dnl else else HD44780_DRIVERS="hd44780-picanlcd.o" fi + if test "$enable_libusb" = yes ; then + HD44780_DRIVERS="$HD44780_DRIVERS hd44780-bwct-usb.o" + fi DRIVERS="$DRIVERS hd44780${SO}" actdrivers=["$actdrivers hd44780"] ;; @@ -149,14 +152,12 @@ dnl else ]) ;; iowarrior) - AC_CHECK_LIB(usb, main,[ - LIBUSB="-lusb" + if test "$enable_libusb" = yes ; then DRIVERS="$DRIVERS IOWarrior${SO}" actdrivers=["$actdrivers iowarrior"] - ],[ -dnl else + else AC_MSG_WARN([The iowarrior driver needs the libusb library.]) - ]) + fi ;; irman) AC_CHECK_LIB(irman, main,[ @@ -239,7 +240,6 @@ actdrivers=`echo $actdrivers | sed 's/ /,/g'` AC_MSG_RESULT([Will compile drivers: $actdrivers]) AC_SUBST(LIBCURSES) -AC_SUBST(LIBUSB) AC_SUBST(LIBIRMAN) AC_SUBST(LIBLIRC_CLIENT) AC_SUBST(LIBSVGA) diff --git a/configure.in b/configure.in index c3356de..1af41c0 100644 --- a/configure.in +++ b/configure.in @@ -166,7 +166,7 @@ AC_ARG_ENABLE(stat-nfs, AC_ARG_ENABLE(stat-smbfs, [ --enable-stat-smbfs display filesystem stats for SMBFS], - AC_DEFINE(STAT_SMBFS,[1],[iDefine to 1 to display filesystem stats for SMBFS]) + AC_DEFINE(STAT_SMBFS,[1],[Define to 1 to display filesystem stats for SMBFS]) ) @@ -200,6 +200,123 @@ AC_DEFINE_UNQUOTED(LOAD_MIN, $LOAD_MIN, [Define min Load Avg at which the backli AC_MODULES_INFO +dnl ###################################################################### +dnl USB support +dnl +dnl not all options have effect at the moment + +AC_SUBST(libusb_libs) +AC_SUBST(libusb_cflags) + +enable_libusb=yes +AC_MSG_CHECKING([if libusb support has been enabled]); +AC_ARG_ENABLE( + libusb, + [ --enable-libusb compile with USB support using libusb. ], + [ + if test "$enable_libusb" = "yes"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + ], + [ + enable_libusb="no"; + AC_MSG_RESULT(no) + ] +) + +AC_PATH_PROG(libusb_config,libusb-config, :) + +if test "$enable_libusb" = "yes"; then +AC_ARG_WITH( + libusb-includes, + [ --with-libusb-includes=DIR + libusb include files are in DIR + (default: found by libusb-config). ], + [ + if test "$withval" = "no"; then + libusb_build_dir=""; + else + libusb_includepath="$withval" + libusb_cflags="-I$withval" + fi + ], + [ + AC_MSG_CHECKING(libusb CFLAGS) + if test "x$libusb_config" != x ; then + libusb_cflags=`$libusb_config --cflags` + else + for libusb_includepath in /usr/include /usr/local/include \ + /usr/include/libusb /usr/local/include/libusb \ + /usr/include/usb /usr/local/include/usb ; do \ + if test -f "${ibusb_includepath}/libusb.h"; then + libusb_cflags="-I$libusb_includepath" + break + fi + done + fi + AC_MSG_RESULT($libusb_cflags) + ] +) + +if test x$libusb_includepath != x ; then +AC_CHECK_FILE( + $libusb_includepath/usb.h, + [ : ] , + [ enable_libusb="no" ] +) +fi +fi + +if test "$enable_libusb" = "yes"; then +AC_ARG_WITH( + libusb-libraries, + [ --with-libusb-libraries=DIR + libusb library files are in DIR + (default: found by libusb-config). ], + [ + if test "$withval" = "no"; then + libusb_build_dir=""; + else + libusb_libs="-L$withval -lusb" + fi + ], + [ + AC_MSG_CHECKING(libusb library path) + if test "x$libusb_config" != x ; then + libusb_libs=`$libusb_config --libs` + else + for libusb_libpath in /lib /usr/lib /usr/local/lib \ + /lib/libusb /usr/lib/libusb /usr/local/lib/libusb \ + /lib/usb /usr/lib/usb /usr/local/lib/usb ; do + if test -f "${libusb_libpath}/libusb.a" -o -f "${libusb_libpath}/libusb.so"; then + libusb_libs="-L$libusb_libpath -lusb" + break + fi + done + fi + AC_MSG_RESULT($libusb_libs) + ] +) + +AC_CHECK_LIB( + usb, + main, + [ : ], + [ enable_libusb="no" ], + $libusb_libs +) +fi + +if test "$enable_libusb" = "yes"; then + AC_DEFINE(HAVE_LIBUSB,[1],[Define to 1 if you have the libusb library]) +else + libusb_libs=""; + libusb_cflags=""; +fi + + LCD_DRIVERS_SELECT dnl ###################################################################### diff --git a/docs/lcdproc-user/drivers/hd44780.docbook b/docs/lcdproc-user/drivers/hd44780.docbook index 66e4319..ebba414 100644 --- a/docs/lcdproc-user/drivers/hd44780.docbook +++ b/docs/lcdproc-user/drivers/hd44780.docbook @@ -1011,6 +1011,22 @@ It does not support a keypad nor backlight switching. + +BWCT USB device "bwctusb" + + +The BWCT USB LCD module is also supported. It is not connected to an LPT port +but to an USB port, which saves you from a lot of potential problems. +To use it, set the connection type in the config file with the ConnectionType= +setting to "bwctusb" (without the quotes). +It does neithert support a keypad nor backlight switching but it supports setting +the display's contrast using the "Contrast" configuration parameter as well as +specifying which one (of multiple BWCT LCD devices) is wanted using the +"SerialNumber" configuration parameter. + + + + @@ -1067,6 +1083,10 @@ it clear, how the ConnectionType is to be set. PIC-an-LCD serial device "picanlcd" picanlcd + +BWCT USB device "bwctusb" +bwctusb + diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am index f708bc2..a824358 100644 --- a/server/drivers/Makefile.am +++ b/server/drivers/Makefile.am @@ -21,15 +21,18 @@ pkglib_PROGRAMS = @DRIVERS@ EXTRA_PROGRAMS = bayrad CFontz CFontz633 curses CwLnx glk hd44780 irman icp_a106 joy lb216 mtc_s16209x lcdm001 lcterm lirc MtxOrb sed1330 sed1520 stv5730 svga t6963 text wirz_sli ms6931 IOWarrior noinst_LIBRARIES = libLCD.a +IOWarrior_CFLAGS = @libusb_cflags@ +hd44780_CFLAGS = @libusb_cflags@ + CFontz_LDADD = libLCD.a CFontz633_LDADD = libLCD.a curses_LDADD = @LIBCURSES@ CwLnx_LDADD = libLCD.a CwLnx_SOURCES = lcd.h CwLnx.c CwLnx.h report.h -hd44780_LDADD = libLCD.a @HD44780_DRIVERS@ +hd44780_LDADD = libLCD.a @HD44780_DRIVERS@ @libusb_libs@ hd44780_DEPENDENCIES = @HD44780_DRIVERS@ icp_a106_LDADD = libLCD.a -IOWarrior_LDADD = @LIBUSB@ libLCD.a +IOWarrior_LDADD = @libusb_libs@ libLCD.a irman_LDADD = @LIBIRMAN@ lirc_LDADD = @LIBLIRC_CLIENT@ lcterm_LDADD = libLCD.a @@ -44,7 +47,7 @@ CFontz633_SOURCES = lcd.h CFontz633.c CFontz633.h CFontz633io.c CFontz633io.h r curses_SOURCES = lcd.h curses_drv.h curses_drv.c report.h glk_SOURCES = lcd.h glk.c glk.h glkproto.c glkproto.h report.h hd44780_SOURCES = lcd.h hd44780.h hd44780.c hd44780-drivers.h hd44780-low.h hd44780-charmap.h report.h -EXTRA_hd44780_SOURCES = hd44780-4bit.c hd44780-4bit.h hd44780-ext8bit.c hd44780-ext8bit.h lcd_sem.c lcd_sem.h hd44780-serialLpt.c hd44780-serialLpt.h hd44780-winamp.c hd44780-winamp.h hd44780-picanlcd.c hd44780-picanlcd.h port.h lpt-port.h timing.h +EXTRA_hd44780_SOURCES = hd44780-4bit.c hd44780-4bit.h hd44780-ext8bit.c hd44780-ext8bit.h lcd_sem.c lcd_sem.h hd44780-serialLpt.c hd44780-serialLpt.h hd44780-winamp.c hd44780-winamp.h hd44780-picanlcd.c hd44780-picanlcd.h hd44780-bwct-usb.c hd44780-bwct-usb.h port.h lpt-port.h timing.h icp_a106_SOURCES = lcd.h icp_a106.c icp_a106.h report.h IOWarrior_SOURCES = lcd.h lcd_lib.h hd44780-charmap.h IOWarrior.c IOWarrior.h report.h diff --git a/server/drivers/hd44780-bwct-usb.c b/server/drivers/hd44780-bwct-usb.c new file mode 100644 index 0000000..ba5a7de --- /dev/null +++ b/server/drivers/hd44780-bwct-usb.c @@ -0,0 +1,202 @@ +/* + * USB driver module for Hitachi HD44780 based LCD displays. + * http://www.bwct.de/lcd.html + * + * Copyright (c) 2004, Bernd Walter + * Contributions: + * Copyright (c) 2004, Peter Marschall + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + */ + +#include "hd44780-bwct-usb.h" + +#include "report.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +/* USB device handle & interface index we write to */ +static usb_dev_handle *bwct_usb; +static int bwct_usb_i; + + +// initialize the driver +int +hd_init_bwct_usb (Driver *drvthis) +{ + PrivateData *p = (PrivateData*) drvthis->private_data; + struct usb_bus *busses; + struct usb_bus *bus; + char device_manufacturer[LCD_MAX_WIDTH+1] = ""; + char device_serial[LCD_MAX_WIDTH+1] = DEFAULT_SERIALNO; + char serial[LCD_MAX_WIDTH+1] = DEFAULT_SERIALNO; + int contrast = -1; /* illegal contrast value (to detect errors) */ + + p->hd44780_functions->senddata = bwct_usb_HD44780_senddata; + p->hd44780_functions->backlight = bwct_usb_HD44780_backlight; + p->hd44780_functions->scankeypad = bwct_usb_HD44780_scankeypad; + + /* Read config file's contents: serial number and contrast */ + + strncpy(serial, drvthis->config_get_string(drvthis->name, "SerialNumber", + 0, DEFAULT_SERIALNO), sizeof(serial)); + serial[sizeof(serial)-1] = '\0'; + if (*serial != '\0') { + report(RPT_INFO, "hd_init_bwct_usb: Using serial number: %s", serial); + } + + contrast = drvthis->config_get_int(drvthis->name, "Contrast", 0, DEFAULT_CONTRAST); + + /* try to find USB device */ +#if 0 + usb_debug = 2; +#endif + + usb_init(); + usb_find_busses(); + usb_find_devices(); + busses = usb_get_busses(); + + bwct_usb = NULL; + for (bus = busses; bus; bus = bus->next) { + struct usb_device *dev; + + for (dev = bus->devices; dev; dev = dev->next) { + int c; + + /* Check if this device is a BWCT device */ + if (dev->descriptor.idVendor != 0x03DA) { + continue; + } + /* Loop through all of the configurations */ + for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { + /* Loop through all of the interfaces */ + for (bwct_usb_i = 0; bwct_usb_i < dev->config[c].bNumInterfaces; bwct_usb_i++) { + int a; + + /* Loop through all of the alternate settings */ + for (a = 0; a < dev->config[c].interface[bwct_usb_i].num_altsetting; a++) { + /* Check if this interface is a BWCT ulcd */ + if (((dev->config[c].interface[bwct_usb_i].altsetting[a].bInterfaceClass == 0xFf) && + (dev->config[c].interface[bwct_usb_i].altsetting[a].bInterfaceSubClass == 0x01)) || + (dev->descriptor.idProduct == 0x0002)) { + + /* BWCT device found; try to find its description and serial number */ + bwct_usb = usb_open(dev); + if (bwct_usb == NULL) { + report(RPT_WARNING, "hd_init_bwct_usb: unable to open device"); + // return -1; /* it's better to continue */ + } + else { + /* get device information & check for serial number */ + //if (usb_get_string_simple(bwct_usb, dev->descriptor.iManufacturer, + // manufacturer, LCD_MAX_WIDTH) <= 0) + // *manufacturer = '\0'; + //manufacturer[sizeof(manufacturer)-1] = '\0'; + + //if (usb_get_string_simple(bwct_usb, dev->descriptor.iProduct, + // product, LCD_MAX_WIDTH) <= 0) + // *product = '\0'; + //product[sizeof(product)-1] = '\0'; + + if (usb_get_string_simple(bwct_usb, dev->descriptor.iSerialNumber, + device_serial, LCD_MAX_WIDTH) <= 0) + *device_serial = '\0'; + device_serial[sizeof(device_serial)-1] = '\0'; + if ((*serial != '\0') && (*device_serial == '\0')) { + report(RPT_ERR, "hd_init_bwct_usb: unable to get device's serial number"); + usb_close(bwct_usb); + return -1; + } + + /* succeed if no serial was given in the config or the 2 numbers match */ + if ((*serial == '\0') || (strcmp(serial, device_serial) == 0)) + goto done; + + usb_close(bwct_usb); + bwct_usb = NULL; + } + } + } + } + } + } + } + + done: + if (bwct_usb != NULL) { + debug(RPT_DEBUG, "hd_init_bwct_usb: opening device succeeded\n"); + + if (usb_claim_interface(bwct_usb, bwct_usb_i) < 0) { +#if defined(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP) + if ((usb_detach_kernel_driver_np(bwct_usb, bwct_usb_i) < 0) || + (usb_claim_interface(bwct_usb, bwct_usb_i) < 0)) { + usb_close(bwct_usb); + report(RPT_ERR, "hd_init_bwct_usb: unable to re-claim interface"); + return -1; + } +#else + usb_close(bwct_usb); + report(RPT_ERR, "hd_init_bwct_usb: unable to claim interface"); + return -1; +#endif + } + } + else { + report(RPT_ERR, "hd_init_bwct_usb: no (matching) BWCT device found"); + return -1; + } + + common_init(p, IF_4BIT); + + /* set contrast */ + if ((0 <= contrast) && (contrast <= 1000)) { + int res = usb_control_msg(bwct_usb, USB_TYPE_VENDOR, VENDOR_LCD_CONTRAST, + (contrast * 255) / 1000, bwct_usb_i, NULL, 0, 1000); + if (res < 0) + report(RPT_WARNING, "hd_init_bwct_usb: setting contrast failed.\n"); + } else { + report(RPT_WARNING, "hd_init_bwct_usb: Using default contrast value.\n"); + } + + return 0; +} + + +// bwct_usb_HD44780_senddata +void +bwct_usb_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch) +{ +int type = (flags == RS_DATA) ? VENDOR_LCD_DATA : VENDOR_LCD_CMD; + + usb_control_msg(bwct_usb, USB_TYPE_VENDOR, type, ch, bwct_usb_i, NULL, 0, 1000); +} + + +void +bwct_usb_HD44780_backlight(PrivateData *p, unsigned char state) +{ +} + + +unsigned char +bwct_usb_HD44780_scankeypad(PrivateData *p) +{ + return 0; +} diff --git a/server/drivers/hd44780-bwct-usb.h b/server/drivers/hd44780-bwct-usb.h new file mode 100644 index 0000000..5ea4bbc --- /dev/null +++ b/server/drivers/hd44780-bwct-usb.h @@ -0,0 +1,22 @@ +#ifndef HD_BWCT_USB_H +#define HD_BWCT_USB_H + +#include "lcd.h" /* for Driver */ +#include "hd44780-low.h" + +#define VENDOR_LCD_RESET 1 +#define VENDOR_LCD_CMD 2 +#define VENDOR_LCD_DATA 3 +#define VENDOR_LCD_CONTRAST 4 + +#define DEFAULT_SERIALNO "" +#define DEFAULT_CONTRAST 300 + +// initialise this particular driver +int hd_init_bwct_usb(Driver *drvthis); + +void bwct_usb_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch); +void bwct_usb_HD44780_backlight(PrivateData *p, unsigned char state); +unsigned char bwct_usb_HD44780_scankeypad(PrivateData *p); + +#endif diff --git a/server/drivers/hd44780-drivers.h b/server/drivers/hd44780-drivers.h index 8b8c654..6939701 100644 --- a/server/drivers/hd44780-drivers.h +++ b/server/drivers/hd44780-drivers.h @@ -17,6 +17,9 @@ # include "hd44780-serialLpt.h" # include "hd44780-winamp.h" #endif +#ifdef HAVE_LIBUSB +# include "hd44780-bwct-usb.h" +#endif #include "hd44780-picanlcd.h" // add new connection type header files here @@ -32,6 +35,9 @@ static const ConnectionMapping connectionMapping[] = { {"winamp", hd_init_winamp, "\tnone\n"}, #endif {"picanlcd", hd_init_picanlcd, "\tnone\n"}, +#ifdef HAVE_LIBUSB + {"bwctusb", hd_init_bwct_usb, "\tnone\n"}, +#endif // add new connection types and their string specifier here // default, end of structure element (do not delete) {NULL, NULL, NULL} diff --git a/server/drivers/hd44780.c b/server/drivers/hd44780.c index 2e06d3f..15e7b79 100644 --- a/server/drivers/hd44780.c +++ b/server/drivers/hd44780.c @@ -129,6 +129,7 @@ HD44780_init (Driver * drvthis, char *args) char buf[40]; char *s; int i; + int usb = 0; PrivateData *p; // Alocate and store private data @@ -163,6 +164,10 @@ HD44780_init (Driver * drvthis, char *args) return -1; // fatal error } else { p->connectiontype_index = i; + # check if ConnectionType contains the string "USB" or "usb" + if ((strstr(connectionMapping[i].name, "usb") != NULL) || + (strstr(connectionMapping[i].name, "USB") != NULL)) + usb = 1; } // Get and parse vspan only when specified @@ -302,11 +307,20 @@ HD44780_init (Driver * drvthis, char *args) HD44780_clear (drvthis); sprintf (buf, "HD44780 %dx%d", p->width, p->height ); HD44780_string (drvthis, 1, 1, buf); + if (usb) { + sprintf (buf, "USB %s%s%s", + (p->have_backlight?" bl":""), + (p->have_keypad?" key":""), + (p->have_output?" out":"") + ); + } + else { sprintf (buf, "LPT 0x%x%s%s%s", p->port, (p->have_backlight?" bl":""), (p->have_keypad?" key":""), (p->have_output?" out":"") ); + } HD44780_string (drvthis, 1, 2, buf); HD44780_flush (drvthis); sleep (2);