From 181cec4348da40331b3e8ab365732c025ec149b2 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Wed, 27 Apr 2011 19:24:15 +0200 Subject: Import upstream version 0.11.0~svn1143 --- drv_USBHUB.c | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 340 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..f0050da --- /dev/null +++ b/drv_USBHUB.c @@ -0,0 +1,340 @@ +/* $Id: drv_USBHUB.c 1126 2010-07-13 03:25:44Z michael $ + * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_USBHUB.c $ + * + * driver for USBHUB + * + * 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. + * + */ + +/* + * + * 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 unsigned int hubVendor = 0x0409; +static unsigned 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", Name); + 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 __attribute__ ((unused)) + 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", Name); + return -1; + } + if (sscanf(buf, "0x%x", &hubVendor) != 1) { + error("%s: Strange Vendor Specification: [%s]", Name, buf); + return -1; + } + } + + buf = cfg_get(section, "Product", NULL); + if (buf) { + if (!*buf) { + error("%s: Strange Product Specification", Name); + return -1; + } + if (sscanf(buf, "0x%x", &hubProduct) != 1) { + error("%s: Strange Product Specification: [%s]", Name, 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("USBHUB"); + return 0; +} + + +/* initialize driver & display */ +int drv_UH_init(const char *section, const int quiet) +{ + int ret; + int i; + + info("%s: %s", Name, "$Rev: 1126 $"); + + + + /* 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