From 8029d9e8c20c56b5013ff3ce2a203084e12dd638 Mon Sep 17 00:00:00 2001 From: reinelt Date: Tue, 8 Aug 2006 19:35:22 +0000 Subject: [lcd4linux @ 2006-08-08 19:35:21 by reinelt] USBHUB driver from Ernst Bachmann git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@683 3ae390bd-cb1e-0410-b409-cd5a39f66f1f --- drv_USBHUB.c | 344 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 drv_USBHUB.c (limited to 'drv_USBHUB.c') diff --git a/drv_USBHUB.c b/drv_USBHUB.c new file mode 100644 index 0000000..871850a --- /dev/null +++ b/drv_USBHUB.c @@ -0,0 +1,344 @@ +/* $Id: drv_USBHUB.c,v 1.1 2006/08/08 19:35:22 reinelt Exp $ + * + * new style driver for USBLCD displays + * + * Copyright (C) 2006 Ernst Bachmann + * Copyright (C) 2004,2006 The LCD4Linux Team + * + * Based on the USBLCD driver Copyright (C) 2003 Michael Reinelt + * + * 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. + * + * + * $Log: drv_USBHUB.c,v $ + * Revision 1.1 2006/08/08 19:35:22 reinelt + * USBHUB driver from Ernst Bachmann + * + * + */ + +/* + * + * exported fuctions: + * + * struct DRIVER drv_USBHUB + * + */ + +#include "config.h" + +#ifdef HAVE_USB_H +# include +#else +# error The USB-HUB driver only makes sense with USB support +#endif + +#include "debug.h" +#include "cfg.h" +#include "qprintf.h" +#include "udelay.h" +#include "drv.h" +#include "drv_generic_gpio.h" + + + +#define HUB_CONTROL_PORT 0x23 +#define HUB_SET_FEATURE 3 +#define HUB_SET_INDICATOR 22 + +static char Name[] = "USBHUB"; + +/* TODO: Better not specify defaults here, + * instead look for the first suitable HUB arround if + * no Vendor/Product specified in config. + */ + +static int hubVendor=0x0409; +static int hubProduct=0x0058; + +static usb_dev_handle *hub=NULL; + +typedef struct _usb_hub_descriptor { + u_int8_t bLength; + u_int8_t bDescriptorType; + u_int8_t nNbrPorts; + u_int8_t wHubCharacteristicLow; + u_int8_t wHubCharacteristicHigh; + u_int8_t bPwrOn2PwrGood; + u_int8_t bHubContrCurrent; + u_int8_t deviceRemovable; + u_int8_t PortPwrCtrlMask[8]; +} usb_hub_descriptor; + +/****************************************/ +/*** hardware dependant functions ***/ +/****************************************/ + + +static int drv_UH_open(void) +{ + struct usb_bus *busses, *bus; + struct usb_device *dev; + + hub = NULL; + + info("%s: scanning for an USB HUB (0x%04x:0x%04x)...", Name,hubVendor,hubProduct); + + usb_init(); + usb_find_busses(); + usb_find_devices(); + busses = usb_get_busses(); + + for (bus = busses; bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if ((dev->descriptor.idVendor == hubVendor) && + (dev->descriptor.idProduct == hubProduct)) { + + unsigned int v = dev->descriptor.bcdDevice; + + info("%s: found USBHUB V%1d%1d.%1d%1d on bus %s device %s", Name, + (v & 0xF000) >> 12, (v & 0xF00) >> 8, (v & 0xF0) >> 4, (v & 0xF), bus->dirname, dev->filename); + + if (dev->descriptor.bDeviceClass != USB_CLASS_HUB) { + error("%s: the specified device claims to be no HUB"); + return -1; + } + + hub = usb_open(dev); + if (!hub) { + error("%s: usb_open() failed!", Name); + return -1; + } + return 0; + } + } + } + error("%s: could not find a USB HUB", Name); + return -1; +} + + +static int drv_UH_close(void) +{ + debug("closing USB handle"); + + usb_close(hub); + + return 0; +} + + +/* + * Set the Indicator status on port "num+1" to val. + * according to the USB Specification, the following values would be allowed: + * + * 0 : Automatic color (display link state etc) + * 1 : Amber + * 2 : Green + * 3 : Off + * 4..255: Reserved + * + */ + +static int drv_UH_set(const int num, const int val) { + int ret; + + if (!hub) + return -1; + + if (val <0 || val > 3) { + info("%s: value %d out of range (0..3)",Name,val); + return -1; + } + + if((ret=usb_control_msg(hub, + HUB_CONTROL_PORT, + HUB_SET_FEATURE, + HUB_SET_INDICATOR, (val << 8) | (num+1), NULL, 0, 1000)) != 0) { + info("%s: usb_control_msg failed with %d",Name,ret); + return -1; + } + + return 0; +} + + +static int drv_UH_start(const char *section, const int quiet) +{ + char * buf; + + usb_hub_descriptor hub_desc; + int ret; + + + buf=cfg_get(section,"Vendor",NULL); + if (buf) { + if (!*buf) { + error("%s: Strange Vendor Specification"); + return -1; + } + if (sscanf(buf,"0x%x",&hubVendor) != 1) { + error("%s: Strange Vendor Specification: [%s]",buf); + return -1; + } + } + + buf=cfg_get(section,"Product",NULL); + if (buf) { + if (!*buf) { + error("%s: Strange Product Specification"); + return -1; + } + if (sscanf(buf,"0x%x",&hubProduct) != 1) { + error("%s: Strange Product Specification: [%s]",buf); + return -1; + } + } + + if (drv_UH_open() < 0) { + return -1; + } + + + if ((ret=usb_control_msg(hub, + USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE, + USB_REQ_GET_DESCRIPTOR,USB_DT_HUB << 8,0,(char *)&hub_desc,sizeof(hub_desc),1000)) <= 8) { + error("%s: hub_get_descriptor failed with %d",Name,ret); + drv_UH_close(); + return -1; + } + GPOS=hub_desc.nNbrPorts; + debug("%s: HUB claims to have %d ports. Configuring them as GPOs",Name,GPOS); + if (!(hub_desc.wHubCharacteristicLow & 0x80)) { + error("%s: HUB claims to have no Indicator LEDs (Characteristics 0x%04x). Bailing out.",Name, + (hub_desc.wHubCharacteristicHigh << 8) | hub_desc.wHubCharacteristicLow); + /* The HUB Tells us that there are no LEDs to control. Breaking? Maybe don't trust it and continue anyways? */ + drv_UH_close(); + return -1; + + } + + return 0; +} + + +/****************************************/ +/*** plugins ***/ +/****************************************/ + +/* none at the moment... */ + + +/****************************************/ +/*** widget callbacks ***/ +/****************************************/ + + +/* using drv_generic_text_draw(W) */ +/* using drv_generic_text_icon_draw(W) */ +/* using drv_generic_text_bar_draw(W) */ + + +/****************************************/ +/*** exported functions ***/ +/****************************************/ + + +/* list models */ +int drv_UH_list(void) +{ + printf("generic"); + return 0; +} + + +/* initialize driver & display */ +int drv_UH_init(const char *section, const int quiet) +{ + int ret; + int i; + + info("%s: %s", Name, "$Revision: 1.1 $"); + + + + /* start display */ + if ((ret = drv_UH_start(section, quiet)) != 0) + return ret; + + + /* real worker functions */ + drv_generic_gpio_real_set=drv_UH_set; + + + /* initialize generic GPIO driver */ + if ((ret = drv_generic_gpio_init(section, Name)) != 0) + return ret; + + /* register gpio widget, done already by generic_gpio */ + + /* register plugins */ + /* none at the moment... */ + + /* greeting */ + if (!quiet) { + /* Light all LEDS green for a greeting */ + for (i=0; i < GPOS; ++i) { + drv_UH_set(i,2); + } + sleep(1); + for (i=0; i < GPOS; ++i) { + drv_UH_set(i,3); // OFF + } + } + + + return 0; +} + + +/* close driver & display */ +int drv_UH_quit(const int quiet) +{ + int i; + debug("%s: shutting down.", Name); + + /* say goodbye... */ + if (!quiet) { + /* Light all LEDS amber for a goodbye */ + for (i=0; i < GPOS; ++i) { + drv_UH_set(i,1); + } + sleep(1); + + } + + drv_generic_gpio_quit(); + + drv_UH_close(); + + info("%s: shutdown complete.", Name); + return 0; +} + + +DRIVER drv_USBHUB = { + name:Name, + list:drv_UH_list, + init:drv_UH_init, + quit:drv_UH_quit, +}; -- cgit v1.2.3