/*
* USB driver module for Hitachi HD44780 based LCD displays.
* http://www.bwct.de/lcd.html
*
* Copyright (c) 2004, Bernd Walter <bernd@bwct.de>
* Contributions:
* Copyright (c) 2004, Peter Marschall <peter@adpm.de>
*
* 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 <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <usb.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#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 *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;
p->hd44780_functions->close = bwct_usb_HD44780_close;
/* 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();
bwct_usb = NULL;
for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
struct usb_device *dev;
for (dev = bus->devices; dev != NULL; dev = dev->next) {
int c;
/* Check if this device is a BWCT device */
if (dev->descriptor.idVendor != BWCT_USB_VENDORID) {
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 lcd */
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 == BWCT_USB_PRODUCTID)) {
/* 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");
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, BWCT_LCD_SET_CONTRAST,
(contrast * 255) / 1000, bwct_usb_i, NULL, 0, 1000);
if (res < 0)
report(RPT_WARNING, "hd_init_bwct_usb: setting contrast failed");
} else {
report(RPT_INFO, "hd_init_bwct_usb: Using default contrast value");
}
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) ? BWCT_LCD_DATA : BWCT_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;
}
void
bwct_usb_HD44780_close(PrivateData *p)
{
if (bwct_usb != NULL) {
usb_close(bwct_usb);
bwct_usb = NULL;
}
}
/* EOF */
syntax highlighted by Code2HTML, v. 0.9.1