diff -Naur usbip-0.1.4/drivers/2.6.15/Makefile trunk/drivers/2.6.15/Makefile --- usbip-0.1.4/drivers/2.6.15/Makefile 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,63 +0,0 @@ -# Makefile for the USB/IP driver -# -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ -# -# Copyright (C) 2003-2006 Takahiro Hirofuchi -# -# -# This 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 of the License, or -# (at your option) any later version. -# -# This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -# USA. -# - - -# Please modify here or set environments. -# KSOURCE should be pointed to the build directory of your kernel. -# -DEBUG ?= n -KSOURCE ?= /usr/src/linux - - -%.x:%.c - gcc -o $@ $< - -KBUILD_VERBOSE:=1 - -HCD_HEADER:=$(KSOURCE)/drivers/usb/core/hcd.h - -obj-m += usbip.o -usbip-objs := usbip_common.o usbip_event.o stub_dev.o stub_main.o stub_rx.o stub_tx.o - -obj-m += vhci-hcd.o -vhci-hcd-objs := usbip_common.o usbip_event.o vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o - - -EXTRA_CFLAGS += -DHCD_HEADER=\"$(HCD_HEADER)\" - -ifeq ($(DEBUG),y) - EXTRA_CFLAGS += -DCONFIG_USB_DEBUG -endif - - -default: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules - -.PHONY: cscope -cscope: - cscope -b -k -R - -.PHONY: clean -clean: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` clean - rm -f *.x *~ diff -Naur usbip-0.1.4/drivers/2.6.15/stub_dev.c trunk/drivers/2.6.15/stub_dev.c --- usbip-0.1.4/drivers/2.6.15/stub_dev.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/stub_dev.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,438 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - - -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void stub_disconnect(struct usb_interface *interface); - - -/* - * Define device IDs here if you want to explicitly limit exportable devices. - * In the most cases, wild card matching will be ok because driver binding can - * be changed dynamically by a userland program. - */ -static struct usb_device_id stub_table[] = { -#if 0 - /* just an example */ - { USB_DEVICE(0x05ac, 0x0301) }, /* Mac 1 button mouse */ - { USB_DEVICE(0x0430, 0x0009) }, /* Plat Home Keyboard */ - { USB_DEVICE(0x059b, 0x0001) }, /* Iomega USB Zip 100 */ - { USB_DEVICE(0x04b3, 0x4427) }, /* IBM USB CD-ROM */ - { USB_DEVICE(0x05a9, 0xa511) }, /* LifeView USB cam */ - { USB_DEVICE(0x55aa, 0x0201) }, /* Imation card reader */ - { USB_DEVICE(0x046d, 0x0870) }, /* Qcam Express(QV-30) */ - { USB_DEVICE(0x04bb, 0x0101) }, /* IO-DATA HD 120GB */ - { USB_DEVICE(0x04bb, 0x0904) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x04bb, 0x0201) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x08bb, 0x2702) }, /* ONKYO USB Speaker */ - { USB_DEVICE(0x046d, 0x08b2) }, /* Logicool Qcam 4000 Pro */ -#endif - /* magic for wild card */ - { .driver_info = 1 }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, stub_table); - - -struct usb_driver stub_driver = { - .name = "usbip", - - .probe = stub_probe, - .disconnect = stub_disconnect, - - .id_table = stub_table, -}; - - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for a usbip-bound device */ - - -/* - * usbip_status shows status of usbip as long as this driver is bound to the - * target device. - */ -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int status; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - spin_lock(&sdev->ud.lock); - status = sdev->ud.status; - spin_unlock(&sdev->ud.lock); - - return snprintf(buf, PAGE_SIZE, "%d\n", status); -} -static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL); - - -/* - * usbip_sockfd gets a socket descriptor of an established TCP connection that - * is used to transfer usbip requests by kernel threads. -1 is a magic number - * by which usbip connection is finished. - */ -static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int sockfd = 0; - struct socket *socket; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - sscanf(buf, "%d", &sockfd); - - if (sockfd != -1) { - uinfo("stub up\n"); - - spin_lock(&sdev->ud.lock); - - if (sdev->ud.status != SDEV_ST_AVAILABLE) { - uerr("not ready\n"); - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - socket = sockfd_to_socket(sockfd); - if (!socket) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - setnodelay(socket); - setkeepalive(socket); - setreuse(socket); - - sdev->ud.tcp_socket = socket; - - spin_unlock(&sdev->ud.lock); - - usbip_start_threads(&sdev->ud); - - spin_lock(&sdev->ud.lock); - sdev->ud.status = SDEV_ST_USED; - spin_unlock(&sdev->ud.lock); - - } else { - uinfo("stub down\n"); - - spin_lock(&sdev->ud.lock); - if (sdev->ud.status != SDEV_ST_USED) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - spin_unlock(&sdev->ud.lock); - - usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); - } - - return count; -} -static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); - -static void stub_add_files(struct device *dev) -{ - device_create_file(dev, &dev_attr_usbip_status); - device_create_file(dev, &dev_attr_usbip_sockfd); - device_create_file(dev, &dev_attr_usbip_debug); -} - -static void stub_remove_files(struct device *dev) -{ - device_remove_file(dev, &dev_attr_usbip_status); - device_remove_file(dev, &dev_attr_usbip_sockfd); - device_remove_file(dev, &dev_attr_usbip_debug); -} - - - -/*-------------------------------------------------------------------------*/ - -/* Event handler functions called by an event handler thread */ - -static void stub_shutdown_connection(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - /* - * When removing an exported device, kernel panic sometimes occurred - * and then EIP was sk_wait_data of stub_rx thread. Is this because - * sk_wait_data returned though stub_rx thread was already finished by - * step 1? - */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - /* 1. stop threads */ - usbip_stop_threads(ud); - - /* 2. close the socket */ - /* - * tcp_socket is freed after threads are killed. - * So usbip_xmit do not touch NULL socket. - */ - if (ud->tcp_socket) { - sock_release(ud->tcp_socket); - ud->tcp_socket = NULL; - } - - /* 3. free used data */ - stub_device_cleanup_urbs(sdev); - - /* 4. free stub_unlink */ - { - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - } -} - -static void stub_device_reset(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - struct usb_device *udev = interface_to_usbdev(sdev->interface); - int ret; - - ret = usb_lock_device_for_reset(udev, sdev->interface); - if (ret < 0) { - uerr("lock for reset\n"); - - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); - - return; - } - - /* try to reset the device */ - ret = usb_reset_device(udev); - - usb_unlock_device(udev); - - spin_lock(&ud->lock); - if (ret) { - uerr("device reset\n"); - ud->status = SDEV_ST_ERROR; - - } else { - uinfo("device reset\n"); - ud->status = SDEV_ST_AVAILABLE; - - } - spin_unlock(&ud->lock); - - return; -} - -static void stub_device_unusable(struct usbip_device *ud) -{ - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); -} - - -/*-------------------------------------------------------------------------*/ - -/** - * stub_device_alloc - allocate a new stub_device struct - * @interface: usb_interface of a new device - * - * Allocates and initializes a new stub_devce struct. - */ -static struct stub_device * stub_device_alloc(struct usb_interface *interface) -{ - struct stub_device *sdev; - - /* yes, it's a new device */ - sdev = (struct stub_device *) kzalloc(sizeof(struct stub_device), GFP_KERNEL); - if (!sdev) { - uerr("no memory for stub_device\n"); - return NULL; - } - - sdev->interface = interface; - - usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop); - usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop); - - sdev->ud.side = USBIP_STUB; - sdev->ud.status = SDEV_ST_AVAILABLE; - sdev->ud.lock = SPIN_LOCK_UNLOCKED; - sdev->ud.tcp_socket = NULL; - - INIT_LIST_HEAD(&sdev->priv_init); - INIT_LIST_HEAD(&sdev->priv_tx); - INIT_LIST_HEAD(&sdev->priv_free); - INIT_LIST_HEAD(&sdev->unlink_free); - INIT_LIST_HEAD(&sdev->unlink_tx); - sdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&sdev->tx_waitq); - - sdev->ud.eh_ops.shutdown = stub_shutdown_connection; - sdev->ud.eh_ops.reset = stub_device_reset; - sdev->ud.eh_ops.unusable = stub_device_unusable; - - usbip_start_eh(&sdev->ud); - - udbg("register new interface\n"); - return sdev; -} - -static int stub_device_free(struct stub_device *sdev) -{ - if (!sdev) - return -EINVAL; - - kfree(sdev); - udbg("kfree udev ok\n"); - - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* - * If a usb device has multiple active interfaces, this driver is bound to all - * the active interfaces. However, usbip exports *a* usb device (i.e. not *an* - * active interface). Currently, a userland program must ensure that it - * looks at the usbip's sysfs entries of only the first active interface. - */ -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct stub_device *sdev = NULL; - char *udev_busid = interface->dev.parent->bus_id; - - udbg("Enter\n"); - - /* check we should claim or not by busid_table */ - if (match_busid(udev_busid)) { - uinfo("this device %s is not in match_busid table. skip!\n", udev_busid); - - /* - * Return value should be ENODEV or ENOXIO to continue trying - * other matched drivers by the driver core. - * See driver_probe_device() in driver/base/dd.c - */ - return -ENODEV; - } - - if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { - udbg("this device %s is a usb hub device. skip!\n", udev_busid); - return -ENODEV; - } - - if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { - udbg("this device %s is attached on vhci_hcd. skip!\n", udev_busid); - return -ENODEV; - } - - /* ok. this is my device. */ - - if ((sdev = stub_device_alloc(interface))) { - struct usb_device *udev = interface_to_usbdev(interface); - - uinfo("USB/IP Stub: register a new interface (bus %u dev %u ifn %u)\n", - udev->bus->busnum, udev->devnum, - interface->cur_altsetting->desc.bInterfaceNumber); - } else - return -ENOMEM; - - /* set private data to usb_interface */ - usb_set_intfdata(interface, sdev); - - stub_add_files(&interface->dev); - - return 0; -} - - -/* - * called in usb_disconnect() or usb_deregister() - * but only if actconfig(active configuration) exists - */ -static void stub_disconnect(struct usb_interface *interface) -{ - struct stub_device *sdev = usb_get_intfdata(interface); - - udbg("Enter\n"); - - /* get stub_device */ - if (!sdev) - BUG(); - - usb_set_intfdata(interface, NULL); - - - /* - * NOTE: - * rx/tx threads are invoked for each usb_device. - */ - stub_remove_files(&interface->dev); - - /* 1. shutdown the current connection */ - usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED); - - /* 2. wait for the stop of the event handler */ - usbip_stop_eh(&sdev->ud); - - /* 3. free sdev */ - stub_device_free(sdev); - - - udbg("bye\n"); -} diff -Naur usbip-0.1.4/drivers/2.6.15/stub.h trunk/drivers/2.6.15/stub.h --- usbip-0.1.4/drivers/2.6.15/stub.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/stub.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,96 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include -#include - -struct stub_device { - struct usb_interface *interface; - struct list_head list; - - struct usbip_device ud; - - /* - * stub_priv preserves private data of each urb. - * It is allocated as stub_priv_cache and assigned to urb->context. - * - * stub_priv is always linked to any one of 3 lists; - * priv_init: linked to this until the comletion of a urb. - * priv_tx : linked to this after the completion of a urb. - * priv_free: linked to this after the sending of the result. - * - * Any of these list operations should be locked by priv_lock. - */ - spinlock_t priv_lock; - struct list_head priv_init; - struct list_head priv_tx; - struct list_head priv_free; - - /* see comments for unlinking in stub_rx.c */ - struct list_head unlink_tx; - struct list_head unlink_free; - - - wait_queue_head_t tx_waitq; -}; - -/* private data into urb->priv */ -struct stub_priv { - unsigned long seqnum; - struct list_head list; - struct stub_device *sdev; - struct urb *urb; - - int unlinking; -}; - -struct stub_unlink { - unsigned long seqnum; - struct list_head list; - __u32 status; -}; - - -extern kmem_cache_t *stub_priv_cache; - - -/*-------------------------------------------------------------------------*/ -/* prototype declarations */ - -/* stub_tx.c */ -void stub_complete(struct urb*, struct pt_regs *); -void stub_tx_loop(struct usbip_task *); - -/* stub_dev.c */ -extern struct usb_driver stub_driver; - -/* stub_rx.c */ -void stub_rx_loop(struct usbip_task *); -void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32); - -/* stub_main.c */ -int match_busid(char *busid); -void stub_device_cleanup_urbs(struct stub_device *sdev); diff -Naur usbip-0.1.4/drivers/2.6.15/stub_main.c trunk/drivers/2.6.15/stub_main.c --- usbip-0.1.4/drivers/2.6.15/stub_main.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/stub_main.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,300 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "stub.h" - -/* Version Information */ -#define DRIVER_VERSION "$Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $" -#define DRIVER_AUTHOR "Takahiro Hirofuchi " -#define DRIVER_DESC "Stub Driver for USB/IP" - - - -/* stub_priv is allocated from stub_priv_cache */ -kmem_cache_t *stub_priv_cache = NULL; - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for the usbip driver */ - - -/* - * busid_tables defines matching busids that usbip can grab. A user can change - * dynamically what device is locally used and what device is exported to a - * remote host. - */ -#define MAX_BUSID 16 -static char busid_table[MAX_BUSID][BUS_ID_SIZE]; -spinlock_t busid_table_lock = SPIN_LOCK_UNLOCKED; - - -int match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* already registerd */ - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return 1; -} - -static ssize_t show_match_busid(struct device_driver *drv, char *buf) -{ - int i; - char *out = buf; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - out += sprintf(out, "%s ", busid_table[i]); - - spin_unlock(&busid_table_lock); - - out += sprintf(out, "\n"); - - return out - buf; -} - -static int add_match_busid(char *busid) -{ - int i; - - if (!match_busid(busid)) - return 0; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!busid_table[i][0]) { - strncpy(busid_table[i], busid, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static int del_match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* found */ - memset(busid_table[i], 0, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static ssize_t store_match_busid(struct device_driver *dev, const char *buf, - size_t count) -{ - int len; - char busid[BUS_ID_SIZE]; - - if (count < 5) - return -EINVAL; - - /* strnlen() does not include \0 */ - len = strnlen(buf + 4, BUS_ID_SIZE); - - /* busid needs to include \0 termination */ - if (!(len < BUS_ID_SIZE)) - return -EINVAL; - - strncpy(busid, buf + 4, BUS_ID_SIZE); - - - if (!strncmp(buf, "add ", 4)) { - if (add_match_busid(busid) < 0) - return -ENOMEM; - else { - udbg("add busid %s\n", busid); - return count; - } - } else if (!strncmp(buf, "del ", 4)) { - if (del_match_busid(busid) < 0) - return -ENODEV; - else { - udbg("del busid %s\n", busid); - return count; - } - } else - return -EINVAL; -} - -static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid, store_match_busid); - - - -/*-------------------------------------------------------------------------*/ - -/* Cleanup functions used to free private data */ - -static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) -{ - struct stub_priv *priv, *tmp; - - list_for_each_entry_safe(priv, tmp, listhead, list) { - list_del(&priv->list); - return priv; - } - - return NULL; -} - -static struct stub_priv *stub_priv_pop(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = stub_priv_pop_from_listhead(&sdev->priv_init); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_tx); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_free); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return NULL; -} - -void stub_device_cleanup_urbs(struct stub_device *sdev) -{ - struct stub_priv *priv; - - udbg("free sdev %p\n", sdev); - - while ((priv = stub_priv_pop(sdev))) { - struct urb *urb = priv->urb; - - udbg(" free urb %p\n", urb); - usb_kill_urb(urb); - - kmem_cache_free(stub_priv_cache, priv); - - if (urb->transfer_buffer != NULL) - kfree(urb->transfer_buffer); - - if (urb->setup_packet != NULL) - kfree(urb->setup_packet); - - usb_free_urb(urb); - } -} - - -/*-------------------------------------------------------------------------*/ - -static int __init usb_stub_init(void) -{ - int ret; - - stub_priv_cache = kmem_cache_create("stub_priv", sizeof(struct stub_priv), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!stub_priv_cache) { - uerr("create stub_priv_cache\n"); - return -ENOMEM; - } - - ret = usb_register(&stub_driver); - if (ret) { - uerr("usb_register failed %d\n", ret); - return ret; - } - - - info(DRIVER_DESC "" DRIVER_VERSION); - - memset(busid_table, 0, sizeof(busid_table)); - - driver_create_file(&stub_driver.driver, &driver_attr_match_busid); - - return ret; -} - -static void __exit usb_stub_exit(void) -{ - int ret; - - udbg("enter\n"); - - driver_remove_file(&stub_driver.driver, &driver_attr_match_busid); - - /* - * deregister() calls stub_disconnect() for all devices. Device - * specific data is cleared in stub_disconnect(). - */ - usb_deregister(&stub_driver); - - ret = kmem_cache_destroy(stub_priv_cache); - if (ret != 0) { - uerr("memory leak of stub_priv, %d\n", ret); - } - - udbg("bye\n"); -} - - - - -module_init (usb_stub_init); -module_exit (usb_stub_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff -Naur usbip-0.1.4/drivers/2.6.15/stub_rx.c trunk/drivers/2.6.15/stub_rx.c --- usbip-0.1.4/drivers/2.6.15/stub_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/stub_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,442 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static int is_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_CLEAR_FEATURE) && - (req->bRequestType == USB_RECIP_ENDPOINT) && - (req->wValue == USB_ENDPOINT_HALT); -} - -static int is_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_INTERFACE) && - (req->bRequestType == USB_RECIP_INTERFACE); -} - -static int is_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_CONFIGURATION) && - (req->bRequestType == USB_RECIP_DEVICE); -} - -static int tweak_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - int target_endp; - int target_dir; - int target_pipe; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - /* - * The stalled endpoint is specified in the wIndex value. The endpoint - * of the urb is the target of this clear_halt request (i.e. control - * endpoint). - */ - target_endp = le16_to_cpu(req->wIndex) & 0x000f; - - /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80. */ - target_dir = le16_to_cpu(req->wIndex) & 0x0080; - - if (target_dir) - target_pipe = usb_rcvctrlpipe(urb->dev, target_endp); - else - target_pipe = usb_sndctrlpipe(urb->dev, target_endp); - - ret = usb_clear_halt(urb->dev, target_pipe); - if (ret < 0) - uinfo("clear_halt error: devnum %d endp %d, %d\n", - urb->dev->devnum, target_endp, ret); - else - uinfo("clear_halt done: devnum %d endp %d\n", - urb->dev->devnum, target_endp); - - return ret; -} - -static int tweak_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 alternate; - __u16 interface; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - alternate = le16_to_cpu(req->wValue); - interface = le16_to_cpu(req->wIndex); - - dbg_stub_rx("set_interface: inf %u alt %u\n", interface, alternate); - - ret = usb_set_interface(urb->dev, interface, alternate); - if (ret < 0) - uinfo("set_interface error: inf %u alt %u, %d\n", - interface, alternate, ret); - else - uinfo("set_interface done: inf %u alt %u\n", interface, alternate); - - return ret; -} - -static int tweak_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 config; - - info("set_configuration is not fully supported yet\n"); - - req = (struct usb_ctrlrequest *) urb->setup_packet; - config = le16_to_cpu(req->wValue); - - uinfo("set_configuration: devnum %d %d\n", urb->dev->devnum, config); - -#if 0 - return usb_set_configuration(urb->dev, config); -#endif - return 0; -} - -/* - * clear_halt, set_interface, and set_configuration require special tricks. - * TODO: set_configuration. but I have never seen a multi-config device. - */ -static void tweak_special_requests(struct urb *urb) -{ - if (!urb || !urb->setup_packet) - return; - - if (usb_pipetype(urb->pipe) != PIPE_CONTROL) - return; - - if (is_clear_halt_cmd(urb)) - /* treak clear_halt */ - tweak_clear_halt_cmd(urb); - - else if (is_set_interface_cmd(urb)) - /* tweak set_interface */ - tweak_set_interface_cmd(urb); - - else if (is_set_configuration_cmd(urb)) - /* tweak set_configuration */ - tweak_set_configuration_cmd(urb); - - else - dbg_stub_rx("no need to tweak\n"); -} - -/* - * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb(). - * By unlinking the urb asynchronously, stub_rx can continuously - * process coming urbs. Even if the urb is unlinked, its completion - * handler will be called and stub_tx will send a return pdu. - * - * See also comments about unlinking strategy in vhci_hcd.c. - */ -static int stub_recv_cmd_unlink(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct list_head *listhead = &sdev->priv_init; - struct list_head *ptr; - unsigned long flags; - - struct stub_priv *priv; - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - for (ptr = listhead->next; ptr != listhead; ptr = ptr->next) { - priv = list_entry(ptr, struct stub_priv, list); - if (priv->seqnum == pdu->u.cmd_unlink.seqnum) { - int ret; - - uinfo("unlink urb %p\n", priv->urb); - - /* - * This matched urb is not completed yet (i.e. be in - * flight in usb hcd hardware/driver). Now we are - * cancelling it. The unlinking flag means that we are - * now not going to return the normal result pdu of a - * submittion request, but going to return a result pdu - * of the unlink request. - */ - priv->unlinking = 1; - - /* - * In the case that unlinking flag is on, prev->seqnum - * is changed from the seqnum of the cancelling urb to - * the seqnum of the unlink request. This will be used - * to make the result pdu of the unlink request. - */ - priv->seqnum = pdu->base.seqnum; - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* - * usb_unlink_urb() is now out of spinlocking to avoid - * spinlock recursion since stub_complete() is - * sometimes called in this context but not in the - * interrupt context. If stub_complete() is executed - * before we call usb_unlink_urb(), usb_unlink_urb() - * will return an error value. In this case, stub_tx - * will return the result pdu of this unlink request - * though submission is completed and actual unlinking - * is not executed. OK? - */ - ret = usb_unlink_urb(priv->urb); - if (ret != -EINPROGRESS) - uerr("faild to unlink a urb %p, ret %d\n", priv->urb, ret); - - return 0; - } - } - - dbg_stub_rx("seqnum %d is not pending\n", pdu->u.cmd_unlink.seqnum); - - /* - * The urb of the unlink target is not found in priv_init queue. It was - * already completed and its results is/was going to be sent by a - * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only - * return the completeness of this unlink request to vhci_hcd. - */ - stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - - return 0; -} - -static int valid_request(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &sdev->ud; - - int bus = interface_to_busnum(sdev->interface); - int dev = interface_to_devnum(sdev->interface); - - if (pdu->base.busnum == bus && pdu->base.devnum == dev) { - spin_lock(&ud->lock); - if (ud->status == SDEV_ST_USED) { - /* A request is valid. */ - spin_unlock(&ud->lock); - return 1; - } - spin_unlock(&ud->lock); - } - - return 0; -} - -static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, - struct usbip_header *pdu) -{ - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - unsigned long flags; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC); - if (!priv) { - uerr("alloc stub_priv\n"); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return NULL; - } - - memset(priv, 0, sizeof(struct stub_priv)); - - priv->seqnum = pdu->base.seqnum; - priv->sdev = sdev; - - /* - * After a stub_priv is linked to a list_head, - * our error handler can free allocated data. - */ - list_add_tail(&priv->list, &sdev->priv_init); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return priv; -} - -static void stub_recv_cmd_submit(struct stub_device *sdev, struct usbip_header *pdu) -{ - int ret; - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - - - priv = stub_priv_alloc(sdev, pdu); - if (!priv) - return; - - /* setup a urb */ - if (usb_pipeisoc(pdu->base.pipe)) - priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, GFP_KERNEL); - else - priv->urb = usb_alloc_urb(0, GFP_KERNEL); - - if (!priv->urb) { - uerr("malloc urb\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - - /* set priv->urb->transfer_buffer */ - if (pdu->u.cmd_submit.transfer_buffer_length > 0) { - priv->urb->transfer_buffer = - kzalloc(pdu->u.cmd_submit.transfer_buffer_length, GFP_KERNEL); - if (!priv->urb->transfer_buffer) { - uerr("malloc x_buff\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - } - - /* set priv->urb->setup_packet */ - priv->urb->setup_packet = kzalloc(8, GFP_KERNEL); - if (!priv->urb->setup_packet) { - uerr("allocate setup_packet\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - memcpy(priv->urb->setup_packet, &pdu->u.cmd_submit.setup, 8); - - /* set other members from the base header of pdu */ - priv->urb->context = (void *) priv; - priv->urb->dev = interface_to_usbdev(sdev->interface); - priv->urb->pipe = pdu->base.pipe; - priv->urb->complete = stub_complete; - - usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); - - - if (usbip_recv_xbuff(ud, priv->urb) < 0) - return; - - if (usbip_recv_iso(ud, priv->urb) < 0) - return; - - tweak_special_requests(priv->urb); - - /* urb is now ready to submit */ - ret = usb_submit_urb(priv->urb, GFP_KERNEL); - - if (ret == 0) - dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum); - else { - uerr("submit_urb error, %d\n", ret); - - /* - * Pessimistic. - * This connection will be discared. - */ - usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); - } - - dbg_stub_rx("Leave\n"); - return; -} - -/* recv a pdu */ -static void stub_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - - dbg_stub_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_stub_rx) - usbip_dump_header(&pdu); - - if (!valid_request(sdev, &pdu)) { - uerr("recv invalid request\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - switch (pdu.base.command) { - case USBIP_CMD_UNLINK: - stub_recv_cmd_unlink(sdev, &pdu); - break; - - case USBIP_CMD_SUBMIT: - stub_recv_cmd_submit(sdev, &pdu); - break; - - default: - /* NOTREACHED */ - uerr("unknown pdu\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - -} - -void stub_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - while (1) { - if (signal_pending(current)) { - dbg_stub_rx("signal catched!\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - stub_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.15/stub_tx.c trunk/drivers/2.6.15/stub_tx.c --- usbip-0.1.4/drivers/2.6.15/stub_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/stub_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,374 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static void stub_free_priv_and_urb(struct stub_priv *priv) -{ - struct urb *urb = priv->urb; - - if (urb->setup_packet) - kfree(urb->setup_packet); - - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); - - list_del(&priv->list); - kmem_cache_free(stub_priv_cache, priv); - - usb_free_urb(urb); -} - -/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ -void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, __u32 status) -{ - struct stub_unlink *unlink; - - unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("alloc stub_unlink\n"); - usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - unlink->seqnum = seqnum; - unlink->status = status; - - list_add_tail(&unlink->list, &sdev->unlink_tx); -} - -/** - * stub_complete - completion handler of a usbip urb - * @urb: pointer to the urb completed - * @regs: - * - * When a urb has completed, the USB core driver calls this function mostly in - * the interrupt context. To return the result of a urb, the completed urb is - * linked to the pending list of returning. - * - */ -void stub_complete(struct urb *urb, struct pt_regs *regs) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - struct stub_device *sdev = priv->sdev; - unsigned long flags; - - dbg_stub_tx("complete! status %d\n", urb->status); - - - switch (urb->status) { - case 0: - /* OK */ - break; - case -ENOENT: - uinfo("stopped by a call of usb_kill_urb()" - "because of cleaning up a virtual connection\n"); - return; - case -ECONNRESET: - uinfo("unlinked by a call of usb_unlink_urb()\n"); - break; - case -EPIPE: - uinfo("endpoint %d is stalled\n", usb_pipeendpoint(urb->pipe)); - break; - case -ESHUTDOWN: - uinfo("device removed?\n"); - break; - default: - uinfo("urb completion with non-zero status %d\n", urb->status); - } - - /* link a urb to the queue of tx. */ - spin_lock_irqsave(&sdev->priv_lock, flags); - - if (priv->unlinking) { - stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status); - stub_free_priv_and_urb(priv); - } else - list_move_tail(&priv->list, &sdev->priv_tx); - - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* wake up tx_thread */ - wake_up(&sdev->tx_waitq); -} - - -/*-------------------------------------------------------------------------*/ -/* fill PDU */ - -static inline void setup_base_pdu(struct usbip_header_basic *base, - __u32 command, __u32 seqnum) -{ - base->command = command; - base->busnum = 0; - base->devnum = 0; - base->seqnum = seqnum; - base->pipe = 0; -} - -static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - - setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum); - - usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1); -} - -static void setup_ret_unlink_pdu(struct usbip_header *rpdu, - struct stub_unlink *unlink) -{ - setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum); - - rpdu->u.ret_unlink.status = unlink->status; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_SUBMIT */ - -static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) { - list_move_tail(&priv->list, &sdev->priv_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - -static int stub_send_ret_submit(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_ret_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (usb_pipein(urb->pipe) && urb->actual_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->actual_length; - txsize += urb->actual_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - if (iso_buffer) - kfree(iso_buffer); - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { - stub_free_priv_and_urb(priv); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_UNLINK */ - -static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_move_tail(&unlink->list, &sdev->unlink_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - - -static int stub_send_ret_unlink(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - struct msghdr msg; - struct kvec iov[1]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum); - - /* 1. setup usbip_header */ - setup_ret_unlink_pdu(&pdu_header, unlink); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void stub_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - while (1) { - if (signal_pending(current)) { - dbg_stub_tx("signal catched\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - /* - * send_ret_submit comes earlier than send_ret_unlink. stub_rx - * looks at only priv_init queue. If the completion of a URB is - * earlier than the recieve of CMD_UNLINK, priv is moved to - * priv_tx queue and stub_rx does not find the target priv. In - * this case, vhci_rx recieves the result of the submit request - * and then recieves the result of the unlink request. The - * result of the submit is given back to the usbcore as the - * completion of the unlink request. The request of the - * unlink is ignored. This is ok because a driver who calls - * usb_unlink_urb() understands the unlink was too late by - * getting the status of the given-backed URB which has the - * status of usb_submit_urb(). - */ - if (stub_send_ret_submit(sdev) < 0) - break; - - if (stub_send_ret_unlink(sdev) < 0) - break; - - wait_event_interruptible(sdev->tx_waitq, - (!list_empty(&sdev->priv_tx) || - !list_empty(&sdev->unlink_tx))); - } -} diff -Naur usbip-0.1.4/drivers/2.6.15/usbip_common.c trunk/drivers/2.6.15/usbip_common.c --- usbip-0.1.4/drivers/2.6.15/usbip_common.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/usbip_common.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,935 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include "usbip_common.h" - - -/*-------------------------------------------------------------------------*/ -/* debug routines */ - -#ifdef CONFIG_USB_DEBUG -unsigned long usbip_debug_flag = 0xffffffff; -#else -unsigned long usbip_debug_flag = 0; -#endif - -static ssize_t show_flag(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lx\n", usbip_debug_flag); -} - -static ssize_t store_flag(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long flag; - - sscanf(buf, "%lx", &flag); - usbip_debug_flag = flag; - - return count; -} -DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag); - -static void usbip_dump_buffer(char *buff, int bufflen) -{ - int i; - - if (bufflen > 128) { - for (i = 0; i< 128; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) printk("| "); - if (i%24 == 23) printk("\n"); - } - printk("... (%d byte)\n", bufflen); - return; - } - - for (i = 0; i< bufflen; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) - printk("| "); - if (i%24 == 23) - printk("\n"); - } - printk("\n"); - -} - -static void usbip_dump_pipe(unsigned int p) -{ - unsigned char type = usb_pipetype(p); - unsigned char ep = usb_pipeendpoint(p); - unsigned char dev = usb_pipedevice(p); - unsigned char dir = usb_pipein(p); - - printk("dev(%d) ", dev); - printk("ep(%d) ", ep); - printk("%s ", dir ? "IN" : "OUT"); - - switch(type) { - case PIPE_ISOCHRONOUS : - printk("%s ", "ISO"); - break; - case PIPE_INTERRUPT : - printk("%s ", "INT"); - break; - case PIPE_CONTROL : - printk("%s ", "CTL"); - break; - case PIPE_BULK : - printk("%s ", "BLK"); - break; - default : - printk("ERR"); - } - - printk("\n"); - -} - -static void usbip_dump_usb_device(struct usb_device *dev) -{ - int i; - - if (!dev) { - printk(" dump usb dev: null pointer!!\n"); - return; - } - - printk(" devnum(%d) devpath(%s)", dev->devnum, dev->devpath); - - switch(dev->speed) { - case USB_SPEED_HIGH : - printk(" SPD_HIGH"); - break; - case USB_SPEED_FULL : - printk(" SPD_FULL"); - break; - case USB_SPEED_LOW : - printk(" SPD_LOW"); - break; - case USB_SPEED_UNKNOWN : - printk(" SPD_UNKNOWN"); - break; - default : - printk(" SPD_ERROR"); - } - - printk(" tt %p, ttport %d", dev->tt, dev->ttport); - printk("\n"); - - printk(" "); - for (i = 0; i < 16; i++) { - printk(" %2u", i); - } - - printk("\n"); - - printk(" toggle0(IN) :"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[0] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - printk(" toggle1(OUT):"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[1] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - - printk(" epmaxp_in :"); - for (i = 0; i < 16; i++) { - if (dev->ep_in[i]) - printk(" %2u", dev->ep_in[i]->desc.wMaxPacketSize); - } - - printk("\n"); - - printk(" epmaxp_out :"); - for (i = 0; i < 16; i++) { - if (dev->ep_out[i]) - printk(" %2u", dev->ep_out[i]->desc.wMaxPacketSize); - } - - printk("\n "); - - printk("parent %p, bus %p", dev->parent, dev->bus); - printk("\n "); - - printk("descriptor %p, config %p, actconfig %p, rawdescriptors %p", - &dev->descriptor, dev->config, dev->actconfig, dev->rawdescriptors); - printk("\n "); - - printk("have_langid %d, string_langid %d", dev->have_langid, dev->string_langid); - printk("\n "); - - printk("maxchild %d, children %p", dev->maxchild, dev->children); - - printk("\n"); -} - -static void usbip_dump_request_type(__u8 rt) -{ - switch(rt & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: - printk("DEVICE"); - break; - case USB_RECIP_INTERFACE: - printk("INTERF"); - break; - case USB_RECIP_ENDPOINT: - printk("ENDPOI"); - break; - case USB_RECIP_OTHER: - printk("OTHER "); - break; - default: - printk("------"); - } -} - -static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd) -{ - if (!cmd) { - printk(" %s : null pointer\n", __FUNCTION__); - return; - } - - printk(" "); - printk("bRequestType(%02X) ", cmd->bRequestType); - printk("bRequest(%02X) " , cmd->bRequest); - printk("wValue(%04X) ", cmd->wValue); - printk("wIndex(%04X) ", cmd->wIndex); - printk("wLength(%04X) ", cmd->wLength); - - printk("\n "); - - if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - printk("STANDARD "); - switch(cmd->bRequest) { - case USB_REQ_GET_STATUS: - printk("GET_STATUS"); - break; - case USB_REQ_CLEAR_FEATURE: - printk("CLEAR_FEAT"); - break; - case USB_REQ_SET_FEATURE: - printk("SET_FEAT "); - break; - case USB_REQ_SET_ADDRESS: - printk("SET_ADDRRS"); - break; - case USB_REQ_GET_DESCRIPTOR: - printk("GET_DESCRI"); - break; - case USB_REQ_SET_DESCRIPTOR: - printk("SET_DESCRI"); - break; - case USB_REQ_GET_CONFIGURATION: - printk("GET_CONFIG"); - break; - case USB_REQ_SET_CONFIGURATION: - printk("SET_CONFIG"); - break; - case USB_REQ_GET_INTERFACE: - printk("GET_INTERF"); - break; - case USB_REQ_SET_INTERFACE: - printk("SET_INTERF"); - break; - case USB_REQ_SYNCH_FRAME: - printk("SYNC_FRAME"); - break; - default: - printk("REQ(%02X) ", cmd->bRequest); - } - - printk(" "); - usbip_dump_request_type(cmd->bRequestType); - - } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) - printk("CLASS "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) - printk("VENDOR "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) - printk("RESERVED"); - - printk("\n"); -} - -void usbip_dump_urb (struct urb *purb) -{ - if (!purb) { - printk(" dump urb: null pointer!!\n"); - return; - } - - printk(" urb :%p\n", purb); - printk(" dev :%p\n", purb->dev); - - usbip_dump_usb_device(purb->dev); - - printk(" pipe :%08x ", purb->pipe); - - usbip_dump_pipe(purb->pipe); - - printk(" status :%d\n", purb->status); - printk(" transfer_flags :%08X\n", purb->transfer_flags); - printk(" transfer_buffer :%p\n", purb->transfer_buffer); - printk(" transfer_buffer_length:%d\n", purb->transfer_buffer_length); - printk(" actual_length :%d\n", purb->actual_length); - printk(" bandwidth :%d\n", purb->actual_length); - printk(" setup_packet :%p\n", purb->setup_packet); - - if (purb->setup_packet && usb_pipetype(purb->pipe) == PIPE_CONTROL) - usbip_dump_usb_ctrlrequest((struct usb_ctrlrequest *) purb->setup_packet); - - printk(" start_frame :%d\n", purb->start_frame); - printk(" number_of_packets :%d\n", purb->number_of_packets); - printk(" interval :%d\n", purb->interval); - printk(" error_count :%d\n", purb->error_count); - printk(" context :%p\n", purb->context); - printk(" complete :%p\n", purb->complete); -} - -void usbip_dump_header(struct usbip_header *pdu) -{ - udbg("BASE: cmd %u bus %u dev %u seq %u pipe %04x\n", - pdu->base.command, - pdu->base.busnum, - pdu->base.devnum, - pdu->base.seqnum, - pdu->base.pipe); - - usbip_dump_pipe(pdu->base.pipe); - - switch(pdu->base.command) { - case USBIP_CMD_SUBMIT: - udbg("CMD_SUBMIT: x_flags %u x_len %u bw %u sf %u #p %u iv %u\n", - pdu->u.cmd_submit.transfer_flags, - pdu->u.cmd_submit.transfer_buffer_length, - pdu->u.cmd_submit.bandwidth, - pdu->u.cmd_submit.start_frame, - pdu->u.cmd_submit.number_of_packets, - pdu->u.cmd_submit.interval); - break; - case USBIP_CMD_UNLINK: - udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum); - break; - case USBIP_RET_SUBMIT: - udbg("RET_SUBMIT: st %d al %u bw %u sf %d ec %d\n", - pdu->u.ret_submit.status, - pdu->u.ret_submit.actual_length, - pdu->u.ret_submit.bandwidth, - pdu->u.ret_submit.start_frame, - pdu->u.ret_submit.error_count); - case USBIP_RET_UNLINK: - udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status); - break; - default: - /* NOT REACHED */ - udbg("UNKNOWN\n"); - } -} - - -/*-------------------------------------------------------------------------*/ -/* thread routines */ - -int usbip_thread(void *param) -{ - struct usbip_task *ut = (struct usbip_task *) param; - - if (!ut) - return -EINVAL; - - lock_kernel(); - daemonize(ut->name); - allow_signal(SIGKILL); - ut->thread = current; - unlock_kernel(); - - /* srv.rb must wait for rx_thread starting */ - complete(&ut->thread_done); - - /* start of while loop */ - ut->loop_ops(ut); - - /* end of loop */ - ut->thread = NULL; - - complete_and_exit(&ut->thread_done, 0); -} - -void usbip_start_threads(struct usbip_device *ud) -{ - /* - * threads are invoked per one device (per one connection). - */ - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_rx, 0); - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_tx, 0); - - /* confirm threads are starting */ - wait_for_completion(&ud->tcp_rx.thread_done); - wait_for_completion(&ud->tcp_tx.thread_done); -} - -void usbip_stop_threads(struct usbip_device *ud) -{ - /* kill threads related to this sdev, if v.c. exists */ - if (ud->tcp_rx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_rx.thread, 1); - wait_for_completion(&ud->tcp_rx.thread_done); - udbg("rx_thread for ud %p has finished\n", ud); - } - - if (ud->tcp_tx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_tx.thread, 1); - wait_for_completion(&ud->tcp_tx.thread_done); - udbg("tx_thread for ud %p has finished\n", ud); - } -} - -void usbip_task_init(struct usbip_task *ut, char *name, - void (*loop_ops)(struct usbip_task *)) -{ - ut->thread = NULL; - init_completion(&ut->thread_done); - ut->name = name; - ut->loop_ops = loop_ops; -} - - -/*-------------------------------------------------------------------------*/ -/* socket routines */ - - /* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */ -int usbip_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags) -{ - int result; - struct msghdr msg; - struct kvec iov; - int total = 0; - - /* for blocks of if (dbg_flag_xmit) */ - char *bp = buf; - int osize= size; - - dbg_xmit("enter\n"); - - if (!sock || !buf || !size) { - uerr("usbip_xmit: invalid arg, sock %p buff %p size %d\n", - sock, buf, size); - return -EINVAL; - } - - - if (dbg_flag_xmit) { - if (send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: sending... , sock %p, buf %p, size %d, msg_flags %d\n", - sock, buf, size, msg_flags); - usbip_dump_buffer(buf, size); - } - } - - - do { - sock->sk->sk_allocation = GFP_NOIO; - iov.iov_base = buf; - iov.iov_len = size; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_namelen = 0; - msg.msg_flags = msg_flags | MSG_NOSIGNAL; - - if (send) - result = kernel_sendmsg(sock, &msg, &iov, 1, size); - else - result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); - - if (result <= 0) { - udbg("usbip_xmit: %s sock %p buf %p size %u ret %d total %d\n", - send ? "send" : "receive", sock, buf, size, result, total); - goto err; - } - - size -= result; - buf += result; - total += result; - - } while (size > 0); - - - if (dbg_flag_xmit) { - if (!send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: receiving....\n"); - usbip_dump_buffer(bp, osize); - printk("usbip_xmit: received, osize %d ret %d size %d total %d\n", - osize, result, size, total); - } - - if (send) { - printk("usbip_xmit: send, total %d\n", total); - } - } - - return total; - -err: - return result; -} - -int setquickack(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setnodelay(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setkeepalive(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -void setreuse(struct socket *socket) -{ - socket->sk->sk_reuse = 1; -} - -struct socket *sockfd_to_socket(unsigned int sockfd) -{ - struct socket *socket; - struct file *file; - struct inode *inode; - - file = fget(sockfd); - if (!file) { - uerr("invalid sockfd\n"); - return NULL; - } - - inode = file->f_dentry->d_inode; - - if (!inode || !S_ISSOCK(inode->i_mode)) - return NULL; - - socket = SOCKET_I(inode); - - return socket; -} - - - -/*-------------------------------------------------------------------------*/ -/* pdu routines */ - -/* there may be more cases to tweak the flags. */ -static unsigned int tweak_transfer_flags(unsigned int flags) -{ - - if (flags & URB_NO_TRANSFER_DMA_MAP) - /* - * vhci_hcd does not provide DMA-mapped I/O. The upper - * driver does not need to set this flag. The remote - * usbip.ko does not still perform DMA-mapped I/O for - * DMA-caplable host controllers. So, clear this flag. - */ - flags &= ~URB_NO_TRANSFER_DMA_MAP; - - if (flags & URB_NO_SETUP_DMA_MAP) - flags &= ~URB_NO_SETUP_DMA_MAP; - - return flags; -} - -static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit; - - /* - * Some members are not still implemented in usbip. I hope this issue - * will be discussed when usbip is ported to other operating systems. - */ - if (pack) { - /* vhci_tx.c */ - spdu->transfer_flags = tweak_transfer_flags(urb->transfer_flags); - - spdu->transfer_buffer_length = urb->transfer_buffer_length; - spdu->bandwidth = urb->bandwidth; - spdu->start_frame = urb->start_frame; - spdu->number_of_packets = urb->number_of_packets; - spdu->interval = urb->interval; - } else { - /* stub_rx.c */ - urb->transfer_flags = spdu->transfer_flags; - - urb->transfer_buffer_length = spdu->transfer_buffer_length; - urb->bandwidth = spdu->bandwidth; - urb->start_frame = spdu->start_frame; - urb->number_of_packets = spdu->number_of_packets; - urb->interval = spdu->interval; - } -} - -static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit; - - if (pack) { - /* stub_tx.c */ - - rpdu->status = urb->status; - rpdu->actual_length = urb->actual_length; - rpdu->bandwidth = urb->bandwidth; - rpdu->start_frame = urb->start_frame; - rpdu->error_count = urb->error_count; - } else { - /* vhci_rx.c */ - - urb->status = rpdu->status; - urb->actual_length = rpdu->actual_length; - urb->bandwidth = rpdu->bandwidth; - urb->start_frame = rpdu->start_frame; - urb->error_count = rpdu->error_count; - } -} - - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack) -{ - switch(cmd) { - case USBIP_CMD_SUBMIT: - usbip_pack_cmd_submit(pdu, urb, pack); - break; - case USBIP_RET_SUBMIT: - usbip_pack_ret_submit(pdu, urb, pack); - break; - default: - /* NOTREACHED */ - BUG(); - } -} - - -static void correct_endian_basic(struct usbip_header_basic *base, int send) -{ - if (send) { - base->command = cpu_to_be32(base->command); - base->busnum = cpu_to_be32(base->busnum); - base->devnum = cpu_to_be32(base->devnum); - base->seqnum = cpu_to_be32(base->seqnum); - base->pipe = cpu_to_be32(base->pipe); - } else { - base->command = be32_to_cpu(base->command); - base->busnum = be32_to_cpu(base->busnum); - base->devnum = be32_to_cpu(base->devnum); - base->seqnum = be32_to_cpu(base->seqnum); - base->pipe = be32_to_cpu(base->pipe); - } -} - -static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu, int send) -{ - if (send) { - pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags); - - cpu_to_be32s(&pdu->transfer_buffer_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->number_of_packets); - cpu_to_be32s(&pdu->interval); - } else { - pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags); - - be32_to_cpus(&pdu->transfer_buffer_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->number_of_packets); - be32_to_cpus(&pdu->interval); - } -} - -static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, int send) -{ - if (send) { - cpu_to_be32s(&pdu->status); - cpu_to_be32s(&pdu->actual_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->error_count); - } else { - be32_to_cpus(&pdu->status); - be32_to_cpus(&pdu->actual_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->error_count); - } -} - -static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu, int send) -{ - if (send) - pdu->seqnum = cpu_to_be32(pdu->seqnum); - else - pdu->seqnum = be32_to_cpu(pdu->seqnum); -} - -static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu, int send) -{ - if (send) - cpu_to_be32s(&pdu->status); - else - be32_to_cpus(&pdu->status); -} - -void usbip_header_correct_endian(struct usbip_header *pdu, int send) -{ - __u32 cmd = 0; - - if (send) - cmd = pdu->base.command; - - correct_endian_basic(&pdu->base, send); - - if (!send) - cmd = pdu->base.command; - - switch (cmd) { - case USBIP_CMD_SUBMIT: - correct_endian_cmd_submit(&pdu->u.cmd_submit, send); - break; - case USBIP_RET_SUBMIT: - correct_endian_ret_submit(&pdu->u.ret_submit, send); - break; - - case USBIP_CMD_UNLINK: - correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send); - break; - case USBIP_RET_UNLINK: - correct_endian_ret_unlink(&pdu->u.ret_unlink, send); - break; - - default: - /* NOTREACHED */ - BUG(); - } -} - -static void usbip_iso_pakcet_correct_endian(struct usbip_iso_packet_descriptor *iso, int send) -{ - /* does not need all members. but copy all simply. */ - if (send) { - iso->offset = cpu_to_be32(iso->offset); - iso->length = cpu_to_be32(iso->length); - iso->status = cpu_to_be32(iso->status); - iso->actual_length = cpu_to_be32(iso->actual_length); - } else { - iso->offset = be32_to_cpu(iso->offset); - iso->length = be32_to_cpu(iso->length); - iso->status = be32_to_cpu(iso->status); - iso->actual_length = be32_to_cpu(iso->actual_length); - } -} - -static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso, - struct usb_iso_packet_descriptor *uiso, int pack) -{ - if (pack) { - iso->offset = uiso->offset; - iso->length = uiso->length; - iso->status = uiso->status; - iso->actual_length = uiso->actual_length; - } else { - uiso->offset = iso->offset; - uiso->length = iso->length; - uiso->status = iso->status; - uiso->actual_length = iso->actual_length; - } -} - - -/* must free buffer */ -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - ssize_t size = np * sizeof(*iso); - int i; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return NULL; - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1); - usbip_iso_pakcet_correct_endian(iso, 1); - } - - *bufflen = size; - - return buff; -} - -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - int size = np * sizeof(*iso); - int i; - int ret; - - if (!usb_pipeisoc(urb->pipe)) - return 0; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0); - if (ret != size) { - uerr("recv iso_frame_descriptor, %d\n", ret); - kfree(buff); - - if (ud->side == USBIP_STUB) - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - else - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - - return -EPIPE; - } - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_iso_pakcet_correct_endian(iso, 0); - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0); - } - - - kfree(buff); - - return ret; -} - - -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) -{ - int ret; - int size; - - if (ud->side == USBIP_STUB) { - /* stub_rx.c */ - /* the direction of urb must be OUT. */ - if (usb_pipein(urb->pipe)) - return 0; - - size = urb->transfer_buffer_length; - } else { - /* vhci_rx.c */ - /* the direction of urb must be IN. */ - if (usb_pipeout(urb->pipe)) - return 0; - - size = urb->actual_length; - } - - /* no need to recv xbuff */ - if (!(size > 0)) - return 0; - - ret = usbip_xmit(0, ud->tcp_socket, (char *) urb->transfer_buffer, size, 0); - if (ret != size) { - uerr("recv xbuf, %d\n", ret); - if (ud->side == USBIP_STUB) { - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - } else { - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return -EPIPE; - } - } - - return ret; -} diff -Naur usbip-0.1.4/drivers/2.6.15/usbip_common.h trunk/drivers/2.6.15/usbip_common.h --- usbip-0.1.4/drivers/2.6.15/usbip_common.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/usbip_common.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,364 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#ifndef __VHCI_COMMON_H -#define __VHCI_COMMON_H - - -#include -#include -#include - -/*-------------------------------------------------------------------------*/ - -/* - * define macros to print messages - */ - -/** - * udbg - print debug messages if CONFIG_USB_DEBUG is defined - * @fmt: - * @args: - */ - -#ifdef CONFIG_USB_DEBUG - -#define udbg(fmt, args...) \ - do{ \ - printk(KERN_DEBUG "%-10s:(%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - }while(0) - -#else /* CONFIG_USB_DEBUG */ - -#define udbg(fmt, args...) do{ }while(0) - -#endif /* CONFIG_USB_DEBUG */ - - -enum { - usbip_debug_xmit = (1 << 0), - usbip_debug_sysfs = (1 << 1), - usbip_debug_urb = (1 << 2), - usbip_debug_eh = (1 << 3), - - usbip_debug_stub_cmp = (1 << 8), - usbip_debug_stub_dev = (1 << 9), - usbip_debug_stub_rx = (1 << 10), - usbip_debug_stub_tx = (1 << 11), - - usbip_debug_vhci_rh = (1 << 8), - usbip_debug_vhci_hc = (1 << 9), - usbip_debug_vhci_rx = (1 << 10), - usbip_debug_vhci_tx = (1 << 11), - usbip_debug_vhci_sysfs = (1 << 12) -}; - -#define dbg_flag_xmit (usbip_debug_flag & usbip_debug_xmit) -#define dbg_flag_vhci_rh (usbip_debug_flag & usbip_debug_vhci_rh) -#define dbg_flag_vhci_hc (usbip_debug_flag & usbip_debug_vhci_hc) -#define dbg_flag_vhci_rx (usbip_debug_flag & usbip_debug_vhci_rx) -#define dbg_flag_vhci_tx (usbip_debug_flag & usbip_debug_vhci_tx) -#define dbg_flag_vhci_sysfs (usbip_debug_flag & usbip_debug_vhci_sysfs) -#define dbg_flag_stub_rx (usbip_debug_flag & usbip_debug_stub_rx) -#define dbg_flag_stub_tx (usbip_debug_flag & usbip_debug_stub_tx) - -extern unsigned long usbip_debug_flag; -extern struct device_attribute dev_attr_usbip_debug; - -#define dbg_with_flag(flag, fmt, args...) \ - do { \ - if(flag & usbip_debug_flag) \ - udbg(fmt , ##args); \ - } while(0) - -#define dbg_sysfs(fmt, args...) dbg_with_flag(usbip_debug_sysfs, fmt , ##args) -#define dbg_xmit(fmt, args...) dbg_with_flag(usbip_debug_xmit, fmt , ##args) -#define dbg_urb(fmt, args...) dbg_with_flag(usbip_debug_urb, fmt , ##args) -#define dbg_eh(fmt, args...) dbg_with_flag(usbip_debug_eh, fmt , ##args) - -#define dbg_vhci_rh(fmt, args...) dbg_with_flag(usbip_debug_vhci_rh, fmt , ##args) -#define dbg_vhci_hc(fmt, args...) dbg_with_flag(usbip_debug_vhci_hc, fmt , ##args) -#define dbg_vhci_rx(fmt, args...) dbg_with_flag(usbip_debug_vhci_rx, fmt , ##args) -#define dbg_vhci_tx(fmt, args...) dbg_with_flag(usbip_debug_vhci_tx, fmt , ##args) -#define dbg_vhci_sysfs(fmt, args...) dbg_with_flag(usbip_debug_vhci_sysfs, fmt , ##args) - -#define dbg_stub_cmp(fmt, args...) dbg_with_flag(usbip_debug_stub_cmp, fmt , ##args) -#define dbg_stub_rx(fmt, args...) dbg_with_flag(usbip_debug_stub_rx, fmt , ##args) -#define dbg_stub_tx(fmt, args...) dbg_with_flag(usbip_debug_stub_tx, fmt , ##args) - - -/** - * uerr - print error messages - * @fmt: - * @args: - */ -#define uerr(fmt, args...) \ - do { \ - printk(KERN_ERR "%-10s: ***ERROR*** (%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - } while(0) - -/** - * uinfo - print information messages - * @fmt: - * @args: - */ -#define uinfo(fmt, args...) \ - do { \ - printk(KERN_INFO "usbip: " fmt , ## args); \ - } while(0) - - -/*-------------------------------------------------------------------------*/ - -/* - * USB/IP packet headers. - * At now, we define 4 packet types: - * - * - CMD_SUBMIT transfers a USB request. This is corresponding to usb_submit_urb(). - * - RET_RETURN transfers a result of a USB request. - * - CMD_UNLINK transfers an unlink request of a pending USB request. - * - RET_UNLINK transfers an unlink request of a pending USB request. - * - * TODO: - * - * - inter-operability between other OSs - */ - -/* - * A basic header followed by other additional headers. - */ -struct usbip_header_basic { -#define USBIP_CMD_SUBMIT 0x0001 -#define USBIP_CMD_UNLINK 0x0002 -#define USBIP_RET_SUBMIT 0x0003 -#define USBIP_RET_UNLINK 0x0004 - __u32 command; - - __u32 busnum; - __u32 devnum; - __u32 seqnum; /* seaquencial number which identifies URBs */ - __u32 pipe; -} __attribute__ ((packed)); - -/* - * An additional header for a CMD_SUBMIT packet. - */ -struct usbip_header_cmd_submit { - __u32 transfer_flags; - __s32 transfer_buffer_length; - __s32 bandwidth; - __s32 start_frame; - __s32 number_of_packets; - __s32 interval; - unsigned char setup[8]; /* CTRL only */ -}__attribute__ ((packed)); - -/* - * An additional header for a RET_SUBMIT packet. - */ -struct usbip_header_ret_submit { - __s32 status; - __s32 actual_length; /* returned data length */ - __s32 bandwidth; - __s32 start_frame; /* ISO and INT */ - __s32 number_of_packets; /* ISO only */ - __s32 error_count; /* ISO only */ -}__attribute__ ((packed)); - -/* - * An additional header for a CMD_UNLINK packet. - */ -struct usbip_header_cmd_unlink { - __u32 seqnum; /* URB's seqnum which will be unlinked */ -}__attribute__ ((packed)); - - -/* - * An additional header for a RET_UNLINK packet. - */ -struct usbip_header_ret_unlink { - __s32 status; -}__attribute__ ((packed)); - - -/* the same as usb_iso_packet_descriptor but packed for pdu */ -struct usbip_iso_packet_descriptor { - __u32 offset; - __u32 length; /* expected length */ - __u32 actual_length; - __u32 status; -}__attribute__ ((packed)); - - -/* - * All usbip packets use a common header to keep code simple. - */ -struct usbip_header { - struct usbip_header_basic base; - - union { - struct usbip_header_cmd_submit cmd_submit; - struct usbip_header_ret_submit ret_submit; - struct usbip_header_cmd_unlink cmd_unlink; - struct usbip_header_ret_unlink ret_unlink; - } u; -}__attribute__ ((packed)); - - - - -/*-------------------------------------------------------------------------*/ - - -int usbip_xmit(int , struct socket *, char *, int , int ); -int usbip_sendmsg(struct socket *, struct msghdr *, int ); - - -static inline int interface_to_busnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->bus->busnum; -} - -static inline int interface_to_devnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->devnum; -} - -static inline int interface_to_infnum(struct usb_interface *interface) -{ - return interface->cur_altsetting->desc.bInterfaceNumber; -} - -int setnodelay(struct socket *); -int setquickack(struct socket *); -int setkeepalive(struct socket *socket); -void setreuse(struct socket *); -struct socket *sockfd_to_socket(unsigned int); -int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss); - - -void usbip_dump_urb (struct urb *purb); -void usbip_dump_header(struct usbip_header *pdu); - - -struct usbip_device; - -struct usbip_task { - struct task_struct *thread; - struct completion thread_done; - char *name; - void (*loop_ops)(struct usbip_task *); -}; - -enum usbip_side { - USBIP_VHCI, - USBIP_STUB, -}; - -enum usbip_status { - /* sdev is available. */ - SDEV_ST_AVAILABLE = 0x01, - /* sdev is now used. */ - SDEV_ST_USED, - /* sdev is unusable because of a fatal error. */ - SDEV_ST_ERROR, - - /* vdev does not connect a remote device. */ - VDEV_ST_NULL, - /* vdev is used, but the USB address is not assigned yet */ - VDEV_ST_NOTASSIGNED, - VDEV_ST_USED, - VDEV_ST_ERROR -}; - -/* a common structure for stub_device and vhci_device */ -struct usbip_device{ - enum usbip_side side; - - enum usbip_status status; - - /* lock for status */ - spinlock_t lock; - - struct socket *tcp_socket; - - struct usbip_task tcp_rx; - struct usbip_task tcp_tx; - - /* event handler */ -#define USBIP_EH_SHUTDOWN (1 << 0) -#define USBIP_EH_BYE (1 << 1) -#define USBIP_EH_RESET (1 << 2) -#define USBIP_EH_UNUSABLE (1 << 3) - -#define SDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE ) -#define SDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_SUBMIT ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE ) - -#define VDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_BYE ) -#define VDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) - - unsigned long event; - struct usbip_task eh; - wait_queue_head_t eh_waitq; - - struct eh_ops { - void (*shutdown)(struct usbip_device *); - void (*reset)(struct usbip_device *); - void (*unusable)(struct usbip_device *); - } eh_ops; -}; - - -void usbip_task_init(struct usbip_task *ut, char *, void (*loop_ops)(struct usbip_task *)); - -void usbip_start_threads(struct usbip_device *ud); -void usbip_stop_threads(struct usbip_device *ud); -int usbip_thread(void *param); - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack); -void usbip_header_correct_endian(struct usbip_header *pdu, int send); -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb); -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen); - - -/* usbip_event.c */ -void usbip_start_eh(struct usbip_device *ud); -void usbip_stop_eh(struct usbip_device *ud); -void usbip_event_add(struct usbip_device *ud, unsigned long event); -int usbip_event_happend(struct usbip_device *ud); - - -#endif diff -Naur usbip-0.1.4/drivers/2.6.15/usbip_event.c trunk/drivers/2.6.15/usbip_event.c --- usbip-0.1.4/drivers/2.6.15/usbip_event.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/usbip_event.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,153 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" - - - - -static void event_handler_loop(struct usbip_task *eh); - -void usbip_start_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - init_waitqueue_head(&ud->eh_waitq); - ud->event = 0; - - usbip_task_init(eh, "usbip_eh", event_handler_loop); - - kernel_thread((int(*)(void *)) usbip_thread, (void *) eh, 0); - - wait_for_completion(&eh->thread_done); -} - -void usbip_stop_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - wait_for_completion(&eh->thread_done); - dbg_eh("usbip_eh has finished\n"); -} - - -void usbip_event_add(struct usbip_device *ud, unsigned long event) -{ - spin_lock(&ud->lock); - - ud->event |= event; - - wake_up(&ud->eh_waitq); - - spin_unlock(&ud->lock); -} - -int usbip_event_happend(struct usbip_device *ud) -{ - int happend = 0; - - spin_lock(&ud->lock); - - if (ud->event != 0) - happend = 1; - - spin_unlock(&ud->lock); - - return happend; -} - - -static int event_handler(struct usbip_device *ud) -{ - - dbg_eh("enter\n"); - - - /* - * Events are handled by only this thread. - */ - while ( usbip_event_happend(ud) ) { - dbg_eh("pending event %lx\n", ud->event); - - /* - * NOTE: shutdown must come first. - * Shutdown the device. - */ - if (ud->event & USBIP_EH_SHUTDOWN) { - ud->eh_ops.shutdown(ud); - - ud->event &= ~USBIP_EH_SHUTDOWN; - - break; - } - - /* Stop the error handler. */ - if (ud->event & USBIP_EH_BYE) - return -1; - - /* Reset the device. */ - if (ud->event & USBIP_EH_RESET) { - ud->eh_ops.reset(ud); - - ud->event &= ~USBIP_EH_RESET; - - break; - } - - /* Mark the device as unusable. */ - if (ud->event & USBIP_EH_UNUSABLE) { - ud->eh_ops.unusable(ud); - - ud->event &= ~USBIP_EH_UNUSABLE; - - break; - } - - /* NOTREACHED */ - uerr("unknown event\n"); - return -1; - } - - return 0; -} - - - - -static void event_handler_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, eh); - - while (1) { - if (signal_pending(current)) { - dbg_eh("signal catched!\n"); - break; - } - - if ( event_handler(ud) < 0) - break; - - wait_event_interruptible(ud->eh_waitq, usbip_event_happend(ud)); - dbg_eh("wakeup\n"); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.15/vhci.h trunk/drivers/2.6.15/vhci.h --- usbip-0.1.4/drivers/2.6.15/vhci.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/vhci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,143 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include HCD_HEADER - - -struct vhci_device { - struct usb_device *udev; - - /* busnum and devnum of a remote device */ - __u32 busnum; - __u32 devnum; - - /* speed of a remote device */ - enum usb_device_speed speed; - - /* vhci root-hub port to which this device is attached */ - __u32 rhport; - - struct usbip_device ud; - - - /* lock for the below link lists */ - spinlock_t priv_lock; - - /* vhci_priv is linked to one of them. */ - struct list_head priv_tx; - struct list_head priv_rx; - - /* vhci_unlink is linked to one of them */ - struct list_head unlink_tx; - struct list_head unlink_rx; - - /* vhci_tx thread sleeps for this queue */ - wait_queue_head_t waitq_tx; -}; - - -/* urb->hcpriv, use container_of() */ -struct vhci_priv { - unsigned long seqnum; - struct list_head list; - - struct vhci_device *vdev; - struct urb *urb; -}; - - -struct vhci_unlink { - /* seqnum of this request */ - unsigned long seqnum; - - struct list_head list; - - /* seqnum of the unlink target */ - unsigned long unlink_seqnum; -}; - -/* - * The number of ports is less than 16 ? - * USB_MAXCHILDREN is statically defined to 16 in usb.h. Its maximum value - * would be 31 because the event_bits[1] of struct usb_hub is defined as - * unsigned long in hub.h - */ -#define VHCI_NPORTS 8 - -/* for usb_bus.hcpriv */ -struct vhci_hcd { - spinlock_t lock; - - u32 port_status[VHCI_NPORTS]; - - unsigned resuming:1; - unsigned long re_timeout; - - atomic_t seqnum; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - * But, the index of this array begins from 0. - */ - struct vhci_device vdev[VHCI_NPORTS]; - - /* vhci_device which has not been assiged its address yet */ - int pending_port; -}; - - -extern struct vhci_hcd *the_controller; -extern struct attribute_group dev_attr_group; - - -/*-------------------------------------------------------------------------*/ -/* prototype declaration */ - -/* vhci_hcd.c */ -void rh_port_connect(int rhport, enum usb_device_speed speed); -void rh_port_disconnect(int rhport); -void vhci_rx_loop(struct usbip_task *ut); -void vhci_tx_loop(struct usbip_task *ut); - -#define hardware (&the_controller->pdev.dev) - -static inline struct vhci_device *port_to_vdev(__u32 port) -{ - return &the_controller->vdev[port]; -} - -static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd) -{ - return (struct vhci_hcd *) (hcd->hcd_priv); -} - -static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci) -{ - return container_of((void *) vhci, struct usb_hcd, hcd_priv); -} - -static inline struct device *vhci_dev(struct vhci_hcd *vhci) -{ - return vhci_to_hcd(vhci)->self.controller; -} diff -Naur usbip-0.1.4/drivers/2.6.15/vhci_hcd.c trunk/drivers/2.6.15/vhci_hcd.c --- usbip-0.1.4/drivers/2.6.15/vhci_hcd.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/vhci_hcd.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1174 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "vhci.h" - -#define DRIVER_VERSION " $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ " -#define DRIVER_AUTHOR "HIROFUCHI Takahiro " -#define DRIVER_DESC "Virtual Host Controller Interface Driver for USB/IP" -#define DRIVER_LICENCE "GPL" -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENCE); - - - -/* - * TODO - * - update root hub emulation - * - move the emulation code to userland ? - * poring to other operating systems - * minimize kernel code - * - add suspend/resume code - * - clean up everything - */ - - -/* See usb gadget dummy hcd */ - - -static int vhci_hub_status (struct usb_hcd *hcd, char *buff); -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buff, u16 wLength); -static int vhci_urb_enqueue (struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags); -static int vhci_urb_dequeue( struct usb_hcd *hcd, struct urb *urb); -static int vhci_start(struct usb_hcd *vhci_hcd); -static void vhci_stop(struct usb_hcd *hcd); -static int vhci_get_frame_number(struct usb_hcd *hcd); - -static const char driver_name[] = "vhci_hcd"; -static const char driver_desc[] = "USB/IP Virtual Host Contoroller"; - - - - -struct vhci_hcd *the_controller = NULL; - - -static const char *bit_desc[] = { - "CONNECTION", /*0*/ - "ENABLE", /*1*/ - "SUSPEND", /*2*/ - "OVER_CURRENT", /*3*/ - "RESET", /*4*/ - "R5", /*5*/ - "R6", /*6*/ - "R7", /*7*/ - "POWER", /*8*/ - "LOWSPEED", /*9*/ - "HIGHSPEED", /*10*/ - "PORT_TEST", /*11*/ - "INDICATOR", /*12*/ - "R13", /*13*/ - "R14", /*14*/ - "R15", /*15*/ - "C_CONNECTION", /*16*/ - "C_ENABLE", /*17*/ - "C_SUSPEND", /*18*/ - "C_OVER_CURRENT", /*19*/ - "C_RESET", /*20*/ - "R21", /*21*/ - "R22", /*22*/ - "R23", /*23*/ - "R24", /*24*/ - "R25", /*25*/ - "R26", /*26*/ - "R27", /*27*/ - "R28", /*28*/ - "R29", /*29*/ - "R30", /*30*/ - "R31", /*31*/ -}; - - -static void dump_port_status(u32 status) -{ - int i = 0; - - printk("status %08x:", status); - for (i = 0; i < 32; i++) { - if (status & (1 << i)) { - printk(" %s", bit_desc[i]); - } - } - - printk("\n"); -} - - - -void rh_port_connect(int rhport, enum usb_device_speed speed) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_connect %d\n", rhport); - - spin_lock_irqsave(&the_controller->lock, flags); - - the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION - | (1 << USB_PORT_FEAT_C_CONNECTION); - - switch (speed) { - case USB_SPEED_HIGH: - the_controller->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - the_controller->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - - //spin_lock(&the_controller->vdev[rhport].ud.lock); - //the_controller->vdev[rhport].ud.status = VDEV_CONNECT; - //spin_unlock(&the_controller->vdev[rhport].ud.lock); - - the_controller->pending_port = rhport; - - spin_unlock_irqrestore(&the_controller->lock, flags); - -} - -void rh_port_disconnect(int rhport) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_disconnect %d\n", rhport); - - spin_lock_irqsave (&the_controller->lock, flags); - //stop_activity (dum, driver); - the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; - the_controller->port_status[rhport] |= (1 << USB_PORT_FEAT_C_CONNECTION); - - - /* not yet complete the disconnection */ - //spin_lock(&vdev->ud.lock); - //vdev->ud.status = VHC_ST_DISCONNECT; - //spin_unlock(&vdev->ud.lock); - - spin_unlock_irqrestore (&the_controller->lock, flags); -} - - - -/*----------------------------------------------------------------------*/ - -#define PORT_C_MASK \ - ((USB_PORT_STAT_C_CONNECTION \ - | USB_PORT_STAT_C_ENABLE \ - | USB_PORT_STAT_C_SUSPEND \ - | USB_PORT_STAT_C_OVERCURRENT \ - | USB_PORT_STAT_C_RESET) << 16) - -/* - * This function is almostly the same as dummy_hcd.c:dummy_hub_status() without - * suspend/resume support. But, it is modified to provide multiple ports. - * - * @buf: a bitmap to show which port status has been changed. - * bit 0: reserved or used for another purpose? - * bit 1: the status of port 0 has been changed. - * bit 2: the status of port 1 has been changed. - * ... - * bit 7: the status of port 6 has been changed. - * bit 8: the status of port 7 has been changed. - * ... - * bit 15: the status of port 14 has been changed. - * - * So, the maximum number of ports is 31 ( port 0 to port 30) ? - * - * The return value is the actual transfered length in byte. If nothing has - * been changed, return 0. In the case that the number of ports is less than or - * equal to 6 (VHCI_NPORTS==7), return 1. - * - */ -static int vhci_hub_status (struct usb_hcd *hcd, char *buf) -{ - struct vhci_hcd *vhci; - unsigned long flags; - int retval = 0; - - /* the enough buffer is allocated according to USB_MAXCHILDREN */ - unsigned long *event_bits = (unsigned long *) buf; - int rhport; - int changed = 0; - - - *event_bits = 0; - - vhci = hcd_to_vhci(hcd); - - spin_lock_irqsave (&vhci->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - dbg_vhci_rh("hw accessible flag in on?\n"); - goto done; - } - - /* check pseudo status register for each port */ - for(rhport = 0; rhport < VHCI_NPORTS; rhport++) { - if ((vhci->port_status[rhport] & PORT_C_MASK)) { - /* The status of a port has been changed, */ - dbg_vhci_rh("port %d is changed\n", rhport); - - *event_bits |= 1 << ( rhport + 1); - changed = 1; - } - } - - if (changed) - retval = 1 + (VHCI_NPORTS / 8); - else - retval = 0; - -done: - spin_unlock_irqrestore (&vhci->lock, flags); - return retval; -} - -/* See hub_configure in hub.c */ -static inline void hub_descriptor(struct usb_hub_descriptor *desc) -{ - memset(desc, 0, sizeof(*desc)); - desc->bDescriptorType = 0x29; - desc->bDescLength = 9; - desc->wHubCharacteristics = (__force __u16) - (__constant_cpu_to_le16 (0x0001)); - desc->bNbrPorts = VHCI_NPORTS; - desc->bitmap [0] = 0xff; - desc->bitmap [1] = 0xff; -} - - -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) -{ - struct vhci_hcd *dum; - int retval = 0; - unsigned long flags; - int rhport; - - u32 prev_port_status[VHCI_NPORTS]; - - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) - return -ETIMEDOUT; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - */ - dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue, wIndex); - if (wIndex > VHCI_NPORTS) - uerr("invalid port number %d\n", wIndex); - rhport = ((__u8 ) (wIndex & 0x00ff)) -1; - - dum = hcd_to_vhci(hcd); - - spin_lock_irqsave (&dum->lock, flags); - - /* store old status and compare now and old later */ - if (dbg_flag_vhci_rh) { - int i = 0; - for (i = 0; i < VHCI_NPORTS; i++) - prev_port_status[i] = dum->port_status[i]; - } - - switch (typeReq) { - case ClearHubFeature: - dbg_vhci_rh(" ClearHubFeature\n"); - break; - case ClearPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if (dum->port_status[rhport] & (1 << USB_PORT_FEAT_SUSPEND)) { - /* 20msec signaling */ - dum->resuming = 1; - dum->re_timeout = jiffies + msecs_to_jiffies(20); - } - break; - case USB_PORT_FEAT_POWER: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_POWER\n"); - dum->port_status[rhport] = 0; - //dum->address = 0; - //dum->hdev = 0; - dum->resuming = 0; - break; - case USB_PORT_FEAT_C_RESET: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_C_RESET\n"); - switch (dum->vdev[rhport].speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - default: - dbg_vhci_rh(" ClearPortFeature: default %x\n", wValue); - dum->port_status[rhport] &= ~(1 << wValue); - } - break; - case GetHubDescriptor: - dbg_vhci_rh(" GetHubDescriptor\n"); - hub_descriptor ((struct usb_hub_descriptor *) buf); - break; - case GetHubStatus: - dbg_vhci_rh(" GetHubStatus\n"); - *(u32 *) buf = __constant_cpu_to_le32 (0); - break; - case GetPortStatus: - dbg_vhci_rh(" GetPortStatus port %x\n", wIndex); - if (wIndex > VHCI_NPORTS || wIndex < 1) { - uerr(" invalid port number %d\n", wIndex); - retval = -EPIPE; - } - - /* we do no care of resume. */ - - /* whoever resets or resumes must GetPortStatus to - * complete it!! - * */ - if (dum->resuming && time_after (jiffies, dum->re_timeout)) { - uerr(" not yet\n"); - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_SUSPEND); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_SUSPEND); - dum->resuming = 0; - dum->re_timeout = 0; - //if (dum->driver && dum->driver->resume) { - // spin_unlock (&dum->lock); - // dum->driver->resume (&dum->gadget); - // spin_lock (&dum->lock); - //} - } - - if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) != 0 - && time_after (jiffies, dum->re_timeout)) { - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_RESET); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_RESET); - dum->re_timeout = 0; - - if (dum->vdev[rhport].ud.status == VDEV_ST_NOTASSIGNED) { - dbg_vhci_rh(" enable rhport %d (status %u)\n", rhport, dum->vdev[rhport].ud.status); - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - } -#if 0 - if (dum->driver) { - - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - /* give it the best speed we agree on */ - dum->gadget.speed = dum->driver->speed; - dum->gadget.ep0->maxpacket = 64; - switch (dum->gadget.speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= - USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->gadget.ep0->maxpacket = 8; - dum->port_status[rhport] |= - USB_PORT_STAT_LOW_SPEED; - break; - default: - dum->gadget.speed = USB_SPEED_FULL; - break; - } - } -#endif - - } - ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status[rhport]); - ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status[rhport] >> 16); - - dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0], ((u16 *)buf)[1] ); - break; - case SetHubFeature: - dbg_vhci_rh(" SetHubFeature\n"); - retval = -EPIPE; - break; - case SetPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_SUSPEND\n"); - uerr(" not yet\n"); -#if 0 - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_SUSPEND); - if (dum->driver->suspend) { - spin_unlock (&dum->lock); - dum->driver->suspend (&dum->gadget); - spin_lock (&dum->lock); - } -#endif - break; - case USB_PORT_FEAT_RESET: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_RESET\n"); - /* if it's already running, disconnect first */ - if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) { - dum->port_status[rhport] &= ~(USB_PORT_STAT_ENABLE - | USB_PORT_STAT_LOW_SPEED - | USB_PORT_STAT_HIGH_SPEED); -#if 0 - if (dum->driver) { - dev_dbg (hardware, "disconnect\n"); - stop_activity (dum, dum->driver); - } -#endif - - /* FIXME test that code path! */ - } - /* 50msec reset signaling */ - dum->re_timeout = jiffies + msecs_to_jiffies(50); - - /* FALLTHROUGH */ - default: - dbg_vhci_rh(" SetPortFeature: default %d\n", wValue); - dum->port_status[rhport] |= (1 << wValue); - } - break; - - default: - uerr(" default: no such request\n"); - //dev_dbg (hardware, - // "hub control req%04x v%04x i%04x l%d\n", - // typeReq, wValue, wIndex, wLength); - - /* "protocol stall" on error */ - retval = -EPIPE; - } - - if (dbg_flag_vhci_rh) { - printk("port %d\n", rhport); - dump_port_status(prev_port_status[rhport]); - dump_port_status(dum->port_status[rhport]); - } - dbg_vhci_rh(" bye\n"); - - spin_unlock_irqrestore (&dum->lock, flags); - - return retval; -} - - - -/*----------------------------------------------------------------------*/ - -static struct vhci_device *get_vdev(struct usb_device *udev) -{ - int i; - - if (!udev) - return NULL; - - for (i=0; i < VHCI_NPORTS; i++) - if (the_controller->vdev[i].udev == udev) - return port_to_vdev(i); - - return NULL; -} - -static void vhci_tx_urb(struct urb *urb) -{ - struct vhci_device *vdev = get_vdev(urb->dev); - struct vhci_priv *priv; - unsigned long flag; - - if (!vdev) - BUG(); - - spin_lock_irqsave(&vdev->priv_lock, flag); - - priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC); - if (!priv) { - uerr("malloc vhci_priv\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flag); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - priv->seqnum = atomic_inc_return(&the_controller->seqnum); - if (priv->seqnum == 0xffff) - uinfo("seqnum max\n"); - - priv->vdev = vdev; - priv->urb = urb; - - urb->hcpriv = (void *) priv; - - - list_add_tail(&priv->list, &vdev->priv_tx); - - wake_up(&vdev->waitq_tx); - spin_unlock_irqrestore(&vdev->priv_lock, flag); -} - -static int vhci_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags) -{ - int ret = 0; - unsigned long flags; - - dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); - - - - /* patch to usb_sg_init() is in 2.5.60 */ - BUG_ON (!urb->transfer_buffer && urb->transfer_buffer_length); - - spin_lock_irqsave (&the_controller->lock, flags); - - /* check HC is active or not */ - if (!HC_IS_RUNNING(hcd->state)) { - uerr("HC is not running\n"); - spin_unlock_irqrestore(&the_controller->lock, flags); - return -ENODEV; - } - - if (urb->status != -EINPROGRESS) { - uerr("URB already unlinked!, status %d\n", urb->status); - spin_unlock_irqrestore(&the_controller->lock, flags); - return urb->status; - } - - /* - * The enumelation process is as follows; - * - * 1. Get_Descriptor request to DevAddrs(0) EndPoint(0) - * to get max packet length of default pipe - * - * 2. Set_Address request to DevAddr(0) EndPoint(0) - * - */ - - if (usb_pipedevice(urb->pipe) == 0) { - __u8 type = usb_pipetype(urb->pipe); - struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; - struct vhci_device *vdev = port_to_vdev(the_controller->pending_port); - - if (type != PIPE_CONTROL || !ctrlreq ) { - uerr("invalid request to devnum 0\n"); - ret = EINVAL; - goto no_need_xmit; - } - - switch (ctrlreq->bRequest) { - - case USB_REQ_SET_ADDRESS: - vdev->udev = urb->dev; - dbg_vhci_hc("SetAddress Request (%d) to port %d\n", - ctrlreq->wValue, vdev->rhport); - - spin_lock(&vdev->ud.lock); - vdev->ud.status = VDEV_ST_USED; - spin_unlock(&vdev->ud.lock); - - spin_lock (&urb->lock); - if (urb->status == -EINPROGRESS) { - /* This request is successfully completed. */ - /* If not -EINPROGRESS, possibly unlinked. */ - urb->status = 0; - } - spin_unlock (&urb->lock); - - goto no_need_xmit; - - case USB_REQ_GET_DESCRIPTOR: - if (ctrlreq->wValue == (USB_DT_DEVICE << 8)) - dbg_vhci_hc("Not yet?: Get_Descriptor to device 0 (get max pipe size)\n"); - - vdev->udev = urb->dev; - goto out; - - default: - /* NOT REACHED */ - uerr("invalid request to devnum 0 bRequest %u, wValue %u\n", - ctrlreq->bRequest, ctrlreq->wValue); - ret = -EINVAL; - goto no_need_xmit; - } - - } - -out: - - - vhci_tx_urb(urb); - - - spin_unlock_irqrestore (&the_controller->lock, flags); - - return 0; - - -no_need_xmit: - - spin_unlock_irqrestore(&the_controller->lock, flags); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - return 0; -} - - -/* - * vhci_rx gives back the urb after recieving the reply of the urb. If an - * unlink pdu is sent or not, vhci_rx recieves a normal return pdu and gives - * back its urb. For the driver unlinking the urb, the content of the urb is - * not important, but the calling to its completion handler is important; the - * completion of unlinking is notified by the completion handler. - * - * - * CLIENT SIDE - * - * - When vhci_hcd recieves RET_SUBMIT, - * - * - case 1a). the urb of the pdu is not unlinking. - * - normal case - * => just give back the urb - * - * - case 1b). the urb of the pdu is unlinking. - * - usbip.ko will return a reply of the unlinking request. - * => give back the urb now and go to case 2b). - * - * - When vhci_hcd recieves RET_UNLINK, - * - * - case 2a). a submit request is still pending in vhci_hcd. - * - urb was really pending in usbip.ko and urb_unlink_urb() was - * completed there. - * => free a pending submit request - * => notify unlink completeness by giving back the urb - * - * - case 2b). a submit request is *not* pending in vhci_hcd. - * - urb was already given back to the core driver. - * => do not give back the urb - * - * - * SERVER SIDE - * - * - When usbip recieves CMD_UNLINK, - * - * - case 3a). the urb of the unlink request is now in submission. - * => do usb_unlink_urb(). - * => after the unlink is completed, send RET_UNLINK. - * - * - case 3b). the urb of the unlink request is not in submission. - * - may be already completed or never be recieved - * => send RET_UNLINK - * - */ -static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -{ - unsigned long flags; - struct vhci_priv *priv; - struct vhci_device *vdev; - - uinfo("vhci_hcd: dequeue a urb %p\n", urb); - - - spin_lock_irqsave(&the_controller->lock, flags); - - priv = urb->hcpriv; - if (!priv) { - /* URB was never linked! or will be soon given back by vhci_rx. */ - spin_unlock_irqrestore(&the_controller->lock, flags); - return 0; - } - - /* send unlink request here? */ - vdev = priv->vdev; - - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - unsigned long flags2; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - uinfo("vhci_hcd: device %p seems to be disconnected\n", vdev); - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - - } else { - /* tcp connection is alive */ - unsigned long flags2; - struct vhci_unlink *unlink; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - /* setup CMD_UNLINK pdu */ - unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("malloc vhci_unlink\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - spin_unlock_irqrestore(&the_controller->lock, flags); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return -ENOMEM; - } - - unlink->seqnum = atomic_inc_return(&the_controller->seqnum); - if (unlink->seqnum == 0xffff) - uinfo("seqnum max\n"); - - unlink->unlink_seqnum = priv->seqnum; - - uinfo("vhci_hcd: device %p seems to be still connected\n", vdev); - - /* send cmd_unlink and try to cancel the pending URB in the peer */ - list_add_tail(&unlink->list, &vdev->unlink_tx); - wake_up(&vdev->waitq_tx); - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - } - - spin_unlock_irqrestore(&the_controller->lock, flags); - - /* - * If tcp connection is alive, we have sent CMD_UNLINK. - * vhci_rx will recieve RET_UNLINK and giveb back the URB. - * Otherwise, we give back it here. - */ - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n", urb); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - dbg_vhci_hc("leave\n"); - return 0; -} - - -static void vhci_device_unlink_cleanup(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock(&vdev->priv_lock); -} - -/* - * The important thing is that only one context begins cleanup. - * This is why error handling and cleanup become simple. - * We do not want to consider race condition as possible. - */ -static void vhci_shutdown_connection(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - /* need this? see stub_dev.c */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - usbip_stop_threads(&vdev->ud); - uinfo("stop threads\n"); - - /* active connection is closed */ - if (vdev->ud.tcp_socket != NULL) { - sock_release(vdev->ud.tcp_socket); - vdev->ud.tcp_socket = NULL; - } - uinfo("release socket\n"); - - vhci_device_unlink_cleanup(vdev); - - /* - * rh_port_disconnect() is a trigger of ... - * usb_disable_device(): - * disable all the endpoints for a USB device. - * usb_disable_endpoint(): - * disable endpoints. pending urbs are unlinked(dequeued). - * - * NOTE: After calling rh_port_disconnect(), the USB device driver of a - * deteched device should release used urbs in a cleanup function(i.e. - * xxx_disconnect()). Therefore, vhci_hcd does not need to release - * pushed urbs and their private data in this function. - * - * NOTE: vhci_dequeue() must be considered carefully. When shutdowning - * a connection, vhci_shutdown_connection() expects vhci_dequeue() - * gives back pushed urbs and frees their private data by request of - * the cleanup function of a USB driver. When unlinking a urb with an - * active connection, vhci_dequeue() does not give back the urb which - * is actually given back by vhci_rx after recieving its return pdu. - * - */ - rh_port_disconnect(vdev->rhport); - - uinfo("disconnect device\n"); -} - - -static void vhci_device_reset(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - spin_lock(&ud->lock); - - vdev->busnum = 0; - vdev->devnum = 0; - vdev->speed = 0; - - ud->tcp_socket = NULL; - - ud->status = VDEV_ST_NULL; - - spin_unlock(&ud->lock); -} - -static void vhci_device_unusable(struct usbip_device* ud) -{ - spin_lock(&ud->lock); - - ud->status = VDEV_ST_ERROR; - - spin_unlock(&ud->lock); -} - -static void vhci_device_init(struct vhci_device *vdev) -{ - memset(vdev, 0, sizeof(*vdev)); - - usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop); - usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop); - - vdev->ud.side = USBIP_VHCI; - vdev->ud.status = VDEV_ST_NULL; - vdev->ud.lock = SPIN_LOCK_UNLOCKED; - - INIT_LIST_HEAD(&vdev->priv_rx); - INIT_LIST_HEAD(&vdev->priv_tx); - INIT_LIST_HEAD(&vdev->unlink_tx); - INIT_LIST_HEAD(&vdev->unlink_rx); - vdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&vdev->waitq_tx); - - vdev->ud.eh_ops.shutdown = vhci_shutdown_connection; - vdev->ud.eh_ops.reset = vhci_device_reset; - vdev->ud.eh_ops.unusable= vhci_device_unusable; - - usbip_start_eh(&vdev->ud); -} - - -/*----------------------------------------------------------------------*/ - -static int vhci_start(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport; - - dbg_vhci_hc("enter vhci_start\n"); - - - /* initialize private data of usb_hcd */ - - for(rhport=0; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - vhci_device_init(vdev); - vdev->rhport = rhport; - } - - atomic_set(&vhci->seqnum, 0); - spin_lock_init(&vhci->lock); - - - - //hcd->power_budget = 0; /* no limit ? */ - hcd->state = HC_STATE_RUNNING; - //hcd->uses_new_polling = 1; - - - /* vhci_hcd is now ready to be controlled through sysfs */ - sysfs_create_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - return 0; -} - -static void vhci_stop(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport = 0; - - dbg_vhci_hc("stop VHCI controller\n"); - - - /* 1. remove the userland interface of vhci_hcd */ - sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - /* 2. shutdown all the ports of vhci_hcd */ - for(rhport = 0 ; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - - usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED); - usbip_stop_eh(&vdev->ud); - } - - - uinfo("vhci_stop done\n"); -} - -/*----------------------------------------------------------------------*/ - -static int vhci_get_frame_number(struct usb_hcd *hcd) -{ - uerr("Not yet implemented\n"); - return 0; -} - - -#ifdef CONFIG_PM - -static int vhci_bus_suspend(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -static int vhci_bus_resume(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -#else - -#define vhci_bus_suspend NULL -#define vhci_bus_resume NULL -#endif - - - -static struct hc_driver vhci_hc_driver = { - .description = driver_name, - .product_desc = driver_desc, - .hcd_priv_size = sizeof(struct vhci_hcd), - - .flags = HCD_USB2, - - .start = vhci_start, - .stop = vhci_stop, - - .urb_enqueue = vhci_urb_enqueue, - .urb_dequeue = vhci_urb_dequeue, - - .get_frame_number = vhci_get_frame_number, - - .hub_status_data = vhci_hub_status, - .hub_control = vhci_hub_control, - .bus_suspend = vhci_bus_suspend, - .bus_resume = vhci_bus_resume, -}; - -static int vhci_hcd_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - int ret; - - uinfo("proving...\n"); - - dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id); - - - /* will be removed */ - if (pdev->dev.dma_mask) { - info("vhci_hcd DMA not supported\n"); - return -EINVAL; - } - - - /* - * Allocate and initialize hcd. - * Our private data is also allocated automatically. - */ - hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, pdev->dev.bus_id); - if (!hcd) { - uerr("create hcd failed\n"); - return -ENOMEM; - } - - - /* this is private data for vhci_hcd */ - the_controller = hcd_to_vhci(hcd); - - /* - * Finish generic HCD structure initialization and register. - * Call the driver's reset() and start() routines. - */ - ret = usb_add_hcd(hcd, 0, 0); - if (ret != 0) { - uerr("usb_add_hcd failed %d\n", ret); - usb_put_hcd(hcd); - the_controller = NULL; - return ret; - } - - - dbg_vhci_hc("bye\n"); - return 0; -} - - -static int vhci_hcd_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - - - hcd = platform_get_drvdata(pdev); - if(!hcd) - return 0; - - /* - * Disconnects the root hub, - * then reverses the effects of usb_add_hcd(), - * invoking the HCD's stop() methods. - */ - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - the_controller = NULL; - - - return 0; -} - - - -#ifdef CONFIG_PM - -/* what should happen for USB/IP under suspend/resume? */ -static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = state; - - return 0; -} - -static int vhci_hcd_resume(struct platform_device *pdev) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = PMSG_ON; - - return 0; -} - -#else - -#define vhci_hcd_suspend NULL -#define vhci_hcd_resume NULL - -#endif - - -static struct platform_driver vhci_driver = { - .probe = vhci_hcd_probe, - .remove = __devexit_p(vhci_hcd_remove), - .suspend = vhci_hcd_suspend, - .resume = vhci_hcd_resume, - .driver = { - .name = (char *) driver_name, - .owner = THIS_MODULE, - }, -}; - -/*----------------------------------------------------------------------*/ - -/* - * The VHCI 'device' is 'virtual'; not a real plug&play hardware. - * We need to add this virtual device as a platform device arbitrarily: - * 1. platform_device_register() - */ -static void the_pdev_release(struct device *dev) -{ - return; -} - -static struct platform_device the_pdev = { - /* should be the same name as driver_name */ - .name = (char *) driver_name, - .id = -1, - .dev = { - //.driver = &vhci_driver, - .release = the_pdev_release, - }, -}; - -static int __init vhci_init(void) -{ - int ret; - - dbg_vhci_hc("enter\n"); - if (usb_disabled()) - return -ENODEV; - - info("driver %s, %s\n", driver_name, DRIVER_VERSION); - - ret = platform_driver_register(&vhci_driver); - if (ret < 0) - goto err_driver_register; - - ret = platform_device_register(&the_pdev); - if (ret < 0) - goto err_platform_device_register; - - - dbg_vhci_hc("bye\n"); - return ret; - - - - /* error occurred */ - -err_platform_device_register: - platform_driver_unregister(&vhci_driver); - -err_driver_register: - - dbg_vhci_hc("bye\n"); - return ret; -} -module_init(vhci_init); - - -static void __exit vhci_cleanup(void) -{ - dbg_vhci_hc("enter\n"); - - platform_device_unregister(&the_pdev); - platform_driver_unregister(&vhci_driver); - - dbg_vhci_hc("bye\n"); -} -module_exit(vhci_cleanup); diff -Naur usbip-0.1.4/drivers/2.6.15/vhci_rx.c trunk/drivers/2.6.15/vhci_rx.c --- usbip-0.1.4/drivers/2.6.15/vhci_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/vhci_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,239 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - - -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) -{ - struct vhci_priv *priv, *tmp; - struct urb *urb = NULL; - - - spin_lock(&vdev->priv_lock); - - - list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { - if (priv->seqnum == seqnum) { - urb = priv->urb; - dbg_vhci_rx("find urb %p vurb %p seqnum %u\n", urb, priv, seqnum); - - - if (urb->status != -EINPROGRESS) { - if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - uinfo("urb %p was unlinked %ssynchronuously.\n", - urb, urb->status == -ENOENT ? "" : "a"); - } else { - uinfo("urb %p may be in a error, status %d\n", - urb, urb->status); - } - } - - - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - - break; - } - } - - spin_unlock(&vdev->priv_lock); - - - return urb; -} - -static void vhci_recv_ret_submit(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &vdev->ud; - struct urb *urb; - - - urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); - - - if (!urb) { - uerr("cannot find a urb of seqnum %u\n", pdu->base.seqnum); - uinfo("max seqnum %d\n", atomic_read(&the_controller->seqnum)); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - - /* unpack the pdu to a urb */ - usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0); - - - /* recv transfer buffer */ - if (usbip_recv_xbuff(ud, urb) < 0) - return; - - - /* recv iso_packet_descriptor */ - if (usbip_recv_iso(ud, urb) < 0) - return; - - - if (dbg_flag_vhci_rx) - usbip_dump_urb(urb); - - - dbg_vhci_rx("now giveback urb %p\n", urb); - - - - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - - dbg_vhci_rx("Leave\n"); - - return; -} - - -static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, - struct usbip_header *pdu) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - uinfo("unlink->seqnum %lu\n", unlink->seqnum); - if (unlink->seqnum == pdu->base.seqnum) { - dbg_vhci_rx("found pending unlink, %lu\n", unlink->seqnum); - list_del(&unlink->list); - - spin_unlock(&vdev->priv_lock); - return unlink; - } - } - - spin_unlock(&vdev->priv_lock); - - return NULL; -} - - -static void vhci_recv_ret_unlink(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct vhci_unlink *unlink; - struct urb *urb; - - usbip_dump_header(pdu); - - unlink = dequeue_pending_unlink(vdev, pdu); - if (!unlink) { - uinfo("cannot find the pending unlink %u\n", pdu->base.seqnum); - return; - } - - urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); - if (!urb) { - /* - * I get the result of a unlink request. But, it seems that I - * already recieved the result of its submit result and gave - * back the URB. - */ - uinfo("the urb (seqnum %d) was already given backed\n", pdu->base.seqnum); - } else { - dbg_vhci_rx("now giveback urb %p\n", urb); - - /* If unlink is succeed, status is -ECONNRESET */ - urb->status = pdu->u.ret_unlink.status; - uinfo("%d\n", urb->status); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - kfree(unlink); - - return; -} - -/* recv a pdu */ -static void vhci_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - - dbg_vhci_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_vhci_rx) - usbip_dump_header(&pdu); - - switch(pdu.base.command) { - case USBIP_RET_SUBMIT: - vhci_recv_ret_submit(vdev, &pdu); - break; - - case USBIP_RET_UNLINK: - vhci_recv_ret_unlink(vdev, &pdu); - break; - default: - /* NOTREACHED */ - uerr("unknown pdu %u\n", pdu.base.command); - usbip_dump_header(&pdu); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - } -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - - while (1) { - if (signal_pending(current)) { - dbg_vhci_rx("signal catched!\n"); - break; - } - - - if (usbip_event_happend(ud)) break; - - vhci_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.15/vhci_sysfs.c trunk/drivers/2.6.15/vhci_sysfs.c --- usbip-0.1.4/drivers/2.6.15/vhci_sysfs.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/vhci_sysfs.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,286 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* TODO: refine locking ?*/ - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to show port status */ - -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *out) -{ - char *s = out; - int i = 0; - - if (!the_controller || !out) - BUG(); - - spin_lock(&the_controller->lock); - - /* - * output example: - * prt sta bus dev socket local_busid - * 000 004 000 000 c5a7bb80 1-2.3 - * 001 004 000 000 d8cee980 2-3.4 - * - * IP address can be retrieved from a socket pointer address by looking - * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a - * port number and its peer IP address. - */ - out += sprintf(out, "prt sta spd bus dev socket local_busid\n"); - - for (i=0; i < VHCI_NPORTS; i++) { - struct vhci_device *vdev = port_to_vdev(i); - - spin_lock(&vdev->ud.lock); - - out += sprintf(out, "%03u %03u ", i, vdev->ud.status); - - if (vdev->ud.status == VDEV_ST_USED) { - out += sprintf(out, "%03u %03u %03u ", - vdev->speed, vdev->busnum, vdev->devnum); - out += sprintf(out, "%16p ", vdev->ud.tcp_socket); - out += sprintf(out, "%s", vdev->udev->dev.bus_id); - - } else - out += sprintf(out, "000 000 000 0000000000000000 0-0"); - - out += sprintf(out, "\n"); - - spin_unlock(&vdev->ud.lock); - } - - spin_unlock(&the_controller->lock); - - return out - s ; -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to shutdown a virtual connection */ - -static int vhci_port_disconnect(__u32 rhport) -{ - struct vhci_device *vdev; - - dbg_vhci_sysfs("enter\n"); - - /* lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - if (vdev->ud.status == VDEV_ST_NULL) { - uerr("not connected %d\n", vdev->ud.status); - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - return -EINVAL; - } - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); - - return 0; -} - -static ssize_t store_detach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) { - int err; - __u32 rhport = 0; - - sscanf(buf, "%u", &rhport); - - /* check rhport */ - if (rhport >= VHCI_NPORTS) { - uerr("invalid port %u\n", rhport); - return -EINVAL; - } - - err = vhci_port_disconnect(rhport); - if (err < 0) { - return -EINVAL; - } - - dbg_vhci_sysfs("Leave\n"); - return count; -} - -static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to establish a virtual connection */ - -static int valid_args(__u32 rhport, __u32 busnum, __u32 devnum, - enum usb_device_speed speed) -{ - /* check rhport */ - if ((rhport < 0) || (rhport >= VHCI_NPORTS)) { - uerr("port %u\n", rhport); - return -EINVAL; - } - - /* check busnum & devnum */ - if ((busnum <= 0) || (busnum >= 128) || (devnum <= 0) || (devnum >= 128)) { - uerr("busnum %u devnum %u\n", busnum, devnum); - return -EINVAL; - } - - /* check speed */ - switch(speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - case USB_SPEED_HIGH: - case USB_SPEED_VARIABLE: - break; - - default: - uerr("speed %d\n", speed); - return -EINVAL; - } - - return 0; -} - -/* - * To start a new USB/IP attachment, a userland program needs to setup a TCP - * connection and then write its socket descriptor with remote device - * information into this sysfs file. - * - * A remote device is virtually attached to the root-hub port of @rhport with - * @speed. @busnum and @devnum are used to convert URBs between a client host - * and a server host. - * - * write() returns 0 on success, else negative errno. - */ -static ssize_t store_attach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vhci_device *vdev; - struct socket *socket; - int sockfd = 0; - __u32 rhport=0, busnum=0, devnum=0, speed=0; - - - /* - * @rhport: port number of vhci_hcd - * @sockfd: socket descriptor of an established TCP connection - * @busnum: usb bus number in a remote host - * @devnum: usb device number in a remote host - * @speed: usb device speed in a remote host - */ - sscanf(buf, "%u %u %u %u %u", &rhport, &sockfd, &busnum, &devnum, &speed); - - dbg_vhci_sysfs("rhport(%u) sockfd(%u) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - - /* check recieved parameters */ - if (valid_args(rhport, busnum, devnum, speed) < 0) - return -EINVAL; - - /* check sockfd */ - socket = sockfd_to_socket(sockfd); - if (!socket) - return -EINVAL; - - setnodelay(socket); - - - /* now need lock until setting vdev status as used */ - - /* begin a lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - - if (vdev->ud.status != VDEV_ST_NULL) { - /* end of the lock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - uerr("port %d already used\n", rhport); - return -EINVAL; - } - - uinfo("rhport(%u) sockfd(%d) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - vdev->busnum = busnum; - vdev->devnum = devnum; - vdev->speed = speed; - vdev->ud.tcp_socket = socket; - vdev->ud.status = VDEV_ST_NOTASSIGNED; - - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - /* end the lock */ - - /* - * this function will sleep, so should be out of the lock. but, it's ok - * because we already marked vdev as being used. really? - */ - usbip_start_threads(&vdev->ud); - - rh_port_connect(rhport, speed); - - return count; -} - -static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach); - - - -/*-------------------------------------------------------------------------*/ - -static struct attribute *dev_attrs[] = { - &dev_attr_status.attr, - &dev_attr_detach.attr, - &dev_attr_attach.attr, - &dev_attr_usbip_debug.attr, - NULL, -}; - -struct attribute_group dev_attr_group = { - .attrs = dev_attrs, -}; diff -Naur usbip-0.1.4/drivers/2.6.15/vhci_tx.c trunk/drivers/2.6.15/vhci_tx.c --- usbip-0.1.4/drivers/2.6.15/vhci_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.15/vhci_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,264 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* @p: pipe whose dev number modified - * @pdev: new devive number */ -static unsigned long tweak_pipe_devnum(__u32 p, __u8 pdev) -{ - __u32 oldp; - oldp = p; - - if (pdev > 0x7f) - uerr("invalid devnum %u\n", pdev); - - pdev &= 0x7f; // 0XXX XXXX confirm MSB be 0 - - p &= 0xffff80ff; /* clear p's devnum */ - - p |= (pdev << 8); - - dbg_vhci_tx("return new pipe, devnum %u -> %u \n", - usb_pipedevice(oldp), usb_pipedevice(p)); - dbg_vhci_tx(" pipe %08x -> %08x\n", oldp, p); - - return p; -} - -static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) -{ - struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv); - struct vhci_device *vdev = priv->vdev; - - dbg_vhci_tx("URB, local devnum(%u), busnum(%u) devnum(%u)\n", - usb_pipedevice(urb->pipe), vdev->busnum, vdev->devnum); - - pdup->base.command = USBIP_CMD_SUBMIT; - pdup->base.busnum = vdev->busnum; - pdup->base.devnum = vdev->devnum; - pdup->base.seqnum = priv->seqnum; - pdup->base.pipe = tweak_pipe_devnum(urb->pipe, vdev->devnum); - - usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1); - - if (urb->setup_packet) - memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8); -} - -static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_priv *priv, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { - list_move_tail(&priv->list, &vdev->priv_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - - - -static int vhci_send_cmd_submit(struct vhci_device *vdev) -{ - struct vhci_priv *priv = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(vdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_cmd_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->transfer_buffer_length; - txsize += urb->transfer_buffer_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&vdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - if (iso_buffer) - kfree(iso_buffer); - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_unlink *unlink, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_move_tail(&unlink->list, &vdev->unlink_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - -static int vhci_send_cmd_unlink(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup cmd unlink, %lu \n", unlink->seqnum); - - - /* 1. setup usbip_header */ - pdu_header.base.command = USBIP_CMD_UNLINK; - pdu_header.base.busnum = vdev->busnum; - pdu_header.base.devnum = vdev->devnum; - pdu_header.base.seqnum = unlink->seqnum; - pdu_header.base.pipe = 0; - pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum; - - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - while (1) { - if (signal_pending(current)) { - uinfo("vhci_tx signal catched\n"); - break; - } - - if (vhci_send_cmd_submit(vdev) < 0) - break; - - if (vhci_send_cmd_unlink(vdev) < 0) - break; - - wait_event_interruptible(vdev->waitq_tx, - (!list_empty(&vdev->priv_tx) || - !list_empty(&vdev->unlink_tx))); - - dbg_vhci_tx("pending urbs ?, now wake up\n"); - } -} diff -Naur usbip-0.1.4/drivers/2.6.16/Makefile trunk/drivers/2.6.16/Makefile --- usbip-0.1.4/drivers/2.6.16/Makefile 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,63 +0,0 @@ -# Makefile for the USB/IP driver -# -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ -# -# Copyright (C) 2003-2006 Takahiro Hirofuchi -# -# -# This 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 of the License, or -# (at your option) any later version. -# -# This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -# USA. -# - - -# Please modify here or set environments. -# KSOURCE should be pointed to the build directory of your kernel. -# -DEBUG ?= n -KSOURCE ?= /usr/src/linux - - -%.x:%.c - gcc -o $@ $< - -KBUILD_VERBOSE:=1 - -HCD_HEADER:=$(KSOURCE)/drivers/usb/core/hcd.h - -obj-m += usbip.o -usbip-objs := usbip_common.o usbip_event.o stub_dev.o stub_main.o stub_rx.o stub_tx.o - -obj-m += vhci-hcd.o -vhci-hcd-objs := usbip_common.o usbip_event.o vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o - - -EXTRA_CFLAGS += -DHCD_HEADER=\"$(HCD_HEADER)\" - -ifeq ($(DEBUG),y) - EXTRA_CFLAGS += -DCONFIG_USB_DEBUG -endif - - -default: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules - -.PHONY: cscope -cscope: - cscope -b -k -R - -.PHONY: clean -clean: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` clean - rm -f *.x *~ diff -Naur usbip-0.1.4/drivers/2.6.16/stub_dev.c trunk/drivers/2.6.16/stub_dev.c --- usbip-0.1.4/drivers/2.6.16/stub_dev.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/stub_dev.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,438 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - - -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void stub_disconnect(struct usb_interface *interface); - - -/* - * Define device IDs here if you want to explicitly limit exportable devices. - * In the most cases, wild card matching will be ok because driver binding can - * be changed dynamically by a userland program. - */ -static struct usb_device_id stub_table[] = { -#if 0 - /* just an example */ - { USB_DEVICE(0x05ac, 0x0301) }, /* Mac 1 button mouse */ - { USB_DEVICE(0x0430, 0x0009) }, /* Plat Home Keyboard */ - { USB_DEVICE(0x059b, 0x0001) }, /* Iomega USB Zip 100 */ - { USB_DEVICE(0x04b3, 0x4427) }, /* IBM USB CD-ROM */ - { USB_DEVICE(0x05a9, 0xa511) }, /* LifeView USB cam */ - { USB_DEVICE(0x55aa, 0x0201) }, /* Imation card reader */ - { USB_DEVICE(0x046d, 0x0870) }, /* Qcam Express(QV-30) */ - { USB_DEVICE(0x04bb, 0x0101) }, /* IO-DATA HD 120GB */ - { USB_DEVICE(0x04bb, 0x0904) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x04bb, 0x0201) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x08bb, 0x2702) }, /* ONKYO USB Speaker */ - { USB_DEVICE(0x046d, 0x08b2) }, /* Logicool Qcam 4000 Pro */ -#endif - /* magic for wild card */ - { .driver_info = 1 }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, stub_table); - - -struct usb_driver stub_driver = { - .name = "usbip", - - .probe = stub_probe, - .disconnect = stub_disconnect, - - .id_table = stub_table, -}; - - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for a usbip-bound device */ - - -/* - * usbip_status shows status of usbip as long as this driver is bound to the - * target device. - */ -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int status; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - spin_lock(&sdev->ud.lock); - status = sdev->ud.status; - spin_unlock(&sdev->ud.lock); - - return snprintf(buf, PAGE_SIZE, "%d\n", status); -} -static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL); - - -/* - * usbip_sockfd gets a socket descriptor of an established TCP connection that - * is used to transfer usbip requests by kernel threads. -1 is a magic number - * by which usbip connection is finished. - */ -static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int sockfd = 0; - struct socket *socket; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - sscanf(buf, "%d", &sockfd); - - if (sockfd != -1) { - uinfo("stub up\n"); - - spin_lock(&sdev->ud.lock); - - if (sdev->ud.status != SDEV_ST_AVAILABLE) { - uerr("not ready\n"); - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - socket = sockfd_to_socket(sockfd); - if (!socket) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - setnodelay(socket); - setkeepalive(socket); - setreuse(socket); - - sdev->ud.tcp_socket = socket; - - spin_unlock(&sdev->ud.lock); - - usbip_start_threads(&sdev->ud); - - spin_lock(&sdev->ud.lock); - sdev->ud.status = SDEV_ST_USED; - spin_unlock(&sdev->ud.lock); - - } else { - uinfo("stub down\n"); - - spin_lock(&sdev->ud.lock); - if (sdev->ud.status != SDEV_ST_USED) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - spin_unlock(&sdev->ud.lock); - - usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); - } - - return count; -} -static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); - -static void stub_add_files(struct device *dev) -{ - device_create_file(dev, &dev_attr_usbip_status); - device_create_file(dev, &dev_attr_usbip_sockfd); - device_create_file(dev, &dev_attr_usbip_debug); -} - -static void stub_remove_files(struct device *dev) -{ - device_remove_file(dev, &dev_attr_usbip_status); - device_remove_file(dev, &dev_attr_usbip_sockfd); - device_remove_file(dev, &dev_attr_usbip_debug); -} - - - -/*-------------------------------------------------------------------------*/ - -/* Event handler functions called by an event handler thread */ - -static void stub_shutdown_connection(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - /* - * When removing an exported device, kernel panic sometimes occurred - * and then EIP was sk_wait_data of stub_rx thread. Is this because - * sk_wait_data returned though stub_rx thread was already finished by - * step 1? - */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - /* 1. stop threads */ - usbip_stop_threads(ud); - - /* 2. close the socket */ - /* - * tcp_socket is freed after threads are killed. - * So usbip_xmit do not touch NULL socket. - */ - if (ud->tcp_socket) { - sock_release(ud->tcp_socket); - ud->tcp_socket = NULL; - } - - /* 3. free used data */ - stub_device_cleanup_urbs(sdev); - - /* 4. free stub_unlink */ - { - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - } -} - -static void stub_device_reset(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - struct usb_device *udev = interface_to_usbdev(sdev->interface); - int ret; - - ret = usb_lock_device_for_reset(udev, sdev->interface); - if (ret < 0) { - uerr("lock for reset\n"); - - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); - - return; - } - - /* try to reset the device */ - ret = usb_reset_device(udev); - - usb_unlock_device(udev); - - spin_lock(&ud->lock); - if (ret) { - uerr("device reset\n"); - ud->status = SDEV_ST_ERROR; - - } else { - uinfo("device reset\n"); - ud->status = SDEV_ST_AVAILABLE; - - } - spin_unlock(&ud->lock); - - return; -} - -static void stub_device_unusable(struct usbip_device *ud) -{ - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); -} - - -/*-------------------------------------------------------------------------*/ - -/** - * stub_device_alloc - allocate a new stub_device struct - * @interface: usb_interface of a new device - * - * Allocates and initializes a new stub_devce struct. - */ -static struct stub_device * stub_device_alloc(struct usb_interface *interface) -{ - struct stub_device *sdev; - - /* yes, it's a new device */ - sdev = (struct stub_device *) kzalloc(sizeof(struct stub_device), GFP_KERNEL); - if (!sdev) { - uerr("no memory for stub_device\n"); - return NULL; - } - - sdev->interface = interface; - - usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop); - usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop); - - sdev->ud.side = USBIP_STUB; - sdev->ud.status = SDEV_ST_AVAILABLE; - sdev->ud.lock = SPIN_LOCK_UNLOCKED; - sdev->ud.tcp_socket = NULL; - - INIT_LIST_HEAD(&sdev->priv_init); - INIT_LIST_HEAD(&sdev->priv_tx); - INIT_LIST_HEAD(&sdev->priv_free); - INIT_LIST_HEAD(&sdev->unlink_free); - INIT_LIST_HEAD(&sdev->unlink_tx); - sdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&sdev->tx_waitq); - - sdev->ud.eh_ops.shutdown = stub_shutdown_connection; - sdev->ud.eh_ops.reset = stub_device_reset; - sdev->ud.eh_ops.unusable = stub_device_unusable; - - usbip_start_eh(&sdev->ud); - - udbg("register new interface\n"); - return sdev; -} - -static int stub_device_free(struct stub_device *sdev) -{ - if (!sdev) - return -EINVAL; - - kfree(sdev); - udbg("kfree udev ok\n"); - - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* - * If a usb device has multiple active interfaces, this driver is bound to all - * the active interfaces. However, usbip exports *a* usb device (i.e. not *an* - * active interface). Currently, a userland program must ensure that it - * looks at the usbip's sysfs entries of only the first active interface. - */ -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct stub_device *sdev = NULL; - char *udev_busid = interface->dev.parent->bus_id; - - udbg("Enter\n"); - - /* check we should claim or not by busid_table */ - if (match_busid(udev_busid)) { - uinfo("this device %s is not in match_busid table. skip!\n", udev_busid); - - /* - * Return value should be ENODEV or ENOXIO to continue trying - * other matched drivers by the driver core. - * See driver_probe_device() in driver/base/dd.c - */ - return -ENODEV; - } - - if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { - udbg("this device %s is a usb hub device. skip!\n", udev_busid); - return -ENODEV; - } - - if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { - udbg("this device %s is attached on vhci_hcd. skip!\n", udev_busid); - return -ENODEV; - } - - /* ok. this is my device. */ - - if ((sdev = stub_device_alloc(interface))) { - struct usb_device *udev = interface_to_usbdev(interface); - - uinfo("USB/IP Stub: register a new interface (bus %u dev %u ifn %u)\n", - udev->bus->busnum, udev->devnum, - interface->cur_altsetting->desc.bInterfaceNumber); - } else - return -ENOMEM; - - /* set private data to usb_interface */ - usb_set_intfdata(interface, sdev); - - stub_add_files(&interface->dev); - - return 0; -} - - -/* - * called in usb_disconnect() or usb_deregister() - * but only if actconfig(active configuration) exists - */ -static void stub_disconnect(struct usb_interface *interface) -{ - struct stub_device *sdev = usb_get_intfdata(interface); - - udbg("Enter\n"); - - /* get stub_device */ - if (!sdev) - BUG(); - - usb_set_intfdata(interface, NULL); - - - /* - * NOTE: - * rx/tx threads are invoked for each usb_device. - */ - stub_remove_files(&interface->dev); - - /* 1. shutdown the current connection */ - usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED); - - /* 2. wait for the stop of the event handler */ - usbip_stop_eh(&sdev->ud); - - /* 3. free sdev */ - stub_device_free(sdev); - - - udbg("bye\n"); -} diff -Naur usbip-0.1.4/drivers/2.6.16/stub.h trunk/drivers/2.6.16/stub.h --- usbip-0.1.4/drivers/2.6.16/stub.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/stub.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,96 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include -#include - -struct stub_device { - struct usb_interface *interface; - struct list_head list; - - struct usbip_device ud; - - /* - * stub_priv preserves private data of each urb. - * It is allocated as stub_priv_cache and assigned to urb->context. - * - * stub_priv is always linked to any one of 3 lists; - * priv_init: linked to this until the comletion of a urb. - * priv_tx : linked to this after the completion of a urb. - * priv_free: linked to this after the sending of the result. - * - * Any of these list operations should be locked by priv_lock. - */ - spinlock_t priv_lock; - struct list_head priv_init; - struct list_head priv_tx; - struct list_head priv_free; - - /* see comments for unlinking in stub_rx.c */ - struct list_head unlink_tx; - struct list_head unlink_free; - - - wait_queue_head_t tx_waitq; -}; - -/* private data into urb->priv */ -struct stub_priv { - unsigned long seqnum; - struct list_head list; - struct stub_device *sdev; - struct urb *urb; - - int unlinking; -}; - -struct stub_unlink { - unsigned long seqnum; - struct list_head list; - __u32 status; -}; - - -extern kmem_cache_t *stub_priv_cache; - - -/*-------------------------------------------------------------------------*/ -/* prototype declarations */ - -/* stub_tx.c */ -void stub_complete(struct urb*, struct pt_regs *); -void stub_tx_loop(struct usbip_task *); - -/* stub_dev.c */ -extern struct usb_driver stub_driver; - -/* stub_rx.c */ -void stub_rx_loop(struct usbip_task *); -void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32); - -/* stub_main.c */ -int match_busid(char *busid); -void stub_device_cleanup_urbs(struct stub_device *sdev); diff -Naur usbip-0.1.4/drivers/2.6.16/stub_main.c trunk/drivers/2.6.16/stub_main.c --- usbip-0.1.4/drivers/2.6.16/stub_main.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/stub_main.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,300 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "stub.h" - -/* Version Information */ -#define DRIVER_VERSION "$Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $" -#define DRIVER_AUTHOR "Takahiro Hirofuchi " -#define DRIVER_DESC "Stub Driver for USB/IP" - - - -/* stub_priv is allocated from stub_priv_cache */ -kmem_cache_t *stub_priv_cache = NULL; - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for the usbip driver */ - - -/* - * busid_tables defines matching busids that usbip can grab. A user can change - * dynamically what device is locally used and what device is exported to a - * remote host. - */ -#define MAX_BUSID 16 -static char busid_table[MAX_BUSID][BUS_ID_SIZE]; -spinlock_t busid_table_lock = SPIN_LOCK_UNLOCKED; - - -int match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* already registerd */ - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return 1; -} - -static ssize_t show_match_busid(struct device_driver *drv, char *buf) -{ - int i; - char *out = buf; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - out += sprintf(out, "%s ", busid_table[i]); - - spin_unlock(&busid_table_lock); - - out += sprintf(out, "\n"); - - return out - buf; -} - -static int add_match_busid(char *busid) -{ - int i; - - if (!match_busid(busid)) - return 0; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!busid_table[i][0]) { - strncpy(busid_table[i], busid, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static int del_match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* found */ - memset(busid_table[i], 0, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static ssize_t store_match_busid(struct device_driver *dev, const char *buf, - size_t count) -{ - int len; - char busid[BUS_ID_SIZE]; - - if (count < 5) - return -EINVAL; - - /* strnlen() does not include \0 */ - len = strnlen(buf + 4, BUS_ID_SIZE); - - /* busid needs to include \0 termination */ - if (!(len < BUS_ID_SIZE)) - return -EINVAL; - - strncpy(busid, buf + 4, BUS_ID_SIZE); - - - if (!strncmp(buf, "add ", 4)) { - if (add_match_busid(busid) < 0) - return -ENOMEM; - else { - udbg("add busid %s\n", busid); - return count; - } - } else if (!strncmp(buf, "del ", 4)) { - if (del_match_busid(busid) < 0) - return -ENODEV; - else { - udbg("del busid %s\n", busid); - return count; - } - } else - return -EINVAL; -} - -static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid, store_match_busid); - - - -/*-------------------------------------------------------------------------*/ - -/* Cleanup functions used to free private data */ - -static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) -{ - struct stub_priv *priv, *tmp; - - list_for_each_entry_safe(priv, tmp, listhead, list) { - list_del(&priv->list); - return priv; - } - - return NULL; -} - -static struct stub_priv *stub_priv_pop(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = stub_priv_pop_from_listhead(&sdev->priv_init); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_tx); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_free); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return NULL; -} - -void stub_device_cleanup_urbs(struct stub_device *sdev) -{ - struct stub_priv *priv; - - udbg("free sdev %p\n", sdev); - - while ((priv = stub_priv_pop(sdev))) { - struct urb *urb = priv->urb; - - udbg(" free urb %p\n", urb); - usb_kill_urb(urb); - - kmem_cache_free(stub_priv_cache, priv); - - if (urb->transfer_buffer != NULL) - kfree(urb->transfer_buffer); - - if (urb->setup_packet != NULL) - kfree(urb->setup_packet); - - usb_free_urb(urb); - } -} - - -/*-------------------------------------------------------------------------*/ - -static int __init usb_stub_init(void) -{ - int ret; - - stub_priv_cache = kmem_cache_create("stub_priv", sizeof(struct stub_priv), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!stub_priv_cache) { - uerr("create stub_priv_cache\n"); - return -ENOMEM; - } - - ret = usb_register(&stub_driver); - if (ret) { - uerr("usb_register failed %d\n", ret); - return ret; - } - - - info(DRIVER_DESC "" DRIVER_VERSION); - - memset(busid_table, 0, sizeof(busid_table)); - - driver_create_file(&stub_driver.driver, &driver_attr_match_busid); - - return ret; -} - -static void __exit usb_stub_exit(void) -{ - int ret; - - udbg("enter\n"); - - driver_remove_file(&stub_driver.driver, &driver_attr_match_busid); - - /* - * deregister() calls stub_disconnect() for all devices. Device - * specific data is cleared in stub_disconnect(). - */ - usb_deregister(&stub_driver); - - ret = kmem_cache_destroy(stub_priv_cache); - if (ret != 0) { - uerr("memory leak of stub_priv, %d\n", ret); - } - - udbg("bye\n"); -} - - - - -module_init (usb_stub_init); -module_exit (usb_stub_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff -Naur usbip-0.1.4/drivers/2.6.16/stub_rx.c trunk/drivers/2.6.16/stub_rx.c --- usbip-0.1.4/drivers/2.6.16/stub_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/stub_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,442 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static int is_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_CLEAR_FEATURE) && - (req->bRequestType == USB_RECIP_ENDPOINT) && - (req->wValue == USB_ENDPOINT_HALT); -} - -static int is_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_INTERFACE) && - (req->bRequestType == USB_RECIP_INTERFACE); -} - -static int is_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_CONFIGURATION) && - (req->bRequestType == USB_RECIP_DEVICE); -} - -static int tweak_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - int target_endp; - int target_dir; - int target_pipe; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - /* - * The stalled endpoint is specified in the wIndex value. The endpoint - * of the urb is the target of this clear_halt request (i.e. control - * endpoint). - */ - target_endp = le16_to_cpu(req->wIndex) & 0x000f; - - /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80. */ - target_dir = le16_to_cpu(req->wIndex) & 0x0080; - - if (target_dir) - target_pipe = usb_rcvctrlpipe(urb->dev, target_endp); - else - target_pipe = usb_sndctrlpipe(urb->dev, target_endp); - - ret = usb_clear_halt(urb->dev, target_pipe); - if (ret < 0) - uinfo("clear_halt error: devnum %d endp %d, %d\n", - urb->dev->devnum, target_endp, ret); - else - uinfo("clear_halt done: devnum %d endp %d\n", - urb->dev->devnum, target_endp); - - return ret; -} - -static int tweak_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 alternate; - __u16 interface; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - alternate = le16_to_cpu(req->wValue); - interface = le16_to_cpu(req->wIndex); - - dbg_stub_rx("set_interface: inf %u alt %u\n", interface, alternate); - - ret = usb_set_interface(urb->dev, interface, alternate); - if (ret < 0) - uinfo("set_interface error: inf %u alt %u, %d\n", - interface, alternate, ret); - else - uinfo("set_interface done: inf %u alt %u\n", interface, alternate); - - return ret; -} - -static int tweak_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 config; - - info("set_configuration is not fully supported yet\n"); - - req = (struct usb_ctrlrequest *) urb->setup_packet; - config = le16_to_cpu(req->wValue); - - uinfo("set_configuration: devnum %d %d\n", urb->dev->devnum, config); - -#if 0 - return usb_set_configuration(urb->dev, config); -#endif - return 0; -} - -/* - * clear_halt, set_interface, and set_configuration require special tricks. - * TODO: set_configuration. but I have never seen a multi-config device. - */ -static void tweak_special_requests(struct urb *urb) -{ - if (!urb || !urb->setup_packet) - return; - - if (usb_pipetype(urb->pipe) != PIPE_CONTROL) - return; - - if (is_clear_halt_cmd(urb)) - /* treak clear_halt */ - tweak_clear_halt_cmd(urb); - - else if (is_set_interface_cmd(urb)) - /* tweak set_interface */ - tweak_set_interface_cmd(urb); - - else if (is_set_configuration_cmd(urb)) - /* tweak set_configuration */ - tweak_set_configuration_cmd(urb); - - else - dbg_stub_rx("no need to tweak\n"); -} - -/* - * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb(). - * By unlinking the urb asynchronously, stub_rx can continuously - * process coming urbs. Even if the urb is unlinked, its completion - * handler will be called and stub_tx will send a return pdu. - * - * See also comments about unlinking strategy in vhci_hcd.c. - */ -static int stub_recv_cmd_unlink(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct list_head *listhead = &sdev->priv_init; - struct list_head *ptr; - unsigned long flags; - - struct stub_priv *priv; - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - for (ptr = listhead->next; ptr != listhead; ptr = ptr->next) { - priv = list_entry(ptr, struct stub_priv, list); - if (priv->seqnum == pdu->u.cmd_unlink.seqnum) { - int ret; - - uinfo("unlink urb %p\n", priv->urb); - - /* - * This matched urb is not completed yet (i.e. be in - * flight in usb hcd hardware/driver). Now we are - * cancelling it. The unlinking flag means that we are - * now not going to return the normal result pdu of a - * submittion request, but going to return a result pdu - * of the unlink request. - */ - priv->unlinking = 1; - - /* - * In the case that unlinking flag is on, prev->seqnum - * is changed from the seqnum of the cancelling urb to - * the seqnum of the unlink request. This will be used - * to make the result pdu of the unlink request. - */ - priv->seqnum = pdu->base.seqnum; - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* - * usb_unlink_urb() is now out of spinlocking to avoid - * spinlock recursion since stub_complete() is - * sometimes called in this context but not in the - * interrupt context. If stub_complete() is executed - * before we call usb_unlink_urb(), usb_unlink_urb() - * will return an error value. In this case, stub_tx - * will return the result pdu of this unlink request - * though submission is completed and actual unlinking - * is not executed. OK? - */ - ret = usb_unlink_urb(priv->urb); - if (ret != -EINPROGRESS) - uerr("faild to unlink a urb %p, ret %d\n", priv->urb, ret); - - return 0; - } - } - - dbg_stub_rx("seqnum %d is not pending\n", pdu->u.cmd_unlink.seqnum); - - /* - * The urb of the unlink target is not found in priv_init queue. It was - * already completed and its results is/was going to be sent by a - * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only - * return the completeness of this unlink request to vhci_hcd. - */ - stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - - return 0; -} - -static int valid_request(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &sdev->ud; - - int bus = interface_to_busnum(sdev->interface); - int dev = interface_to_devnum(sdev->interface); - - if (pdu->base.busnum == bus && pdu->base.devnum == dev) { - spin_lock(&ud->lock); - if (ud->status == SDEV_ST_USED) { - /* A request is valid. */ - spin_unlock(&ud->lock); - return 1; - } - spin_unlock(&ud->lock); - } - - return 0; -} - -static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, - struct usbip_header *pdu) -{ - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - unsigned long flags; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC); - if (!priv) { - uerr("alloc stub_priv\n"); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return NULL; - } - - memset(priv, 0, sizeof(struct stub_priv)); - - priv->seqnum = pdu->base.seqnum; - priv->sdev = sdev; - - /* - * After a stub_priv is linked to a list_head, - * our error handler can free allocated data. - */ - list_add_tail(&priv->list, &sdev->priv_init); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return priv; -} - -static void stub_recv_cmd_submit(struct stub_device *sdev, struct usbip_header *pdu) -{ - int ret; - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - - - priv = stub_priv_alloc(sdev, pdu); - if (!priv) - return; - - /* setup a urb */ - if (usb_pipeisoc(pdu->base.pipe)) - priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, GFP_KERNEL); - else - priv->urb = usb_alloc_urb(0, GFP_KERNEL); - - if (!priv->urb) { - uerr("malloc urb\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - - /* set priv->urb->transfer_buffer */ - if (pdu->u.cmd_submit.transfer_buffer_length > 0) { - priv->urb->transfer_buffer = - kzalloc(pdu->u.cmd_submit.transfer_buffer_length, GFP_KERNEL); - if (!priv->urb->transfer_buffer) { - uerr("malloc x_buff\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - } - - /* set priv->urb->setup_packet */ - priv->urb->setup_packet = kzalloc(8, GFP_KERNEL); - if (!priv->urb->setup_packet) { - uerr("allocate setup_packet\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - memcpy(priv->urb->setup_packet, &pdu->u.cmd_submit.setup, 8); - - /* set other members from the base header of pdu */ - priv->urb->context = (void *) priv; - priv->urb->dev = interface_to_usbdev(sdev->interface); - priv->urb->pipe = pdu->base.pipe; - priv->urb->complete = stub_complete; - - usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); - - - if (usbip_recv_xbuff(ud, priv->urb) < 0) - return; - - if (usbip_recv_iso(ud, priv->urb) < 0) - return; - - tweak_special_requests(priv->urb); - - /* urb is now ready to submit */ - ret = usb_submit_urb(priv->urb, GFP_KERNEL); - - if (ret == 0) - dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum); - else { - uerr("submit_urb error, %d\n", ret); - - /* - * Pessimistic. - * This connection will be discared. - */ - usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); - } - - dbg_stub_rx("Leave\n"); - return; -} - -/* recv a pdu */ -static void stub_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - - dbg_stub_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_stub_rx) - usbip_dump_header(&pdu); - - if (!valid_request(sdev, &pdu)) { - uerr("recv invalid request\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - switch (pdu.base.command) { - case USBIP_CMD_UNLINK: - stub_recv_cmd_unlink(sdev, &pdu); - break; - - case USBIP_CMD_SUBMIT: - stub_recv_cmd_submit(sdev, &pdu); - break; - - default: - /* NOTREACHED */ - uerr("unknown pdu\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - -} - -void stub_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - while (1) { - if (signal_pending(current)) { - dbg_stub_rx("signal catched!\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - stub_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.16/stub_tx.c trunk/drivers/2.6.16/stub_tx.c --- usbip-0.1.4/drivers/2.6.16/stub_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/stub_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,374 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static void stub_free_priv_and_urb(struct stub_priv *priv) -{ - struct urb *urb = priv->urb; - - if (urb->setup_packet) - kfree(urb->setup_packet); - - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); - - list_del(&priv->list); - kmem_cache_free(stub_priv_cache, priv); - - usb_free_urb(urb); -} - -/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ -void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, __u32 status) -{ - struct stub_unlink *unlink; - - unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("alloc stub_unlink\n"); - usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - unlink->seqnum = seqnum; - unlink->status = status; - - list_add_tail(&unlink->list, &sdev->unlink_tx); -} - -/** - * stub_complete - completion handler of a usbip urb - * @urb: pointer to the urb completed - * @regs: - * - * When a urb has completed, the USB core driver calls this function mostly in - * the interrupt context. To return the result of a urb, the completed urb is - * linked to the pending list of returning. - * - */ -void stub_complete(struct urb *urb, struct pt_regs *regs) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - struct stub_device *sdev = priv->sdev; - unsigned long flags; - - dbg_stub_tx("complete! status %d\n", urb->status); - - - switch (urb->status) { - case 0: - /* OK */ - break; - case -ENOENT: - uinfo("stopped by a call of usb_kill_urb()" - "because of cleaning up a virtual connection\n"); - return; - case -ECONNRESET: - uinfo("unlinked by a call of usb_unlink_urb()\n"); - break; - case -EPIPE: - uinfo("endpoint %d is stalled\n", usb_pipeendpoint(urb->pipe)); - break; - case -ESHUTDOWN: - uinfo("device removed?\n"); - break; - default: - uinfo("urb completion with non-zero status %d\n", urb->status); - } - - /* link a urb to the queue of tx. */ - spin_lock_irqsave(&sdev->priv_lock, flags); - - if (priv->unlinking) { - stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status); - stub_free_priv_and_urb(priv); - } else - list_move_tail(&priv->list, &sdev->priv_tx); - - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* wake up tx_thread */ - wake_up(&sdev->tx_waitq); -} - - -/*-------------------------------------------------------------------------*/ -/* fill PDU */ - -static inline void setup_base_pdu(struct usbip_header_basic *base, - __u32 command, __u32 seqnum) -{ - base->command = command; - base->busnum = 0; - base->devnum = 0; - base->seqnum = seqnum; - base->pipe = 0; -} - -static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - - setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum); - - usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1); -} - -static void setup_ret_unlink_pdu(struct usbip_header *rpdu, - struct stub_unlink *unlink) -{ - setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum); - - rpdu->u.ret_unlink.status = unlink->status; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_SUBMIT */ - -static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) { - list_move_tail(&priv->list, &sdev->priv_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - -static int stub_send_ret_submit(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_ret_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (usb_pipein(urb->pipe) && urb->actual_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->actual_length; - txsize += urb->actual_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - if (iso_buffer) - kfree(iso_buffer); - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { - stub_free_priv_and_urb(priv); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_UNLINK */ - -static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_move_tail(&unlink->list, &sdev->unlink_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - - -static int stub_send_ret_unlink(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - struct msghdr msg; - struct kvec iov[1]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum); - - /* 1. setup usbip_header */ - setup_ret_unlink_pdu(&pdu_header, unlink); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void stub_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - while (1) { - if (signal_pending(current)) { - dbg_stub_tx("signal catched\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - /* - * send_ret_submit comes earlier than send_ret_unlink. stub_rx - * looks at only priv_init queue. If the completion of a URB is - * earlier than the recieve of CMD_UNLINK, priv is moved to - * priv_tx queue and stub_rx does not find the target priv. In - * this case, vhci_rx recieves the result of the submit request - * and then recieves the result of the unlink request. The - * result of the submit is given back to the usbcore as the - * completion of the unlink request. The request of the - * unlink is ignored. This is ok because a driver who calls - * usb_unlink_urb() understands the unlink was too late by - * getting the status of the given-backed URB which has the - * status of usb_submit_urb(). - */ - if (stub_send_ret_submit(sdev) < 0) - break; - - if (stub_send_ret_unlink(sdev) < 0) - break; - - wait_event_interruptible(sdev->tx_waitq, - (!list_empty(&sdev->priv_tx) || - !list_empty(&sdev->unlink_tx))); - } -} diff -Naur usbip-0.1.4/drivers/2.6.16/usbip_common.c trunk/drivers/2.6.16/usbip_common.c --- usbip-0.1.4/drivers/2.6.16/usbip_common.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/usbip_common.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,935 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include "usbip_common.h" - - -/*-------------------------------------------------------------------------*/ -/* debug routines */ - -#ifdef CONFIG_USB_DEBUG -unsigned long usbip_debug_flag = 0xffffffff; -#else -unsigned long usbip_debug_flag = 0; -#endif - -static ssize_t show_flag(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lx\n", usbip_debug_flag); -} - -static ssize_t store_flag(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long flag; - - sscanf(buf, "%lx", &flag); - usbip_debug_flag = flag; - - return count; -} -DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag); - -static void usbip_dump_buffer(char *buff, int bufflen) -{ - int i; - - if (bufflen > 128) { - for (i = 0; i< 128; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) printk("| "); - if (i%24 == 23) printk("\n"); - } - printk("... (%d byte)\n", bufflen); - return; - } - - for (i = 0; i< bufflen; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) - printk("| "); - if (i%24 == 23) - printk("\n"); - } - printk("\n"); - -} - -static void usbip_dump_pipe(unsigned int p) -{ - unsigned char type = usb_pipetype(p); - unsigned char ep = usb_pipeendpoint(p); - unsigned char dev = usb_pipedevice(p); - unsigned char dir = usb_pipein(p); - - printk("dev(%d) ", dev); - printk("ep(%d) ", ep); - printk("%s ", dir ? "IN" : "OUT"); - - switch(type) { - case PIPE_ISOCHRONOUS : - printk("%s ", "ISO"); - break; - case PIPE_INTERRUPT : - printk("%s ", "INT"); - break; - case PIPE_CONTROL : - printk("%s ", "CTL"); - break; - case PIPE_BULK : - printk("%s ", "BLK"); - break; - default : - printk("ERR"); - } - - printk("\n"); - -} - -static void usbip_dump_usb_device(struct usb_device *dev) -{ - int i; - - if (!dev) { - printk(" dump usb dev: null pointer!!\n"); - return; - } - - printk(" devnum(%d) devpath(%s)", dev->devnum, dev->devpath); - - switch(dev->speed) { - case USB_SPEED_HIGH : - printk(" SPD_HIGH"); - break; - case USB_SPEED_FULL : - printk(" SPD_FULL"); - break; - case USB_SPEED_LOW : - printk(" SPD_LOW"); - break; - case USB_SPEED_UNKNOWN : - printk(" SPD_UNKNOWN"); - break; - default : - printk(" SPD_ERROR"); - } - - printk(" tt %p, ttport %d", dev->tt, dev->ttport); - printk("\n"); - - printk(" "); - for (i = 0; i < 16; i++) { - printk(" %2u", i); - } - - printk("\n"); - - printk(" toggle0(IN) :"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[0] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - printk(" toggle1(OUT):"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[1] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - - printk(" epmaxp_in :"); - for (i = 0; i < 16; i++) { - if (dev->ep_in[i]) - printk(" %2u", dev->ep_in[i]->desc.wMaxPacketSize); - } - - printk("\n"); - - printk(" epmaxp_out :"); - for (i = 0; i < 16; i++) { - if (dev->ep_out[i]) - printk(" %2u", dev->ep_out[i]->desc.wMaxPacketSize); - } - - printk("\n "); - - printk("parent %p, bus %p", dev->parent, dev->bus); - printk("\n "); - - printk("descriptor %p, config %p, actconfig %p, rawdescriptors %p", - &dev->descriptor, dev->config, dev->actconfig, dev->rawdescriptors); - printk("\n "); - - printk("have_langid %d, string_langid %d", dev->have_langid, dev->string_langid); - printk("\n "); - - printk("maxchild %d, children %p", dev->maxchild, dev->children); - - printk("\n"); -} - -static void usbip_dump_request_type(__u8 rt) -{ - switch(rt & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: - printk("DEVICE"); - break; - case USB_RECIP_INTERFACE: - printk("INTERF"); - break; - case USB_RECIP_ENDPOINT: - printk("ENDPOI"); - break; - case USB_RECIP_OTHER: - printk("OTHER "); - break; - default: - printk("------"); - } -} - -static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd) -{ - if (!cmd) { - printk(" %s : null pointer\n", __FUNCTION__); - return; - } - - printk(" "); - printk("bRequestType(%02X) ", cmd->bRequestType); - printk("bRequest(%02X) " , cmd->bRequest); - printk("wValue(%04X) ", cmd->wValue); - printk("wIndex(%04X) ", cmd->wIndex); - printk("wLength(%04X) ", cmd->wLength); - - printk("\n "); - - if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - printk("STANDARD "); - switch(cmd->bRequest) { - case USB_REQ_GET_STATUS: - printk("GET_STATUS"); - break; - case USB_REQ_CLEAR_FEATURE: - printk("CLEAR_FEAT"); - break; - case USB_REQ_SET_FEATURE: - printk("SET_FEAT "); - break; - case USB_REQ_SET_ADDRESS: - printk("SET_ADDRRS"); - break; - case USB_REQ_GET_DESCRIPTOR: - printk("GET_DESCRI"); - break; - case USB_REQ_SET_DESCRIPTOR: - printk("SET_DESCRI"); - break; - case USB_REQ_GET_CONFIGURATION: - printk("GET_CONFIG"); - break; - case USB_REQ_SET_CONFIGURATION: - printk("SET_CONFIG"); - break; - case USB_REQ_GET_INTERFACE: - printk("GET_INTERF"); - break; - case USB_REQ_SET_INTERFACE: - printk("SET_INTERF"); - break; - case USB_REQ_SYNCH_FRAME: - printk("SYNC_FRAME"); - break; - default: - printk("REQ(%02X) ", cmd->bRequest); - } - - printk(" "); - usbip_dump_request_type(cmd->bRequestType); - - } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) - printk("CLASS "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) - printk("VENDOR "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) - printk("RESERVED"); - - printk("\n"); -} - -void usbip_dump_urb (struct urb *purb) -{ - if (!purb) { - printk(" dump urb: null pointer!!\n"); - return; - } - - printk(" urb :%p\n", purb); - printk(" dev :%p\n", purb->dev); - - usbip_dump_usb_device(purb->dev); - - printk(" pipe :%08x ", purb->pipe); - - usbip_dump_pipe(purb->pipe); - - printk(" status :%d\n", purb->status); - printk(" transfer_flags :%08X\n", purb->transfer_flags); - printk(" transfer_buffer :%p\n", purb->transfer_buffer); - printk(" transfer_buffer_length:%d\n", purb->transfer_buffer_length); - printk(" actual_length :%d\n", purb->actual_length); - printk(" bandwidth :%d\n", purb->actual_length); - printk(" setup_packet :%p\n", purb->setup_packet); - - if (purb->setup_packet && usb_pipetype(purb->pipe) == PIPE_CONTROL) - usbip_dump_usb_ctrlrequest((struct usb_ctrlrequest *) purb->setup_packet); - - printk(" start_frame :%d\n", purb->start_frame); - printk(" number_of_packets :%d\n", purb->number_of_packets); - printk(" interval :%d\n", purb->interval); - printk(" error_count :%d\n", purb->error_count); - printk(" context :%p\n", purb->context); - printk(" complete :%p\n", purb->complete); -} - -void usbip_dump_header(struct usbip_header *pdu) -{ - udbg("BASE: cmd %u bus %u dev %u seq %u pipe %04x\n", - pdu->base.command, - pdu->base.busnum, - pdu->base.devnum, - pdu->base.seqnum, - pdu->base.pipe); - - usbip_dump_pipe(pdu->base.pipe); - - switch(pdu->base.command) { - case USBIP_CMD_SUBMIT: - udbg("CMD_SUBMIT: x_flags %u x_len %u bw %u sf %u #p %u iv %u\n", - pdu->u.cmd_submit.transfer_flags, - pdu->u.cmd_submit.transfer_buffer_length, - pdu->u.cmd_submit.bandwidth, - pdu->u.cmd_submit.start_frame, - pdu->u.cmd_submit.number_of_packets, - pdu->u.cmd_submit.interval); - break; - case USBIP_CMD_UNLINK: - udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum); - break; - case USBIP_RET_SUBMIT: - udbg("RET_SUBMIT: st %d al %u bw %u sf %d ec %d\n", - pdu->u.ret_submit.status, - pdu->u.ret_submit.actual_length, - pdu->u.ret_submit.bandwidth, - pdu->u.ret_submit.start_frame, - pdu->u.ret_submit.error_count); - case USBIP_RET_UNLINK: - udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status); - break; - default: - /* NOT REACHED */ - udbg("UNKNOWN\n"); - } -} - - -/*-------------------------------------------------------------------------*/ -/* thread routines */ - -int usbip_thread(void *param) -{ - struct usbip_task *ut = (struct usbip_task *) param; - - if (!ut) - return -EINVAL; - - lock_kernel(); - daemonize(ut->name); - allow_signal(SIGKILL); - ut->thread = current; - unlock_kernel(); - - /* srv.rb must wait for rx_thread starting */ - complete(&ut->thread_done); - - /* start of while loop */ - ut->loop_ops(ut); - - /* end of loop */ - ut->thread = NULL; - - complete_and_exit(&ut->thread_done, 0); -} - -void usbip_start_threads(struct usbip_device *ud) -{ - /* - * threads are invoked per one device (per one connection). - */ - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_rx, 0); - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_tx, 0); - - /* confirm threads are starting */ - wait_for_completion(&ud->tcp_rx.thread_done); - wait_for_completion(&ud->tcp_tx.thread_done); -} - -void usbip_stop_threads(struct usbip_device *ud) -{ - /* kill threads related to this sdev, if v.c. exists */ - if (ud->tcp_rx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_rx.thread, 1); - wait_for_completion(&ud->tcp_rx.thread_done); - udbg("rx_thread for ud %p has finished\n", ud); - } - - if (ud->tcp_tx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_tx.thread, 1); - wait_for_completion(&ud->tcp_tx.thread_done); - udbg("tx_thread for ud %p has finished\n", ud); - } -} - -void usbip_task_init(struct usbip_task *ut, char *name, - void (*loop_ops)(struct usbip_task *)) -{ - ut->thread = NULL; - init_completion(&ut->thread_done); - ut->name = name; - ut->loop_ops = loop_ops; -} - - -/*-------------------------------------------------------------------------*/ -/* socket routines */ - - /* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */ -int usbip_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags) -{ - int result; - struct msghdr msg; - struct kvec iov; - int total = 0; - - /* for blocks of if (dbg_flag_xmit) */ - char *bp = buf; - int osize= size; - - dbg_xmit("enter\n"); - - if (!sock || !buf || !size) { - uerr("usbip_xmit: invalid arg, sock %p buff %p size %d\n", - sock, buf, size); - return -EINVAL; - } - - - if (dbg_flag_xmit) { - if (send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: sending... , sock %p, buf %p, size %d, msg_flags %d\n", - sock, buf, size, msg_flags); - usbip_dump_buffer(buf, size); - } - } - - - do { - sock->sk->sk_allocation = GFP_NOIO; - iov.iov_base = buf; - iov.iov_len = size; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_namelen = 0; - msg.msg_flags = msg_flags | MSG_NOSIGNAL; - - if (send) - result = kernel_sendmsg(sock, &msg, &iov, 1, size); - else - result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); - - if (result <= 0) { - udbg("usbip_xmit: %s sock %p buf %p size %u ret %d total %d\n", - send ? "send" : "receive", sock, buf, size, result, total); - goto err; - } - - size -= result; - buf += result; - total += result; - - } while (size > 0); - - - if (dbg_flag_xmit) { - if (!send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: receiving....\n"); - usbip_dump_buffer(bp, osize); - printk("usbip_xmit: received, osize %d ret %d size %d total %d\n", - osize, result, size, total); - } - - if (send) { - printk("usbip_xmit: send, total %d\n", total); - } - } - - return total; - -err: - return result; -} - -int setquickack(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setnodelay(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setkeepalive(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -void setreuse(struct socket *socket) -{ - socket->sk->sk_reuse = 1; -} - -struct socket *sockfd_to_socket(unsigned int sockfd) -{ - struct socket *socket; - struct file *file; - struct inode *inode; - - file = fget(sockfd); - if (!file) { - uerr("invalid sockfd\n"); - return NULL; - } - - inode = file->f_dentry->d_inode; - - if (!inode || !S_ISSOCK(inode->i_mode)) - return NULL; - - socket = SOCKET_I(inode); - - return socket; -} - - - -/*-------------------------------------------------------------------------*/ -/* pdu routines */ - -/* there may be more cases to tweak the flags. */ -static unsigned int tweak_transfer_flags(unsigned int flags) -{ - - if (flags & URB_NO_TRANSFER_DMA_MAP) - /* - * vhci_hcd does not provide DMA-mapped I/O. The upper - * driver does not need to set this flag. The remote - * usbip.ko does not still perform DMA-mapped I/O for - * DMA-caplable host controllers. So, clear this flag. - */ - flags &= ~URB_NO_TRANSFER_DMA_MAP; - - if (flags & URB_NO_SETUP_DMA_MAP) - flags &= ~URB_NO_SETUP_DMA_MAP; - - return flags; -} - -static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit; - - /* - * Some members are not still implemented in usbip. I hope this issue - * will be discussed when usbip is ported to other operating systems. - */ - if (pack) { - /* vhci_tx.c */ - spdu->transfer_flags = tweak_transfer_flags(urb->transfer_flags); - - spdu->transfer_buffer_length = urb->transfer_buffer_length; - spdu->bandwidth = urb->bandwidth; - spdu->start_frame = urb->start_frame; - spdu->number_of_packets = urb->number_of_packets; - spdu->interval = urb->interval; - } else { - /* stub_rx.c */ - urb->transfer_flags = spdu->transfer_flags; - - urb->transfer_buffer_length = spdu->transfer_buffer_length; - urb->bandwidth = spdu->bandwidth; - urb->start_frame = spdu->start_frame; - urb->number_of_packets = spdu->number_of_packets; - urb->interval = spdu->interval; - } -} - -static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit; - - if (pack) { - /* stub_tx.c */ - - rpdu->status = urb->status; - rpdu->actual_length = urb->actual_length; - rpdu->bandwidth = urb->bandwidth; - rpdu->start_frame = urb->start_frame; - rpdu->error_count = urb->error_count; - } else { - /* vhci_rx.c */ - - urb->status = rpdu->status; - urb->actual_length = rpdu->actual_length; - urb->bandwidth = rpdu->bandwidth; - urb->start_frame = rpdu->start_frame; - urb->error_count = rpdu->error_count; - } -} - - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack) -{ - switch(cmd) { - case USBIP_CMD_SUBMIT: - usbip_pack_cmd_submit(pdu, urb, pack); - break; - case USBIP_RET_SUBMIT: - usbip_pack_ret_submit(pdu, urb, pack); - break; - default: - /* NOTREACHED */ - BUG(); - } -} - - -static void correct_endian_basic(struct usbip_header_basic *base, int send) -{ - if (send) { - base->command = cpu_to_be32(base->command); - base->busnum = cpu_to_be32(base->busnum); - base->devnum = cpu_to_be32(base->devnum); - base->seqnum = cpu_to_be32(base->seqnum); - base->pipe = cpu_to_be32(base->pipe); - } else { - base->command = be32_to_cpu(base->command); - base->busnum = be32_to_cpu(base->busnum); - base->devnum = be32_to_cpu(base->devnum); - base->seqnum = be32_to_cpu(base->seqnum); - base->pipe = be32_to_cpu(base->pipe); - } -} - -static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu, int send) -{ - if (send) { - pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags); - - cpu_to_be32s(&pdu->transfer_buffer_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->number_of_packets); - cpu_to_be32s(&pdu->interval); - } else { - pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags); - - be32_to_cpus(&pdu->transfer_buffer_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->number_of_packets); - be32_to_cpus(&pdu->interval); - } -} - -static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, int send) -{ - if (send) { - cpu_to_be32s(&pdu->status); - cpu_to_be32s(&pdu->actual_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->error_count); - } else { - be32_to_cpus(&pdu->status); - be32_to_cpus(&pdu->actual_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->error_count); - } -} - -static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu, int send) -{ - if (send) - pdu->seqnum = cpu_to_be32(pdu->seqnum); - else - pdu->seqnum = be32_to_cpu(pdu->seqnum); -} - -static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu, int send) -{ - if (send) - cpu_to_be32s(&pdu->status); - else - be32_to_cpus(&pdu->status); -} - -void usbip_header_correct_endian(struct usbip_header *pdu, int send) -{ - __u32 cmd = 0; - - if (send) - cmd = pdu->base.command; - - correct_endian_basic(&pdu->base, send); - - if (!send) - cmd = pdu->base.command; - - switch (cmd) { - case USBIP_CMD_SUBMIT: - correct_endian_cmd_submit(&pdu->u.cmd_submit, send); - break; - case USBIP_RET_SUBMIT: - correct_endian_ret_submit(&pdu->u.ret_submit, send); - break; - - case USBIP_CMD_UNLINK: - correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send); - break; - case USBIP_RET_UNLINK: - correct_endian_ret_unlink(&pdu->u.ret_unlink, send); - break; - - default: - /* NOTREACHED */ - BUG(); - } -} - -static void usbip_iso_pakcet_correct_endian(struct usbip_iso_packet_descriptor *iso, int send) -{ - /* does not need all members. but copy all simply. */ - if (send) { - iso->offset = cpu_to_be32(iso->offset); - iso->length = cpu_to_be32(iso->length); - iso->status = cpu_to_be32(iso->status); - iso->actual_length = cpu_to_be32(iso->actual_length); - } else { - iso->offset = be32_to_cpu(iso->offset); - iso->length = be32_to_cpu(iso->length); - iso->status = be32_to_cpu(iso->status); - iso->actual_length = be32_to_cpu(iso->actual_length); - } -} - -static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso, - struct usb_iso_packet_descriptor *uiso, int pack) -{ - if (pack) { - iso->offset = uiso->offset; - iso->length = uiso->length; - iso->status = uiso->status; - iso->actual_length = uiso->actual_length; - } else { - uiso->offset = iso->offset; - uiso->length = iso->length; - uiso->status = iso->status; - uiso->actual_length = iso->actual_length; - } -} - - -/* must free buffer */ -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - ssize_t size = np * sizeof(*iso); - int i; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return NULL; - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1); - usbip_iso_pakcet_correct_endian(iso, 1); - } - - *bufflen = size; - - return buff; -} - -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - int size = np * sizeof(*iso); - int i; - int ret; - - if (!usb_pipeisoc(urb->pipe)) - return 0; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0); - if (ret != size) { - uerr("recv iso_frame_descriptor, %d\n", ret); - kfree(buff); - - if (ud->side == USBIP_STUB) - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - else - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - - return -EPIPE; - } - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_iso_pakcet_correct_endian(iso, 0); - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0); - } - - - kfree(buff); - - return ret; -} - - -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) -{ - int ret; - int size; - - if (ud->side == USBIP_STUB) { - /* stub_rx.c */ - /* the direction of urb must be OUT. */ - if (usb_pipein(urb->pipe)) - return 0; - - size = urb->transfer_buffer_length; - } else { - /* vhci_rx.c */ - /* the direction of urb must be IN. */ - if (usb_pipeout(urb->pipe)) - return 0; - - size = urb->actual_length; - } - - /* no need to recv xbuff */ - if (!(size > 0)) - return 0; - - ret = usbip_xmit(0, ud->tcp_socket, (char *) urb->transfer_buffer, size, 0); - if (ret != size) { - uerr("recv xbuf, %d\n", ret); - if (ud->side == USBIP_STUB) { - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - } else { - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return -EPIPE; - } - } - - return ret; -} diff -Naur usbip-0.1.4/drivers/2.6.16/usbip_common.h trunk/drivers/2.6.16/usbip_common.h --- usbip-0.1.4/drivers/2.6.16/usbip_common.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/usbip_common.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,364 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#ifndef __VHCI_COMMON_H -#define __VHCI_COMMON_H - - -#include -#include -#include - -/*-------------------------------------------------------------------------*/ - -/* - * define macros to print messages - */ - -/** - * udbg - print debug messages if CONFIG_USB_DEBUG is defined - * @fmt: - * @args: - */ - -#ifdef CONFIG_USB_DEBUG - -#define udbg(fmt, args...) \ - do{ \ - printk(KERN_DEBUG "%-10s:(%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - }while(0) - -#else /* CONFIG_USB_DEBUG */ - -#define udbg(fmt, args...) do{ }while(0) - -#endif /* CONFIG_USB_DEBUG */ - - -enum { - usbip_debug_xmit = (1 << 0), - usbip_debug_sysfs = (1 << 1), - usbip_debug_urb = (1 << 2), - usbip_debug_eh = (1 << 3), - - usbip_debug_stub_cmp = (1 << 8), - usbip_debug_stub_dev = (1 << 9), - usbip_debug_stub_rx = (1 << 10), - usbip_debug_stub_tx = (1 << 11), - - usbip_debug_vhci_rh = (1 << 8), - usbip_debug_vhci_hc = (1 << 9), - usbip_debug_vhci_rx = (1 << 10), - usbip_debug_vhci_tx = (1 << 11), - usbip_debug_vhci_sysfs = (1 << 12) -}; - -#define dbg_flag_xmit (usbip_debug_flag & usbip_debug_xmit) -#define dbg_flag_vhci_rh (usbip_debug_flag & usbip_debug_vhci_rh) -#define dbg_flag_vhci_hc (usbip_debug_flag & usbip_debug_vhci_hc) -#define dbg_flag_vhci_rx (usbip_debug_flag & usbip_debug_vhci_rx) -#define dbg_flag_vhci_tx (usbip_debug_flag & usbip_debug_vhci_tx) -#define dbg_flag_vhci_sysfs (usbip_debug_flag & usbip_debug_vhci_sysfs) -#define dbg_flag_stub_rx (usbip_debug_flag & usbip_debug_stub_rx) -#define dbg_flag_stub_tx (usbip_debug_flag & usbip_debug_stub_tx) - -extern unsigned long usbip_debug_flag; -extern struct device_attribute dev_attr_usbip_debug; - -#define dbg_with_flag(flag, fmt, args...) \ - do { \ - if(flag & usbip_debug_flag) \ - udbg(fmt , ##args); \ - } while(0) - -#define dbg_sysfs(fmt, args...) dbg_with_flag(usbip_debug_sysfs, fmt , ##args) -#define dbg_xmit(fmt, args...) dbg_with_flag(usbip_debug_xmit, fmt , ##args) -#define dbg_urb(fmt, args...) dbg_with_flag(usbip_debug_urb, fmt , ##args) -#define dbg_eh(fmt, args...) dbg_with_flag(usbip_debug_eh, fmt , ##args) - -#define dbg_vhci_rh(fmt, args...) dbg_with_flag(usbip_debug_vhci_rh, fmt , ##args) -#define dbg_vhci_hc(fmt, args...) dbg_with_flag(usbip_debug_vhci_hc, fmt , ##args) -#define dbg_vhci_rx(fmt, args...) dbg_with_flag(usbip_debug_vhci_rx, fmt , ##args) -#define dbg_vhci_tx(fmt, args...) dbg_with_flag(usbip_debug_vhci_tx, fmt , ##args) -#define dbg_vhci_sysfs(fmt, args...) dbg_with_flag(usbip_debug_vhci_sysfs, fmt , ##args) - -#define dbg_stub_cmp(fmt, args...) dbg_with_flag(usbip_debug_stub_cmp, fmt , ##args) -#define dbg_stub_rx(fmt, args...) dbg_with_flag(usbip_debug_stub_rx, fmt , ##args) -#define dbg_stub_tx(fmt, args...) dbg_with_flag(usbip_debug_stub_tx, fmt , ##args) - - -/** - * uerr - print error messages - * @fmt: - * @args: - */ -#define uerr(fmt, args...) \ - do { \ - printk(KERN_ERR "%-10s: ***ERROR*** (%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - } while(0) - -/** - * uinfo - print information messages - * @fmt: - * @args: - */ -#define uinfo(fmt, args...) \ - do { \ - printk(KERN_INFO "usbip: " fmt , ## args); \ - } while(0) - - -/*-------------------------------------------------------------------------*/ - -/* - * USB/IP packet headers. - * At now, we define 4 packet types: - * - * - CMD_SUBMIT transfers a USB request. This is corresponding to usb_submit_urb(). - * - RET_RETURN transfers a result of a USB request. - * - CMD_UNLINK transfers an unlink request of a pending USB request. - * - RET_UNLINK transfers an unlink request of a pending USB request. - * - * TODO: - * - * - inter-operability between other OSs - */ - -/* - * A basic header followed by other additional headers. - */ -struct usbip_header_basic { -#define USBIP_CMD_SUBMIT 0x0001 -#define USBIP_CMD_UNLINK 0x0002 -#define USBIP_RET_SUBMIT 0x0003 -#define USBIP_RET_UNLINK 0x0004 - __u32 command; - - __u32 busnum; - __u32 devnum; - __u32 seqnum; /* seaquencial number which identifies URBs */ - __u32 pipe; -} __attribute__ ((packed)); - -/* - * An additional header for a CMD_SUBMIT packet. - */ -struct usbip_header_cmd_submit { - __u32 transfer_flags; - __s32 transfer_buffer_length; - __s32 bandwidth; - __s32 start_frame; - __s32 number_of_packets; - __s32 interval; - unsigned char setup[8]; /* CTRL only */ -}__attribute__ ((packed)); - -/* - * An additional header for a RET_SUBMIT packet. - */ -struct usbip_header_ret_submit { - __s32 status; - __s32 actual_length; /* returned data length */ - __s32 bandwidth; - __s32 start_frame; /* ISO and INT */ - __s32 number_of_packets; /* ISO only */ - __s32 error_count; /* ISO only */ -}__attribute__ ((packed)); - -/* - * An additional header for a CMD_UNLINK packet. - */ -struct usbip_header_cmd_unlink { - __u32 seqnum; /* URB's seqnum which will be unlinked */ -}__attribute__ ((packed)); - - -/* - * An additional header for a RET_UNLINK packet. - */ -struct usbip_header_ret_unlink { - __s32 status; -}__attribute__ ((packed)); - - -/* the same as usb_iso_packet_descriptor but packed for pdu */ -struct usbip_iso_packet_descriptor { - __u32 offset; - __u32 length; /* expected length */ - __u32 actual_length; - __u32 status; -}__attribute__ ((packed)); - - -/* - * All usbip packets use a common header to keep code simple. - */ -struct usbip_header { - struct usbip_header_basic base; - - union { - struct usbip_header_cmd_submit cmd_submit; - struct usbip_header_ret_submit ret_submit; - struct usbip_header_cmd_unlink cmd_unlink; - struct usbip_header_ret_unlink ret_unlink; - } u; -}__attribute__ ((packed)); - - - - -/*-------------------------------------------------------------------------*/ - - -int usbip_xmit(int , struct socket *, char *, int , int ); -int usbip_sendmsg(struct socket *, struct msghdr *, int ); - - -static inline int interface_to_busnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->bus->busnum; -} - -static inline int interface_to_devnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->devnum; -} - -static inline int interface_to_infnum(struct usb_interface *interface) -{ - return interface->cur_altsetting->desc.bInterfaceNumber; -} - -int setnodelay(struct socket *); -int setquickack(struct socket *); -int setkeepalive(struct socket *socket); -void setreuse(struct socket *); -struct socket *sockfd_to_socket(unsigned int); -int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss); - - -void usbip_dump_urb (struct urb *purb); -void usbip_dump_header(struct usbip_header *pdu); - - -struct usbip_device; - -struct usbip_task { - struct task_struct *thread; - struct completion thread_done; - char *name; - void (*loop_ops)(struct usbip_task *); -}; - -enum usbip_side { - USBIP_VHCI, - USBIP_STUB, -}; - -enum usbip_status { - /* sdev is available. */ - SDEV_ST_AVAILABLE = 0x01, - /* sdev is now used. */ - SDEV_ST_USED, - /* sdev is unusable because of a fatal error. */ - SDEV_ST_ERROR, - - /* vdev does not connect a remote device. */ - VDEV_ST_NULL, - /* vdev is used, but the USB address is not assigned yet */ - VDEV_ST_NOTASSIGNED, - VDEV_ST_USED, - VDEV_ST_ERROR -}; - -/* a common structure for stub_device and vhci_device */ -struct usbip_device{ - enum usbip_side side; - - enum usbip_status status; - - /* lock for status */ - spinlock_t lock; - - struct socket *tcp_socket; - - struct usbip_task tcp_rx; - struct usbip_task tcp_tx; - - /* event handler */ -#define USBIP_EH_SHUTDOWN (1 << 0) -#define USBIP_EH_BYE (1 << 1) -#define USBIP_EH_RESET (1 << 2) -#define USBIP_EH_UNUSABLE (1 << 3) - -#define SDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE ) -#define SDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_SUBMIT ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE ) - -#define VDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_BYE ) -#define VDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) - - unsigned long event; - struct usbip_task eh; - wait_queue_head_t eh_waitq; - - struct eh_ops { - void (*shutdown)(struct usbip_device *); - void (*reset)(struct usbip_device *); - void (*unusable)(struct usbip_device *); - } eh_ops; -}; - - -void usbip_task_init(struct usbip_task *ut, char *, void (*loop_ops)(struct usbip_task *)); - -void usbip_start_threads(struct usbip_device *ud); -void usbip_stop_threads(struct usbip_device *ud); -int usbip_thread(void *param); - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack); -void usbip_header_correct_endian(struct usbip_header *pdu, int send); -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb); -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen); - - -/* usbip_event.c */ -void usbip_start_eh(struct usbip_device *ud); -void usbip_stop_eh(struct usbip_device *ud); -void usbip_event_add(struct usbip_device *ud, unsigned long event); -int usbip_event_happend(struct usbip_device *ud); - - -#endif diff -Naur usbip-0.1.4/drivers/2.6.16/usbip_event.c trunk/drivers/2.6.16/usbip_event.c --- usbip-0.1.4/drivers/2.6.16/usbip_event.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/usbip_event.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,153 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" - - - - -static void event_handler_loop(struct usbip_task *eh); - -void usbip_start_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - init_waitqueue_head(&ud->eh_waitq); - ud->event = 0; - - usbip_task_init(eh, "usbip_eh", event_handler_loop); - - kernel_thread((int(*)(void *)) usbip_thread, (void *) eh, 0); - - wait_for_completion(&eh->thread_done); -} - -void usbip_stop_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - wait_for_completion(&eh->thread_done); - dbg_eh("usbip_eh has finished\n"); -} - - -void usbip_event_add(struct usbip_device *ud, unsigned long event) -{ - spin_lock(&ud->lock); - - ud->event |= event; - - wake_up(&ud->eh_waitq); - - spin_unlock(&ud->lock); -} - -int usbip_event_happend(struct usbip_device *ud) -{ - int happend = 0; - - spin_lock(&ud->lock); - - if (ud->event != 0) - happend = 1; - - spin_unlock(&ud->lock); - - return happend; -} - - -static int event_handler(struct usbip_device *ud) -{ - - dbg_eh("enter\n"); - - - /* - * Events are handled by only this thread. - */ - while ( usbip_event_happend(ud) ) { - dbg_eh("pending event %lx\n", ud->event); - - /* - * NOTE: shutdown must come first. - * Shutdown the device. - */ - if (ud->event & USBIP_EH_SHUTDOWN) { - ud->eh_ops.shutdown(ud); - - ud->event &= ~USBIP_EH_SHUTDOWN; - - break; - } - - /* Stop the error handler. */ - if (ud->event & USBIP_EH_BYE) - return -1; - - /* Reset the device. */ - if (ud->event & USBIP_EH_RESET) { - ud->eh_ops.reset(ud); - - ud->event &= ~USBIP_EH_RESET; - - break; - } - - /* Mark the device as unusable. */ - if (ud->event & USBIP_EH_UNUSABLE) { - ud->eh_ops.unusable(ud); - - ud->event &= ~USBIP_EH_UNUSABLE; - - break; - } - - /* NOTREACHED */ - uerr("unknown event\n"); - return -1; - } - - return 0; -} - - - - -static void event_handler_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, eh); - - while (1) { - if (signal_pending(current)) { - dbg_eh("signal catched!\n"); - break; - } - - if ( event_handler(ud) < 0) - break; - - wait_event_interruptible(ud->eh_waitq, usbip_event_happend(ud)); - dbg_eh("wakeup\n"); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.16/vhci.h trunk/drivers/2.6.16/vhci.h --- usbip-0.1.4/drivers/2.6.16/vhci.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/vhci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,143 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include HCD_HEADER - - -struct vhci_device { - struct usb_device *udev; - - /* busnum and devnum of a remote device */ - __u32 busnum; - __u32 devnum; - - /* speed of a remote device */ - enum usb_device_speed speed; - - /* vhci root-hub port to which this device is attached */ - __u32 rhport; - - struct usbip_device ud; - - - /* lock for the below link lists */ - spinlock_t priv_lock; - - /* vhci_priv is linked to one of them. */ - struct list_head priv_tx; - struct list_head priv_rx; - - /* vhci_unlink is linked to one of them */ - struct list_head unlink_tx; - struct list_head unlink_rx; - - /* vhci_tx thread sleeps for this queue */ - wait_queue_head_t waitq_tx; -}; - - -/* urb->hcpriv, use container_of() */ -struct vhci_priv { - unsigned long seqnum; - struct list_head list; - - struct vhci_device *vdev; - struct urb *urb; -}; - - -struct vhci_unlink { - /* seqnum of this request */ - unsigned long seqnum; - - struct list_head list; - - /* seqnum of the unlink target */ - unsigned long unlink_seqnum; -}; - -/* - * The number of ports is less than 16 ? - * USB_MAXCHILDREN is statically defined to 16 in usb.h. Its maximum value - * would be 31 because the event_bits[1] of struct usb_hub is defined as - * unsigned long in hub.h - */ -#define VHCI_NPORTS 8 - -/* for usb_bus.hcpriv */ -struct vhci_hcd { - spinlock_t lock; - - u32 port_status[VHCI_NPORTS]; - - unsigned resuming:1; - unsigned long re_timeout; - - atomic_t seqnum; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - * But, the index of this array begins from 0. - */ - struct vhci_device vdev[VHCI_NPORTS]; - - /* vhci_device which has not been assiged its address yet */ - int pending_port; -}; - - -extern struct vhci_hcd *the_controller; -extern struct attribute_group dev_attr_group; - - -/*-------------------------------------------------------------------------*/ -/* prototype declaration */ - -/* vhci_hcd.c */ -void rh_port_connect(int rhport, enum usb_device_speed speed); -void rh_port_disconnect(int rhport); -void vhci_rx_loop(struct usbip_task *ut); -void vhci_tx_loop(struct usbip_task *ut); - -#define hardware (&the_controller->pdev.dev) - -static inline struct vhci_device *port_to_vdev(__u32 port) -{ - return &the_controller->vdev[port]; -} - -static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd) -{ - return (struct vhci_hcd *) (hcd->hcd_priv); -} - -static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci) -{ - return container_of((void *) vhci, struct usb_hcd, hcd_priv); -} - -static inline struct device *vhci_dev(struct vhci_hcd *vhci) -{ - return vhci_to_hcd(vhci)->self.controller; -} diff -Naur usbip-0.1.4/drivers/2.6.16/vhci_hcd.c trunk/drivers/2.6.16/vhci_hcd.c --- usbip-0.1.4/drivers/2.6.16/vhci_hcd.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/vhci_hcd.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1174 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "vhci.h" - -#define DRIVER_VERSION " $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ " -#define DRIVER_AUTHOR "HIROFUCHI Takahiro " -#define DRIVER_DESC "Virtual Host Controller Interface Driver for USB/IP" -#define DRIVER_LICENCE "GPL" -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENCE); - - - -/* - * TODO - * - update root hub emulation - * - move the emulation code to userland ? - * poring to other operating systems - * minimize kernel code - * - add suspend/resume code - * - clean up everything - */ - - -/* See usb gadget dummy hcd */ - - -static int vhci_hub_status (struct usb_hcd *hcd, char *buff); -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buff, u16 wLength); -static int vhci_urb_enqueue (struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags); -static int vhci_urb_dequeue( struct usb_hcd *hcd, struct urb *urb); -static int vhci_start(struct usb_hcd *vhci_hcd); -static void vhci_stop(struct usb_hcd *hcd); -static int vhci_get_frame_number(struct usb_hcd *hcd); - -static const char driver_name[] = "vhci_hcd"; -static const char driver_desc[] = "USB/IP Virtual Host Contoroller"; - - - - -struct vhci_hcd *the_controller = NULL; - - -static const char *bit_desc[] = { - "CONNECTION", /*0*/ - "ENABLE", /*1*/ - "SUSPEND", /*2*/ - "OVER_CURRENT", /*3*/ - "RESET", /*4*/ - "R5", /*5*/ - "R6", /*6*/ - "R7", /*7*/ - "POWER", /*8*/ - "LOWSPEED", /*9*/ - "HIGHSPEED", /*10*/ - "PORT_TEST", /*11*/ - "INDICATOR", /*12*/ - "R13", /*13*/ - "R14", /*14*/ - "R15", /*15*/ - "C_CONNECTION", /*16*/ - "C_ENABLE", /*17*/ - "C_SUSPEND", /*18*/ - "C_OVER_CURRENT", /*19*/ - "C_RESET", /*20*/ - "R21", /*21*/ - "R22", /*22*/ - "R23", /*23*/ - "R24", /*24*/ - "R25", /*25*/ - "R26", /*26*/ - "R27", /*27*/ - "R28", /*28*/ - "R29", /*29*/ - "R30", /*30*/ - "R31", /*31*/ -}; - - -static void dump_port_status(u32 status) -{ - int i = 0; - - printk("status %08x:", status); - for (i = 0; i < 32; i++) { - if (status & (1 << i)) { - printk(" %s", bit_desc[i]); - } - } - - printk("\n"); -} - - - -void rh_port_connect(int rhport, enum usb_device_speed speed) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_connect %d\n", rhport); - - spin_lock_irqsave(&the_controller->lock, flags); - - the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION - | (1 << USB_PORT_FEAT_C_CONNECTION); - - switch (speed) { - case USB_SPEED_HIGH: - the_controller->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - the_controller->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - - //spin_lock(&the_controller->vdev[rhport].ud.lock); - //the_controller->vdev[rhport].ud.status = VDEV_CONNECT; - //spin_unlock(&the_controller->vdev[rhport].ud.lock); - - the_controller->pending_port = rhport; - - spin_unlock_irqrestore(&the_controller->lock, flags); - -} - -void rh_port_disconnect(int rhport) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_disconnect %d\n", rhport); - - spin_lock_irqsave (&the_controller->lock, flags); - //stop_activity (dum, driver); - the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; - the_controller->port_status[rhport] |= (1 << USB_PORT_FEAT_C_CONNECTION); - - - /* not yet complete the disconnection */ - //spin_lock(&vdev->ud.lock); - //vdev->ud.status = VHC_ST_DISCONNECT; - //spin_unlock(&vdev->ud.lock); - - spin_unlock_irqrestore (&the_controller->lock, flags); -} - - - -/*----------------------------------------------------------------------*/ - -#define PORT_C_MASK \ - ((USB_PORT_STAT_C_CONNECTION \ - | USB_PORT_STAT_C_ENABLE \ - | USB_PORT_STAT_C_SUSPEND \ - | USB_PORT_STAT_C_OVERCURRENT \ - | USB_PORT_STAT_C_RESET) << 16) - -/* - * This function is almostly the same as dummy_hcd.c:dummy_hub_status() without - * suspend/resume support. But, it is modified to provide multiple ports. - * - * @buf: a bitmap to show which port status has been changed. - * bit 0: reserved or used for another purpose? - * bit 1: the status of port 0 has been changed. - * bit 2: the status of port 1 has been changed. - * ... - * bit 7: the status of port 6 has been changed. - * bit 8: the status of port 7 has been changed. - * ... - * bit 15: the status of port 14 has been changed. - * - * So, the maximum number of ports is 31 ( port 0 to port 30) ? - * - * The return value is the actual transfered length in byte. If nothing has - * been changed, return 0. In the case that the number of ports is less than or - * equal to 6 (VHCI_NPORTS==7), return 1. - * - */ -static int vhci_hub_status (struct usb_hcd *hcd, char *buf) -{ - struct vhci_hcd *vhci; - unsigned long flags; - int retval = 0; - - /* the enough buffer is allocated according to USB_MAXCHILDREN */ - unsigned long *event_bits = (unsigned long *) buf; - int rhport; - int changed = 0; - - - *event_bits = 0; - - vhci = hcd_to_vhci(hcd); - - spin_lock_irqsave (&vhci->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - dbg_vhci_rh("hw accessible flag in on?\n"); - goto done; - } - - /* check pseudo status register for each port */ - for(rhport = 0; rhport < VHCI_NPORTS; rhport++) { - if ((vhci->port_status[rhport] & PORT_C_MASK)) { - /* The status of a port has been changed, */ - dbg_vhci_rh("port %d is changed\n", rhport); - - *event_bits |= 1 << ( rhport + 1); - changed = 1; - } - } - - if (changed) - retval = 1 + (VHCI_NPORTS / 8); - else - retval = 0; - -done: - spin_unlock_irqrestore (&vhci->lock, flags); - return retval; -} - -/* See hub_configure in hub.c */ -static inline void hub_descriptor(struct usb_hub_descriptor *desc) -{ - memset(desc, 0, sizeof(*desc)); - desc->bDescriptorType = 0x29; - desc->bDescLength = 9; - desc->wHubCharacteristics = (__force __u16) - (__constant_cpu_to_le16 (0x0001)); - desc->bNbrPorts = VHCI_NPORTS; - desc->bitmap [0] = 0xff; - desc->bitmap [1] = 0xff; -} - - -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) -{ - struct vhci_hcd *dum; - int retval = 0; - unsigned long flags; - int rhport; - - u32 prev_port_status[VHCI_NPORTS]; - - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) - return -ETIMEDOUT; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - */ - dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue, wIndex); - if (wIndex > VHCI_NPORTS) - uerr("invalid port number %d\n", wIndex); - rhport = ((__u8 ) (wIndex & 0x00ff)) -1; - - dum = hcd_to_vhci(hcd); - - spin_lock_irqsave (&dum->lock, flags); - - /* store old status and compare now and old later */ - if (dbg_flag_vhci_rh) { - int i = 0; - for (i = 0; i < VHCI_NPORTS; i++) - prev_port_status[i] = dum->port_status[i]; - } - - switch (typeReq) { - case ClearHubFeature: - dbg_vhci_rh(" ClearHubFeature\n"); - break; - case ClearPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if (dum->port_status[rhport] & (1 << USB_PORT_FEAT_SUSPEND)) { - /* 20msec signaling */ - dum->resuming = 1; - dum->re_timeout = jiffies + msecs_to_jiffies(20); - } - break; - case USB_PORT_FEAT_POWER: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_POWER\n"); - dum->port_status[rhport] = 0; - //dum->address = 0; - //dum->hdev = 0; - dum->resuming = 0; - break; - case USB_PORT_FEAT_C_RESET: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_C_RESET\n"); - switch (dum->vdev[rhport].speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - default: - dbg_vhci_rh(" ClearPortFeature: default %x\n", wValue); - dum->port_status[rhport] &= ~(1 << wValue); - } - break; - case GetHubDescriptor: - dbg_vhci_rh(" GetHubDescriptor\n"); - hub_descriptor ((struct usb_hub_descriptor *) buf); - break; - case GetHubStatus: - dbg_vhci_rh(" GetHubStatus\n"); - *(u32 *) buf = __constant_cpu_to_le32 (0); - break; - case GetPortStatus: - dbg_vhci_rh(" GetPortStatus port %x\n", wIndex); - if (wIndex > VHCI_NPORTS || wIndex < 1) { - uerr(" invalid port number %d\n", wIndex); - retval = -EPIPE; - } - - /* we do no care of resume. */ - - /* whoever resets or resumes must GetPortStatus to - * complete it!! - * */ - if (dum->resuming && time_after (jiffies, dum->re_timeout)) { - uerr(" not yet\n"); - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_SUSPEND); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_SUSPEND); - dum->resuming = 0; - dum->re_timeout = 0; - //if (dum->driver && dum->driver->resume) { - // spin_unlock (&dum->lock); - // dum->driver->resume (&dum->gadget); - // spin_lock (&dum->lock); - //} - } - - if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) != 0 - && time_after (jiffies, dum->re_timeout)) { - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_RESET); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_RESET); - dum->re_timeout = 0; - - if (dum->vdev[rhport].ud.status == VDEV_ST_NOTASSIGNED) { - dbg_vhci_rh(" enable rhport %d (status %u)\n", rhport, dum->vdev[rhport].ud.status); - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - } -#if 0 - if (dum->driver) { - - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - /* give it the best speed we agree on */ - dum->gadget.speed = dum->driver->speed; - dum->gadget.ep0->maxpacket = 64; - switch (dum->gadget.speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= - USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->gadget.ep0->maxpacket = 8; - dum->port_status[rhport] |= - USB_PORT_STAT_LOW_SPEED; - break; - default: - dum->gadget.speed = USB_SPEED_FULL; - break; - } - } -#endif - - } - ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status[rhport]); - ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status[rhport] >> 16); - - dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0], ((u16 *)buf)[1] ); - break; - case SetHubFeature: - dbg_vhci_rh(" SetHubFeature\n"); - retval = -EPIPE; - break; - case SetPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_SUSPEND\n"); - uerr(" not yet\n"); -#if 0 - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_SUSPEND); - if (dum->driver->suspend) { - spin_unlock (&dum->lock); - dum->driver->suspend (&dum->gadget); - spin_lock (&dum->lock); - } -#endif - break; - case USB_PORT_FEAT_RESET: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_RESET\n"); - /* if it's already running, disconnect first */ - if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) { - dum->port_status[rhport] &= ~(USB_PORT_STAT_ENABLE - | USB_PORT_STAT_LOW_SPEED - | USB_PORT_STAT_HIGH_SPEED); -#if 0 - if (dum->driver) { - dev_dbg (hardware, "disconnect\n"); - stop_activity (dum, dum->driver); - } -#endif - - /* FIXME test that code path! */ - } - /* 50msec reset signaling */ - dum->re_timeout = jiffies + msecs_to_jiffies(50); - - /* FALLTHROUGH */ - default: - dbg_vhci_rh(" SetPortFeature: default %d\n", wValue); - dum->port_status[rhport] |= (1 << wValue); - } - break; - - default: - uerr(" default: no such request\n"); - //dev_dbg (hardware, - // "hub control req%04x v%04x i%04x l%d\n", - // typeReq, wValue, wIndex, wLength); - - /* "protocol stall" on error */ - retval = -EPIPE; - } - - if (dbg_flag_vhci_rh) { - printk("port %d\n", rhport); - dump_port_status(prev_port_status[rhport]); - dump_port_status(dum->port_status[rhport]); - } - dbg_vhci_rh(" bye\n"); - - spin_unlock_irqrestore (&dum->lock, flags); - - return retval; -} - - - -/*----------------------------------------------------------------------*/ - -static struct vhci_device *get_vdev(struct usb_device *udev) -{ - int i; - - if (!udev) - return NULL; - - for (i=0; i < VHCI_NPORTS; i++) - if (the_controller->vdev[i].udev == udev) - return port_to_vdev(i); - - return NULL; -} - -static void vhci_tx_urb(struct urb *urb) -{ - struct vhci_device *vdev = get_vdev(urb->dev); - struct vhci_priv *priv; - unsigned long flag; - - if (!vdev) - BUG(); - - spin_lock_irqsave(&vdev->priv_lock, flag); - - priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC); - if (!priv) { - uerr("malloc vhci_priv\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flag); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - priv->seqnum = atomic_inc_return(&the_controller->seqnum); - if (priv->seqnum == 0xffff) - uinfo("seqnum max\n"); - - priv->vdev = vdev; - priv->urb = urb; - - urb->hcpriv = (void *) priv; - - - list_add_tail(&priv->list, &vdev->priv_tx); - - wake_up(&vdev->waitq_tx); - spin_unlock_irqrestore(&vdev->priv_lock, flag); -} - -static int vhci_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags) -{ - int ret = 0; - unsigned long flags; - - dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); - - - - /* patch to usb_sg_init() is in 2.5.60 */ - BUG_ON (!urb->transfer_buffer && urb->transfer_buffer_length); - - spin_lock_irqsave (&the_controller->lock, flags); - - /* check HC is active or not */ - if (!HC_IS_RUNNING(hcd->state)) { - uerr("HC is not running\n"); - spin_unlock_irqrestore(&the_controller->lock, flags); - return -ENODEV; - } - - if (urb->status != -EINPROGRESS) { - uerr("URB already unlinked!, status %d\n", urb->status); - spin_unlock_irqrestore(&the_controller->lock, flags); - return urb->status; - } - - /* - * The enumelation process is as follows; - * - * 1. Get_Descriptor request to DevAddrs(0) EndPoint(0) - * to get max packet length of default pipe - * - * 2. Set_Address request to DevAddr(0) EndPoint(0) - * - */ - - if (usb_pipedevice(urb->pipe) == 0) { - __u8 type = usb_pipetype(urb->pipe); - struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; - struct vhci_device *vdev = port_to_vdev(the_controller->pending_port); - - if (type != PIPE_CONTROL || !ctrlreq ) { - uerr("invalid request to devnum 0\n"); - ret = EINVAL; - goto no_need_xmit; - } - - switch (ctrlreq->bRequest) { - - case USB_REQ_SET_ADDRESS: - vdev->udev = urb->dev; - dbg_vhci_hc("SetAddress Request (%d) to port %d\n", - ctrlreq->wValue, vdev->rhport); - - spin_lock(&vdev->ud.lock); - vdev->ud.status = VDEV_ST_USED; - spin_unlock(&vdev->ud.lock); - - spin_lock (&urb->lock); - if (urb->status == -EINPROGRESS) { - /* This request is successfully completed. */ - /* If not -EINPROGRESS, possibly unlinked. */ - urb->status = 0; - } - spin_unlock (&urb->lock); - - goto no_need_xmit; - - case USB_REQ_GET_DESCRIPTOR: - if (ctrlreq->wValue == (USB_DT_DEVICE << 8)) - dbg_vhci_hc("Not yet?: Get_Descriptor to device 0 (get max pipe size)\n"); - - vdev->udev = urb->dev; - goto out; - - default: - /* NOT REACHED */ - uerr("invalid request to devnum 0 bRequest %u, wValue %u\n", - ctrlreq->bRequest, ctrlreq->wValue); - ret = -EINVAL; - goto no_need_xmit; - } - - } - -out: - - - vhci_tx_urb(urb); - - - spin_unlock_irqrestore (&the_controller->lock, flags); - - return 0; - - -no_need_xmit: - - spin_unlock_irqrestore(&the_controller->lock, flags); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - return 0; -} - - -/* - * vhci_rx gives back the urb after recieving the reply of the urb. If an - * unlink pdu is sent or not, vhci_rx recieves a normal return pdu and gives - * back its urb. For the driver unlinking the urb, the content of the urb is - * not important, but the calling to its completion handler is important; the - * completion of unlinking is notified by the completion handler. - * - * - * CLIENT SIDE - * - * - When vhci_hcd recieves RET_SUBMIT, - * - * - case 1a). the urb of the pdu is not unlinking. - * - normal case - * => just give back the urb - * - * - case 1b). the urb of the pdu is unlinking. - * - usbip.ko will return a reply of the unlinking request. - * => give back the urb now and go to case 2b). - * - * - When vhci_hcd recieves RET_UNLINK, - * - * - case 2a). a submit request is still pending in vhci_hcd. - * - urb was really pending in usbip.ko and urb_unlink_urb() was - * completed there. - * => free a pending submit request - * => notify unlink completeness by giving back the urb - * - * - case 2b). a submit request is *not* pending in vhci_hcd. - * - urb was already given back to the core driver. - * => do not give back the urb - * - * - * SERVER SIDE - * - * - When usbip recieves CMD_UNLINK, - * - * - case 3a). the urb of the unlink request is now in submission. - * => do usb_unlink_urb(). - * => after the unlink is completed, send RET_UNLINK. - * - * - case 3b). the urb of the unlink request is not in submission. - * - may be already completed or never be recieved - * => send RET_UNLINK - * - */ -static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -{ - unsigned long flags; - struct vhci_priv *priv; - struct vhci_device *vdev; - - uinfo("vhci_hcd: dequeue a urb %p\n", urb); - - - spin_lock_irqsave(&the_controller->lock, flags); - - priv = urb->hcpriv; - if (!priv) { - /* URB was never linked! or will be soon given back by vhci_rx. */ - spin_unlock_irqrestore(&the_controller->lock, flags); - return 0; - } - - /* send unlink request here? */ - vdev = priv->vdev; - - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - unsigned long flags2; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - uinfo("vhci_hcd: device %p seems to be disconnected\n", vdev); - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - - } else { - /* tcp connection is alive */ - unsigned long flags2; - struct vhci_unlink *unlink; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - /* setup CMD_UNLINK pdu */ - unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("malloc vhci_unlink\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - spin_unlock_irqrestore(&the_controller->lock, flags); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return -ENOMEM; - } - - unlink->seqnum = atomic_inc_return(&the_controller->seqnum); - if (unlink->seqnum == 0xffff) - uinfo("seqnum max\n"); - - unlink->unlink_seqnum = priv->seqnum; - - uinfo("vhci_hcd: device %p seems to be still connected\n", vdev); - - /* send cmd_unlink and try to cancel the pending URB in the peer */ - list_add_tail(&unlink->list, &vdev->unlink_tx); - wake_up(&vdev->waitq_tx); - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - } - - spin_unlock_irqrestore(&the_controller->lock, flags); - - /* - * If tcp connection is alive, we have sent CMD_UNLINK. - * vhci_rx will recieve RET_UNLINK and giveb back the URB. - * Otherwise, we give back it here. - */ - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n", urb); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - dbg_vhci_hc("leave\n"); - return 0; -} - - -static void vhci_device_unlink_cleanup(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock(&vdev->priv_lock); -} - -/* - * The important thing is that only one context begins cleanup. - * This is why error handling and cleanup become simple. - * We do not want to consider race condition as possible. - */ -static void vhci_shutdown_connection(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - /* need this? see stub_dev.c */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - usbip_stop_threads(&vdev->ud); - uinfo("stop threads\n"); - - /* active connection is closed */ - if (vdev->ud.tcp_socket != NULL) { - sock_release(vdev->ud.tcp_socket); - vdev->ud.tcp_socket = NULL; - } - uinfo("release socket\n"); - - vhci_device_unlink_cleanup(vdev); - - /* - * rh_port_disconnect() is a trigger of ... - * usb_disable_device(): - * disable all the endpoints for a USB device. - * usb_disable_endpoint(): - * disable endpoints. pending urbs are unlinked(dequeued). - * - * NOTE: After calling rh_port_disconnect(), the USB device driver of a - * deteched device should release used urbs in a cleanup function(i.e. - * xxx_disconnect()). Therefore, vhci_hcd does not need to release - * pushed urbs and their private data in this function. - * - * NOTE: vhci_dequeue() must be considered carefully. When shutdowning - * a connection, vhci_shutdown_connection() expects vhci_dequeue() - * gives back pushed urbs and frees their private data by request of - * the cleanup function of a USB driver. When unlinking a urb with an - * active connection, vhci_dequeue() does not give back the urb which - * is actually given back by vhci_rx after recieving its return pdu. - * - */ - rh_port_disconnect(vdev->rhport); - - uinfo("disconnect device\n"); -} - - -static void vhci_device_reset(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - spin_lock(&ud->lock); - - vdev->busnum = 0; - vdev->devnum = 0; - vdev->speed = 0; - - ud->tcp_socket = NULL; - - ud->status = VDEV_ST_NULL; - - spin_unlock(&ud->lock); -} - -static void vhci_device_unusable(struct usbip_device* ud) -{ - spin_lock(&ud->lock); - - ud->status = VDEV_ST_ERROR; - - spin_unlock(&ud->lock); -} - -static void vhci_device_init(struct vhci_device *vdev) -{ - memset(vdev, 0, sizeof(*vdev)); - - usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop); - usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop); - - vdev->ud.side = USBIP_VHCI; - vdev->ud.status = VDEV_ST_NULL; - vdev->ud.lock = SPIN_LOCK_UNLOCKED; - - INIT_LIST_HEAD(&vdev->priv_rx); - INIT_LIST_HEAD(&vdev->priv_tx); - INIT_LIST_HEAD(&vdev->unlink_tx); - INIT_LIST_HEAD(&vdev->unlink_rx); - vdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&vdev->waitq_tx); - - vdev->ud.eh_ops.shutdown = vhci_shutdown_connection; - vdev->ud.eh_ops.reset = vhci_device_reset; - vdev->ud.eh_ops.unusable= vhci_device_unusable; - - usbip_start_eh(&vdev->ud); -} - - -/*----------------------------------------------------------------------*/ - -static int vhci_start(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport; - - dbg_vhci_hc("enter vhci_start\n"); - - - /* initialize private data of usb_hcd */ - - for(rhport=0; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - vhci_device_init(vdev); - vdev->rhport = rhport; - } - - atomic_set(&vhci->seqnum, 0); - spin_lock_init(&vhci->lock); - - - - //hcd->power_budget = 0; /* no limit ? */ - hcd->state = HC_STATE_RUNNING; - //hcd->uses_new_polling = 1; - - - /* vhci_hcd is now ready to be controlled through sysfs */ - sysfs_create_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - return 0; -} - -static void vhci_stop(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport = 0; - - dbg_vhci_hc("stop VHCI controller\n"); - - - /* 1. remove the userland interface of vhci_hcd */ - sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - /* 2. shutdown all the ports of vhci_hcd */ - for(rhport = 0 ; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - - usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED); - usbip_stop_eh(&vdev->ud); - } - - - uinfo("vhci_stop done\n"); -} - -/*----------------------------------------------------------------------*/ - -static int vhci_get_frame_number(struct usb_hcd *hcd) -{ - uerr("Not yet implemented\n"); - return 0; -} - - -#ifdef CONFIG_PM - -static int vhci_bus_suspend(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -static int vhci_bus_resume(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -#else - -#define vhci_bus_suspend NULL -#define vhci_bus_resume NULL -#endif - - - -static struct hc_driver vhci_hc_driver = { - .description = driver_name, - .product_desc = driver_desc, - .hcd_priv_size = sizeof(struct vhci_hcd), - - .flags = HCD_USB2, - - .start = vhci_start, - .stop = vhci_stop, - - .urb_enqueue = vhci_urb_enqueue, - .urb_dequeue = vhci_urb_dequeue, - - .get_frame_number = vhci_get_frame_number, - - .hub_status_data = vhci_hub_status, - .hub_control = vhci_hub_control, - .bus_suspend = vhci_bus_suspend, - .bus_resume = vhci_bus_resume, -}; - -static int vhci_hcd_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - int ret; - - uinfo("proving...\n"); - - dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id); - - - /* will be removed */ - if (pdev->dev.dma_mask) { - info("vhci_hcd DMA not supported\n"); - return -EINVAL; - } - - - /* - * Allocate and initialize hcd. - * Our private data is also allocated automatically. - */ - hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, pdev->dev.bus_id); - if (!hcd) { - uerr("create hcd failed\n"); - return -ENOMEM; - } - - - /* this is private data for vhci_hcd */ - the_controller = hcd_to_vhci(hcd); - - /* - * Finish generic HCD structure initialization and register. - * Call the driver's reset() and start() routines. - */ - ret = usb_add_hcd(hcd, 0, 0); - if (ret != 0) { - uerr("usb_add_hcd failed %d\n", ret); - usb_put_hcd(hcd); - the_controller = NULL; - return ret; - } - - - dbg_vhci_hc("bye\n"); - return 0; -} - - -static int vhci_hcd_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - - - hcd = platform_get_drvdata(pdev); - if(!hcd) - return 0; - - /* - * Disconnects the root hub, - * then reverses the effects of usb_add_hcd(), - * invoking the HCD's stop() methods. - */ - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - the_controller = NULL; - - - return 0; -} - - - -#ifdef CONFIG_PM - -/* what should happen for USB/IP under suspend/resume? */ -static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = state; - - return 0; -} - -static int vhci_hcd_resume(struct platform_device *pdev) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = PMSG_ON; - - return 0; -} - -#else - -#define vhci_hcd_suspend NULL -#define vhci_hcd_resume NULL - -#endif - - -static struct platform_driver vhci_driver = { - .probe = vhci_hcd_probe, - .remove = __devexit_p(vhci_hcd_remove), - .suspend = vhci_hcd_suspend, - .resume = vhci_hcd_resume, - .driver = { - .name = (char *) driver_name, - .owner = THIS_MODULE, - }, -}; - -/*----------------------------------------------------------------------*/ - -/* - * The VHCI 'device' is 'virtual'; not a real plug&play hardware. - * We need to add this virtual device as a platform device arbitrarily: - * 1. platform_device_register() - */ -static void the_pdev_release(struct device *dev) -{ - return; -} - -static struct platform_device the_pdev = { - /* should be the same name as driver_name */ - .name = (char *) driver_name, - .id = -1, - .dev = { - //.driver = &vhci_driver, - .release = the_pdev_release, - }, -}; - -static int __init vhci_init(void) -{ - int ret; - - dbg_vhci_hc("enter\n"); - if (usb_disabled()) - return -ENODEV; - - info("driver %s, %s\n", driver_name, DRIVER_VERSION); - - ret = platform_driver_register(&vhci_driver); - if (ret < 0) - goto err_driver_register; - - ret = platform_device_register(&the_pdev); - if (ret < 0) - goto err_platform_device_register; - - - dbg_vhci_hc("bye\n"); - return ret; - - - - /* error occurred */ - -err_platform_device_register: - platform_driver_unregister(&vhci_driver); - -err_driver_register: - - dbg_vhci_hc("bye\n"); - return ret; -} -module_init(vhci_init); - - -static void __exit vhci_cleanup(void) -{ - dbg_vhci_hc("enter\n"); - - platform_device_unregister(&the_pdev); - platform_driver_unregister(&vhci_driver); - - dbg_vhci_hc("bye\n"); -} -module_exit(vhci_cleanup); diff -Naur usbip-0.1.4/drivers/2.6.16/vhci_rx.c trunk/drivers/2.6.16/vhci_rx.c --- usbip-0.1.4/drivers/2.6.16/vhci_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/vhci_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,239 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - - -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) -{ - struct vhci_priv *priv, *tmp; - struct urb *urb = NULL; - - - spin_lock(&vdev->priv_lock); - - - list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { - if (priv->seqnum == seqnum) { - urb = priv->urb; - dbg_vhci_rx("find urb %p vurb %p seqnum %u\n", urb, priv, seqnum); - - - if (urb->status != -EINPROGRESS) { - if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - uinfo("urb %p was unlinked %ssynchronuously.\n", - urb, urb->status == -ENOENT ? "" : "a"); - } else { - uinfo("urb %p may be in a error, status %d\n", - urb, urb->status); - } - } - - - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - - break; - } - } - - spin_unlock(&vdev->priv_lock); - - - return urb; -} - -static void vhci_recv_ret_submit(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &vdev->ud; - struct urb *urb; - - - urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); - - - if (!urb) { - uerr("cannot find a urb of seqnum %u\n", pdu->base.seqnum); - uinfo("max seqnum %d\n", atomic_read(&the_controller->seqnum)); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - - /* unpack the pdu to a urb */ - usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0); - - - /* recv transfer buffer */ - if (usbip_recv_xbuff(ud, urb) < 0) - return; - - - /* recv iso_packet_descriptor */ - if (usbip_recv_iso(ud, urb) < 0) - return; - - - if (dbg_flag_vhci_rx) - usbip_dump_urb(urb); - - - dbg_vhci_rx("now giveback urb %p\n", urb); - - - - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - - dbg_vhci_rx("Leave\n"); - - return; -} - - -static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, - struct usbip_header *pdu) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - uinfo("unlink->seqnum %lu\n", unlink->seqnum); - if (unlink->seqnum == pdu->base.seqnum) { - dbg_vhci_rx("found pending unlink, %lu\n", unlink->seqnum); - list_del(&unlink->list); - - spin_unlock(&vdev->priv_lock); - return unlink; - } - } - - spin_unlock(&vdev->priv_lock); - - return NULL; -} - - -static void vhci_recv_ret_unlink(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct vhci_unlink *unlink; - struct urb *urb; - - usbip_dump_header(pdu); - - unlink = dequeue_pending_unlink(vdev, pdu); - if (!unlink) { - uinfo("cannot find the pending unlink %u\n", pdu->base.seqnum); - return; - } - - urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); - if (!urb) { - /* - * I get the result of a unlink request. But, it seems that I - * already recieved the result of its submit result and gave - * back the URB. - */ - uinfo("the urb (seqnum %d) was already given backed\n", pdu->base.seqnum); - } else { - dbg_vhci_rx("now giveback urb %p\n", urb); - - /* If unlink is succeed, status is -ECONNRESET */ - urb->status = pdu->u.ret_unlink.status; - uinfo("%d\n", urb->status); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - kfree(unlink); - - return; -} - -/* recv a pdu */ -static void vhci_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - - dbg_vhci_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_vhci_rx) - usbip_dump_header(&pdu); - - switch(pdu.base.command) { - case USBIP_RET_SUBMIT: - vhci_recv_ret_submit(vdev, &pdu); - break; - - case USBIP_RET_UNLINK: - vhci_recv_ret_unlink(vdev, &pdu); - break; - default: - /* NOTREACHED */ - uerr("unknown pdu %u\n", pdu.base.command); - usbip_dump_header(&pdu); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - } -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - - while (1) { - if (signal_pending(current)) { - dbg_vhci_rx("signal catched!\n"); - break; - } - - - if (usbip_event_happend(ud)) break; - - vhci_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.16/vhci_sysfs.c trunk/drivers/2.6.16/vhci_sysfs.c --- usbip-0.1.4/drivers/2.6.16/vhci_sysfs.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/vhci_sysfs.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,286 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* TODO: refine locking ?*/ - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to show port status */ - -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *out) -{ - char *s = out; - int i = 0; - - if (!the_controller || !out) - BUG(); - - spin_lock(&the_controller->lock); - - /* - * output example: - * prt sta bus dev socket local_busid - * 000 004 000 000 c5a7bb80 1-2.3 - * 001 004 000 000 d8cee980 2-3.4 - * - * IP address can be retrieved from a socket pointer address by looking - * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a - * port number and its peer IP address. - */ - out += sprintf(out, "prt sta spd bus dev socket local_busid\n"); - - for (i=0; i < VHCI_NPORTS; i++) { - struct vhci_device *vdev = port_to_vdev(i); - - spin_lock(&vdev->ud.lock); - - out += sprintf(out, "%03u %03u ", i, vdev->ud.status); - - if (vdev->ud.status == VDEV_ST_USED) { - out += sprintf(out, "%03u %03u %03u ", - vdev->speed, vdev->busnum, vdev->devnum); - out += sprintf(out, "%16p ", vdev->ud.tcp_socket); - out += sprintf(out, "%s", vdev->udev->dev.bus_id); - - } else - out += sprintf(out, "000 000 000 0000000000000000 0-0"); - - out += sprintf(out, "\n"); - - spin_unlock(&vdev->ud.lock); - } - - spin_unlock(&the_controller->lock); - - return out - s ; -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to shutdown a virtual connection */ - -static int vhci_port_disconnect(__u32 rhport) -{ - struct vhci_device *vdev; - - dbg_vhci_sysfs("enter\n"); - - /* lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - if (vdev->ud.status == VDEV_ST_NULL) { - uerr("not connected %d\n", vdev->ud.status); - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - return -EINVAL; - } - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); - - return 0; -} - -static ssize_t store_detach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) { - int err; - __u32 rhport = 0; - - sscanf(buf, "%u", &rhport); - - /* check rhport */ - if (rhport >= VHCI_NPORTS) { - uerr("invalid port %u\n", rhport); - return -EINVAL; - } - - err = vhci_port_disconnect(rhport); - if (err < 0) { - return -EINVAL; - } - - dbg_vhci_sysfs("Leave\n"); - return count; -} - -static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to establish a virtual connection */ - -static int valid_args(__u32 rhport, __u32 busnum, __u32 devnum, - enum usb_device_speed speed) -{ - /* check rhport */ - if ((rhport < 0) || (rhport >= VHCI_NPORTS)) { - uerr("port %u\n", rhport); - return -EINVAL; - } - - /* check busnum & devnum */ - if ((busnum <= 0) || (busnum >= 128) || (devnum <= 0) || (devnum >= 128)) { - uerr("busnum %u devnum %u\n", busnum, devnum); - return -EINVAL; - } - - /* check speed */ - switch(speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - case USB_SPEED_HIGH: - case USB_SPEED_VARIABLE: - break; - - default: - uerr("speed %d\n", speed); - return -EINVAL; - } - - return 0; -} - -/* - * To start a new USB/IP attachment, a userland program needs to setup a TCP - * connection and then write its socket descriptor with remote device - * information into this sysfs file. - * - * A remote device is virtually attached to the root-hub port of @rhport with - * @speed. @busnum and @devnum are used to convert URBs between a client host - * and a server host. - * - * write() returns 0 on success, else negative errno. - */ -static ssize_t store_attach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vhci_device *vdev; - struct socket *socket; - int sockfd = 0; - __u32 rhport=0, busnum=0, devnum=0, speed=0; - - - /* - * @rhport: port number of vhci_hcd - * @sockfd: socket descriptor of an established TCP connection - * @busnum: usb bus number in a remote host - * @devnum: usb device number in a remote host - * @speed: usb device speed in a remote host - */ - sscanf(buf, "%u %u %u %u %u", &rhport, &sockfd, &busnum, &devnum, &speed); - - dbg_vhci_sysfs("rhport(%u) sockfd(%u) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - - /* check recieved parameters */ - if (valid_args(rhport, busnum, devnum, speed) < 0) - return -EINVAL; - - /* check sockfd */ - socket = sockfd_to_socket(sockfd); - if (!socket) - return -EINVAL; - - setnodelay(socket); - - - /* now need lock until setting vdev status as used */ - - /* begin a lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - - if (vdev->ud.status != VDEV_ST_NULL) { - /* end of the lock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - uerr("port %d already used\n", rhport); - return -EINVAL; - } - - uinfo("rhport(%u) sockfd(%d) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - vdev->busnum = busnum; - vdev->devnum = devnum; - vdev->speed = speed; - vdev->ud.tcp_socket = socket; - vdev->ud.status = VDEV_ST_NOTASSIGNED; - - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - /* end the lock */ - - /* - * this function will sleep, so should be out of the lock. but, it's ok - * because we already marked vdev as being used. really? - */ - usbip_start_threads(&vdev->ud); - - rh_port_connect(rhport, speed); - - return count; -} - -static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach); - - - -/*-------------------------------------------------------------------------*/ - -static struct attribute *dev_attrs[] = { - &dev_attr_status.attr, - &dev_attr_detach.attr, - &dev_attr_attach.attr, - &dev_attr_usbip_debug.attr, - NULL, -}; - -struct attribute_group dev_attr_group = { - .attrs = dev_attrs, -}; diff -Naur usbip-0.1.4/drivers/2.6.16/vhci_tx.c trunk/drivers/2.6.16/vhci_tx.c --- usbip-0.1.4/drivers/2.6.16/vhci_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.16/vhci_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,264 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* @p: pipe whose dev number modified - * @pdev: new devive number */ -static unsigned long tweak_pipe_devnum(__u32 p, __u8 pdev) -{ - __u32 oldp; - oldp = p; - - if (pdev > 0x7f) - uerr("invalid devnum %u\n", pdev); - - pdev &= 0x7f; // 0XXX XXXX confirm MSB be 0 - - p &= 0xffff80ff; /* clear p's devnum */ - - p |= (pdev << 8); - - dbg_vhci_tx("return new pipe, devnum %u -> %u \n", - usb_pipedevice(oldp), usb_pipedevice(p)); - dbg_vhci_tx(" pipe %08x -> %08x\n", oldp, p); - - return p; -} - -static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) -{ - struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv); - struct vhci_device *vdev = priv->vdev; - - dbg_vhci_tx("URB, local devnum(%u), busnum(%u) devnum(%u)\n", - usb_pipedevice(urb->pipe), vdev->busnum, vdev->devnum); - - pdup->base.command = USBIP_CMD_SUBMIT; - pdup->base.busnum = vdev->busnum; - pdup->base.devnum = vdev->devnum; - pdup->base.seqnum = priv->seqnum; - pdup->base.pipe = tweak_pipe_devnum(urb->pipe, vdev->devnum); - - usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1); - - if (urb->setup_packet) - memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8); -} - -static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_priv *priv, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { - list_move_tail(&priv->list, &vdev->priv_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - - - -static int vhci_send_cmd_submit(struct vhci_device *vdev) -{ - struct vhci_priv *priv = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(vdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_cmd_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->transfer_buffer_length; - txsize += urb->transfer_buffer_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&vdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - if (iso_buffer) - kfree(iso_buffer); - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_unlink *unlink, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_move_tail(&unlink->list, &vdev->unlink_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - -static int vhci_send_cmd_unlink(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup cmd unlink, %lu \n", unlink->seqnum); - - - /* 1. setup usbip_header */ - pdu_header.base.command = USBIP_CMD_UNLINK; - pdu_header.base.busnum = vdev->busnum; - pdu_header.base.devnum = vdev->devnum; - pdu_header.base.seqnum = unlink->seqnum; - pdu_header.base.pipe = 0; - pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum; - - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - while (1) { - if (signal_pending(current)) { - uinfo("vhci_tx signal catched\n"); - break; - } - - if (vhci_send_cmd_submit(vdev) < 0) - break; - - if (vhci_send_cmd_unlink(vdev) < 0) - break; - - wait_event_interruptible(vdev->waitq_tx, - (!list_empty(&vdev->priv_tx) || - !list_empty(&vdev->unlink_tx))); - - dbg_vhci_tx("pending urbs ?, now wake up\n"); - } -} diff -Naur usbip-0.1.4/drivers/2.6.17/Makefile trunk/drivers/2.6.17/Makefile --- usbip-0.1.4/drivers/2.6.17/Makefile 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,63 +0,0 @@ -# Makefile for the USB/IP driver -# -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ -# -# Copyright (C) 2003-2006 Takahiro Hirofuchi -# -# -# This 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 of the License, or -# (at your option) any later version. -# -# This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -# USA. -# - - -# Please modify here or set environments. -# KSOURCE should be pointed to the build directory of your kernel. -# -DEBUG ?= n -KSOURCE ?= /usr/src/linux - - -%.x:%.c - gcc -o $@ $< - -KBUILD_VERBOSE:=1 - -HCD_HEADER:=$(KSOURCE)/drivers/usb/core/hcd.h - -obj-m += usbip.o -usbip-objs := usbip_common.o usbip_event.o stub_dev.o stub_main.o stub_rx.o stub_tx.o - -obj-m += vhci-hcd.o -vhci-hcd-objs := usbip_common.o usbip_event.o vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o - - -EXTRA_CFLAGS += -DHCD_HEADER=\"$(HCD_HEADER)\" - -ifeq ($(DEBUG),y) - EXTRA_CFLAGS += -DCONFIG_USB_DEBUG -endif - - -default: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules - -.PHONY: cscope -cscope: - cscope -b -k -R - -.PHONY: clean -clean: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` clean - rm -f *.x *~ diff -Naur usbip-0.1.4/drivers/2.6.17/stub_dev.c trunk/drivers/2.6.17/stub_dev.c --- usbip-0.1.4/drivers/2.6.17/stub_dev.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/stub_dev.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,438 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - - -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void stub_disconnect(struct usb_interface *interface); - - -/* - * Define device IDs here if you want to explicitly limit exportable devices. - * In the most cases, wild card matching will be ok because driver binding can - * be changed dynamically by a userland program. - */ -static struct usb_device_id stub_table[] = { -#if 0 - /* just an example */ - { USB_DEVICE(0x05ac, 0x0301) }, /* Mac 1 button mouse */ - { USB_DEVICE(0x0430, 0x0009) }, /* Plat Home Keyboard */ - { USB_DEVICE(0x059b, 0x0001) }, /* Iomega USB Zip 100 */ - { USB_DEVICE(0x04b3, 0x4427) }, /* IBM USB CD-ROM */ - { USB_DEVICE(0x05a9, 0xa511) }, /* LifeView USB cam */ - { USB_DEVICE(0x55aa, 0x0201) }, /* Imation card reader */ - { USB_DEVICE(0x046d, 0x0870) }, /* Qcam Express(QV-30) */ - { USB_DEVICE(0x04bb, 0x0101) }, /* IO-DATA HD 120GB */ - { USB_DEVICE(0x04bb, 0x0904) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x04bb, 0x0201) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x08bb, 0x2702) }, /* ONKYO USB Speaker */ - { USB_DEVICE(0x046d, 0x08b2) }, /* Logicool Qcam 4000 Pro */ -#endif - /* magic for wild card */ - { .driver_info = 1 }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, stub_table); - - -struct usb_driver stub_driver = { - .name = "usbip", - - .probe = stub_probe, - .disconnect = stub_disconnect, - - .id_table = stub_table, -}; - - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for a usbip-bound device */ - - -/* - * usbip_status shows status of usbip as long as this driver is bound to the - * target device. - */ -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int status; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - spin_lock(&sdev->ud.lock); - status = sdev->ud.status; - spin_unlock(&sdev->ud.lock); - - return snprintf(buf, PAGE_SIZE, "%d\n", status); -} -static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL); - - -/* - * usbip_sockfd gets a socket descriptor of an established TCP connection that - * is used to transfer usbip requests by kernel threads. -1 is a magic number - * by which usbip connection is finished. - */ -static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int sockfd = 0; - struct socket *socket; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - sscanf(buf, "%d", &sockfd); - - if (sockfd != -1) { - uinfo("stub up\n"); - - spin_lock(&sdev->ud.lock); - - if (sdev->ud.status != SDEV_ST_AVAILABLE) { - uerr("not ready\n"); - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - socket = sockfd_to_socket(sockfd); - if (!socket) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - setnodelay(socket); - setkeepalive(socket); - setreuse(socket); - - sdev->ud.tcp_socket = socket; - - spin_unlock(&sdev->ud.lock); - - usbip_start_threads(&sdev->ud); - - spin_lock(&sdev->ud.lock); - sdev->ud.status = SDEV_ST_USED; - spin_unlock(&sdev->ud.lock); - - } else { - uinfo("stub down\n"); - - spin_lock(&sdev->ud.lock); - if (sdev->ud.status != SDEV_ST_USED) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - spin_unlock(&sdev->ud.lock); - - usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); - } - - return count; -} -static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); - -static void stub_add_files(struct device *dev) -{ - device_create_file(dev, &dev_attr_usbip_status); - device_create_file(dev, &dev_attr_usbip_sockfd); - device_create_file(dev, &dev_attr_usbip_debug); -} - -static void stub_remove_files(struct device *dev) -{ - device_remove_file(dev, &dev_attr_usbip_status); - device_remove_file(dev, &dev_attr_usbip_sockfd); - device_remove_file(dev, &dev_attr_usbip_debug); -} - - - -/*-------------------------------------------------------------------------*/ - -/* Event handler functions called by an event handler thread */ - -static void stub_shutdown_connection(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - /* - * When removing an exported device, kernel panic sometimes occurred - * and then EIP was sk_wait_data of stub_rx thread. Is this because - * sk_wait_data returned though stub_rx thread was already finished by - * step 1? - */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - /* 1. stop threads */ - usbip_stop_threads(ud); - - /* 2. close the socket */ - /* - * tcp_socket is freed after threads are killed. - * So usbip_xmit do not touch NULL socket. - */ - if (ud->tcp_socket) { - sock_release(ud->tcp_socket); - ud->tcp_socket = NULL; - } - - /* 3. free used data */ - stub_device_cleanup_urbs(sdev); - - /* 4. free stub_unlink */ - { - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - } -} - -static void stub_device_reset(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - struct usb_device *udev = interface_to_usbdev(sdev->interface); - int ret; - - ret = usb_lock_device_for_reset(udev, sdev->interface); - if (ret < 0) { - uerr("lock for reset\n"); - - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); - - return; - } - - /* try to reset the device */ - ret = usb_reset_device(udev); - - usb_unlock_device(udev); - - spin_lock(&ud->lock); - if (ret) { - uerr("device reset\n"); - ud->status = SDEV_ST_ERROR; - - } else { - uinfo("device reset\n"); - ud->status = SDEV_ST_AVAILABLE; - - } - spin_unlock(&ud->lock); - - return; -} - -static void stub_device_unusable(struct usbip_device *ud) -{ - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); -} - - -/*-------------------------------------------------------------------------*/ - -/** - * stub_device_alloc - allocate a new stub_device struct - * @interface: usb_interface of a new device - * - * Allocates and initializes a new stub_devce struct. - */ -static struct stub_device * stub_device_alloc(struct usb_interface *interface) -{ - struct stub_device *sdev; - - /* yes, it's a new device */ - sdev = (struct stub_device *) kzalloc(sizeof(struct stub_device), GFP_KERNEL); - if (!sdev) { - uerr("no memory for stub_device\n"); - return NULL; - } - - sdev->interface = interface; - - usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop); - usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop); - - sdev->ud.side = USBIP_STUB; - sdev->ud.status = SDEV_ST_AVAILABLE; - sdev->ud.lock = SPIN_LOCK_UNLOCKED; - sdev->ud.tcp_socket = NULL; - - INIT_LIST_HEAD(&sdev->priv_init); - INIT_LIST_HEAD(&sdev->priv_tx); - INIT_LIST_HEAD(&sdev->priv_free); - INIT_LIST_HEAD(&sdev->unlink_free); - INIT_LIST_HEAD(&sdev->unlink_tx); - sdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&sdev->tx_waitq); - - sdev->ud.eh_ops.shutdown = stub_shutdown_connection; - sdev->ud.eh_ops.reset = stub_device_reset; - sdev->ud.eh_ops.unusable = stub_device_unusable; - - usbip_start_eh(&sdev->ud); - - udbg("register new interface\n"); - return sdev; -} - -static int stub_device_free(struct stub_device *sdev) -{ - if (!sdev) - return -EINVAL; - - kfree(sdev); - udbg("kfree udev ok\n"); - - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* - * If a usb device has multiple active interfaces, this driver is bound to all - * the active interfaces. However, usbip exports *a* usb device (i.e. not *an* - * active interface). Currently, a userland program must ensure that it - * looks at the usbip's sysfs entries of only the first active interface. - */ -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct stub_device *sdev = NULL; - char *udev_busid = interface->dev.parent->bus_id; - - udbg("Enter\n"); - - /* check we should claim or not by busid_table */ - if (match_busid(udev_busid)) { - uinfo("this device %s is not in match_busid table. skip!\n", udev_busid); - - /* - * Return value should be ENODEV or ENOXIO to continue trying - * other matched drivers by the driver core. - * See driver_probe_device() in driver/base/dd.c - */ - return -ENODEV; - } - - if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { - udbg("this device %s is a usb hub device. skip!\n", udev_busid); - return -ENODEV; - } - - if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { - udbg("this device %s is attached on vhci_hcd. skip!\n", udev_busid); - return -ENODEV; - } - - /* ok. this is my device. */ - - if ((sdev = stub_device_alloc(interface))) { - struct usb_device *udev = interface_to_usbdev(interface); - - uinfo("USB/IP Stub: register a new interface (bus %u dev %u ifn %u)\n", - udev->bus->busnum, udev->devnum, - interface->cur_altsetting->desc.bInterfaceNumber); - } else - return -ENOMEM; - - /* set private data to usb_interface */ - usb_set_intfdata(interface, sdev); - - stub_add_files(&interface->dev); - - return 0; -} - - -/* - * called in usb_disconnect() or usb_deregister() - * but only if actconfig(active configuration) exists - */ -static void stub_disconnect(struct usb_interface *interface) -{ - struct stub_device *sdev = usb_get_intfdata(interface); - - udbg("Enter\n"); - - /* get stub_device */ - if (!sdev) - BUG(); - - usb_set_intfdata(interface, NULL); - - - /* - * NOTE: - * rx/tx threads are invoked for each usb_device. - */ - stub_remove_files(&interface->dev); - - /* 1. shutdown the current connection */ - usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED); - - /* 2. wait for the stop of the event handler */ - usbip_stop_eh(&sdev->ud); - - /* 3. free sdev */ - stub_device_free(sdev); - - - udbg("bye\n"); -} diff -Naur usbip-0.1.4/drivers/2.6.17/stub.h trunk/drivers/2.6.17/stub.h --- usbip-0.1.4/drivers/2.6.17/stub.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/stub.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,96 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include -#include - -struct stub_device { - struct usb_interface *interface; - struct list_head list; - - struct usbip_device ud; - - /* - * stub_priv preserves private data of each urb. - * It is allocated as stub_priv_cache and assigned to urb->context. - * - * stub_priv is always linked to any one of 3 lists; - * priv_init: linked to this until the comletion of a urb. - * priv_tx : linked to this after the completion of a urb. - * priv_free: linked to this after the sending of the result. - * - * Any of these list operations should be locked by priv_lock. - */ - spinlock_t priv_lock; - struct list_head priv_init; - struct list_head priv_tx; - struct list_head priv_free; - - /* see comments for unlinking in stub_rx.c */ - struct list_head unlink_tx; - struct list_head unlink_free; - - - wait_queue_head_t tx_waitq; -}; - -/* private data into urb->priv */ -struct stub_priv { - unsigned long seqnum; - struct list_head list; - struct stub_device *sdev; - struct urb *urb; - - int unlinking; -}; - -struct stub_unlink { - unsigned long seqnum; - struct list_head list; - __u32 status; -}; - - -extern kmem_cache_t *stub_priv_cache; - - -/*-------------------------------------------------------------------------*/ -/* prototype declarations */ - -/* stub_tx.c */ -void stub_complete(struct urb*, struct pt_regs *); -void stub_tx_loop(struct usbip_task *); - -/* stub_dev.c */ -extern struct usb_driver stub_driver; - -/* stub_rx.c */ -void stub_rx_loop(struct usbip_task *); -void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32); - -/* stub_main.c */ -int match_busid(char *busid); -void stub_device_cleanup_urbs(struct stub_device *sdev); diff -Naur usbip-0.1.4/drivers/2.6.17/stub_main.c trunk/drivers/2.6.17/stub_main.c --- usbip-0.1.4/drivers/2.6.17/stub_main.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/stub_main.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,300 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "stub.h" - -/* Version Information */ -#define DRIVER_VERSION "$Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $" -#define DRIVER_AUTHOR "Takahiro Hirofuchi " -#define DRIVER_DESC "Stub Driver for USB/IP" - - - -/* stub_priv is allocated from stub_priv_cache */ -kmem_cache_t *stub_priv_cache = NULL; - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for the usbip driver */ - - -/* - * busid_tables defines matching busids that usbip can grab. A user can change - * dynamically what device is locally used and what device is exported to a - * remote host. - */ -#define MAX_BUSID 16 -static char busid_table[MAX_BUSID][BUS_ID_SIZE]; -spinlock_t busid_table_lock = SPIN_LOCK_UNLOCKED; - - -int match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* already registerd */ - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return 1; -} - -static ssize_t show_match_busid(struct device_driver *drv, char *buf) -{ - int i; - char *out = buf; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - out += sprintf(out, "%s ", busid_table[i]); - - spin_unlock(&busid_table_lock); - - out += sprintf(out, "\n"); - - return out - buf; -} - -static int add_match_busid(char *busid) -{ - int i; - - if (!match_busid(busid)) - return 0; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!busid_table[i][0]) { - strncpy(busid_table[i], busid, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static int del_match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* found */ - memset(busid_table[i], 0, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static ssize_t store_match_busid(struct device_driver *dev, const char *buf, - size_t count) -{ - int len; - char busid[BUS_ID_SIZE]; - - if (count < 5) - return -EINVAL; - - /* strnlen() does not include \0 */ - len = strnlen(buf + 4, BUS_ID_SIZE); - - /* busid needs to include \0 termination */ - if (!(len < BUS_ID_SIZE)) - return -EINVAL; - - strncpy(busid, buf + 4, BUS_ID_SIZE); - - - if (!strncmp(buf, "add ", 4)) { - if (add_match_busid(busid) < 0) - return -ENOMEM; - else { - udbg("add busid %s\n", busid); - return count; - } - } else if (!strncmp(buf, "del ", 4)) { - if (del_match_busid(busid) < 0) - return -ENODEV; - else { - udbg("del busid %s\n", busid); - return count; - } - } else - return -EINVAL; -} - -static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid, store_match_busid); - - - -/*-------------------------------------------------------------------------*/ - -/* Cleanup functions used to free private data */ - -static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) -{ - struct stub_priv *priv, *tmp; - - list_for_each_entry_safe(priv, tmp, listhead, list) { - list_del(&priv->list); - return priv; - } - - return NULL; -} - -static struct stub_priv *stub_priv_pop(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = stub_priv_pop_from_listhead(&sdev->priv_init); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_tx); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_free); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return NULL; -} - -void stub_device_cleanup_urbs(struct stub_device *sdev) -{ - struct stub_priv *priv; - - udbg("free sdev %p\n", sdev); - - while ((priv = stub_priv_pop(sdev))) { - struct urb *urb = priv->urb; - - udbg(" free urb %p\n", urb); - usb_kill_urb(urb); - - kmem_cache_free(stub_priv_cache, priv); - - if (urb->transfer_buffer != NULL) - kfree(urb->transfer_buffer); - - if (urb->setup_packet != NULL) - kfree(urb->setup_packet); - - usb_free_urb(urb); - } -} - - -/*-------------------------------------------------------------------------*/ - -static int __init usb_stub_init(void) -{ - int ret; - - stub_priv_cache = kmem_cache_create("stub_priv", sizeof(struct stub_priv), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!stub_priv_cache) { - uerr("create stub_priv_cache\n"); - return -ENOMEM; - } - - ret = usb_register(&stub_driver); - if (ret) { - uerr("usb_register failed %d\n", ret); - return ret; - } - - - info(DRIVER_DESC "" DRIVER_VERSION); - - memset(busid_table, 0, sizeof(busid_table)); - - driver_create_file(&stub_driver.driver, &driver_attr_match_busid); - - return ret; -} - -static void __exit usb_stub_exit(void) -{ - int ret; - - udbg("enter\n"); - - driver_remove_file(&stub_driver.driver, &driver_attr_match_busid); - - /* - * deregister() calls stub_disconnect() for all devices. Device - * specific data is cleared in stub_disconnect(). - */ - usb_deregister(&stub_driver); - - ret = kmem_cache_destroy(stub_priv_cache); - if (ret != 0) { - uerr("memory leak of stub_priv, %d\n", ret); - } - - udbg("bye\n"); -} - - - - -module_init (usb_stub_init); -module_exit (usb_stub_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff -Naur usbip-0.1.4/drivers/2.6.17/stub_rx.c trunk/drivers/2.6.17/stub_rx.c --- usbip-0.1.4/drivers/2.6.17/stub_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/stub_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,442 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static int is_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_CLEAR_FEATURE) && - (req->bRequestType == USB_RECIP_ENDPOINT) && - (req->wValue == USB_ENDPOINT_HALT); -} - -static int is_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_INTERFACE) && - (req->bRequestType == USB_RECIP_INTERFACE); -} - -static int is_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_CONFIGURATION) && - (req->bRequestType == USB_RECIP_DEVICE); -} - -static int tweak_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - int target_endp; - int target_dir; - int target_pipe; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - /* - * The stalled endpoint is specified in the wIndex value. The endpoint - * of the urb is the target of this clear_halt request (i.e. control - * endpoint). - */ - target_endp = le16_to_cpu(req->wIndex) & 0x000f; - - /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80. */ - target_dir = le16_to_cpu(req->wIndex) & 0x0080; - - if (target_dir) - target_pipe = usb_rcvctrlpipe(urb->dev, target_endp); - else - target_pipe = usb_sndctrlpipe(urb->dev, target_endp); - - ret = usb_clear_halt(urb->dev, target_pipe); - if (ret < 0) - uinfo("clear_halt error: devnum %d endp %d, %d\n", - urb->dev->devnum, target_endp, ret); - else - uinfo("clear_halt done: devnum %d endp %d\n", - urb->dev->devnum, target_endp); - - return ret; -} - -static int tweak_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 alternate; - __u16 interface; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - alternate = le16_to_cpu(req->wValue); - interface = le16_to_cpu(req->wIndex); - - dbg_stub_rx("set_interface: inf %u alt %u\n", interface, alternate); - - ret = usb_set_interface(urb->dev, interface, alternate); - if (ret < 0) - uinfo("set_interface error: inf %u alt %u, %d\n", - interface, alternate, ret); - else - uinfo("set_interface done: inf %u alt %u\n", interface, alternate); - - return ret; -} - -static int tweak_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 config; - - info("set_configuration is not fully supported yet\n"); - - req = (struct usb_ctrlrequest *) urb->setup_packet; - config = le16_to_cpu(req->wValue); - - uinfo("set_configuration: devnum %d %d\n", urb->dev->devnum, config); - -#if 0 - return usb_set_configuration(urb->dev, config); -#endif - return 0; -} - -/* - * clear_halt, set_interface, and set_configuration require special tricks. - * TODO: set_configuration. but I have never seen a multi-config device. - */ -static void tweak_special_requests(struct urb *urb) -{ - if (!urb || !urb->setup_packet) - return; - - if (usb_pipetype(urb->pipe) != PIPE_CONTROL) - return; - - if (is_clear_halt_cmd(urb)) - /* treak clear_halt */ - tweak_clear_halt_cmd(urb); - - else if (is_set_interface_cmd(urb)) - /* tweak set_interface */ - tweak_set_interface_cmd(urb); - - else if (is_set_configuration_cmd(urb)) - /* tweak set_configuration */ - tweak_set_configuration_cmd(urb); - - else - dbg_stub_rx("no need to tweak\n"); -} - -/* - * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb(). - * By unlinking the urb asynchronously, stub_rx can continuously - * process coming urbs. Even if the urb is unlinked, its completion - * handler will be called and stub_tx will send a return pdu. - * - * See also comments about unlinking strategy in vhci_hcd.c. - */ -static int stub_recv_cmd_unlink(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct list_head *listhead = &sdev->priv_init; - struct list_head *ptr; - unsigned long flags; - - struct stub_priv *priv; - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - for (ptr = listhead->next; ptr != listhead; ptr = ptr->next) { - priv = list_entry(ptr, struct stub_priv, list); - if (priv->seqnum == pdu->u.cmd_unlink.seqnum) { - int ret; - - uinfo("unlink urb %p\n", priv->urb); - - /* - * This matched urb is not completed yet (i.e. be in - * flight in usb hcd hardware/driver). Now we are - * cancelling it. The unlinking flag means that we are - * now not going to return the normal result pdu of a - * submittion request, but going to return a result pdu - * of the unlink request. - */ - priv->unlinking = 1; - - /* - * In the case that unlinking flag is on, prev->seqnum - * is changed from the seqnum of the cancelling urb to - * the seqnum of the unlink request. This will be used - * to make the result pdu of the unlink request. - */ - priv->seqnum = pdu->base.seqnum; - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* - * usb_unlink_urb() is now out of spinlocking to avoid - * spinlock recursion since stub_complete() is - * sometimes called in this context but not in the - * interrupt context. If stub_complete() is executed - * before we call usb_unlink_urb(), usb_unlink_urb() - * will return an error value. In this case, stub_tx - * will return the result pdu of this unlink request - * though submission is completed and actual unlinking - * is not executed. OK? - */ - ret = usb_unlink_urb(priv->urb); - if (ret != -EINPROGRESS) - uerr("faild to unlink a urb %p, ret %d\n", priv->urb, ret); - - return 0; - } - } - - dbg_stub_rx("seqnum %d is not pending\n", pdu->u.cmd_unlink.seqnum); - - /* - * The urb of the unlink target is not found in priv_init queue. It was - * already completed and its results is/was going to be sent by a - * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only - * return the completeness of this unlink request to vhci_hcd. - */ - stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - - return 0; -} - -static int valid_request(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &sdev->ud; - - int bus = interface_to_busnum(sdev->interface); - int dev = interface_to_devnum(sdev->interface); - - if (pdu->base.busnum == bus && pdu->base.devnum == dev) { - spin_lock(&ud->lock); - if (ud->status == SDEV_ST_USED) { - /* A request is valid. */ - spin_unlock(&ud->lock); - return 1; - } - spin_unlock(&ud->lock); - } - - return 0; -} - -static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, - struct usbip_header *pdu) -{ - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - unsigned long flags; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC); - if (!priv) { - uerr("alloc stub_priv\n"); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return NULL; - } - - memset(priv, 0, sizeof(struct stub_priv)); - - priv->seqnum = pdu->base.seqnum; - priv->sdev = sdev; - - /* - * After a stub_priv is linked to a list_head, - * our error handler can free allocated data. - */ - list_add_tail(&priv->list, &sdev->priv_init); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return priv; -} - -static void stub_recv_cmd_submit(struct stub_device *sdev, struct usbip_header *pdu) -{ - int ret; - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - - - priv = stub_priv_alloc(sdev, pdu); - if (!priv) - return; - - /* setup a urb */ - if (usb_pipeisoc(pdu->base.pipe)) - priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, GFP_KERNEL); - else - priv->urb = usb_alloc_urb(0, GFP_KERNEL); - - if (!priv->urb) { - uerr("malloc urb\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - - /* set priv->urb->transfer_buffer */ - if (pdu->u.cmd_submit.transfer_buffer_length > 0) { - priv->urb->transfer_buffer = - kzalloc(pdu->u.cmd_submit.transfer_buffer_length, GFP_KERNEL); - if (!priv->urb->transfer_buffer) { - uerr("malloc x_buff\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - } - - /* set priv->urb->setup_packet */ - priv->urb->setup_packet = kzalloc(8, GFP_KERNEL); - if (!priv->urb->setup_packet) { - uerr("allocate setup_packet\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - memcpy(priv->urb->setup_packet, &pdu->u.cmd_submit.setup, 8); - - /* set other members from the base header of pdu */ - priv->urb->context = (void *) priv; - priv->urb->dev = interface_to_usbdev(sdev->interface); - priv->urb->pipe = pdu->base.pipe; - priv->urb->complete = stub_complete; - - usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); - - - if (usbip_recv_xbuff(ud, priv->urb) < 0) - return; - - if (usbip_recv_iso(ud, priv->urb) < 0) - return; - - tweak_special_requests(priv->urb); - - /* urb is now ready to submit */ - ret = usb_submit_urb(priv->urb, GFP_KERNEL); - - if (ret == 0) - dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum); - else { - uerr("submit_urb error, %d\n", ret); - - /* - * Pessimistic. - * This connection will be discared. - */ - usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); - } - - dbg_stub_rx("Leave\n"); - return; -} - -/* recv a pdu */ -static void stub_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - - dbg_stub_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_stub_rx) - usbip_dump_header(&pdu); - - if (!valid_request(sdev, &pdu)) { - uerr("recv invalid request\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - switch (pdu.base.command) { - case USBIP_CMD_UNLINK: - stub_recv_cmd_unlink(sdev, &pdu); - break; - - case USBIP_CMD_SUBMIT: - stub_recv_cmd_submit(sdev, &pdu); - break; - - default: - /* NOTREACHED */ - uerr("unknown pdu\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - -} - -void stub_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - while (1) { - if (signal_pending(current)) { - dbg_stub_rx("signal catched!\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - stub_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.17/stub_tx.c trunk/drivers/2.6.17/stub_tx.c --- usbip-0.1.4/drivers/2.6.17/stub_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/stub_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,374 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static void stub_free_priv_and_urb(struct stub_priv *priv) -{ - struct urb *urb = priv->urb; - - if (urb->setup_packet) - kfree(urb->setup_packet); - - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); - - list_del(&priv->list); - kmem_cache_free(stub_priv_cache, priv); - - usb_free_urb(urb); -} - -/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ -void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, __u32 status) -{ - struct stub_unlink *unlink; - - unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("alloc stub_unlink\n"); - usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - unlink->seqnum = seqnum; - unlink->status = status; - - list_add_tail(&unlink->list, &sdev->unlink_tx); -} - -/** - * stub_complete - completion handler of a usbip urb - * @urb: pointer to the urb completed - * @regs: - * - * When a urb has completed, the USB core driver calls this function mostly in - * the interrupt context. To return the result of a urb, the completed urb is - * linked to the pending list of returning. - * - */ -void stub_complete(struct urb *urb, struct pt_regs *regs) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - struct stub_device *sdev = priv->sdev; - unsigned long flags; - - dbg_stub_tx("complete! status %d\n", urb->status); - - - switch (urb->status) { - case 0: - /* OK */ - break; - case -ENOENT: - uinfo("stopped by a call of usb_kill_urb()" - "because of cleaning up a virtual connection\n"); - return; - case -ECONNRESET: - uinfo("unlinked by a call of usb_unlink_urb()\n"); - break; - case -EPIPE: - uinfo("endpoint %d is stalled\n", usb_pipeendpoint(urb->pipe)); - break; - case -ESHUTDOWN: - uinfo("device removed?\n"); - break; - default: - uinfo("urb completion with non-zero status %d\n", urb->status); - } - - /* link a urb to the queue of tx. */ - spin_lock_irqsave(&sdev->priv_lock, flags); - - if (priv->unlinking) { - stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status); - stub_free_priv_and_urb(priv); - } else - list_move_tail(&priv->list, &sdev->priv_tx); - - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* wake up tx_thread */ - wake_up(&sdev->tx_waitq); -} - - -/*-------------------------------------------------------------------------*/ -/* fill PDU */ - -static inline void setup_base_pdu(struct usbip_header_basic *base, - __u32 command, __u32 seqnum) -{ - base->command = command; - base->busnum = 0; - base->devnum = 0; - base->seqnum = seqnum; - base->pipe = 0; -} - -static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - - setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum); - - usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1); -} - -static void setup_ret_unlink_pdu(struct usbip_header *rpdu, - struct stub_unlink *unlink) -{ - setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum); - - rpdu->u.ret_unlink.status = unlink->status; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_SUBMIT */ - -static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) { - list_move_tail(&priv->list, &sdev->priv_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - -static int stub_send_ret_submit(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_ret_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (usb_pipein(urb->pipe) && urb->actual_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->actual_length; - txsize += urb->actual_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - if (iso_buffer) - kfree(iso_buffer); - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { - stub_free_priv_and_urb(priv); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_UNLINK */ - -static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_move_tail(&unlink->list, &sdev->unlink_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - - -static int stub_send_ret_unlink(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - struct msghdr msg; - struct kvec iov[1]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum); - - /* 1. setup usbip_header */ - setup_ret_unlink_pdu(&pdu_header, unlink); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void stub_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - while (1) { - if (signal_pending(current)) { - dbg_stub_tx("signal catched\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - /* - * send_ret_submit comes earlier than send_ret_unlink. stub_rx - * looks at only priv_init queue. If the completion of a URB is - * earlier than the recieve of CMD_UNLINK, priv is moved to - * priv_tx queue and stub_rx does not find the target priv. In - * this case, vhci_rx recieves the result of the submit request - * and then recieves the result of the unlink request. The - * result of the submit is given back to the usbcore as the - * completion of the unlink request. The request of the - * unlink is ignored. This is ok because a driver who calls - * usb_unlink_urb() understands the unlink was too late by - * getting the status of the given-backed URB which has the - * status of usb_submit_urb(). - */ - if (stub_send_ret_submit(sdev) < 0) - break; - - if (stub_send_ret_unlink(sdev) < 0) - break; - - wait_event_interruptible(sdev->tx_waitq, - (!list_empty(&sdev->priv_tx) || - !list_empty(&sdev->unlink_tx))); - } -} diff -Naur usbip-0.1.4/drivers/2.6.17/usbip_common.c trunk/drivers/2.6.17/usbip_common.c --- usbip-0.1.4/drivers/2.6.17/usbip_common.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/usbip_common.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,935 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include "usbip_common.h" - - -/*-------------------------------------------------------------------------*/ -/* debug routines */ - -#ifdef CONFIG_USB_DEBUG -unsigned long usbip_debug_flag = 0xffffffff; -#else -unsigned long usbip_debug_flag = 0; -#endif - -static ssize_t show_flag(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lx\n", usbip_debug_flag); -} - -static ssize_t store_flag(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long flag; - - sscanf(buf, "%lx", &flag); - usbip_debug_flag = flag; - - return count; -} -DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag); - -static void usbip_dump_buffer(char *buff, int bufflen) -{ - int i; - - if (bufflen > 128) { - for (i = 0; i< 128; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) printk("| "); - if (i%24 == 23) printk("\n"); - } - printk("... (%d byte)\n", bufflen); - return; - } - - for (i = 0; i< bufflen; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) - printk("| "); - if (i%24 == 23) - printk("\n"); - } - printk("\n"); - -} - -static void usbip_dump_pipe(unsigned int p) -{ - unsigned char type = usb_pipetype(p); - unsigned char ep = usb_pipeendpoint(p); - unsigned char dev = usb_pipedevice(p); - unsigned char dir = usb_pipein(p); - - printk("dev(%d) ", dev); - printk("ep(%d) ", ep); - printk("%s ", dir ? "IN" : "OUT"); - - switch(type) { - case PIPE_ISOCHRONOUS : - printk("%s ", "ISO"); - break; - case PIPE_INTERRUPT : - printk("%s ", "INT"); - break; - case PIPE_CONTROL : - printk("%s ", "CTL"); - break; - case PIPE_BULK : - printk("%s ", "BLK"); - break; - default : - printk("ERR"); - } - - printk("\n"); - -} - -static void usbip_dump_usb_device(struct usb_device *dev) -{ - int i; - - if (!dev) { - printk(" dump usb dev: null pointer!!\n"); - return; - } - - printk(" devnum(%d) devpath(%s)", dev->devnum, dev->devpath); - - switch(dev->speed) { - case USB_SPEED_HIGH : - printk(" SPD_HIGH"); - break; - case USB_SPEED_FULL : - printk(" SPD_FULL"); - break; - case USB_SPEED_LOW : - printk(" SPD_LOW"); - break; - case USB_SPEED_UNKNOWN : - printk(" SPD_UNKNOWN"); - break; - default : - printk(" SPD_ERROR"); - } - - printk(" tt %p, ttport %d", dev->tt, dev->ttport); - printk("\n"); - - printk(" "); - for (i = 0; i < 16; i++) { - printk(" %2u", i); - } - - printk("\n"); - - printk(" toggle0(IN) :"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[0] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - printk(" toggle1(OUT):"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[1] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - - printk(" epmaxp_in :"); - for (i = 0; i < 16; i++) { - if (dev->ep_in[i]) - printk(" %2u", dev->ep_in[i]->desc.wMaxPacketSize); - } - - printk("\n"); - - printk(" epmaxp_out :"); - for (i = 0; i < 16; i++) { - if (dev->ep_out[i]) - printk(" %2u", dev->ep_out[i]->desc.wMaxPacketSize); - } - - printk("\n "); - - printk("parent %p, bus %p", dev->parent, dev->bus); - printk("\n "); - - printk("descriptor %p, config %p, actconfig %p, rawdescriptors %p", - &dev->descriptor, dev->config, dev->actconfig, dev->rawdescriptors); - printk("\n "); - - printk("have_langid %d, string_langid %d", dev->have_langid, dev->string_langid); - printk("\n "); - - printk("maxchild %d, children %p", dev->maxchild, dev->children); - - printk("\n"); -} - -static void usbip_dump_request_type(__u8 rt) -{ - switch(rt & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: - printk("DEVICE"); - break; - case USB_RECIP_INTERFACE: - printk("INTERF"); - break; - case USB_RECIP_ENDPOINT: - printk("ENDPOI"); - break; - case USB_RECIP_OTHER: - printk("OTHER "); - break; - default: - printk("------"); - } -} - -static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd) -{ - if (!cmd) { - printk(" %s : null pointer\n", __FUNCTION__); - return; - } - - printk(" "); - printk("bRequestType(%02X) ", cmd->bRequestType); - printk("bRequest(%02X) " , cmd->bRequest); - printk("wValue(%04X) ", cmd->wValue); - printk("wIndex(%04X) ", cmd->wIndex); - printk("wLength(%04X) ", cmd->wLength); - - printk("\n "); - - if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - printk("STANDARD "); - switch(cmd->bRequest) { - case USB_REQ_GET_STATUS: - printk("GET_STATUS"); - break; - case USB_REQ_CLEAR_FEATURE: - printk("CLEAR_FEAT"); - break; - case USB_REQ_SET_FEATURE: - printk("SET_FEAT "); - break; - case USB_REQ_SET_ADDRESS: - printk("SET_ADDRRS"); - break; - case USB_REQ_GET_DESCRIPTOR: - printk("GET_DESCRI"); - break; - case USB_REQ_SET_DESCRIPTOR: - printk("SET_DESCRI"); - break; - case USB_REQ_GET_CONFIGURATION: - printk("GET_CONFIG"); - break; - case USB_REQ_SET_CONFIGURATION: - printk("SET_CONFIG"); - break; - case USB_REQ_GET_INTERFACE: - printk("GET_INTERF"); - break; - case USB_REQ_SET_INTERFACE: - printk("SET_INTERF"); - break; - case USB_REQ_SYNCH_FRAME: - printk("SYNC_FRAME"); - break; - default: - printk("REQ(%02X) ", cmd->bRequest); - } - - printk(" "); - usbip_dump_request_type(cmd->bRequestType); - - } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) - printk("CLASS "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) - printk("VENDOR "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) - printk("RESERVED"); - - printk("\n"); -} - -void usbip_dump_urb (struct urb *purb) -{ - if (!purb) { - printk(" dump urb: null pointer!!\n"); - return; - } - - printk(" urb :%p\n", purb); - printk(" dev :%p\n", purb->dev); - - usbip_dump_usb_device(purb->dev); - - printk(" pipe :%08x ", purb->pipe); - - usbip_dump_pipe(purb->pipe); - - printk(" status :%d\n", purb->status); - printk(" transfer_flags :%08X\n", purb->transfer_flags); - printk(" transfer_buffer :%p\n", purb->transfer_buffer); - printk(" transfer_buffer_length:%d\n", purb->transfer_buffer_length); - printk(" actual_length :%d\n", purb->actual_length); - printk(" bandwidth :%d\n", purb->actual_length); - printk(" setup_packet :%p\n", purb->setup_packet); - - if (purb->setup_packet && usb_pipetype(purb->pipe) == PIPE_CONTROL) - usbip_dump_usb_ctrlrequest((struct usb_ctrlrequest *) purb->setup_packet); - - printk(" start_frame :%d\n", purb->start_frame); - printk(" number_of_packets :%d\n", purb->number_of_packets); - printk(" interval :%d\n", purb->interval); - printk(" error_count :%d\n", purb->error_count); - printk(" context :%p\n", purb->context); - printk(" complete :%p\n", purb->complete); -} - -void usbip_dump_header(struct usbip_header *pdu) -{ - udbg("BASE: cmd %u bus %u dev %u seq %u pipe %04x\n", - pdu->base.command, - pdu->base.busnum, - pdu->base.devnum, - pdu->base.seqnum, - pdu->base.pipe); - - usbip_dump_pipe(pdu->base.pipe); - - switch(pdu->base.command) { - case USBIP_CMD_SUBMIT: - udbg("CMD_SUBMIT: x_flags %u x_len %u bw %u sf %u #p %u iv %u\n", - pdu->u.cmd_submit.transfer_flags, - pdu->u.cmd_submit.transfer_buffer_length, - pdu->u.cmd_submit.bandwidth, - pdu->u.cmd_submit.start_frame, - pdu->u.cmd_submit.number_of_packets, - pdu->u.cmd_submit.interval); - break; - case USBIP_CMD_UNLINK: - udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum); - break; - case USBIP_RET_SUBMIT: - udbg("RET_SUBMIT: st %d al %u bw %u sf %d ec %d\n", - pdu->u.ret_submit.status, - pdu->u.ret_submit.actual_length, - pdu->u.ret_submit.bandwidth, - pdu->u.ret_submit.start_frame, - pdu->u.ret_submit.error_count); - case USBIP_RET_UNLINK: - udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status); - break; - default: - /* NOT REACHED */ - udbg("UNKNOWN\n"); - } -} - - -/*-------------------------------------------------------------------------*/ -/* thread routines */ - -int usbip_thread(void *param) -{ - struct usbip_task *ut = (struct usbip_task *) param; - - if (!ut) - return -EINVAL; - - lock_kernel(); - daemonize(ut->name); - allow_signal(SIGKILL); - ut->thread = current; - unlock_kernel(); - - /* srv.rb must wait for rx_thread starting */ - complete(&ut->thread_done); - - /* start of while loop */ - ut->loop_ops(ut); - - /* end of loop */ - ut->thread = NULL; - - complete_and_exit(&ut->thread_done, 0); -} - -void usbip_start_threads(struct usbip_device *ud) -{ - /* - * threads are invoked per one device (per one connection). - */ - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_rx, 0); - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_tx, 0); - - /* confirm threads are starting */ - wait_for_completion(&ud->tcp_rx.thread_done); - wait_for_completion(&ud->tcp_tx.thread_done); -} - -void usbip_stop_threads(struct usbip_device *ud) -{ - /* kill threads related to this sdev, if v.c. exists */ - if (ud->tcp_rx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_rx.thread, 1); - wait_for_completion(&ud->tcp_rx.thread_done); - udbg("rx_thread for ud %p has finished\n", ud); - } - - if (ud->tcp_tx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_tx.thread, 1); - wait_for_completion(&ud->tcp_tx.thread_done); - udbg("tx_thread for ud %p has finished\n", ud); - } -} - -void usbip_task_init(struct usbip_task *ut, char *name, - void (*loop_ops)(struct usbip_task *)) -{ - ut->thread = NULL; - init_completion(&ut->thread_done); - ut->name = name; - ut->loop_ops = loop_ops; -} - - -/*-------------------------------------------------------------------------*/ -/* socket routines */ - - /* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */ -int usbip_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags) -{ - int result; - struct msghdr msg; - struct kvec iov; - int total = 0; - - /* for blocks of if (dbg_flag_xmit) */ - char *bp = buf; - int osize= size; - - dbg_xmit("enter\n"); - - if (!sock || !buf || !size) { - uerr("usbip_xmit: invalid arg, sock %p buff %p size %d\n", - sock, buf, size); - return -EINVAL; - } - - - if (dbg_flag_xmit) { - if (send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: sending... , sock %p, buf %p, size %d, msg_flags %d\n", - sock, buf, size, msg_flags); - usbip_dump_buffer(buf, size); - } - } - - - do { - sock->sk->sk_allocation = GFP_NOIO; - iov.iov_base = buf; - iov.iov_len = size; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_namelen = 0; - msg.msg_flags = msg_flags | MSG_NOSIGNAL; - - if (send) - result = kernel_sendmsg(sock, &msg, &iov, 1, size); - else - result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); - - if (result <= 0) { - udbg("usbip_xmit: %s sock %p buf %p size %u ret %d total %d\n", - send ? "send" : "receive", sock, buf, size, result, total); - goto err; - } - - size -= result; - buf += result; - total += result; - - } while (size > 0); - - - if (dbg_flag_xmit) { - if (!send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: receiving....\n"); - usbip_dump_buffer(bp, osize); - printk("usbip_xmit: received, osize %d ret %d size %d total %d\n", - osize, result, size, total); - } - - if (send) { - printk("usbip_xmit: send, total %d\n", total); - } - } - - return total; - -err: - return result; -} - -int setquickack(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setnodelay(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setkeepalive(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -void setreuse(struct socket *socket) -{ - socket->sk->sk_reuse = 1; -} - -struct socket *sockfd_to_socket(unsigned int sockfd) -{ - struct socket *socket; - struct file *file; - struct inode *inode; - - file = fget(sockfd); - if (!file) { - uerr("invalid sockfd\n"); - return NULL; - } - - inode = file->f_dentry->d_inode; - - if (!inode || !S_ISSOCK(inode->i_mode)) - return NULL; - - socket = SOCKET_I(inode); - - return socket; -} - - - -/*-------------------------------------------------------------------------*/ -/* pdu routines */ - -/* there may be more cases to tweak the flags. */ -static unsigned int tweak_transfer_flags(unsigned int flags) -{ - - if (flags & URB_NO_TRANSFER_DMA_MAP) - /* - * vhci_hcd does not provide DMA-mapped I/O. The upper - * driver does not need to set this flag. The remote - * usbip.ko does not still perform DMA-mapped I/O for - * DMA-caplable host controllers. So, clear this flag. - */ - flags &= ~URB_NO_TRANSFER_DMA_MAP; - - if (flags & URB_NO_SETUP_DMA_MAP) - flags &= ~URB_NO_SETUP_DMA_MAP; - - return flags; -} - -static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit; - - /* - * Some members are not still implemented in usbip. I hope this issue - * will be discussed when usbip is ported to other operating systems. - */ - if (pack) { - /* vhci_tx.c */ - spdu->transfer_flags = tweak_transfer_flags(urb->transfer_flags); - - spdu->transfer_buffer_length = urb->transfer_buffer_length; - spdu->bandwidth = urb->bandwidth; - spdu->start_frame = urb->start_frame; - spdu->number_of_packets = urb->number_of_packets; - spdu->interval = urb->interval; - } else { - /* stub_rx.c */ - urb->transfer_flags = spdu->transfer_flags; - - urb->transfer_buffer_length = spdu->transfer_buffer_length; - urb->bandwidth = spdu->bandwidth; - urb->start_frame = spdu->start_frame; - urb->number_of_packets = spdu->number_of_packets; - urb->interval = spdu->interval; - } -} - -static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit; - - if (pack) { - /* stub_tx.c */ - - rpdu->status = urb->status; - rpdu->actual_length = urb->actual_length; - rpdu->bandwidth = urb->bandwidth; - rpdu->start_frame = urb->start_frame; - rpdu->error_count = urb->error_count; - } else { - /* vhci_rx.c */ - - urb->status = rpdu->status; - urb->actual_length = rpdu->actual_length; - urb->bandwidth = rpdu->bandwidth; - urb->start_frame = rpdu->start_frame; - urb->error_count = rpdu->error_count; - } -} - - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack) -{ - switch(cmd) { - case USBIP_CMD_SUBMIT: - usbip_pack_cmd_submit(pdu, urb, pack); - break; - case USBIP_RET_SUBMIT: - usbip_pack_ret_submit(pdu, urb, pack); - break; - default: - /* NOTREACHED */ - BUG(); - } -} - - -static void correct_endian_basic(struct usbip_header_basic *base, int send) -{ - if (send) { - base->command = cpu_to_be32(base->command); - base->busnum = cpu_to_be32(base->busnum); - base->devnum = cpu_to_be32(base->devnum); - base->seqnum = cpu_to_be32(base->seqnum); - base->pipe = cpu_to_be32(base->pipe); - } else { - base->command = be32_to_cpu(base->command); - base->busnum = be32_to_cpu(base->busnum); - base->devnum = be32_to_cpu(base->devnum); - base->seqnum = be32_to_cpu(base->seqnum); - base->pipe = be32_to_cpu(base->pipe); - } -} - -static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu, int send) -{ - if (send) { - pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags); - - cpu_to_be32s(&pdu->transfer_buffer_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->number_of_packets); - cpu_to_be32s(&pdu->interval); - } else { - pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags); - - be32_to_cpus(&pdu->transfer_buffer_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->number_of_packets); - be32_to_cpus(&pdu->interval); - } -} - -static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, int send) -{ - if (send) { - cpu_to_be32s(&pdu->status); - cpu_to_be32s(&pdu->actual_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->error_count); - } else { - be32_to_cpus(&pdu->status); - be32_to_cpus(&pdu->actual_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->error_count); - } -} - -static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu, int send) -{ - if (send) - pdu->seqnum = cpu_to_be32(pdu->seqnum); - else - pdu->seqnum = be32_to_cpu(pdu->seqnum); -} - -static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu, int send) -{ - if (send) - cpu_to_be32s(&pdu->status); - else - be32_to_cpus(&pdu->status); -} - -void usbip_header_correct_endian(struct usbip_header *pdu, int send) -{ - __u32 cmd = 0; - - if (send) - cmd = pdu->base.command; - - correct_endian_basic(&pdu->base, send); - - if (!send) - cmd = pdu->base.command; - - switch (cmd) { - case USBIP_CMD_SUBMIT: - correct_endian_cmd_submit(&pdu->u.cmd_submit, send); - break; - case USBIP_RET_SUBMIT: - correct_endian_ret_submit(&pdu->u.ret_submit, send); - break; - - case USBIP_CMD_UNLINK: - correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send); - break; - case USBIP_RET_UNLINK: - correct_endian_ret_unlink(&pdu->u.ret_unlink, send); - break; - - default: - /* NOTREACHED */ - BUG(); - } -} - -static void usbip_iso_pakcet_correct_endian(struct usbip_iso_packet_descriptor *iso, int send) -{ - /* does not need all members. but copy all simply. */ - if (send) { - iso->offset = cpu_to_be32(iso->offset); - iso->length = cpu_to_be32(iso->length); - iso->status = cpu_to_be32(iso->status); - iso->actual_length = cpu_to_be32(iso->actual_length); - } else { - iso->offset = be32_to_cpu(iso->offset); - iso->length = be32_to_cpu(iso->length); - iso->status = be32_to_cpu(iso->status); - iso->actual_length = be32_to_cpu(iso->actual_length); - } -} - -static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso, - struct usb_iso_packet_descriptor *uiso, int pack) -{ - if (pack) { - iso->offset = uiso->offset; - iso->length = uiso->length; - iso->status = uiso->status; - iso->actual_length = uiso->actual_length; - } else { - uiso->offset = iso->offset; - uiso->length = iso->length; - uiso->status = iso->status; - uiso->actual_length = iso->actual_length; - } -} - - -/* must free buffer */ -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - ssize_t size = np * sizeof(*iso); - int i; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return NULL; - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1); - usbip_iso_pakcet_correct_endian(iso, 1); - } - - *bufflen = size; - - return buff; -} - -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - int size = np * sizeof(*iso); - int i; - int ret; - - if (!usb_pipeisoc(urb->pipe)) - return 0; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0); - if (ret != size) { - uerr("recv iso_frame_descriptor, %d\n", ret); - kfree(buff); - - if (ud->side == USBIP_STUB) - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - else - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - - return -EPIPE; - } - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_iso_pakcet_correct_endian(iso, 0); - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0); - } - - - kfree(buff); - - return ret; -} - - -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) -{ - int ret; - int size; - - if (ud->side == USBIP_STUB) { - /* stub_rx.c */ - /* the direction of urb must be OUT. */ - if (usb_pipein(urb->pipe)) - return 0; - - size = urb->transfer_buffer_length; - } else { - /* vhci_rx.c */ - /* the direction of urb must be IN. */ - if (usb_pipeout(urb->pipe)) - return 0; - - size = urb->actual_length; - } - - /* no need to recv xbuff */ - if (!(size > 0)) - return 0; - - ret = usbip_xmit(0, ud->tcp_socket, (char *) urb->transfer_buffer, size, 0); - if (ret != size) { - uerr("recv xbuf, %d\n", ret); - if (ud->side == USBIP_STUB) { - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - } else { - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return -EPIPE; - } - } - - return ret; -} diff -Naur usbip-0.1.4/drivers/2.6.17/usbip_common.h trunk/drivers/2.6.17/usbip_common.h --- usbip-0.1.4/drivers/2.6.17/usbip_common.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/usbip_common.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,364 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#ifndef __VHCI_COMMON_H -#define __VHCI_COMMON_H - - -#include -#include -#include - -/*-------------------------------------------------------------------------*/ - -/* - * define macros to print messages - */ - -/** - * udbg - print debug messages if CONFIG_USB_DEBUG is defined - * @fmt: - * @args: - */ - -#ifdef CONFIG_USB_DEBUG - -#define udbg(fmt, args...) \ - do{ \ - printk(KERN_DEBUG "%-10s:(%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - }while(0) - -#else /* CONFIG_USB_DEBUG */ - -#define udbg(fmt, args...) do{ }while(0) - -#endif /* CONFIG_USB_DEBUG */ - - -enum { - usbip_debug_xmit = (1 << 0), - usbip_debug_sysfs = (1 << 1), - usbip_debug_urb = (1 << 2), - usbip_debug_eh = (1 << 3), - - usbip_debug_stub_cmp = (1 << 8), - usbip_debug_stub_dev = (1 << 9), - usbip_debug_stub_rx = (1 << 10), - usbip_debug_stub_tx = (1 << 11), - - usbip_debug_vhci_rh = (1 << 8), - usbip_debug_vhci_hc = (1 << 9), - usbip_debug_vhci_rx = (1 << 10), - usbip_debug_vhci_tx = (1 << 11), - usbip_debug_vhci_sysfs = (1 << 12) -}; - -#define dbg_flag_xmit (usbip_debug_flag & usbip_debug_xmit) -#define dbg_flag_vhci_rh (usbip_debug_flag & usbip_debug_vhci_rh) -#define dbg_flag_vhci_hc (usbip_debug_flag & usbip_debug_vhci_hc) -#define dbg_flag_vhci_rx (usbip_debug_flag & usbip_debug_vhci_rx) -#define dbg_flag_vhci_tx (usbip_debug_flag & usbip_debug_vhci_tx) -#define dbg_flag_vhci_sysfs (usbip_debug_flag & usbip_debug_vhci_sysfs) -#define dbg_flag_stub_rx (usbip_debug_flag & usbip_debug_stub_rx) -#define dbg_flag_stub_tx (usbip_debug_flag & usbip_debug_stub_tx) - -extern unsigned long usbip_debug_flag; -extern struct device_attribute dev_attr_usbip_debug; - -#define dbg_with_flag(flag, fmt, args...) \ - do { \ - if(flag & usbip_debug_flag) \ - udbg(fmt , ##args); \ - } while(0) - -#define dbg_sysfs(fmt, args...) dbg_with_flag(usbip_debug_sysfs, fmt , ##args) -#define dbg_xmit(fmt, args...) dbg_with_flag(usbip_debug_xmit, fmt , ##args) -#define dbg_urb(fmt, args...) dbg_with_flag(usbip_debug_urb, fmt , ##args) -#define dbg_eh(fmt, args...) dbg_with_flag(usbip_debug_eh, fmt , ##args) - -#define dbg_vhci_rh(fmt, args...) dbg_with_flag(usbip_debug_vhci_rh, fmt , ##args) -#define dbg_vhci_hc(fmt, args...) dbg_with_flag(usbip_debug_vhci_hc, fmt , ##args) -#define dbg_vhci_rx(fmt, args...) dbg_with_flag(usbip_debug_vhci_rx, fmt , ##args) -#define dbg_vhci_tx(fmt, args...) dbg_with_flag(usbip_debug_vhci_tx, fmt , ##args) -#define dbg_vhci_sysfs(fmt, args...) dbg_with_flag(usbip_debug_vhci_sysfs, fmt , ##args) - -#define dbg_stub_cmp(fmt, args...) dbg_with_flag(usbip_debug_stub_cmp, fmt , ##args) -#define dbg_stub_rx(fmt, args...) dbg_with_flag(usbip_debug_stub_rx, fmt , ##args) -#define dbg_stub_tx(fmt, args...) dbg_with_flag(usbip_debug_stub_tx, fmt , ##args) - - -/** - * uerr - print error messages - * @fmt: - * @args: - */ -#define uerr(fmt, args...) \ - do { \ - printk(KERN_ERR "%-10s: ***ERROR*** (%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - } while(0) - -/** - * uinfo - print information messages - * @fmt: - * @args: - */ -#define uinfo(fmt, args...) \ - do { \ - printk(KERN_INFO "usbip: " fmt , ## args); \ - } while(0) - - -/*-------------------------------------------------------------------------*/ - -/* - * USB/IP packet headers. - * At now, we define 4 packet types: - * - * - CMD_SUBMIT transfers a USB request. This is corresponding to usb_submit_urb(). - * - RET_RETURN transfers a result of a USB request. - * - CMD_UNLINK transfers an unlink request of a pending USB request. - * - RET_UNLINK transfers an unlink request of a pending USB request. - * - * TODO: - * - * - inter-operability between other OSs - */ - -/* - * A basic header followed by other additional headers. - */ -struct usbip_header_basic { -#define USBIP_CMD_SUBMIT 0x0001 -#define USBIP_CMD_UNLINK 0x0002 -#define USBIP_RET_SUBMIT 0x0003 -#define USBIP_RET_UNLINK 0x0004 - __u32 command; - - __u32 busnum; - __u32 devnum; - __u32 seqnum; /* seaquencial number which identifies URBs */ - __u32 pipe; -} __attribute__ ((packed)); - -/* - * An additional header for a CMD_SUBMIT packet. - */ -struct usbip_header_cmd_submit { - __u32 transfer_flags; - __s32 transfer_buffer_length; - __s32 bandwidth; - __s32 start_frame; - __s32 number_of_packets; - __s32 interval; - unsigned char setup[8]; /* CTRL only */ -}__attribute__ ((packed)); - -/* - * An additional header for a RET_SUBMIT packet. - */ -struct usbip_header_ret_submit { - __s32 status; - __s32 actual_length; /* returned data length */ - __s32 bandwidth; - __s32 start_frame; /* ISO and INT */ - __s32 number_of_packets; /* ISO only */ - __s32 error_count; /* ISO only */ -}__attribute__ ((packed)); - -/* - * An additional header for a CMD_UNLINK packet. - */ -struct usbip_header_cmd_unlink { - __u32 seqnum; /* URB's seqnum which will be unlinked */ -}__attribute__ ((packed)); - - -/* - * An additional header for a RET_UNLINK packet. - */ -struct usbip_header_ret_unlink { - __s32 status; -}__attribute__ ((packed)); - - -/* the same as usb_iso_packet_descriptor but packed for pdu */ -struct usbip_iso_packet_descriptor { - __u32 offset; - __u32 length; /* expected length */ - __u32 actual_length; - __u32 status; -}__attribute__ ((packed)); - - -/* - * All usbip packets use a common header to keep code simple. - */ -struct usbip_header { - struct usbip_header_basic base; - - union { - struct usbip_header_cmd_submit cmd_submit; - struct usbip_header_ret_submit ret_submit; - struct usbip_header_cmd_unlink cmd_unlink; - struct usbip_header_ret_unlink ret_unlink; - } u; -}__attribute__ ((packed)); - - - - -/*-------------------------------------------------------------------------*/ - - -int usbip_xmit(int , struct socket *, char *, int , int ); -int usbip_sendmsg(struct socket *, struct msghdr *, int ); - - -static inline int interface_to_busnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->bus->busnum; -} - -static inline int interface_to_devnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->devnum; -} - -static inline int interface_to_infnum(struct usb_interface *interface) -{ - return interface->cur_altsetting->desc.bInterfaceNumber; -} - -int setnodelay(struct socket *); -int setquickack(struct socket *); -int setkeepalive(struct socket *socket); -void setreuse(struct socket *); -struct socket *sockfd_to_socket(unsigned int); -int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss); - - -void usbip_dump_urb (struct urb *purb); -void usbip_dump_header(struct usbip_header *pdu); - - -struct usbip_device; - -struct usbip_task { - struct task_struct *thread; - struct completion thread_done; - char *name; - void (*loop_ops)(struct usbip_task *); -}; - -enum usbip_side { - USBIP_VHCI, - USBIP_STUB, -}; - -enum usbip_status { - /* sdev is available. */ - SDEV_ST_AVAILABLE = 0x01, - /* sdev is now used. */ - SDEV_ST_USED, - /* sdev is unusable because of a fatal error. */ - SDEV_ST_ERROR, - - /* vdev does not connect a remote device. */ - VDEV_ST_NULL, - /* vdev is used, but the USB address is not assigned yet */ - VDEV_ST_NOTASSIGNED, - VDEV_ST_USED, - VDEV_ST_ERROR -}; - -/* a common structure for stub_device and vhci_device */ -struct usbip_device{ - enum usbip_side side; - - enum usbip_status status; - - /* lock for status */ - spinlock_t lock; - - struct socket *tcp_socket; - - struct usbip_task tcp_rx; - struct usbip_task tcp_tx; - - /* event handler */ -#define USBIP_EH_SHUTDOWN (1 << 0) -#define USBIP_EH_BYE (1 << 1) -#define USBIP_EH_RESET (1 << 2) -#define USBIP_EH_UNUSABLE (1 << 3) - -#define SDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE ) -#define SDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_SUBMIT ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE ) - -#define VDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_BYE ) -#define VDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) - - unsigned long event; - struct usbip_task eh; - wait_queue_head_t eh_waitq; - - struct eh_ops { - void (*shutdown)(struct usbip_device *); - void (*reset)(struct usbip_device *); - void (*unusable)(struct usbip_device *); - } eh_ops; -}; - - -void usbip_task_init(struct usbip_task *ut, char *, void (*loop_ops)(struct usbip_task *)); - -void usbip_start_threads(struct usbip_device *ud); -void usbip_stop_threads(struct usbip_device *ud); -int usbip_thread(void *param); - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack); -void usbip_header_correct_endian(struct usbip_header *pdu, int send); -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb); -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen); - - -/* usbip_event.c */ -void usbip_start_eh(struct usbip_device *ud); -void usbip_stop_eh(struct usbip_device *ud); -void usbip_event_add(struct usbip_device *ud, unsigned long event); -int usbip_event_happend(struct usbip_device *ud); - - -#endif diff -Naur usbip-0.1.4/drivers/2.6.17/usbip_event.c trunk/drivers/2.6.17/usbip_event.c --- usbip-0.1.4/drivers/2.6.17/usbip_event.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/usbip_event.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,153 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" - - - - -static void event_handler_loop(struct usbip_task *eh); - -void usbip_start_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - init_waitqueue_head(&ud->eh_waitq); - ud->event = 0; - - usbip_task_init(eh, "usbip_eh", event_handler_loop); - - kernel_thread((int(*)(void *)) usbip_thread, (void *) eh, 0); - - wait_for_completion(&eh->thread_done); -} - -void usbip_stop_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - wait_for_completion(&eh->thread_done); - dbg_eh("usbip_eh has finished\n"); -} - - -void usbip_event_add(struct usbip_device *ud, unsigned long event) -{ - spin_lock(&ud->lock); - - ud->event |= event; - - wake_up(&ud->eh_waitq); - - spin_unlock(&ud->lock); -} - -int usbip_event_happend(struct usbip_device *ud) -{ - int happend = 0; - - spin_lock(&ud->lock); - - if (ud->event != 0) - happend = 1; - - spin_unlock(&ud->lock); - - return happend; -} - - -static int event_handler(struct usbip_device *ud) -{ - - dbg_eh("enter\n"); - - - /* - * Events are handled by only this thread. - */ - while ( usbip_event_happend(ud) ) { - dbg_eh("pending event %lx\n", ud->event); - - /* - * NOTE: shutdown must come first. - * Shutdown the device. - */ - if (ud->event & USBIP_EH_SHUTDOWN) { - ud->eh_ops.shutdown(ud); - - ud->event &= ~USBIP_EH_SHUTDOWN; - - break; - } - - /* Stop the error handler. */ - if (ud->event & USBIP_EH_BYE) - return -1; - - /* Reset the device. */ - if (ud->event & USBIP_EH_RESET) { - ud->eh_ops.reset(ud); - - ud->event &= ~USBIP_EH_RESET; - - break; - } - - /* Mark the device as unusable. */ - if (ud->event & USBIP_EH_UNUSABLE) { - ud->eh_ops.unusable(ud); - - ud->event &= ~USBIP_EH_UNUSABLE; - - break; - } - - /* NOTREACHED */ - uerr("unknown event\n"); - return -1; - } - - return 0; -} - - - - -static void event_handler_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, eh); - - while (1) { - if (signal_pending(current)) { - dbg_eh("signal catched!\n"); - break; - } - - if ( event_handler(ud) < 0) - break; - - wait_event_interruptible(ud->eh_waitq, usbip_event_happend(ud)); - dbg_eh("wakeup\n"); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.17/vhci.h trunk/drivers/2.6.17/vhci.h --- usbip-0.1.4/drivers/2.6.17/vhci.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/vhci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,143 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include HCD_HEADER - - -struct vhci_device { - struct usb_device *udev; - - /* busnum and devnum of a remote device */ - __u32 busnum; - __u32 devnum; - - /* speed of a remote device */ - enum usb_device_speed speed; - - /* vhci root-hub port to which this device is attached */ - __u32 rhport; - - struct usbip_device ud; - - - /* lock for the below link lists */ - spinlock_t priv_lock; - - /* vhci_priv is linked to one of them. */ - struct list_head priv_tx; - struct list_head priv_rx; - - /* vhci_unlink is linked to one of them */ - struct list_head unlink_tx; - struct list_head unlink_rx; - - /* vhci_tx thread sleeps for this queue */ - wait_queue_head_t waitq_tx; -}; - - -/* urb->hcpriv, use container_of() */ -struct vhci_priv { - unsigned long seqnum; - struct list_head list; - - struct vhci_device *vdev; - struct urb *urb; -}; - - -struct vhci_unlink { - /* seqnum of this request */ - unsigned long seqnum; - - struct list_head list; - - /* seqnum of the unlink target */ - unsigned long unlink_seqnum; -}; - -/* - * The number of ports is less than 16 ? - * USB_MAXCHILDREN is statically defined to 16 in usb.h. Its maximum value - * would be 31 because the event_bits[1] of struct usb_hub is defined as - * unsigned long in hub.h - */ -#define VHCI_NPORTS 8 - -/* for usb_bus.hcpriv */ -struct vhci_hcd { - spinlock_t lock; - - u32 port_status[VHCI_NPORTS]; - - unsigned resuming:1; - unsigned long re_timeout; - - atomic_t seqnum; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - * But, the index of this array begins from 0. - */ - struct vhci_device vdev[VHCI_NPORTS]; - - /* vhci_device which has not been assiged its address yet */ - int pending_port; -}; - - -extern struct vhci_hcd *the_controller; -extern struct attribute_group dev_attr_group; - - -/*-------------------------------------------------------------------------*/ -/* prototype declaration */ - -/* vhci_hcd.c */ -void rh_port_connect(int rhport, enum usb_device_speed speed); -void rh_port_disconnect(int rhport); -void vhci_rx_loop(struct usbip_task *ut); -void vhci_tx_loop(struct usbip_task *ut); - -#define hardware (&the_controller->pdev.dev) - -static inline struct vhci_device *port_to_vdev(__u32 port) -{ - return &the_controller->vdev[port]; -} - -static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd) -{ - return (struct vhci_hcd *) (hcd->hcd_priv); -} - -static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci) -{ - return container_of((void *) vhci, struct usb_hcd, hcd_priv); -} - -static inline struct device *vhci_dev(struct vhci_hcd *vhci) -{ - return vhci_to_hcd(vhci)->self.controller; -} diff -Naur usbip-0.1.4/drivers/2.6.17/vhci_hcd.c trunk/drivers/2.6.17/vhci_hcd.c --- usbip-0.1.4/drivers/2.6.17/vhci_hcd.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/vhci_hcd.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1174 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "vhci.h" - -#define DRIVER_VERSION " $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ " -#define DRIVER_AUTHOR "HIROFUCHI Takahiro " -#define DRIVER_DESC "Virtual Host Controller Interface Driver for USB/IP" -#define DRIVER_LICENCE "GPL" -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENCE); - - - -/* - * TODO - * - update root hub emulation - * - move the emulation code to userland ? - * poring to other operating systems - * minimize kernel code - * - add suspend/resume code - * - clean up everything - */ - - -/* See usb gadget dummy hcd */ - - -static int vhci_hub_status (struct usb_hcd *hcd, char *buff); -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buff, u16 wLength); -static int vhci_urb_enqueue (struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags); -static int vhci_urb_dequeue( struct usb_hcd *hcd, struct urb *urb); -static int vhci_start(struct usb_hcd *vhci_hcd); -static void vhci_stop(struct usb_hcd *hcd); -static int vhci_get_frame_number(struct usb_hcd *hcd); - -static const char driver_name[] = "vhci_hcd"; -static const char driver_desc[] = "USB/IP Virtual Host Contoroller"; - - - - -struct vhci_hcd *the_controller = NULL; - - -static const char *bit_desc[] = { - "CONNECTION", /*0*/ - "ENABLE", /*1*/ - "SUSPEND", /*2*/ - "OVER_CURRENT", /*3*/ - "RESET", /*4*/ - "R5", /*5*/ - "R6", /*6*/ - "R7", /*7*/ - "POWER", /*8*/ - "LOWSPEED", /*9*/ - "HIGHSPEED", /*10*/ - "PORT_TEST", /*11*/ - "INDICATOR", /*12*/ - "R13", /*13*/ - "R14", /*14*/ - "R15", /*15*/ - "C_CONNECTION", /*16*/ - "C_ENABLE", /*17*/ - "C_SUSPEND", /*18*/ - "C_OVER_CURRENT", /*19*/ - "C_RESET", /*20*/ - "R21", /*21*/ - "R22", /*22*/ - "R23", /*23*/ - "R24", /*24*/ - "R25", /*25*/ - "R26", /*26*/ - "R27", /*27*/ - "R28", /*28*/ - "R29", /*29*/ - "R30", /*30*/ - "R31", /*31*/ -}; - - -static void dump_port_status(u32 status) -{ - int i = 0; - - printk("status %08x:", status); - for (i = 0; i < 32; i++) { - if (status & (1 << i)) { - printk(" %s", bit_desc[i]); - } - } - - printk("\n"); -} - - - -void rh_port_connect(int rhport, enum usb_device_speed speed) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_connect %d\n", rhport); - - spin_lock_irqsave(&the_controller->lock, flags); - - the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION - | (1 << USB_PORT_FEAT_C_CONNECTION); - - switch (speed) { - case USB_SPEED_HIGH: - the_controller->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - the_controller->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - - //spin_lock(&the_controller->vdev[rhport].ud.lock); - //the_controller->vdev[rhport].ud.status = VDEV_CONNECT; - //spin_unlock(&the_controller->vdev[rhport].ud.lock); - - the_controller->pending_port = rhport; - - spin_unlock_irqrestore(&the_controller->lock, flags); - -} - -void rh_port_disconnect(int rhport) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_disconnect %d\n", rhport); - - spin_lock_irqsave (&the_controller->lock, flags); - //stop_activity (dum, driver); - the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; - the_controller->port_status[rhport] |= (1 << USB_PORT_FEAT_C_CONNECTION); - - - /* not yet complete the disconnection */ - //spin_lock(&vdev->ud.lock); - //vdev->ud.status = VHC_ST_DISCONNECT; - //spin_unlock(&vdev->ud.lock); - - spin_unlock_irqrestore (&the_controller->lock, flags); -} - - - -/*----------------------------------------------------------------------*/ - -#define PORT_C_MASK \ - ((USB_PORT_STAT_C_CONNECTION \ - | USB_PORT_STAT_C_ENABLE \ - | USB_PORT_STAT_C_SUSPEND \ - | USB_PORT_STAT_C_OVERCURRENT \ - | USB_PORT_STAT_C_RESET) << 16) - -/* - * This function is almostly the same as dummy_hcd.c:dummy_hub_status() without - * suspend/resume support. But, it is modified to provide multiple ports. - * - * @buf: a bitmap to show which port status has been changed. - * bit 0: reserved or used for another purpose? - * bit 1: the status of port 0 has been changed. - * bit 2: the status of port 1 has been changed. - * ... - * bit 7: the status of port 6 has been changed. - * bit 8: the status of port 7 has been changed. - * ... - * bit 15: the status of port 14 has been changed. - * - * So, the maximum number of ports is 31 ( port 0 to port 30) ? - * - * The return value is the actual transfered length in byte. If nothing has - * been changed, return 0. In the case that the number of ports is less than or - * equal to 6 (VHCI_NPORTS==7), return 1. - * - */ -static int vhci_hub_status (struct usb_hcd *hcd, char *buf) -{ - struct vhci_hcd *vhci; - unsigned long flags; - int retval = 0; - - /* the enough buffer is allocated according to USB_MAXCHILDREN */ - unsigned long *event_bits = (unsigned long *) buf; - int rhport; - int changed = 0; - - - *event_bits = 0; - - vhci = hcd_to_vhci(hcd); - - spin_lock_irqsave (&vhci->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - dbg_vhci_rh("hw accessible flag in on?\n"); - goto done; - } - - /* check pseudo status register for each port */ - for(rhport = 0; rhport < VHCI_NPORTS; rhport++) { - if ((vhci->port_status[rhport] & PORT_C_MASK)) { - /* The status of a port has been changed, */ - dbg_vhci_rh("port %d is changed\n", rhport); - - *event_bits |= 1 << ( rhport + 1); - changed = 1; - } - } - - if (changed) - retval = 1 + (VHCI_NPORTS / 8); - else - retval = 0; - -done: - spin_unlock_irqrestore (&vhci->lock, flags); - return retval; -} - -/* See hub_configure in hub.c */ -static inline void hub_descriptor(struct usb_hub_descriptor *desc) -{ - memset(desc, 0, sizeof(*desc)); - desc->bDescriptorType = 0x29; - desc->bDescLength = 9; - desc->wHubCharacteristics = (__force __u16) - (__constant_cpu_to_le16 (0x0001)); - desc->bNbrPorts = VHCI_NPORTS; - desc->bitmap [0] = 0xff; - desc->bitmap [1] = 0xff; -} - - -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) -{ - struct vhci_hcd *dum; - int retval = 0; - unsigned long flags; - int rhport; - - u32 prev_port_status[VHCI_NPORTS]; - - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) - return -ETIMEDOUT; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - */ - dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue, wIndex); - if (wIndex > VHCI_NPORTS) - uerr("invalid port number %d\n", wIndex); - rhport = ((__u8 ) (wIndex & 0x00ff)) -1; - - dum = hcd_to_vhci(hcd); - - spin_lock_irqsave (&dum->lock, flags); - - /* store old status and compare now and old later */ - if (dbg_flag_vhci_rh) { - int i = 0; - for (i = 0; i < VHCI_NPORTS; i++) - prev_port_status[i] = dum->port_status[i]; - } - - switch (typeReq) { - case ClearHubFeature: - dbg_vhci_rh(" ClearHubFeature\n"); - break; - case ClearPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if (dum->port_status[rhport] & (1 << USB_PORT_FEAT_SUSPEND)) { - /* 20msec signaling */ - dum->resuming = 1; - dum->re_timeout = jiffies + msecs_to_jiffies(20); - } - break; - case USB_PORT_FEAT_POWER: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_POWER\n"); - dum->port_status[rhport] = 0; - //dum->address = 0; - //dum->hdev = 0; - dum->resuming = 0; - break; - case USB_PORT_FEAT_C_RESET: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_C_RESET\n"); - switch (dum->vdev[rhport].speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - default: - dbg_vhci_rh(" ClearPortFeature: default %x\n", wValue); - dum->port_status[rhport] &= ~(1 << wValue); - } - break; - case GetHubDescriptor: - dbg_vhci_rh(" GetHubDescriptor\n"); - hub_descriptor ((struct usb_hub_descriptor *) buf); - break; - case GetHubStatus: - dbg_vhci_rh(" GetHubStatus\n"); - *(u32 *) buf = __constant_cpu_to_le32 (0); - break; - case GetPortStatus: - dbg_vhci_rh(" GetPortStatus port %x\n", wIndex); - if (wIndex > VHCI_NPORTS || wIndex < 1) { - uerr(" invalid port number %d\n", wIndex); - retval = -EPIPE; - } - - /* we do no care of resume. */ - - /* whoever resets or resumes must GetPortStatus to - * complete it!! - * */ - if (dum->resuming && time_after (jiffies, dum->re_timeout)) { - uerr(" not yet\n"); - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_SUSPEND); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_SUSPEND); - dum->resuming = 0; - dum->re_timeout = 0; - //if (dum->driver && dum->driver->resume) { - // spin_unlock (&dum->lock); - // dum->driver->resume (&dum->gadget); - // spin_lock (&dum->lock); - //} - } - - if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) != 0 - && time_after (jiffies, dum->re_timeout)) { - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_RESET); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_RESET); - dum->re_timeout = 0; - - if (dum->vdev[rhport].ud.status == VDEV_ST_NOTASSIGNED) { - dbg_vhci_rh(" enable rhport %d (status %u)\n", rhport, dum->vdev[rhport].ud.status); - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - } -#if 0 - if (dum->driver) { - - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - /* give it the best speed we agree on */ - dum->gadget.speed = dum->driver->speed; - dum->gadget.ep0->maxpacket = 64; - switch (dum->gadget.speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= - USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->gadget.ep0->maxpacket = 8; - dum->port_status[rhport] |= - USB_PORT_STAT_LOW_SPEED; - break; - default: - dum->gadget.speed = USB_SPEED_FULL; - break; - } - } -#endif - - } - ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status[rhport]); - ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status[rhport] >> 16); - - dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0], ((u16 *)buf)[1] ); - break; - case SetHubFeature: - dbg_vhci_rh(" SetHubFeature\n"); - retval = -EPIPE; - break; - case SetPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_SUSPEND\n"); - uerr(" not yet\n"); -#if 0 - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_SUSPEND); - if (dum->driver->suspend) { - spin_unlock (&dum->lock); - dum->driver->suspend (&dum->gadget); - spin_lock (&dum->lock); - } -#endif - break; - case USB_PORT_FEAT_RESET: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_RESET\n"); - /* if it's already running, disconnect first */ - if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) { - dum->port_status[rhport] &= ~(USB_PORT_STAT_ENABLE - | USB_PORT_STAT_LOW_SPEED - | USB_PORT_STAT_HIGH_SPEED); -#if 0 - if (dum->driver) { - dev_dbg (hardware, "disconnect\n"); - stop_activity (dum, dum->driver); - } -#endif - - /* FIXME test that code path! */ - } - /* 50msec reset signaling */ - dum->re_timeout = jiffies + msecs_to_jiffies(50); - - /* FALLTHROUGH */ - default: - dbg_vhci_rh(" SetPortFeature: default %d\n", wValue); - dum->port_status[rhport] |= (1 << wValue); - } - break; - - default: - uerr(" default: no such request\n"); - //dev_dbg (hardware, - // "hub control req%04x v%04x i%04x l%d\n", - // typeReq, wValue, wIndex, wLength); - - /* "protocol stall" on error */ - retval = -EPIPE; - } - - if (dbg_flag_vhci_rh) { - printk("port %d\n", rhport); - dump_port_status(prev_port_status[rhport]); - dump_port_status(dum->port_status[rhport]); - } - dbg_vhci_rh(" bye\n"); - - spin_unlock_irqrestore (&dum->lock, flags); - - return retval; -} - - - -/*----------------------------------------------------------------------*/ - -static struct vhci_device *get_vdev(struct usb_device *udev) -{ - int i; - - if (!udev) - return NULL; - - for (i=0; i < VHCI_NPORTS; i++) - if (the_controller->vdev[i].udev == udev) - return port_to_vdev(i); - - return NULL; -} - -static void vhci_tx_urb(struct urb *urb) -{ - struct vhci_device *vdev = get_vdev(urb->dev); - struct vhci_priv *priv; - unsigned long flag; - - if (!vdev) - BUG(); - - spin_lock_irqsave(&vdev->priv_lock, flag); - - priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC); - if (!priv) { - uerr("malloc vhci_priv\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flag); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - priv->seqnum = atomic_inc_return(&the_controller->seqnum); - if (priv->seqnum == 0xffff) - uinfo("seqnum max\n"); - - priv->vdev = vdev; - priv->urb = urb; - - urb->hcpriv = (void *) priv; - - - list_add_tail(&priv->list, &vdev->priv_tx); - - wake_up(&vdev->waitq_tx); - spin_unlock_irqrestore(&vdev->priv_lock, flag); -} - -static int vhci_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags) -{ - int ret = 0; - unsigned long flags; - - dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); - - - - /* patch to usb_sg_init() is in 2.5.60 */ - BUG_ON (!urb->transfer_buffer && urb->transfer_buffer_length); - - spin_lock_irqsave (&the_controller->lock, flags); - - /* check HC is active or not */ - if (!HC_IS_RUNNING(hcd->state)) { - uerr("HC is not running\n"); - spin_unlock_irqrestore(&the_controller->lock, flags); - return -ENODEV; - } - - if (urb->status != -EINPROGRESS) { - uerr("URB already unlinked!, status %d\n", urb->status); - spin_unlock_irqrestore(&the_controller->lock, flags); - return urb->status; - } - - /* - * The enumelation process is as follows; - * - * 1. Get_Descriptor request to DevAddrs(0) EndPoint(0) - * to get max packet length of default pipe - * - * 2. Set_Address request to DevAddr(0) EndPoint(0) - * - */ - - if (usb_pipedevice(urb->pipe) == 0) { - __u8 type = usb_pipetype(urb->pipe); - struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; - struct vhci_device *vdev = port_to_vdev(the_controller->pending_port); - - if (type != PIPE_CONTROL || !ctrlreq ) { - uerr("invalid request to devnum 0\n"); - ret = EINVAL; - goto no_need_xmit; - } - - switch (ctrlreq->bRequest) { - - case USB_REQ_SET_ADDRESS: - vdev->udev = urb->dev; - dbg_vhci_hc("SetAddress Request (%d) to port %d\n", - ctrlreq->wValue, vdev->rhport); - - spin_lock(&vdev->ud.lock); - vdev->ud.status = VDEV_ST_USED; - spin_unlock(&vdev->ud.lock); - - spin_lock (&urb->lock); - if (urb->status == -EINPROGRESS) { - /* This request is successfully completed. */ - /* If not -EINPROGRESS, possibly unlinked. */ - urb->status = 0; - } - spin_unlock (&urb->lock); - - goto no_need_xmit; - - case USB_REQ_GET_DESCRIPTOR: - if (ctrlreq->wValue == (USB_DT_DEVICE << 8)) - dbg_vhci_hc("Not yet?: Get_Descriptor to device 0 (get max pipe size)\n"); - - vdev->udev = urb->dev; - goto out; - - default: - /* NOT REACHED */ - uerr("invalid request to devnum 0 bRequest %u, wValue %u\n", - ctrlreq->bRequest, ctrlreq->wValue); - ret = -EINVAL; - goto no_need_xmit; - } - - } - -out: - - - vhci_tx_urb(urb); - - - spin_unlock_irqrestore (&the_controller->lock, flags); - - return 0; - - -no_need_xmit: - - spin_unlock_irqrestore(&the_controller->lock, flags); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - return 0; -} - - -/* - * vhci_rx gives back the urb after recieving the reply of the urb. If an - * unlink pdu is sent or not, vhci_rx recieves a normal return pdu and gives - * back its urb. For the driver unlinking the urb, the content of the urb is - * not important, but the calling to its completion handler is important; the - * completion of unlinking is notified by the completion handler. - * - * - * CLIENT SIDE - * - * - When vhci_hcd recieves RET_SUBMIT, - * - * - case 1a). the urb of the pdu is not unlinking. - * - normal case - * => just give back the urb - * - * - case 1b). the urb of the pdu is unlinking. - * - usbip.ko will return a reply of the unlinking request. - * => give back the urb now and go to case 2b). - * - * - When vhci_hcd recieves RET_UNLINK, - * - * - case 2a). a submit request is still pending in vhci_hcd. - * - urb was really pending in usbip.ko and urb_unlink_urb() was - * completed there. - * => free a pending submit request - * => notify unlink completeness by giving back the urb - * - * - case 2b). a submit request is *not* pending in vhci_hcd. - * - urb was already given back to the core driver. - * => do not give back the urb - * - * - * SERVER SIDE - * - * - When usbip recieves CMD_UNLINK, - * - * - case 3a). the urb of the unlink request is now in submission. - * => do usb_unlink_urb(). - * => after the unlink is completed, send RET_UNLINK. - * - * - case 3b). the urb of the unlink request is not in submission. - * - may be already completed or never be recieved - * => send RET_UNLINK - * - */ -static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -{ - unsigned long flags; - struct vhci_priv *priv; - struct vhci_device *vdev; - - uinfo("vhci_hcd: dequeue a urb %p\n", urb); - - - spin_lock_irqsave(&the_controller->lock, flags); - - priv = urb->hcpriv; - if (!priv) { - /* URB was never linked! or will be soon given back by vhci_rx. */ - spin_unlock_irqrestore(&the_controller->lock, flags); - return 0; - } - - /* send unlink request here? */ - vdev = priv->vdev; - - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - unsigned long flags2; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - uinfo("vhci_hcd: device %p seems to be disconnected\n", vdev); - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - - } else { - /* tcp connection is alive */ - unsigned long flags2; - struct vhci_unlink *unlink; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - /* setup CMD_UNLINK pdu */ - unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("malloc vhci_unlink\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - spin_unlock_irqrestore(&the_controller->lock, flags); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return -ENOMEM; - } - - unlink->seqnum = atomic_inc_return(&the_controller->seqnum); - if (unlink->seqnum == 0xffff) - uinfo("seqnum max\n"); - - unlink->unlink_seqnum = priv->seqnum; - - uinfo("vhci_hcd: device %p seems to be still connected\n", vdev); - - /* send cmd_unlink and try to cancel the pending URB in the peer */ - list_add_tail(&unlink->list, &vdev->unlink_tx); - wake_up(&vdev->waitq_tx); - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - } - - spin_unlock_irqrestore(&the_controller->lock, flags); - - /* - * If tcp connection is alive, we have sent CMD_UNLINK. - * vhci_rx will recieve RET_UNLINK and giveb back the URB. - * Otherwise, we give back it here. - */ - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n", urb); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - dbg_vhci_hc("leave\n"); - return 0; -} - - -static void vhci_device_unlink_cleanup(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock(&vdev->priv_lock); -} - -/* - * The important thing is that only one context begins cleanup. - * This is why error handling and cleanup become simple. - * We do not want to consider race condition as possible. - */ -static void vhci_shutdown_connection(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - /* need this? see stub_dev.c */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - usbip_stop_threads(&vdev->ud); - uinfo("stop threads\n"); - - /* active connection is closed */ - if (vdev->ud.tcp_socket != NULL) { - sock_release(vdev->ud.tcp_socket); - vdev->ud.tcp_socket = NULL; - } - uinfo("release socket\n"); - - vhci_device_unlink_cleanup(vdev); - - /* - * rh_port_disconnect() is a trigger of ... - * usb_disable_device(): - * disable all the endpoints for a USB device. - * usb_disable_endpoint(): - * disable endpoints. pending urbs are unlinked(dequeued). - * - * NOTE: After calling rh_port_disconnect(), the USB device driver of a - * deteched device should release used urbs in a cleanup function(i.e. - * xxx_disconnect()). Therefore, vhci_hcd does not need to release - * pushed urbs and their private data in this function. - * - * NOTE: vhci_dequeue() must be considered carefully. When shutdowning - * a connection, vhci_shutdown_connection() expects vhci_dequeue() - * gives back pushed urbs and frees their private data by request of - * the cleanup function of a USB driver. When unlinking a urb with an - * active connection, vhci_dequeue() does not give back the urb which - * is actually given back by vhci_rx after recieving its return pdu. - * - */ - rh_port_disconnect(vdev->rhport); - - uinfo("disconnect device\n"); -} - - -static void vhci_device_reset(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - spin_lock(&ud->lock); - - vdev->busnum = 0; - vdev->devnum = 0; - vdev->speed = 0; - - ud->tcp_socket = NULL; - - ud->status = VDEV_ST_NULL; - - spin_unlock(&ud->lock); -} - -static void vhci_device_unusable(struct usbip_device* ud) -{ - spin_lock(&ud->lock); - - ud->status = VDEV_ST_ERROR; - - spin_unlock(&ud->lock); -} - -static void vhci_device_init(struct vhci_device *vdev) -{ - memset(vdev, 0, sizeof(*vdev)); - - usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop); - usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop); - - vdev->ud.side = USBIP_VHCI; - vdev->ud.status = VDEV_ST_NULL; - vdev->ud.lock = SPIN_LOCK_UNLOCKED; - - INIT_LIST_HEAD(&vdev->priv_rx); - INIT_LIST_HEAD(&vdev->priv_tx); - INIT_LIST_HEAD(&vdev->unlink_tx); - INIT_LIST_HEAD(&vdev->unlink_rx); - vdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&vdev->waitq_tx); - - vdev->ud.eh_ops.shutdown = vhci_shutdown_connection; - vdev->ud.eh_ops.reset = vhci_device_reset; - vdev->ud.eh_ops.unusable= vhci_device_unusable; - - usbip_start_eh(&vdev->ud); -} - - -/*----------------------------------------------------------------------*/ - -static int vhci_start(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport; - - dbg_vhci_hc("enter vhci_start\n"); - - - /* initialize private data of usb_hcd */ - - for(rhport=0; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - vhci_device_init(vdev); - vdev->rhport = rhport; - } - - atomic_set(&vhci->seqnum, 0); - spin_lock_init(&vhci->lock); - - - - //hcd->power_budget = 0; /* no limit ? */ - hcd->state = HC_STATE_RUNNING; - //hcd->uses_new_polling = 1; - - - /* vhci_hcd is now ready to be controlled through sysfs */ - sysfs_create_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - return 0; -} - -static void vhci_stop(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport = 0; - - dbg_vhci_hc("stop VHCI controller\n"); - - - /* 1. remove the userland interface of vhci_hcd */ - sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - /* 2. shutdown all the ports of vhci_hcd */ - for(rhport = 0 ; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - - usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED); - usbip_stop_eh(&vdev->ud); - } - - - uinfo("vhci_stop done\n"); -} - -/*----------------------------------------------------------------------*/ - -static int vhci_get_frame_number(struct usb_hcd *hcd) -{ - uerr("Not yet implemented\n"); - return 0; -} - - -#ifdef CONFIG_PM - -static int vhci_bus_suspend(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -static int vhci_bus_resume(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -#else - -#define vhci_bus_suspend NULL -#define vhci_bus_resume NULL -#endif - - - -static struct hc_driver vhci_hc_driver = { - .description = driver_name, - .product_desc = driver_desc, - .hcd_priv_size = sizeof(struct vhci_hcd), - - .flags = HCD_USB2, - - .start = vhci_start, - .stop = vhci_stop, - - .urb_enqueue = vhci_urb_enqueue, - .urb_dequeue = vhci_urb_dequeue, - - .get_frame_number = vhci_get_frame_number, - - .hub_status_data = vhci_hub_status, - .hub_control = vhci_hub_control, - .bus_suspend = vhci_bus_suspend, - .bus_resume = vhci_bus_resume, -}; - -static int vhci_hcd_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - int ret; - - uinfo("proving...\n"); - - dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id); - - - /* will be removed */ - if (pdev->dev.dma_mask) { - info("vhci_hcd DMA not supported\n"); - return -EINVAL; - } - - - /* - * Allocate and initialize hcd. - * Our private data is also allocated automatically. - */ - hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, pdev->dev.bus_id); - if (!hcd) { - uerr("create hcd failed\n"); - return -ENOMEM; - } - - - /* this is private data for vhci_hcd */ - the_controller = hcd_to_vhci(hcd); - - /* - * Finish generic HCD structure initialization and register. - * Call the driver's reset() and start() routines. - */ - ret = usb_add_hcd(hcd, 0, 0); - if (ret != 0) { - uerr("usb_add_hcd failed %d\n", ret); - usb_put_hcd(hcd); - the_controller = NULL; - return ret; - } - - - dbg_vhci_hc("bye\n"); - return 0; -} - - -static int vhci_hcd_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - - - hcd = platform_get_drvdata(pdev); - if(!hcd) - return 0; - - /* - * Disconnects the root hub, - * then reverses the effects of usb_add_hcd(), - * invoking the HCD's stop() methods. - */ - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - the_controller = NULL; - - - return 0; -} - - - -#ifdef CONFIG_PM - -/* what should happen for USB/IP under suspend/resume? */ -static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = state; - - return 0; -} - -static int vhci_hcd_resume(struct platform_device *pdev) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = PMSG_ON; - - return 0; -} - -#else - -#define vhci_hcd_suspend NULL -#define vhci_hcd_resume NULL - -#endif - - -static struct platform_driver vhci_driver = { - .probe = vhci_hcd_probe, - .remove = __devexit_p(vhci_hcd_remove), - .suspend = vhci_hcd_suspend, - .resume = vhci_hcd_resume, - .driver = { - .name = (char *) driver_name, - .owner = THIS_MODULE, - }, -}; - -/*----------------------------------------------------------------------*/ - -/* - * The VHCI 'device' is 'virtual'; not a real plug&play hardware. - * We need to add this virtual device as a platform device arbitrarily: - * 1. platform_device_register() - */ -static void the_pdev_release(struct device *dev) -{ - return; -} - -static struct platform_device the_pdev = { - /* should be the same name as driver_name */ - .name = (char *) driver_name, - .id = -1, - .dev = { - //.driver = &vhci_driver, - .release = the_pdev_release, - }, -}; - -static int __init vhci_init(void) -{ - int ret; - - dbg_vhci_hc("enter\n"); - if (usb_disabled()) - return -ENODEV; - - info("driver %s, %s\n", driver_name, DRIVER_VERSION); - - ret = platform_driver_register(&vhci_driver); - if (ret < 0) - goto err_driver_register; - - ret = platform_device_register(&the_pdev); - if (ret < 0) - goto err_platform_device_register; - - - dbg_vhci_hc("bye\n"); - return ret; - - - - /* error occurred */ - -err_platform_device_register: - platform_driver_unregister(&vhci_driver); - -err_driver_register: - - dbg_vhci_hc("bye\n"); - return ret; -} -module_init(vhci_init); - - -static void __exit vhci_cleanup(void) -{ - dbg_vhci_hc("enter\n"); - - platform_device_unregister(&the_pdev); - platform_driver_unregister(&vhci_driver); - - dbg_vhci_hc("bye\n"); -} -module_exit(vhci_cleanup); diff -Naur usbip-0.1.4/drivers/2.6.17/vhci_rx.c trunk/drivers/2.6.17/vhci_rx.c --- usbip-0.1.4/drivers/2.6.17/vhci_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/vhci_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,239 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - - -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) -{ - struct vhci_priv *priv, *tmp; - struct urb *urb = NULL; - - - spin_lock(&vdev->priv_lock); - - - list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { - if (priv->seqnum == seqnum) { - urb = priv->urb; - dbg_vhci_rx("find urb %p vurb %p seqnum %u\n", urb, priv, seqnum); - - - if (urb->status != -EINPROGRESS) { - if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - uinfo("urb %p was unlinked %ssynchronuously.\n", - urb, urb->status == -ENOENT ? "" : "a"); - } else { - uinfo("urb %p may be in a error, status %d\n", - urb, urb->status); - } - } - - - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - - break; - } - } - - spin_unlock(&vdev->priv_lock); - - - return urb; -} - -static void vhci_recv_ret_submit(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &vdev->ud; - struct urb *urb; - - - urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); - - - if (!urb) { - uerr("cannot find a urb of seqnum %u\n", pdu->base.seqnum); - uinfo("max seqnum %d\n", atomic_read(&the_controller->seqnum)); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - - /* unpack the pdu to a urb */ - usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0); - - - /* recv transfer buffer */ - if (usbip_recv_xbuff(ud, urb) < 0) - return; - - - /* recv iso_packet_descriptor */ - if (usbip_recv_iso(ud, urb) < 0) - return; - - - if (dbg_flag_vhci_rx) - usbip_dump_urb(urb); - - - dbg_vhci_rx("now giveback urb %p\n", urb); - - - - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - - dbg_vhci_rx("Leave\n"); - - return; -} - - -static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, - struct usbip_header *pdu) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - uinfo("unlink->seqnum %lu\n", unlink->seqnum); - if (unlink->seqnum == pdu->base.seqnum) { - dbg_vhci_rx("found pending unlink, %lu\n", unlink->seqnum); - list_del(&unlink->list); - - spin_unlock(&vdev->priv_lock); - return unlink; - } - } - - spin_unlock(&vdev->priv_lock); - - return NULL; -} - - -static void vhci_recv_ret_unlink(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct vhci_unlink *unlink; - struct urb *urb; - - usbip_dump_header(pdu); - - unlink = dequeue_pending_unlink(vdev, pdu); - if (!unlink) { - uinfo("cannot find the pending unlink %u\n", pdu->base.seqnum); - return; - } - - urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); - if (!urb) { - /* - * I get the result of a unlink request. But, it seems that I - * already recieved the result of its submit result and gave - * back the URB. - */ - uinfo("the urb (seqnum %d) was already given backed\n", pdu->base.seqnum); - } else { - dbg_vhci_rx("now giveback urb %p\n", urb); - - /* If unlink is succeed, status is -ECONNRESET */ - urb->status = pdu->u.ret_unlink.status; - uinfo("%d\n", urb->status); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - kfree(unlink); - - return; -} - -/* recv a pdu */ -static void vhci_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - - dbg_vhci_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_vhci_rx) - usbip_dump_header(&pdu); - - switch(pdu.base.command) { - case USBIP_RET_SUBMIT: - vhci_recv_ret_submit(vdev, &pdu); - break; - - case USBIP_RET_UNLINK: - vhci_recv_ret_unlink(vdev, &pdu); - break; - default: - /* NOTREACHED */ - uerr("unknown pdu %u\n", pdu.base.command); - usbip_dump_header(&pdu); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - } -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - - while (1) { - if (signal_pending(current)) { - dbg_vhci_rx("signal catched!\n"); - break; - } - - - if (usbip_event_happend(ud)) break; - - vhci_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.17/vhci_sysfs.c trunk/drivers/2.6.17/vhci_sysfs.c --- usbip-0.1.4/drivers/2.6.17/vhci_sysfs.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/vhci_sysfs.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,286 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* TODO: refine locking ?*/ - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to show port status */ - -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *out) -{ - char *s = out; - int i = 0; - - if (!the_controller || !out) - BUG(); - - spin_lock(&the_controller->lock); - - /* - * output example: - * prt sta bus dev socket local_busid - * 000 004 000 000 c5a7bb80 1-2.3 - * 001 004 000 000 d8cee980 2-3.4 - * - * IP address can be retrieved from a socket pointer address by looking - * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a - * port number and its peer IP address. - */ - out += sprintf(out, "prt sta spd bus dev socket local_busid\n"); - - for (i=0; i < VHCI_NPORTS; i++) { - struct vhci_device *vdev = port_to_vdev(i); - - spin_lock(&vdev->ud.lock); - - out += sprintf(out, "%03u %03u ", i, vdev->ud.status); - - if (vdev->ud.status == VDEV_ST_USED) { - out += sprintf(out, "%03u %03u %03u ", - vdev->speed, vdev->busnum, vdev->devnum); - out += sprintf(out, "%16p ", vdev->ud.tcp_socket); - out += sprintf(out, "%s", vdev->udev->dev.bus_id); - - } else - out += sprintf(out, "000 000 000 0000000000000000 0-0"); - - out += sprintf(out, "\n"); - - spin_unlock(&vdev->ud.lock); - } - - spin_unlock(&the_controller->lock); - - return out - s ; -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to shutdown a virtual connection */ - -static int vhci_port_disconnect(__u32 rhport) -{ - struct vhci_device *vdev; - - dbg_vhci_sysfs("enter\n"); - - /* lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - if (vdev->ud.status == VDEV_ST_NULL) { - uerr("not connected %d\n", vdev->ud.status); - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - return -EINVAL; - } - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); - - return 0; -} - -static ssize_t store_detach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) { - int err; - __u32 rhport = 0; - - sscanf(buf, "%u", &rhport); - - /* check rhport */ - if (rhport >= VHCI_NPORTS) { - uerr("invalid port %u\n", rhport); - return -EINVAL; - } - - err = vhci_port_disconnect(rhport); - if (err < 0) { - return -EINVAL; - } - - dbg_vhci_sysfs("Leave\n"); - return count; -} - -static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to establish a virtual connection */ - -static int valid_args(__u32 rhport, __u32 busnum, __u32 devnum, - enum usb_device_speed speed) -{ - /* check rhport */ - if ((rhport < 0) || (rhport >= VHCI_NPORTS)) { - uerr("port %u\n", rhport); - return -EINVAL; - } - - /* check busnum & devnum */ - if ((busnum <= 0) || (busnum >= 128) || (devnum <= 0) || (devnum >= 128)) { - uerr("busnum %u devnum %u\n", busnum, devnum); - return -EINVAL; - } - - /* check speed */ - switch(speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - case USB_SPEED_HIGH: - case USB_SPEED_VARIABLE: - break; - - default: - uerr("speed %d\n", speed); - return -EINVAL; - } - - return 0; -} - -/* - * To start a new USB/IP attachment, a userland program needs to setup a TCP - * connection and then write its socket descriptor with remote device - * information into this sysfs file. - * - * A remote device is virtually attached to the root-hub port of @rhport with - * @speed. @busnum and @devnum are used to convert URBs between a client host - * and a server host. - * - * write() returns 0 on success, else negative errno. - */ -static ssize_t store_attach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vhci_device *vdev; - struct socket *socket; - int sockfd = 0; - __u32 rhport=0, busnum=0, devnum=0, speed=0; - - - /* - * @rhport: port number of vhci_hcd - * @sockfd: socket descriptor of an established TCP connection - * @busnum: usb bus number in a remote host - * @devnum: usb device number in a remote host - * @speed: usb device speed in a remote host - */ - sscanf(buf, "%u %u %u %u %u", &rhport, &sockfd, &busnum, &devnum, &speed); - - dbg_vhci_sysfs("rhport(%u) sockfd(%u) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - - /* check recieved parameters */ - if (valid_args(rhport, busnum, devnum, speed) < 0) - return -EINVAL; - - /* check sockfd */ - socket = sockfd_to_socket(sockfd); - if (!socket) - return -EINVAL; - - setnodelay(socket); - - - /* now need lock until setting vdev status as used */ - - /* begin a lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - - if (vdev->ud.status != VDEV_ST_NULL) { - /* end of the lock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - uerr("port %d already used\n", rhport); - return -EINVAL; - } - - uinfo("rhport(%u) sockfd(%d) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - vdev->busnum = busnum; - vdev->devnum = devnum; - vdev->speed = speed; - vdev->ud.tcp_socket = socket; - vdev->ud.status = VDEV_ST_NOTASSIGNED; - - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - /* end the lock */ - - /* - * this function will sleep, so should be out of the lock. but, it's ok - * because we already marked vdev as being used. really? - */ - usbip_start_threads(&vdev->ud); - - rh_port_connect(rhport, speed); - - return count; -} - -static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach); - - - -/*-------------------------------------------------------------------------*/ - -static struct attribute *dev_attrs[] = { - &dev_attr_status.attr, - &dev_attr_detach.attr, - &dev_attr_attach.attr, - &dev_attr_usbip_debug.attr, - NULL, -}; - -struct attribute_group dev_attr_group = { - .attrs = dev_attrs, -}; diff -Naur usbip-0.1.4/drivers/2.6.17/vhci_tx.c trunk/drivers/2.6.17/vhci_tx.c --- usbip-0.1.4/drivers/2.6.17/vhci_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.17/vhci_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,264 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* @p: pipe whose dev number modified - * @pdev: new devive number */ -static unsigned long tweak_pipe_devnum(__u32 p, __u8 pdev) -{ - __u32 oldp; - oldp = p; - - if (pdev > 0x7f) - uerr("invalid devnum %u\n", pdev); - - pdev &= 0x7f; // 0XXX XXXX confirm MSB be 0 - - p &= 0xffff80ff; /* clear p's devnum */ - - p |= (pdev << 8); - - dbg_vhci_tx("return new pipe, devnum %u -> %u \n", - usb_pipedevice(oldp), usb_pipedevice(p)); - dbg_vhci_tx(" pipe %08x -> %08x\n", oldp, p); - - return p; -} - -static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) -{ - struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv); - struct vhci_device *vdev = priv->vdev; - - dbg_vhci_tx("URB, local devnum(%u), busnum(%u) devnum(%u)\n", - usb_pipedevice(urb->pipe), vdev->busnum, vdev->devnum); - - pdup->base.command = USBIP_CMD_SUBMIT; - pdup->base.busnum = vdev->busnum; - pdup->base.devnum = vdev->devnum; - pdup->base.seqnum = priv->seqnum; - pdup->base.pipe = tweak_pipe_devnum(urb->pipe, vdev->devnum); - - usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1); - - if (urb->setup_packet) - memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8); -} - -static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_priv *priv, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { - list_move_tail(&priv->list, &vdev->priv_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - - - -static int vhci_send_cmd_submit(struct vhci_device *vdev) -{ - struct vhci_priv *priv = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(vdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_cmd_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->transfer_buffer_length; - txsize += urb->transfer_buffer_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&vdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - if (iso_buffer) - kfree(iso_buffer); - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_unlink *unlink, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_move_tail(&unlink->list, &vdev->unlink_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - -static int vhci_send_cmd_unlink(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup cmd unlink, %lu \n", unlink->seqnum); - - - /* 1. setup usbip_header */ - pdu_header.base.command = USBIP_CMD_UNLINK; - pdu_header.base.busnum = vdev->busnum; - pdu_header.base.devnum = vdev->devnum; - pdu_header.base.seqnum = unlink->seqnum; - pdu_header.base.pipe = 0; - pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum; - - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - while (1) { - if (signal_pending(current)) { - uinfo("vhci_tx signal catched\n"); - break; - } - - if (vhci_send_cmd_submit(vdev) < 0) - break; - - if (vhci_send_cmd_unlink(vdev) < 0) - break; - - wait_event_interruptible(vdev->waitq_tx, - (!list_empty(&vdev->priv_tx) || - !list_empty(&vdev->unlink_tx))); - - dbg_vhci_tx("pending urbs ?, now wake up\n"); - } -} diff -Naur usbip-0.1.4/drivers/2.6.18/Makefile trunk/drivers/2.6.18/Makefile --- usbip-0.1.4/drivers/2.6.18/Makefile 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,63 +0,0 @@ -# Makefile for the USB/IP driver -# -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ -# -# Copyright (C) 2003-2006 Takahiro Hirofuchi -# -# -# This 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 of the License, or -# (at your option) any later version. -# -# This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -# USA. -# - - -# Please modify here or set environments. -# KSOURCE should be pointed to the build directory of your kernel. -# -DEBUG ?= n -KSOURCE ?= /usr/src/linux - - -%.x:%.c - gcc -o $@ $< - -KBUILD_VERBOSE:=1 - -HCD_HEADER:=$(KSOURCE)/drivers/usb/core/hcd.h - -obj-m += usbip.o -usbip-objs := usbip_common.o usbip_event.o stub_dev.o stub_main.o stub_rx.o stub_tx.o - -obj-m += vhci-hcd.o -vhci-hcd-objs := usbip_common.o usbip_event.o vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o - - -EXTRA_CFLAGS += -DHCD_HEADER=\"$(HCD_HEADER)\" - -ifeq ($(DEBUG),y) - EXTRA_CFLAGS += -DCONFIG_USB_DEBUG -endif - - -default: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules - -.PHONY: cscope -cscope: - cscope -b -k -R - -.PHONY: clean -clean: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` clean - rm -f *.x *~ diff -Naur usbip-0.1.4/drivers/2.6.18/stub_dev.c trunk/drivers/2.6.18/stub_dev.c --- usbip-0.1.4/drivers/2.6.18/stub_dev.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/stub_dev.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,438 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - - -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void stub_disconnect(struct usb_interface *interface); - - -/* - * Define device IDs here if you want to explicitly limit exportable devices. - * In the most cases, wild card matching will be ok because driver binding can - * be changed dynamically by a userland program. - */ -static struct usb_device_id stub_table[] = { -#if 0 - /* just an example */ - { USB_DEVICE(0x05ac, 0x0301) }, /* Mac 1 button mouse */ - { USB_DEVICE(0x0430, 0x0009) }, /* Plat Home Keyboard */ - { USB_DEVICE(0x059b, 0x0001) }, /* Iomega USB Zip 100 */ - { USB_DEVICE(0x04b3, 0x4427) }, /* IBM USB CD-ROM */ - { USB_DEVICE(0x05a9, 0xa511) }, /* LifeView USB cam */ - { USB_DEVICE(0x55aa, 0x0201) }, /* Imation card reader */ - { USB_DEVICE(0x046d, 0x0870) }, /* Qcam Express(QV-30) */ - { USB_DEVICE(0x04bb, 0x0101) }, /* IO-DATA HD 120GB */ - { USB_DEVICE(0x04bb, 0x0904) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x04bb, 0x0201) }, /* IO-DATA USB-ET/TX */ - { USB_DEVICE(0x08bb, 0x2702) }, /* ONKYO USB Speaker */ - { USB_DEVICE(0x046d, 0x08b2) }, /* Logicool Qcam 4000 Pro */ -#endif - /* magic for wild card */ - { .driver_info = 1 }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, stub_table); - - -struct usb_driver stub_driver = { - .name = "usbip", - - .probe = stub_probe, - .disconnect = stub_disconnect, - - .id_table = stub_table, -}; - - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for a usbip-bound device */ - - -/* - * usbip_status shows status of usbip as long as this driver is bound to the - * target device. - */ -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int status; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - spin_lock(&sdev->ud.lock); - status = sdev->ud.status; - spin_unlock(&sdev->ud.lock); - - return snprintf(buf, PAGE_SIZE, "%d\n", status); -} -static DEVICE_ATTR(usbip_status, S_IRUGO, show_status, NULL); - - -/* - * usbip_sockfd gets a socket descriptor of an established TCP connection that - * is used to transfer usbip requests by kernel threads. -1 is a magic number - * by which usbip connection is finished. - */ -static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct stub_device *sdev = dev_get_drvdata(dev); - int sockfd = 0; - struct socket *socket; - - if (!sdev) { - uerr("sdev is null\n"); - return -ENODEV; - } - - sscanf(buf, "%d", &sockfd); - - if (sockfd != -1) { - uinfo("stub up\n"); - - spin_lock(&sdev->ud.lock); - - if (sdev->ud.status != SDEV_ST_AVAILABLE) { - uerr("not ready\n"); - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - socket = sockfd_to_socket(sockfd); - if (!socket) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - - setnodelay(socket); - setkeepalive(socket); - setreuse(socket); - - sdev->ud.tcp_socket = socket; - - spin_unlock(&sdev->ud.lock); - - usbip_start_threads(&sdev->ud); - - spin_lock(&sdev->ud.lock); - sdev->ud.status = SDEV_ST_USED; - spin_unlock(&sdev->ud.lock); - - } else { - uinfo("stub down\n"); - - spin_lock(&sdev->ud.lock); - if (sdev->ud.status != SDEV_ST_USED) { - spin_unlock(&sdev->ud.lock); - return -EINVAL; - } - spin_unlock(&sdev->ud.lock); - - usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); - } - - return count; -} -static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); - -static void stub_add_files(struct device *dev) -{ - device_create_file(dev, &dev_attr_usbip_status); - device_create_file(dev, &dev_attr_usbip_sockfd); - device_create_file(dev, &dev_attr_usbip_debug); -} - -static void stub_remove_files(struct device *dev) -{ - device_remove_file(dev, &dev_attr_usbip_status); - device_remove_file(dev, &dev_attr_usbip_sockfd); - device_remove_file(dev, &dev_attr_usbip_debug); -} - - - -/*-------------------------------------------------------------------------*/ - -/* Event handler functions called by an event handler thread */ - -static void stub_shutdown_connection(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - /* - * When removing an exported device, kernel panic sometimes occurred - * and then EIP was sk_wait_data of stub_rx thread. Is this because - * sk_wait_data returned though stub_rx thread was already finished by - * step 1? - */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - /* 1. stop threads */ - usbip_stop_threads(ud); - - /* 2. close the socket */ - /* - * tcp_socket is freed after threads are killed. - * So usbip_xmit do not touch NULL socket. - */ - if (ud->tcp_socket) { - sock_release(ud->tcp_socket); - ud->tcp_socket = NULL; - } - - /* 3. free used data */ - stub_device_cleanup_urbs(sdev); - - /* 4. free stub_unlink */ - { - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - } -} - -static void stub_device_reset(struct usbip_device *ud) -{ - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - struct usb_device *udev = interface_to_usbdev(sdev->interface); - int ret; - - ret = usb_lock_device_for_reset(udev, sdev->interface); - if (ret < 0) { - uerr("lock for reset\n"); - - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); - - return; - } - - /* try to reset the device */ - ret = usb_reset_device(udev); - - usb_unlock_device(udev); - - spin_lock(&ud->lock); - if (ret) { - uerr("device reset\n"); - ud->status = SDEV_ST_ERROR; - - } else { - uinfo("device reset\n"); - ud->status = SDEV_ST_AVAILABLE; - - } - spin_unlock(&ud->lock); - - return; -} - -static void stub_device_unusable(struct usbip_device *ud) -{ - spin_lock(&ud->lock); - ud->status = SDEV_ST_ERROR; - spin_unlock(&ud->lock); -} - - -/*-------------------------------------------------------------------------*/ - -/** - * stub_device_alloc - allocate a new stub_device struct - * @interface: usb_interface of a new device - * - * Allocates and initializes a new stub_devce struct. - */ -static struct stub_device * stub_device_alloc(struct usb_interface *interface) -{ - struct stub_device *sdev; - - /* yes, it's a new device */ - sdev = (struct stub_device *) kzalloc(sizeof(struct stub_device), GFP_KERNEL); - if (!sdev) { - uerr("no memory for stub_device\n"); - return NULL; - } - - sdev->interface = interface; - - usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop); - usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop); - - sdev->ud.side = USBIP_STUB; - sdev->ud.status = SDEV_ST_AVAILABLE; - sdev->ud.lock = SPIN_LOCK_UNLOCKED; - sdev->ud.tcp_socket = NULL; - - INIT_LIST_HEAD(&sdev->priv_init); - INIT_LIST_HEAD(&sdev->priv_tx); - INIT_LIST_HEAD(&sdev->priv_free); - INIT_LIST_HEAD(&sdev->unlink_free); - INIT_LIST_HEAD(&sdev->unlink_tx); - sdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&sdev->tx_waitq); - - sdev->ud.eh_ops.shutdown = stub_shutdown_connection; - sdev->ud.eh_ops.reset = stub_device_reset; - sdev->ud.eh_ops.unusable = stub_device_unusable; - - usbip_start_eh(&sdev->ud); - - udbg("register new interface\n"); - return sdev; -} - -static int stub_device_free(struct stub_device *sdev) -{ - if (!sdev) - return -EINVAL; - - kfree(sdev); - udbg("kfree udev ok\n"); - - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* - * If a usb device has multiple active interfaces, this driver is bound to all - * the active interfaces. However, usbip exports *a* usb device (i.e. not *an* - * active interface). Currently, a userland program must ensure that it - * looks at the usbip's sysfs entries of only the first active interface. - */ -static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct stub_device *sdev = NULL; - char *udev_busid = interface->dev.parent->bus_id; - - udbg("Enter\n"); - - /* check we should claim or not by busid_table */ - if (match_busid(udev_busid)) { - uinfo("this device %s is not in match_busid table. skip!\n", udev_busid); - - /* - * Return value should be ENODEV or ENOXIO to continue trying - * other matched drivers by the driver core. - * See driver_probe_device() in driver/base/dd.c - */ - return -ENODEV; - } - - if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { - udbg("this device %s is a usb hub device. skip!\n", udev_busid); - return -ENODEV; - } - - if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { - udbg("this device %s is attached on vhci_hcd. skip!\n", udev_busid); - return -ENODEV; - } - - /* ok. this is my device. */ - - if ((sdev = stub_device_alloc(interface))) { - struct usb_device *udev = interface_to_usbdev(interface); - - uinfo("USB/IP Stub: register a new interface (bus %u dev %u ifn %u)\n", - udev->bus->busnum, udev->devnum, - interface->cur_altsetting->desc.bInterfaceNumber); - } else - return -ENOMEM; - - /* set private data to usb_interface */ - usb_set_intfdata(interface, sdev); - - stub_add_files(&interface->dev); - - return 0; -} - - -/* - * called in usb_disconnect() or usb_deregister() - * but only if actconfig(active configuration) exists - */ -static void stub_disconnect(struct usb_interface *interface) -{ - struct stub_device *sdev = usb_get_intfdata(interface); - - udbg("Enter\n"); - - /* get stub_device */ - if (!sdev) - BUG(); - - usb_set_intfdata(interface, NULL); - - - /* - * NOTE: - * rx/tx threads are invoked for each usb_device. - */ - stub_remove_files(&interface->dev); - - /* 1. shutdown the current connection */ - usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED); - - /* 2. wait for the stop of the event handler */ - usbip_stop_eh(&sdev->ud); - - /* 3. free sdev */ - stub_device_free(sdev); - - - udbg("bye\n"); -} diff -Naur usbip-0.1.4/drivers/2.6.18/stub.h trunk/drivers/2.6.18/stub.h --- usbip-0.1.4/drivers/2.6.18/stub.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/stub.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,96 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include -#include - -struct stub_device { - struct usb_interface *interface; - struct list_head list; - - struct usbip_device ud; - - /* - * stub_priv preserves private data of each urb. - * It is allocated as stub_priv_cache and assigned to urb->context. - * - * stub_priv is always linked to any one of 3 lists; - * priv_init: linked to this until the comletion of a urb. - * priv_tx : linked to this after the completion of a urb. - * priv_free: linked to this after the sending of the result. - * - * Any of these list operations should be locked by priv_lock. - */ - spinlock_t priv_lock; - struct list_head priv_init; - struct list_head priv_tx; - struct list_head priv_free; - - /* see comments for unlinking in stub_rx.c */ - struct list_head unlink_tx; - struct list_head unlink_free; - - - wait_queue_head_t tx_waitq; -}; - -/* private data into urb->priv */ -struct stub_priv { - unsigned long seqnum; - struct list_head list; - struct stub_device *sdev; - struct urb *urb; - - int unlinking; -}; - -struct stub_unlink { - unsigned long seqnum; - struct list_head list; - __u32 status; -}; - - -extern kmem_cache_t *stub_priv_cache; - - -/*-------------------------------------------------------------------------*/ -/* prototype declarations */ - -/* stub_tx.c */ -void stub_complete(struct urb*, struct pt_regs *); -void stub_tx_loop(struct usbip_task *); - -/* stub_dev.c */ -extern struct usb_driver stub_driver; - -/* stub_rx.c */ -void stub_rx_loop(struct usbip_task *); -void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32); - -/* stub_main.c */ -int match_busid(char *busid); -void stub_device_cleanup_urbs(struct stub_device *sdev); diff -Naur usbip-0.1.4/drivers/2.6.18/stub_main.c trunk/drivers/2.6.18/stub_main.c --- usbip-0.1.4/drivers/2.6.18/stub_main.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/stub_main.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,300 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "stub.h" - -/* Version Information */ -#define DRIVER_VERSION "$Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $" -#define DRIVER_AUTHOR "Takahiro Hirofuchi " -#define DRIVER_DESC "Stub Driver for USB/IP" - - - -/* stub_priv is allocated from stub_priv_cache */ -kmem_cache_t *stub_priv_cache = NULL; - - -/*-------------------------------------------------------------------------*/ - -/* Define sysfs entries for the usbip driver */ - - -/* - * busid_tables defines matching busids that usbip can grab. A user can change - * dynamically what device is locally used and what device is exported to a - * remote host. - */ -#define MAX_BUSID 16 -static char busid_table[MAX_BUSID][BUS_ID_SIZE]; -spinlock_t busid_table_lock = SPIN_LOCK_UNLOCKED; - - -int match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* already registerd */ - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return 1; -} - -static ssize_t show_match_busid(struct device_driver *drv, char *buf) -{ - int i; - char *out = buf; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (busid_table[i][0]) - out += sprintf(out, "%s ", busid_table[i]); - - spin_unlock(&busid_table_lock); - - out += sprintf(out, "\n"); - - return out - buf; -} - -static int add_match_busid(char *busid) -{ - int i; - - if (!match_busid(busid)) - return 0; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!busid_table[i][0]) { - strncpy(busid_table[i], busid, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static int del_match_busid(char *busid) -{ - int i; - - spin_lock(&busid_table_lock); - - for (i = 0; i < MAX_BUSID; i++) - if (!strncmp(busid_table[i], busid, BUS_ID_SIZE)) { - /* found */ - memset(busid_table[i], 0, BUS_ID_SIZE); - spin_unlock(&busid_table_lock); - return 0; - } - - spin_unlock(&busid_table_lock); - - return -1; -} - -static ssize_t store_match_busid(struct device_driver *dev, const char *buf, - size_t count) -{ - int len; - char busid[BUS_ID_SIZE]; - - if (count < 5) - return -EINVAL; - - /* strnlen() does not include \0 */ - len = strnlen(buf + 4, BUS_ID_SIZE); - - /* busid needs to include \0 termination */ - if (!(len < BUS_ID_SIZE)) - return -EINVAL; - - strncpy(busid, buf + 4, BUS_ID_SIZE); - - - if (!strncmp(buf, "add ", 4)) { - if (add_match_busid(busid) < 0) - return -ENOMEM; - else { - udbg("add busid %s\n", busid); - return count; - } - } else if (!strncmp(buf, "del ", 4)) { - if (del_match_busid(busid) < 0) - return -ENODEV; - else { - udbg("del busid %s\n", busid); - return count; - } - } else - return -EINVAL; -} - -static DRIVER_ATTR(match_busid, S_IRUSR|S_IWUSR, show_match_busid, store_match_busid); - - - -/*-------------------------------------------------------------------------*/ - -/* Cleanup functions used to free private data */ - -static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead) -{ - struct stub_priv *priv, *tmp; - - list_for_each_entry_safe(priv, tmp, listhead, list) { - list_del(&priv->list); - return priv; - } - - return NULL; -} - -static struct stub_priv *stub_priv_pop(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = stub_priv_pop_from_listhead(&sdev->priv_init); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_tx); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - priv = stub_priv_pop_from_listhead(&sdev->priv_free); - if (priv) { - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return NULL; -} - -void stub_device_cleanup_urbs(struct stub_device *sdev) -{ - struct stub_priv *priv; - - udbg("free sdev %p\n", sdev); - - while ((priv = stub_priv_pop(sdev))) { - struct urb *urb = priv->urb; - - udbg(" free urb %p\n", urb); - usb_kill_urb(urb); - - kmem_cache_free(stub_priv_cache, priv); - - if (urb->transfer_buffer != NULL) - kfree(urb->transfer_buffer); - - if (urb->setup_packet != NULL) - kfree(urb->setup_packet); - - usb_free_urb(urb); - } -} - - -/*-------------------------------------------------------------------------*/ - -static int __init usb_stub_init(void) -{ - int ret; - - stub_priv_cache = kmem_cache_create("stub_priv", sizeof(struct stub_priv), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (!stub_priv_cache) { - uerr("create stub_priv_cache\n"); - return -ENOMEM; - } - - ret = usb_register(&stub_driver); - if (ret) { - uerr("usb_register failed %d\n", ret); - return ret; - } - - - info(DRIVER_DESC "" DRIVER_VERSION); - - memset(busid_table, 0, sizeof(busid_table)); - - driver_create_file(&stub_driver.driver, &driver_attr_match_busid); - - return ret; -} - -static void __exit usb_stub_exit(void) -{ - int ret; - - udbg("enter\n"); - - driver_remove_file(&stub_driver.driver, &driver_attr_match_busid); - - /* - * deregister() calls stub_disconnect() for all devices. Device - * specific data is cleared in stub_disconnect(). - */ - usb_deregister(&stub_driver); - - ret = kmem_cache_destroy(stub_priv_cache); - if (ret != 0) { - uerr("memory leak of stub_priv, %d\n", ret); - } - - udbg("bye\n"); -} - - - - -module_init (usb_stub_init); -module_exit (usb_stub_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff -Naur usbip-0.1.4/drivers/2.6.18/stub_rx.c trunk/drivers/2.6.18/stub_rx.c --- usbip-0.1.4/drivers/2.6.18/stub_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/stub_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,442 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static int is_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_CLEAR_FEATURE) && - (req->bRequestType == USB_RECIP_ENDPOINT) && - (req->wValue == USB_ENDPOINT_HALT); -} - -static int is_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_INTERFACE) && - (req->bRequestType == USB_RECIP_INTERFACE); -} - -static int is_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - return (req->bRequest == USB_REQ_SET_CONFIGURATION) && - (req->bRequestType == USB_RECIP_DEVICE); -} - -static int tweak_clear_halt_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - int target_endp; - int target_dir; - int target_pipe; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - - /* - * The stalled endpoint is specified in the wIndex value. The endpoint - * of the urb is the target of this clear_halt request (i.e. control - * endpoint). - */ - target_endp = le16_to_cpu(req->wIndex) & 0x000f; - - /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80. */ - target_dir = le16_to_cpu(req->wIndex) & 0x0080; - - if (target_dir) - target_pipe = usb_rcvctrlpipe(urb->dev, target_endp); - else - target_pipe = usb_sndctrlpipe(urb->dev, target_endp); - - ret = usb_clear_halt(urb->dev, target_pipe); - if (ret < 0) - uinfo("clear_halt error: devnum %d endp %d, %d\n", - urb->dev->devnum, target_endp, ret); - else - uinfo("clear_halt done: devnum %d endp %d\n", - urb->dev->devnum, target_endp); - - return ret; -} - -static int tweak_set_interface_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 alternate; - __u16 interface; - int ret; - - req = (struct usb_ctrlrequest *) urb->setup_packet; - alternate = le16_to_cpu(req->wValue); - interface = le16_to_cpu(req->wIndex); - - dbg_stub_rx("set_interface: inf %u alt %u\n", interface, alternate); - - ret = usb_set_interface(urb->dev, interface, alternate); - if (ret < 0) - uinfo("set_interface error: inf %u alt %u, %d\n", - interface, alternate, ret); - else - uinfo("set_interface done: inf %u alt %u\n", interface, alternate); - - return ret; -} - -static int tweak_set_configuration_cmd(struct urb *urb) -{ - struct usb_ctrlrequest *req; - __u16 config; - - info("set_configuration is not fully supported yet\n"); - - req = (struct usb_ctrlrequest *) urb->setup_packet; - config = le16_to_cpu(req->wValue); - - uinfo("set_configuration: devnum %d %d\n", urb->dev->devnum, config); - -#if 0 - return usb_set_configuration(urb->dev, config); -#endif - return 0; -} - -/* - * clear_halt, set_interface, and set_configuration require special tricks. - * TODO: set_configuration. but I have never seen a multi-config device. - */ -static void tweak_special_requests(struct urb *urb) -{ - if (!urb || !urb->setup_packet) - return; - - if (usb_pipetype(urb->pipe) != PIPE_CONTROL) - return; - - if (is_clear_halt_cmd(urb)) - /* treak clear_halt */ - tweak_clear_halt_cmd(urb); - - else if (is_set_interface_cmd(urb)) - /* tweak set_interface */ - tweak_set_interface_cmd(urb); - - else if (is_set_configuration_cmd(urb)) - /* tweak set_configuration */ - tweak_set_configuration_cmd(urb); - - else - dbg_stub_rx("no need to tweak\n"); -} - -/* - * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb(). - * By unlinking the urb asynchronously, stub_rx can continuously - * process coming urbs. Even if the urb is unlinked, its completion - * handler will be called and stub_tx will send a return pdu. - * - * See also comments about unlinking strategy in vhci_hcd.c. - */ -static int stub_recv_cmd_unlink(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct list_head *listhead = &sdev->priv_init; - struct list_head *ptr; - unsigned long flags; - - struct stub_priv *priv; - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - for (ptr = listhead->next; ptr != listhead; ptr = ptr->next) { - priv = list_entry(ptr, struct stub_priv, list); - if (priv->seqnum == pdu->u.cmd_unlink.seqnum) { - int ret; - - uinfo("unlink urb %p\n", priv->urb); - - /* - * This matched urb is not completed yet (i.e. be in - * flight in usb hcd hardware/driver). Now we are - * cancelling it. The unlinking flag means that we are - * now not going to return the normal result pdu of a - * submittion request, but going to return a result pdu - * of the unlink request. - */ - priv->unlinking = 1; - - /* - * In the case that unlinking flag is on, prev->seqnum - * is changed from the seqnum of the cancelling urb to - * the seqnum of the unlink request. This will be used - * to make the result pdu of the unlink request. - */ - priv->seqnum = pdu->base.seqnum; - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* - * usb_unlink_urb() is now out of spinlocking to avoid - * spinlock recursion since stub_complete() is - * sometimes called in this context but not in the - * interrupt context. If stub_complete() is executed - * before we call usb_unlink_urb(), usb_unlink_urb() - * will return an error value. In this case, stub_tx - * will return the result pdu of this unlink request - * though submission is completed and actual unlinking - * is not executed. OK? - */ - ret = usb_unlink_urb(priv->urb); - if (ret != -EINPROGRESS) - uerr("faild to unlink a urb %p, ret %d\n", priv->urb, ret); - - return 0; - } - } - - dbg_stub_rx("seqnum %d is not pending\n", pdu->u.cmd_unlink.seqnum); - - /* - * The urb of the unlink target is not found in priv_init queue. It was - * already completed and its results is/was going to be sent by a - * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only - * return the completeness of this unlink request to vhci_hcd. - */ - stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - - return 0; -} - -static int valid_request(struct stub_device *sdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &sdev->ud; - - int bus = interface_to_busnum(sdev->interface); - int dev = interface_to_devnum(sdev->interface); - - if (pdu->base.busnum == bus && pdu->base.devnum == dev) { - spin_lock(&ud->lock); - if (ud->status == SDEV_ST_USED) { - /* A request is valid. */ - spin_unlock(&ud->lock); - return 1; - } - spin_unlock(&ud->lock); - } - - return 0; -} - -static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, - struct usbip_header *pdu) -{ - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - unsigned long flags; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - priv = kmem_cache_alloc(stub_priv_cache, GFP_ATOMIC); - if (!priv) { - uerr("alloc stub_priv\n"); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return NULL; - } - - memset(priv, 0, sizeof(struct stub_priv)); - - priv->seqnum = pdu->base.seqnum; - priv->sdev = sdev; - - /* - * After a stub_priv is linked to a list_head, - * our error handler can free allocated data. - */ - list_add_tail(&priv->list, &sdev->priv_init); - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return priv; -} - -static void stub_recv_cmd_submit(struct stub_device *sdev, struct usbip_header *pdu) -{ - int ret; - struct stub_priv *priv; - struct usbip_device *ud = &sdev->ud; - - - priv = stub_priv_alloc(sdev, pdu); - if (!priv) - return; - - /* setup a urb */ - if (usb_pipeisoc(pdu->base.pipe)) - priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets, GFP_KERNEL); - else - priv->urb = usb_alloc_urb(0, GFP_KERNEL); - - if (!priv->urb) { - uerr("malloc urb\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - - /* set priv->urb->transfer_buffer */ - if (pdu->u.cmd_submit.transfer_buffer_length > 0) { - priv->urb->transfer_buffer = - kzalloc(pdu->u.cmd_submit.transfer_buffer_length, GFP_KERNEL); - if (!priv->urb->transfer_buffer) { - uerr("malloc x_buff\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - } - - /* set priv->urb->setup_packet */ - priv->urb->setup_packet = kzalloc(8, GFP_KERNEL); - if (!priv->urb->setup_packet) { - uerr("allocate setup_packet\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC); - return; - } - memcpy(priv->urb->setup_packet, &pdu->u.cmd_submit.setup, 8); - - /* set other members from the base header of pdu */ - priv->urb->context = (void *) priv; - priv->urb->dev = interface_to_usbdev(sdev->interface); - priv->urb->pipe = pdu->base.pipe; - priv->urb->complete = stub_complete; - - usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0); - - - if (usbip_recv_xbuff(ud, priv->urb) < 0) - return; - - if (usbip_recv_iso(ud, priv->urb) < 0) - return; - - tweak_special_requests(priv->urb); - - /* urb is now ready to submit */ - ret = usb_submit_urb(priv->urb, GFP_KERNEL); - - if (ret == 0) - dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum); - else { - uerr("submit_urb error, %d\n", ret); - - /* - * Pessimistic. - * This connection will be discared. - */ - usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); - } - - dbg_stub_rx("Leave\n"); - return; -} - -/* recv a pdu */ -static void stub_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - - dbg_stub_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_stub_rx) - usbip_dump_header(&pdu); - - if (!valid_request(sdev, &pdu)) { - uerr("recv invalid request\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - - switch (pdu.base.command) { - case USBIP_CMD_UNLINK: - stub_recv_cmd_unlink(sdev, &pdu); - break; - - case USBIP_CMD_SUBMIT: - stub_recv_cmd_submit(sdev, &pdu); - break; - - default: - /* NOTREACHED */ - uerr("unknown pdu\n"); - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - return; - } - -} - -void stub_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - while (1) { - if (signal_pending(current)) { - dbg_stub_rx("signal catched!\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - stub_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.18/stub_tx.c trunk/drivers/2.6.18/stub_tx.c --- usbip-0.1.4/drivers/2.6.18/stub_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/stub_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,374 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "stub.h" - - -static void stub_free_priv_and_urb(struct stub_priv *priv) -{ - struct urb *urb = priv->urb; - - if (urb->setup_packet) - kfree(urb->setup_packet); - - if (urb->transfer_buffer) - kfree(urb->transfer_buffer); - - list_del(&priv->list); - kmem_cache_free(stub_priv_cache, priv); - - usb_free_urb(urb); -} - -/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */ -void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum, __u32 status) -{ - struct stub_unlink *unlink; - - unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("alloc stub_unlink\n"); - usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - unlink->seqnum = seqnum; - unlink->status = status; - - list_add_tail(&unlink->list, &sdev->unlink_tx); -} - -/** - * stub_complete - completion handler of a usbip urb - * @urb: pointer to the urb completed - * @regs: - * - * When a urb has completed, the USB core driver calls this function mostly in - * the interrupt context. To return the result of a urb, the completed urb is - * linked to the pending list of returning. - * - */ -void stub_complete(struct urb *urb, struct pt_regs *regs) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - struct stub_device *sdev = priv->sdev; - unsigned long flags; - - dbg_stub_tx("complete! status %d\n", urb->status); - - - switch (urb->status) { - case 0: - /* OK */ - break; - case -ENOENT: - uinfo("stopped by a call of usb_kill_urb()" - "because of cleaning up a virtual connection\n"); - return; - case -ECONNRESET: - uinfo("unlinked by a call of usb_unlink_urb()\n"); - break; - case -EPIPE: - uinfo("endpoint %d is stalled\n", usb_pipeendpoint(urb->pipe)); - break; - case -ESHUTDOWN: - uinfo("device removed?\n"); - break; - default: - uinfo("urb completion with non-zero status %d\n", urb->status); - } - - /* link a urb to the queue of tx. */ - spin_lock_irqsave(&sdev->priv_lock, flags); - - if (priv->unlinking) { - stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status); - stub_free_priv_and_urb(priv); - } else - list_move_tail(&priv->list, &sdev->priv_tx); - - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - /* wake up tx_thread */ - wake_up(&sdev->tx_waitq); -} - - -/*-------------------------------------------------------------------------*/ -/* fill PDU */ - -static inline void setup_base_pdu(struct usbip_header_basic *base, - __u32 command, __u32 seqnum) -{ - base->command = command; - base->busnum = 0; - base->devnum = 0; - base->seqnum = seqnum; - base->pipe = 0; -} - -static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb) -{ - struct stub_priv *priv = (struct stub_priv *) urb->context; - - setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum); - - usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1); -} - -static void setup_ret_unlink_pdu(struct usbip_header *rpdu, - struct stub_unlink *unlink) -{ - setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum); - - rpdu->u.ret_unlink.status = unlink->status; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_SUBMIT */ - -static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) { - list_move_tail(&priv->list, &sdev->priv_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - -static int stub_send_ret_submit(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_priv *priv, *tmp; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(sdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_ret_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (usb_pipein(urb->pipe) && urb->actual_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->actual_length; - txsize += urb->actual_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - if (iso_buffer) - kfree(iso_buffer); - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) { - stub_free_priv_and_urb(priv); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ -/* send RET_UNLINK */ - -static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) { - list_move_tail(&unlink->list, &sdev->unlink_free); - spin_unlock_irqrestore(&sdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return NULL; -} - - -static int stub_send_ret_unlink(struct stub_device *sdev) -{ - unsigned long flags; - struct stub_unlink *unlink, *tmp; - - struct msghdr msg; - struct kvec iov[1]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum); - - /* 1. setup usbip_header */ - setup_ret_unlink_pdu(&pdu_header, unlink); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_stub_tx("send txdata\n"); - - total_size += txsize; - } - - - spin_lock_irqsave(&sdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock_irqrestore(&sdev->priv_lock, flags); - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void stub_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct stub_device *sdev = container_of(ud, struct stub_device, ud); - - while (1) { - if (signal_pending(current)) { - dbg_stub_tx("signal catched\n"); - break; - } - - if (usbip_event_happend(ud)) - break; - - /* - * send_ret_submit comes earlier than send_ret_unlink. stub_rx - * looks at only priv_init queue. If the completion of a URB is - * earlier than the recieve of CMD_UNLINK, priv is moved to - * priv_tx queue and stub_rx does not find the target priv. In - * this case, vhci_rx recieves the result of the submit request - * and then recieves the result of the unlink request. The - * result of the submit is given back to the usbcore as the - * completion of the unlink request. The request of the - * unlink is ignored. This is ok because a driver who calls - * usb_unlink_urb() understands the unlink was too late by - * getting the status of the given-backed URB which has the - * status of usb_submit_urb(). - */ - if (stub_send_ret_submit(sdev) < 0) - break; - - if (stub_send_ret_unlink(sdev) < 0) - break; - - wait_event_interruptible(sdev->tx_waitq, - (!list_empty(&sdev->priv_tx) || - !list_empty(&sdev->unlink_tx))); - } -} diff -Naur usbip-0.1.4/drivers/2.6.18/usbip_common.c trunk/drivers/2.6.18/usbip_common.c --- usbip-0.1.4/drivers/2.6.18/usbip_common.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/usbip_common.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,935 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include -#include -#include -#include "usbip_common.h" - - -/*-------------------------------------------------------------------------*/ -/* debug routines */ - -#ifdef CONFIG_USB_DEBUG -unsigned long usbip_debug_flag = 0xffffffff; -#else -unsigned long usbip_debug_flag = 0; -#endif - -static ssize_t show_flag(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%lx\n", usbip_debug_flag); -} - -static ssize_t store_flag(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long flag; - - sscanf(buf, "%lx", &flag); - usbip_debug_flag = flag; - - return count; -} -DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag); - -static void usbip_dump_buffer(char *buff, int bufflen) -{ - int i; - - if (bufflen > 128) { - for (i = 0; i< 128; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) printk("| "); - if (i%24 == 23) printk("\n"); - } - printk("... (%d byte)\n", bufflen); - return; - } - - for (i = 0; i< bufflen; i++) { - if (i%24 == 0) - printk(" "); - printk("%02x ", (unsigned char ) buff[i]); - if (i%4 == 3) - printk("| "); - if (i%24 == 23) - printk("\n"); - } - printk("\n"); - -} - -static void usbip_dump_pipe(unsigned int p) -{ - unsigned char type = usb_pipetype(p); - unsigned char ep = usb_pipeendpoint(p); - unsigned char dev = usb_pipedevice(p); - unsigned char dir = usb_pipein(p); - - printk("dev(%d) ", dev); - printk("ep(%d) ", ep); - printk("%s ", dir ? "IN" : "OUT"); - - switch(type) { - case PIPE_ISOCHRONOUS : - printk("%s ", "ISO"); - break; - case PIPE_INTERRUPT : - printk("%s ", "INT"); - break; - case PIPE_CONTROL : - printk("%s ", "CTL"); - break; - case PIPE_BULK : - printk("%s ", "BLK"); - break; - default : - printk("ERR"); - } - - printk("\n"); - -} - -static void usbip_dump_usb_device(struct usb_device *dev) -{ - int i; - - if (!dev) { - printk(" dump usb dev: null pointer!!\n"); - return; - } - - printk(" devnum(%d) devpath(%s)", dev->devnum, dev->devpath); - - switch(dev->speed) { - case USB_SPEED_HIGH : - printk(" SPD_HIGH"); - break; - case USB_SPEED_FULL : - printk(" SPD_FULL"); - break; - case USB_SPEED_LOW : - printk(" SPD_LOW"); - break; - case USB_SPEED_UNKNOWN : - printk(" SPD_UNKNOWN"); - break; - default : - printk(" SPD_ERROR"); - } - - printk(" tt %p, ttport %d", dev->tt, dev->ttport); - printk("\n"); - - printk(" "); - for (i = 0; i < 16; i++) { - printk(" %2u", i); - } - - printk("\n"); - - printk(" toggle0(IN) :"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[0] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - printk(" toggle1(OUT):"); - for (i = 0; i< 16; i++) { - printk(" %2u", ( dev->toggle[1] & (1 << i) ) ? 1 : 0); - } - - printk("\n"); - - - printk(" epmaxp_in :"); - for (i = 0; i < 16; i++) { - if (dev->ep_in[i]) - printk(" %2u", dev->ep_in[i]->desc.wMaxPacketSize); - } - - printk("\n"); - - printk(" epmaxp_out :"); - for (i = 0; i < 16; i++) { - if (dev->ep_out[i]) - printk(" %2u", dev->ep_out[i]->desc.wMaxPacketSize); - } - - printk("\n "); - - printk("parent %p, bus %p", dev->parent, dev->bus); - printk("\n "); - - printk("descriptor %p, config %p, actconfig %p, rawdescriptors %p", - &dev->descriptor, dev->config, dev->actconfig, dev->rawdescriptors); - printk("\n "); - - printk("have_langid %d, string_langid %d", dev->have_langid, dev->string_langid); - printk("\n "); - - printk("maxchild %d, children %p", dev->maxchild, dev->children); - - printk("\n"); -} - -static void usbip_dump_request_type(__u8 rt) -{ - switch(rt & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: - printk("DEVICE"); - break; - case USB_RECIP_INTERFACE: - printk("INTERF"); - break; - case USB_RECIP_ENDPOINT: - printk("ENDPOI"); - break; - case USB_RECIP_OTHER: - printk("OTHER "); - break; - default: - printk("------"); - } -} - -static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd) -{ - if (!cmd) { - printk(" %s : null pointer\n", __FUNCTION__); - return; - } - - printk(" "); - printk("bRequestType(%02X) ", cmd->bRequestType); - printk("bRequest(%02X) " , cmd->bRequest); - printk("wValue(%04X) ", cmd->wValue); - printk("wIndex(%04X) ", cmd->wIndex); - printk("wLength(%04X) ", cmd->wLength); - - printk("\n "); - - if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { - printk("STANDARD "); - switch(cmd->bRequest) { - case USB_REQ_GET_STATUS: - printk("GET_STATUS"); - break; - case USB_REQ_CLEAR_FEATURE: - printk("CLEAR_FEAT"); - break; - case USB_REQ_SET_FEATURE: - printk("SET_FEAT "); - break; - case USB_REQ_SET_ADDRESS: - printk("SET_ADDRRS"); - break; - case USB_REQ_GET_DESCRIPTOR: - printk("GET_DESCRI"); - break; - case USB_REQ_SET_DESCRIPTOR: - printk("SET_DESCRI"); - break; - case USB_REQ_GET_CONFIGURATION: - printk("GET_CONFIG"); - break; - case USB_REQ_SET_CONFIGURATION: - printk("SET_CONFIG"); - break; - case USB_REQ_GET_INTERFACE: - printk("GET_INTERF"); - break; - case USB_REQ_SET_INTERFACE: - printk("SET_INTERF"); - break; - case USB_REQ_SYNCH_FRAME: - printk("SYNC_FRAME"); - break; - default: - printk("REQ(%02X) ", cmd->bRequest); - } - - printk(" "); - usbip_dump_request_type(cmd->bRequestType); - - } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) - printk("CLASS "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) - printk("VENDOR "); - - else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) - printk("RESERVED"); - - printk("\n"); -} - -void usbip_dump_urb (struct urb *purb) -{ - if (!purb) { - printk(" dump urb: null pointer!!\n"); - return; - } - - printk(" urb :%p\n", purb); - printk(" dev :%p\n", purb->dev); - - usbip_dump_usb_device(purb->dev); - - printk(" pipe :%08x ", purb->pipe); - - usbip_dump_pipe(purb->pipe); - - printk(" status :%d\n", purb->status); - printk(" transfer_flags :%08X\n", purb->transfer_flags); - printk(" transfer_buffer :%p\n", purb->transfer_buffer); - printk(" transfer_buffer_length:%d\n", purb->transfer_buffer_length); - printk(" actual_length :%d\n", purb->actual_length); - printk(" bandwidth :%d\n", purb->actual_length); - printk(" setup_packet :%p\n", purb->setup_packet); - - if (purb->setup_packet && usb_pipetype(purb->pipe) == PIPE_CONTROL) - usbip_dump_usb_ctrlrequest((struct usb_ctrlrequest *) purb->setup_packet); - - printk(" start_frame :%d\n", purb->start_frame); - printk(" number_of_packets :%d\n", purb->number_of_packets); - printk(" interval :%d\n", purb->interval); - printk(" error_count :%d\n", purb->error_count); - printk(" context :%p\n", purb->context); - printk(" complete :%p\n", purb->complete); -} - -void usbip_dump_header(struct usbip_header *pdu) -{ - udbg("BASE: cmd %u bus %u dev %u seq %u pipe %04x\n", - pdu->base.command, - pdu->base.busnum, - pdu->base.devnum, - pdu->base.seqnum, - pdu->base.pipe); - - usbip_dump_pipe(pdu->base.pipe); - - switch(pdu->base.command) { - case USBIP_CMD_SUBMIT: - udbg("CMD_SUBMIT: x_flags %u x_len %u bw %u sf %u #p %u iv %u\n", - pdu->u.cmd_submit.transfer_flags, - pdu->u.cmd_submit.transfer_buffer_length, - pdu->u.cmd_submit.bandwidth, - pdu->u.cmd_submit.start_frame, - pdu->u.cmd_submit.number_of_packets, - pdu->u.cmd_submit.interval); - break; - case USBIP_CMD_UNLINK: - udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum); - break; - case USBIP_RET_SUBMIT: - udbg("RET_SUBMIT: st %d al %u bw %u sf %d ec %d\n", - pdu->u.ret_submit.status, - pdu->u.ret_submit.actual_length, - pdu->u.ret_submit.bandwidth, - pdu->u.ret_submit.start_frame, - pdu->u.ret_submit.error_count); - case USBIP_RET_UNLINK: - udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status); - break; - default: - /* NOT REACHED */ - udbg("UNKNOWN\n"); - } -} - - -/*-------------------------------------------------------------------------*/ -/* thread routines */ - -int usbip_thread(void *param) -{ - struct usbip_task *ut = (struct usbip_task *) param; - - if (!ut) - return -EINVAL; - - lock_kernel(); - daemonize(ut->name); - allow_signal(SIGKILL); - ut->thread = current; - unlock_kernel(); - - /* srv.rb must wait for rx_thread starting */ - complete(&ut->thread_done); - - /* start of while loop */ - ut->loop_ops(ut); - - /* end of loop */ - ut->thread = NULL; - - complete_and_exit(&ut->thread_done, 0); -} - -void usbip_start_threads(struct usbip_device *ud) -{ - /* - * threads are invoked per one device (per one connection). - */ - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_rx, 0); - kernel_thread((int(*)(void *))usbip_thread, (void *)&ud->tcp_tx, 0); - - /* confirm threads are starting */ - wait_for_completion(&ud->tcp_rx.thread_done); - wait_for_completion(&ud->tcp_tx.thread_done); -} - -void usbip_stop_threads(struct usbip_device *ud) -{ - /* kill threads related to this sdev, if v.c. exists */ - if (ud->tcp_rx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_rx.thread, 1); - wait_for_completion(&ud->tcp_rx.thread_done); - udbg("rx_thread for ud %p has finished\n", ud); - } - - if (ud->tcp_tx.thread != NULL) { - send_sig(SIGKILL, ud->tcp_tx.thread, 1); - wait_for_completion(&ud->tcp_tx.thread_done); - udbg("tx_thread for ud %p has finished\n", ud); - } -} - -void usbip_task_init(struct usbip_task *ut, char *name, - void (*loop_ops)(struct usbip_task *)) -{ - ut->thread = NULL; - init_completion(&ut->thread_done); - ut->name = name; - ut->loop_ops = loop_ops; -} - - -/*-------------------------------------------------------------------------*/ -/* socket routines */ - - /* Send/receive messages over TCP/IP. I refer drivers/block/nbd.c */ -int usbip_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags) -{ - int result; - struct msghdr msg; - struct kvec iov; - int total = 0; - - /* for blocks of if (dbg_flag_xmit) */ - char *bp = buf; - int osize= size; - - dbg_xmit("enter\n"); - - if (!sock || !buf || !size) { - uerr("usbip_xmit: invalid arg, sock %p buff %p size %d\n", - sock, buf, size); - return -EINVAL; - } - - - if (dbg_flag_xmit) { - if (send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: sending... , sock %p, buf %p, size %d, msg_flags %d\n", - sock, buf, size, msg_flags); - usbip_dump_buffer(buf, size); - } - } - - - do { - sock->sk->sk_allocation = GFP_NOIO; - iov.iov_base = buf; - iov.iov_len = size; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_namelen = 0; - msg.msg_flags = msg_flags | MSG_NOSIGNAL; - - if (send) - result = kernel_sendmsg(sock, &msg, &iov, 1, size); - else - result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL); - - if (result <= 0) { - udbg("usbip_xmit: %s sock %p buf %p size %u ret %d total %d\n", - send ? "send" : "receive", sock, buf, size, result, total); - goto err; - } - - size -= result; - buf += result; - total += result; - - } while (size > 0); - - - if (dbg_flag_xmit) { - if (!send) { - if (!in_interrupt()) - printk(KERN_DEBUG "%-10s:", current->comm); - else - printk(KERN_DEBUG "interupt :"); - - printk("usbip_xmit: receiving....\n"); - usbip_dump_buffer(bp, osize); - printk("usbip_xmit: received, osize %d ret %d size %d total %d\n", - osize, result, size, total); - } - - if (send) { - printk("usbip_xmit: send, total %d\n", total); - } - } - - return total; - -err: - return result; -} - -int setquickack(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setnodelay(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -int setkeepalive(struct socket *socket) -{ - mm_segment_t oldfs; - int val = 1; - int ret; - - oldfs = get_fs(); - set_fs(get_ds()); - ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, - (char __user *) &val, sizeof(ret)); - set_fs(oldfs); - - return ret; -} - -void setreuse(struct socket *socket) -{ - socket->sk->sk_reuse = 1; -} - -struct socket *sockfd_to_socket(unsigned int sockfd) -{ - struct socket *socket; - struct file *file; - struct inode *inode; - - file = fget(sockfd); - if (!file) { - uerr("invalid sockfd\n"); - return NULL; - } - - inode = file->f_dentry->d_inode; - - if (!inode || !S_ISSOCK(inode->i_mode)) - return NULL; - - socket = SOCKET_I(inode); - - return socket; -} - - - -/*-------------------------------------------------------------------------*/ -/* pdu routines */ - -/* there may be more cases to tweak the flags. */ -static unsigned int tweak_transfer_flags(unsigned int flags) -{ - - if (flags & URB_NO_TRANSFER_DMA_MAP) - /* - * vhci_hcd does not provide DMA-mapped I/O. The upper - * driver does not need to set this flag. The remote - * usbip.ko does not still perform DMA-mapped I/O for - * DMA-caplable host controllers. So, clear this flag. - */ - flags &= ~URB_NO_TRANSFER_DMA_MAP; - - if (flags & URB_NO_SETUP_DMA_MAP) - flags &= ~URB_NO_SETUP_DMA_MAP; - - return flags; -} - -static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit; - - /* - * Some members are not still implemented in usbip. I hope this issue - * will be discussed when usbip is ported to other operating systems. - */ - if (pack) { - /* vhci_tx.c */ - spdu->transfer_flags = tweak_transfer_flags(urb->transfer_flags); - - spdu->transfer_buffer_length = urb->transfer_buffer_length; - spdu->bandwidth = urb->bandwidth; - spdu->start_frame = urb->start_frame; - spdu->number_of_packets = urb->number_of_packets; - spdu->interval = urb->interval; - } else { - /* stub_rx.c */ - urb->transfer_flags = spdu->transfer_flags; - - urb->transfer_buffer_length = spdu->transfer_buffer_length; - urb->bandwidth = spdu->bandwidth; - urb->start_frame = spdu->start_frame; - urb->number_of_packets = spdu->number_of_packets; - urb->interval = spdu->interval; - } -} - -static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb, int pack) -{ - struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit; - - if (pack) { - /* stub_tx.c */ - - rpdu->status = urb->status; - rpdu->actual_length = urb->actual_length; - rpdu->bandwidth = urb->bandwidth; - rpdu->start_frame = urb->start_frame; - rpdu->error_count = urb->error_count; - } else { - /* vhci_rx.c */ - - urb->status = rpdu->status; - urb->actual_length = rpdu->actual_length; - urb->bandwidth = rpdu->bandwidth; - urb->start_frame = rpdu->start_frame; - urb->error_count = rpdu->error_count; - } -} - - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack) -{ - switch(cmd) { - case USBIP_CMD_SUBMIT: - usbip_pack_cmd_submit(pdu, urb, pack); - break; - case USBIP_RET_SUBMIT: - usbip_pack_ret_submit(pdu, urb, pack); - break; - default: - /* NOTREACHED */ - BUG(); - } -} - - -static void correct_endian_basic(struct usbip_header_basic *base, int send) -{ - if (send) { - base->command = cpu_to_be32(base->command); - base->busnum = cpu_to_be32(base->busnum); - base->devnum = cpu_to_be32(base->devnum); - base->seqnum = cpu_to_be32(base->seqnum); - base->pipe = cpu_to_be32(base->pipe); - } else { - base->command = be32_to_cpu(base->command); - base->busnum = be32_to_cpu(base->busnum); - base->devnum = be32_to_cpu(base->devnum); - base->seqnum = be32_to_cpu(base->seqnum); - base->pipe = be32_to_cpu(base->pipe); - } -} - -static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu, int send) -{ - if (send) { - pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags); - - cpu_to_be32s(&pdu->transfer_buffer_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->number_of_packets); - cpu_to_be32s(&pdu->interval); - } else { - pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags); - - be32_to_cpus(&pdu->transfer_buffer_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->number_of_packets); - be32_to_cpus(&pdu->interval); - } -} - -static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu, int send) -{ - if (send) { - cpu_to_be32s(&pdu->status); - cpu_to_be32s(&pdu->actual_length); - cpu_to_be32s(&pdu->bandwidth); - cpu_to_be32s(&pdu->start_frame); - cpu_to_be32s(&pdu->error_count); - } else { - be32_to_cpus(&pdu->status); - be32_to_cpus(&pdu->actual_length); - be32_to_cpus(&pdu->bandwidth); - be32_to_cpus(&pdu->start_frame); - be32_to_cpus(&pdu->error_count); - } -} - -static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu, int send) -{ - if (send) - pdu->seqnum = cpu_to_be32(pdu->seqnum); - else - pdu->seqnum = be32_to_cpu(pdu->seqnum); -} - -static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu, int send) -{ - if (send) - cpu_to_be32s(&pdu->status); - else - be32_to_cpus(&pdu->status); -} - -void usbip_header_correct_endian(struct usbip_header *pdu, int send) -{ - __u32 cmd = 0; - - if (send) - cmd = pdu->base.command; - - correct_endian_basic(&pdu->base, send); - - if (!send) - cmd = pdu->base.command; - - switch (cmd) { - case USBIP_CMD_SUBMIT: - correct_endian_cmd_submit(&pdu->u.cmd_submit, send); - break; - case USBIP_RET_SUBMIT: - correct_endian_ret_submit(&pdu->u.ret_submit, send); - break; - - case USBIP_CMD_UNLINK: - correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send); - break; - case USBIP_RET_UNLINK: - correct_endian_ret_unlink(&pdu->u.ret_unlink, send); - break; - - default: - /* NOTREACHED */ - BUG(); - } -} - -static void usbip_iso_pakcet_correct_endian(struct usbip_iso_packet_descriptor *iso, int send) -{ - /* does not need all members. but copy all simply. */ - if (send) { - iso->offset = cpu_to_be32(iso->offset); - iso->length = cpu_to_be32(iso->length); - iso->status = cpu_to_be32(iso->status); - iso->actual_length = cpu_to_be32(iso->actual_length); - } else { - iso->offset = be32_to_cpu(iso->offset); - iso->length = be32_to_cpu(iso->length); - iso->status = be32_to_cpu(iso->status); - iso->actual_length = be32_to_cpu(iso->actual_length); - } -} - -static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso, - struct usb_iso_packet_descriptor *uiso, int pack) -{ - if (pack) { - iso->offset = uiso->offset; - iso->length = uiso->length; - iso->status = uiso->status; - iso->actual_length = uiso->actual_length; - } else { - uiso->offset = iso->offset; - uiso->length = iso->length; - uiso->status = iso->status; - uiso->actual_length = iso->actual_length; - } -} - - -/* must free buffer */ -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - ssize_t size = np * sizeof(*iso); - int i; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return NULL; - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 1); - usbip_iso_pakcet_correct_endian(iso, 1); - } - - *bufflen = size; - - return buff; -} - -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb) -{ - void *buff; - struct usbip_iso_packet_descriptor *iso; - int np = urb->number_of_packets; - int size = np * sizeof(*iso); - int i; - int ret; - - if (!usb_pipeisoc(urb->pipe)) - return 0; - - buff = kzalloc(size, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - ret = usbip_xmit(0, ud->tcp_socket, buff, size, 0); - if (ret != size) { - uerr("recv iso_frame_descriptor, %d\n", ret); - kfree(buff); - - if (ud->side == USBIP_STUB) - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - else - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - - return -EPIPE; - } - - for (i = 0; i < np; i++) { - iso = buff + (i * sizeof(*iso)); - - usbip_iso_pakcet_correct_endian(iso, 0); - usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0); - } - - - kfree(buff); - - return ret; -} - - -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) -{ - int ret; - int size; - - if (ud->side == USBIP_STUB) { - /* stub_rx.c */ - /* the direction of urb must be OUT. */ - if (usb_pipein(urb->pipe)) - return 0; - - size = urb->transfer_buffer_length; - } else { - /* vhci_rx.c */ - /* the direction of urb must be IN. */ - if (usb_pipeout(urb->pipe)) - return 0; - - size = urb->actual_length; - } - - /* no need to recv xbuff */ - if (!(size > 0)) - return 0; - - ret = usbip_xmit(0, ud->tcp_socket, (char *) urb->transfer_buffer, size, 0); - if (ret != size) { - uerr("recv xbuf, %d\n", ret); - if (ud->side == USBIP_STUB) { - usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); - } else { - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return -EPIPE; - } - } - - return ret; -} diff -Naur usbip-0.1.4/drivers/2.6.18/usbip_common.h trunk/drivers/2.6.18/usbip_common.h --- usbip-0.1.4/drivers/2.6.18/usbip_common.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/usbip_common.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,364 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#ifndef __VHCI_COMMON_H -#define __VHCI_COMMON_H - - -#include -#include -#include - -/*-------------------------------------------------------------------------*/ - -/* - * define macros to print messages - */ - -/** - * udbg - print debug messages if CONFIG_USB_DEBUG is defined - * @fmt: - * @args: - */ - -#ifdef CONFIG_USB_DEBUG - -#define udbg(fmt, args...) \ - do{ \ - printk(KERN_DEBUG "%-10s:(%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - }while(0) - -#else /* CONFIG_USB_DEBUG */ - -#define udbg(fmt, args...) do{ }while(0) - -#endif /* CONFIG_USB_DEBUG */ - - -enum { - usbip_debug_xmit = (1 << 0), - usbip_debug_sysfs = (1 << 1), - usbip_debug_urb = (1 << 2), - usbip_debug_eh = (1 << 3), - - usbip_debug_stub_cmp = (1 << 8), - usbip_debug_stub_dev = (1 << 9), - usbip_debug_stub_rx = (1 << 10), - usbip_debug_stub_tx = (1 << 11), - - usbip_debug_vhci_rh = (1 << 8), - usbip_debug_vhci_hc = (1 << 9), - usbip_debug_vhci_rx = (1 << 10), - usbip_debug_vhci_tx = (1 << 11), - usbip_debug_vhci_sysfs = (1 << 12) -}; - -#define dbg_flag_xmit (usbip_debug_flag & usbip_debug_xmit) -#define dbg_flag_vhci_rh (usbip_debug_flag & usbip_debug_vhci_rh) -#define dbg_flag_vhci_hc (usbip_debug_flag & usbip_debug_vhci_hc) -#define dbg_flag_vhci_rx (usbip_debug_flag & usbip_debug_vhci_rx) -#define dbg_flag_vhci_tx (usbip_debug_flag & usbip_debug_vhci_tx) -#define dbg_flag_vhci_sysfs (usbip_debug_flag & usbip_debug_vhci_sysfs) -#define dbg_flag_stub_rx (usbip_debug_flag & usbip_debug_stub_rx) -#define dbg_flag_stub_tx (usbip_debug_flag & usbip_debug_stub_tx) - -extern unsigned long usbip_debug_flag; -extern struct device_attribute dev_attr_usbip_debug; - -#define dbg_with_flag(flag, fmt, args...) \ - do { \ - if(flag & usbip_debug_flag) \ - udbg(fmt , ##args); \ - } while(0) - -#define dbg_sysfs(fmt, args...) dbg_with_flag(usbip_debug_sysfs, fmt , ##args) -#define dbg_xmit(fmt, args...) dbg_with_flag(usbip_debug_xmit, fmt , ##args) -#define dbg_urb(fmt, args...) dbg_with_flag(usbip_debug_urb, fmt , ##args) -#define dbg_eh(fmt, args...) dbg_with_flag(usbip_debug_eh, fmt , ##args) - -#define dbg_vhci_rh(fmt, args...) dbg_with_flag(usbip_debug_vhci_rh, fmt , ##args) -#define dbg_vhci_hc(fmt, args...) dbg_with_flag(usbip_debug_vhci_hc, fmt , ##args) -#define dbg_vhci_rx(fmt, args...) dbg_with_flag(usbip_debug_vhci_rx, fmt , ##args) -#define dbg_vhci_tx(fmt, args...) dbg_with_flag(usbip_debug_vhci_tx, fmt , ##args) -#define dbg_vhci_sysfs(fmt, args...) dbg_with_flag(usbip_debug_vhci_sysfs, fmt , ##args) - -#define dbg_stub_cmp(fmt, args...) dbg_with_flag(usbip_debug_stub_cmp, fmt , ##args) -#define dbg_stub_rx(fmt, args...) dbg_with_flag(usbip_debug_stub_rx, fmt , ##args) -#define dbg_stub_tx(fmt, args...) dbg_with_flag(usbip_debug_stub_tx, fmt , ##args) - - -/** - * uerr - print error messages - * @fmt: - * @args: - */ -#define uerr(fmt, args...) \ - do { \ - printk(KERN_ERR "%-10s: ***ERROR*** (%s,%d) %s: " fmt, \ - (in_interrupt() ? "interrupt" : (current)->comm),\ - __FILE__, __LINE__, __FUNCTION__ , ##args); \ - } while(0) - -/** - * uinfo - print information messages - * @fmt: - * @args: - */ -#define uinfo(fmt, args...) \ - do { \ - printk(KERN_INFO "usbip: " fmt , ## args); \ - } while(0) - - -/*-------------------------------------------------------------------------*/ - -/* - * USB/IP packet headers. - * At now, we define 4 packet types: - * - * - CMD_SUBMIT transfers a USB request. This is corresponding to usb_submit_urb(). - * - RET_RETURN transfers a result of a USB request. - * - CMD_UNLINK transfers an unlink request of a pending USB request. - * - RET_UNLINK transfers an unlink request of a pending USB request. - * - * TODO: - * - * - inter-operability between other OSs - */ - -/* - * A basic header followed by other additional headers. - */ -struct usbip_header_basic { -#define USBIP_CMD_SUBMIT 0x0001 -#define USBIP_CMD_UNLINK 0x0002 -#define USBIP_RET_SUBMIT 0x0003 -#define USBIP_RET_UNLINK 0x0004 - __u32 command; - - __u32 busnum; - __u32 devnum; - __u32 seqnum; /* seaquencial number which identifies URBs */ - __u32 pipe; -} __attribute__ ((packed)); - -/* - * An additional header for a CMD_SUBMIT packet. - */ -struct usbip_header_cmd_submit { - __u32 transfer_flags; - __s32 transfer_buffer_length; - __s32 bandwidth; - __s32 start_frame; - __s32 number_of_packets; - __s32 interval; - unsigned char setup[8]; /* CTRL only */ -}__attribute__ ((packed)); - -/* - * An additional header for a RET_SUBMIT packet. - */ -struct usbip_header_ret_submit { - __s32 status; - __s32 actual_length; /* returned data length */ - __s32 bandwidth; - __s32 start_frame; /* ISO and INT */ - __s32 number_of_packets; /* ISO only */ - __s32 error_count; /* ISO only */ -}__attribute__ ((packed)); - -/* - * An additional header for a CMD_UNLINK packet. - */ -struct usbip_header_cmd_unlink { - __u32 seqnum; /* URB's seqnum which will be unlinked */ -}__attribute__ ((packed)); - - -/* - * An additional header for a RET_UNLINK packet. - */ -struct usbip_header_ret_unlink { - __s32 status; -}__attribute__ ((packed)); - - -/* the same as usb_iso_packet_descriptor but packed for pdu */ -struct usbip_iso_packet_descriptor { - __u32 offset; - __u32 length; /* expected length */ - __u32 actual_length; - __u32 status; -}__attribute__ ((packed)); - - -/* - * All usbip packets use a common header to keep code simple. - */ -struct usbip_header { - struct usbip_header_basic base; - - union { - struct usbip_header_cmd_submit cmd_submit; - struct usbip_header_ret_submit ret_submit; - struct usbip_header_cmd_unlink cmd_unlink; - struct usbip_header_ret_unlink ret_unlink; - } u; -}__attribute__ ((packed)); - - - - -/*-------------------------------------------------------------------------*/ - - -int usbip_xmit(int , struct socket *, char *, int , int ); -int usbip_sendmsg(struct socket *, struct msghdr *, int ); - - -static inline int interface_to_busnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->bus->busnum; -} - -static inline int interface_to_devnum(struct usb_interface *interface) -{ - struct usb_device *udev = interface_to_usbdev(interface); - return udev->devnum; -} - -static inline int interface_to_infnum(struct usb_interface *interface) -{ - return interface->cur_altsetting->desc.bInterfaceNumber; -} - -int setnodelay(struct socket *); -int setquickack(struct socket *); -int setkeepalive(struct socket *socket); -void setreuse(struct socket *); -struct socket *sockfd_to_socket(unsigned int); -int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss); - - -void usbip_dump_urb (struct urb *purb); -void usbip_dump_header(struct usbip_header *pdu); - - -struct usbip_device; - -struct usbip_task { - struct task_struct *thread; - struct completion thread_done; - char *name; - void (*loop_ops)(struct usbip_task *); -}; - -enum usbip_side { - USBIP_VHCI, - USBIP_STUB, -}; - -enum usbip_status { - /* sdev is available. */ - SDEV_ST_AVAILABLE = 0x01, - /* sdev is now used. */ - SDEV_ST_USED, - /* sdev is unusable because of a fatal error. */ - SDEV_ST_ERROR, - - /* vdev does not connect a remote device. */ - VDEV_ST_NULL, - /* vdev is used, but the USB address is not assigned yet */ - VDEV_ST_NOTASSIGNED, - VDEV_ST_USED, - VDEV_ST_ERROR -}; - -/* a common structure for stub_device and vhci_device */ -struct usbip_device{ - enum usbip_side side; - - enum usbip_status status; - - /* lock for status */ - spinlock_t lock; - - struct socket *tcp_socket; - - struct usbip_task tcp_rx; - struct usbip_task tcp_tx; - - /* event handler */ -#define USBIP_EH_SHUTDOWN (1 << 0) -#define USBIP_EH_BYE (1 << 1) -#define USBIP_EH_RESET (1 << 2) -#define USBIP_EH_UNUSABLE (1 << 3) - -#define SDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE ) -#define SDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_SUBMIT ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE ) - -#define VDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_BYE ) -#define VDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) - - unsigned long event; - struct usbip_task eh; - wait_queue_head_t eh_waitq; - - struct eh_ops { - void (*shutdown)(struct usbip_device *); - void (*reset)(struct usbip_device *); - void (*unusable)(struct usbip_device *); - } eh_ops; -}; - - -void usbip_task_init(struct usbip_task *ut, char *, void (*loop_ops)(struct usbip_task *)); - -void usbip_start_threads(struct usbip_device *ud); -void usbip_stop_threads(struct usbip_device *ud); -int usbip_thread(void *param); - -void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack); -void usbip_header_correct_endian(struct usbip_header *pdu, int send); -/* some members of urb must be substituted before. */ -int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb); -/* some members of urb must be substituted before. */ -int usbip_recv_iso(struct usbip_device *ud, struct urb *urb); -void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen); - - -/* usbip_event.c */ -void usbip_start_eh(struct usbip_device *ud); -void usbip_stop_eh(struct usbip_device *ud); -void usbip_event_add(struct usbip_device *ud, unsigned long event); -int usbip_event_happend(struct usbip_device *ud); - - -#endif diff -Naur usbip-0.1.4/drivers/2.6.18/usbip_event.c trunk/drivers/2.6.18/usbip_event.c --- usbip-0.1.4/drivers/2.6.18/usbip_event.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/usbip_event.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,153 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" - - - - -static void event_handler_loop(struct usbip_task *eh); - -void usbip_start_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - init_waitqueue_head(&ud->eh_waitq); - ud->event = 0; - - usbip_task_init(eh, "usbip_eh", event_handler_loop); - - kernel_thread((int(*)(void *)) usbip_thread, (void *) eh, 0); - - wait_for_completion(&eh->thread_done); -} - -void usbip_stop_eh(struct usbip_device *ud) -{ - struct usbip_task *eh = &ud->eh; - - wait_for_completion(&eh->thread_done); - dbg_eh("usbip_eh has finished\n"); -} - - -void usbip_event_add(struct usbip_device *ud, unsigned long event) -{ - spin_lock(&ud->lock); - - ud->event |= event; - - wake_up(&ud->eh_waitq); - - spin_unlock(&ud->lock); -} - -int usbip_event_happend(struct usbip_device *ud) -{ - int happend = 0; - - spin_lock(&ud->lock); - - if (ud->event != 0) - happend = 1; - - spin_unlock(&ud->lock); - - return happend; -} - - -static int event_handler(struct usbip_device *ud) -{ - - dbg_eh("enter\n"); - - - /* - * Events are handled by only this thread. - */ - while ( usbip_event_happend(ud) ) { - dbg_eh("pending event %lx\n", ud->event); - - /* - * NOTE: shutdown must come first. - * Shutdown the device. - */ - if (ud->event & USBIP_EH_SHUTDOWN) { - ud->eh_ops.shutdown(ud); - - ud->event &= ~USBIP_EH_SHUTDOWN; - - break; - } - - /* Stop the error handler. */ - if (ud->event & USBIP_EH_BYE) - return -1; - - /* Reset the device. */ - if (ud->event & USBIP_EH_RESET) { - ud->eh_ops.reset(ud); - - ud->event &= ~USBIP_EH_RESET; - - break; - } - - /* Mark the device as unusable. */ - if (ud->event & USBIP_EH_UNUSABLE) { - ud->eh_ops.unusable(ud); - - ud->event &= ~USBIP_EH_UNUSABLE; - - break; - } - - /* NOTREACHED */ - uerr("unknown event\n"); - return -1; - } - - return 0; -} - - - - -static void event_handler_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, eh); - - while (1) { - if (signal_pending(current)) { - dbg_eh("signal catched!\n"); - break; - } - - if ( event_handler(ud) < 0) - break; - - wait_event_interruptible(ud->eh_waitq, usbip_event_happend(ud)); - dbg_eh("wakeup\n"); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.18/vhci.h trunk/drivers/2.6.18/vhci.h --- usbip-0.1.4/drivers/2.6.18/vhci.h 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/vhci.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,143 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include -#include HCD_HEADER - - -struct vhci_device { - struct usb_device *udev; - - /* busnum and devnum of a remote device */ - __u32 busnum; - __u32 devnum; - - /* speed of a remote device */ - enum usb_device_speed speed; - - /* vhci root-hub port to which this device is attached */ - __u32 rhport; - - struct usbip_device ud; - - - /* lock for the below link lists */ - spinlock_t priv_lock; - - /* vhci_priv is linked to one of them. */ - struct list_head priv_tx; - struct list_head priv_rx; - - /* vhci_unlink is linked to one of them */ - struct list_head unlink_tx; - struct list_head unlink_rx; - - /* vhci_tx thread sleeps for this queue */ - wait_queue_head_t waitq_tx; -}; - - -/* urb->hcpriv, use container_of() */ -struct vhci_priv { - unsigned long seqnum; - struct list_head list; - - struct vhci_device *vdev; - struct urb *urb; -}; - - -struct vhci_unlink { - /* seqnum of this request */ - unsigned long seqnum; - - struct list_head list; - - /* seqnum of the unlink target */ - unsigned long unlink_seqnum; -}; - -/* - * The number of ports is less than 16 ? - * USB_MAXCHILDREN is statically defined to 16 in usb.h. Its maximum value - * would be 31 because the event_bits[1] of struct usb_hub is defined as - * unsigned long in hub.h - */ -#define VHCI_NPORTS 8 - -/* for usb_bus.hcpriv */ -struct vhci_hcd { - spinlock_t lock; - - u32 port_status[VHCI_NPORTS]; - - unsigned resuming:1; - unsigned long re_timeout; - - atomic_t seqnum; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - * But, the index of this array begins from 0. - */ - struct vhci_device vdev[VHCI_NPORTS]; - - /* vhci_device which has not been assiged its address yet */ - int pending_port; -}; - - -extern struct vhci_hcd *the_controller; -extern struct attribute_group dev_attr_group; - - -/*-------------------------------------------------------------------------*/ -/* prototype declaration */ - -/* vhci_hcd.c */ -void rh_port_connect(int rhport, enum usb_device_speed speed); -void rh_port_disconnect(int rhport); -void vhci_rx_loop(struct usbip_task *ut); -void vhci_tx_loop(struct usbip_task *ut); - -#define hardware (&the_controller->pdev.dev) - -static inline struct vhci_device *port_to_vdev(__u32 port) -{ - return &the_controller->vdev[port]; -} - -static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd) -{ - return (struct vhci_hcd *) (hcd->hcd_priv); -} - -static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci) -{ - return container_of((void *) vhci, struct usb_hcd, hcd_priv); -} - -static inline struct device *vhci_dev(struct vhci_hcd *vhci) -{ - return vhci_to_hcd(vhci)->self.controller; -} diff -Naur usbip-0.1.4/drivers/2.6.18/vhci_hcd.c trunk/drivers/2.6.18/vhci_hcd.c --- usbip-0.1.4/drivers/2.6.18/vhci_hcd.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/vhci_hcd.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,1174 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - - -#include "usbip_common.h" -#include "vhci.h" - -#define DRIVER_VERSION " $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ " -#define DRIVER_AUTHOR "HIROFUCHI Takahiro " -#define DRIVER_DESC "Virtual Host Controller Interface Driver for USB/IP" -#define DRIVER_LICENCE "GPL" -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE(DRIVER_LICENCE); - - - -/* - * TODO - * - update root hub emulation - * - move the emulation code to userland ? - * poring to other operating systems - * minimize kernel code - * - add suspend/resume code - * - clean up everything - */ - - -/* See usb gadget dummy hcd */ - - -static int vhci_hub_status (struct usb_hcd *hcd, char *buff); -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buff, u16 wLength); -static int vhci_urb_enqueue (struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags); -static int vhci_urb_dequeue( struct usb_hcd *hcd, struct urb *urb); -static int vhci_start(struct usb_hcd *vhci_hcd); -static void vhci_stop(struct usb_hcd *hcd); -static int vhci_get_frame_number(struct usb_hcd *hcd); - -static const char driver_name[] = "vhci_hcd"; -static const char driver_desc[] = "USB/IP Virtual Host Contoroller"; - - - - -struct vhci_hcd *the_controller = NULL; - - -static const char *bit_desc[] = { - "CONNECTION", /*0*/ - "ENABLE", /*1*/ - "SUSPEND", /*2*/ - "OVER_CURRENT", /*3*/ - "RESET", /*4*/ - "R5", /*5*/ - "R6", /*6*/ - "R7", /*7*/ - "POWER", /*8*/ - "LOWSPEED", /*9*/ - "HIGHSPEED", /*10*/ - "PORT_TEST", /*11*/ - "INDICATOR", /*12*/ - "R13", /*13*/ - "R14", /*14*/ - "R15", /*15*/ - "C_CONNECTION", /*16*/ - "C_ENABLE", /*17*/ - "C_SUSPEND", /*18*/ - "C_OVER_CURRENT", /*19*/ - "C_RESET", /*20*/ - "R21", /*21*/ - "R22", /*22*/ - "R23", /*23*/ - "R24", /*24*/ - "R25", /*25*/ - "R26", /*26*/ - "R27", /*27*/ - "R28", /*28*/ - "R29", /*29*/ - "R30", /*30*/ - "R31", /*31*/ -}; - - -static void dump_port_status(u32 status) -{ - int i = 0; - - printk("status %08x:", status); - for (i = 0; i < 32; i++) { - if (status & (1 << i)) { - printk(" %s", bit_desc[i]); - } - } - - printk("\n"); -} - - - -void rh_port_connect(int rhport, enum usb_device_speed speed) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_connect %d\n", rhport); - - spin_lock_irqsave(&the_controller->lock, flags); - - the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION - | (1 << USB_PORT_FEAT_C_CONNECTION); - - switch (speed) { - case USB_SPEED_HIGH: - the_controller->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - the_controller->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - - //spin_lock(&the_controller->vdev[rhport].ud.lock); - //the_controller->vdev[rhport].ud.status = VDEV_CONNECT; - //spin_unlock(&the_controller->vdev[rhport].ud.lock); - - the_controller->pending_port = rhport; - - spin_unlock_irqrestore(&the_controller->lock, flags); - -} - -void rh_port_disconnect(int rhport) -{ - unsigned long flags; - - dbg_vhci_rh("rh_port_disconnect %d\n", rhport); - - spin_lock_irqsave (&the_controller->lock, flags); - //stop_activity (dum, driver); - the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; - the_controller->port_status[rhport] |= (1 << USB_PORT_FEAT_C_CONNECTION); - - - /* not yet complete the disconnection */ - //spin_lock(&vdev->ud.lock); - //vdev->ud.status = VHC_ST_DISCONNECT; - //spin_unlock(&vdev->ud.lock); - - spin_unlock_irqrestore (&the_controller->lock, flags); -} - - - -/*----------------------------------------------------------------------*/ - -#define PORT_C_MASK \ - ((USB_PORT_STAT_C_CONNECTION \ - | USB_PORT_STAT_C_ENABLE \ - | USB_PORT_STAT_C_SUSPEND \ - | USB_PORT_STAT_C_OVERCURRENT \ - | USB_PORT_STAT_C_RESET) << 16) - -/* - * This function is almostly the same as dummy_hcd.c:dummy_hub_status() without - * suspend/resume support. But, it is modified to provide multiple ports. - * - * @buf: a bitmap to show which port status has been changed. - * bit 0: reserved or used for another purpose? - * bit 1: the status of port 0 has been changed. - * bit 2: the status of port 1 has been changed. - * ... - * bit 7: the status of port 6 has been changed. - * bit 8: the status of port 7 has been changed. - * ... - * bit 15: the status of port 14 has been changed. - * - * So, the maximum number of ports is 31 ( port 0 to port 30) ? - * - * The return value is the actual transfered length in byte. If nothing has - * been changed, return 0. In the case that the number of ports is less than or - * equal to 6 (VHCI_NPORTS==7), return 1. - * - */ -static int vhci_hub_status (struct usb_hcd *hcd, char *buf) -{ - struct vhci_hcd *vhci; - unsigned long flags; - int retval = 0; - - /* the enough buffer is allocated according to USB_MAXCHILDREN */ - unsigned long *event_bits = (unsigned long *) buf; - int rhport; - int changed = 0; - - - *event_bits = 0; - - vhci = hcd_to_vhci(hcd); - - spin_lock_irqsave (&vhci->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - dbg_vhci_rh("hw accessible flag in on?\n"); - goto done; - } - - /* check pseudo status register for each port */ - for(rhport = 0; rhport < VHCI_NPORTS; rhport++) { - if ((vhci->port_status[rhport] & PORT_C_MASK)) { - /* The status of a port has been changed, */ - dbg_vhci_rh("port %d is changed\n", rhport); - - *event_bits |= 1 << ( rhport + 1); - changed = 1; - } - } - - if (changed) - retval = 1 + (VHCI_NPORTS / 8); - else - retval = 0; - -done: - spin_unlock_irqrestore (&vhci->lock, flags); - return retval; -} - -/* See hub_configure in hub.c */ -static inline void hub_descriptor(struct usb_hub_descriptor *desc) -{ - memset(desc, 0, sizeof(*desc)); - desc->bDescriptorType = 0x29; - desc->bDescLength = 9; - desc->wHubCharacteristics = (__force __u16) - (__constant_cpu_to_le16 (0x0001)); - desc->bNbrPorts = VHCI_NPORTS; - desc->bitmap [0] = 0xff; - desc->bitmap [1] = 0xff; -} - - -static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) -{ - struct vhci_hcd *dum; - int retval = 0; - unsigned long flags; - int rhport; - - u32 prev_port_status[VHCI_NPORTS]; - - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) - return -ETIMEDOUT; - - /* - * NOTE: - * wIndex shows the port number and begins from 1. - */ - dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue, wIndex); - if (wIndex > VHCI_NPORTS) - uerr("invalid port number %d\n", wIndex); - rhport = ((__u8 ) (wIndex & 0x00ff)) -1; - - dum = hcd_to_vhci(hcd); - - spin_lock_irqsave (&dum->lock, flags); - - /* store old status and compare now and old later */ - if (dbg_flag_vhci_rh) { - int i = 0; - for (i = 0; i < VHCI_NPORTS; i++) - prev_port_status[i] = dum->port_status[i]; - } - - switch (typeReq) { - case ClearHubFeature: - dbg_vhci_rh(" ClearHubFeature\n"); - break; - case ClearPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if (dum->port_status[rhport] & (1 << USB_PORT_FEAT_SUSPEND)) { - /* 20msec signaling */ - dum->resuming = 1; - dum->re_timeout = jiffies + msecs_to_jiffies(20); - } - break; - case USB_PORT_FEAT_POWER: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_POWER\n"); - dum->port_status[rhport] = 0; - //dum->address = 0; - //dum->hdev = 0; - dum->resuming = 0; - break; - case USB_PORT_FEAT_C_RESET: - dbg_vhci_rh(" ClearPortFeature: USB_PORT_FEAT_C_RESET\n"); - switch (dum->vdev[rhport].speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED; - break; - default: - break; - } - default: - dbg_vhci_rh(" ClearPortFeature: default %x\n", wValue); - dum->port_status[rhport] &= ~(1 << wValue); - } - break; - case GetHubDescriptor: - dbg_vhci_rh(" GetHubDescriptor\n"); - hub_descriptor ((struct usb_hub_descriptor *) buf); - break; - case GetHubStatus: - dbg_vhci_rh(" GetHubStatus\n"); - *(u32 *) buf = __constant_cpu_to_le32 (0); - break; - case GetPortStatus: - dbg_vhci_rh(" GetPortStatus port %x\n", wIndex); - if (wIndex > VHCI_NPORTS || wIndex < 1) { - uerr(" invalid port number %d\n", wIndex); - retval = -EPIPE; - } - - /* we do no care of resume. */ - - /* whoever resets or resumes must GetPortStatus to - * complete it!! - * */ - if (dum->resuming && time_after (jiffies, dum->re_timeout)) { - uerr(" not yet\n"); - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_SUSPEND); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_SUSPEND); - dum->resuming = 0; - dum->re_timeout = 0; - //if (dum->driver && dum->driver->resume) { - // spin_unlock (&dum->lock); - // dum->driver->resume (&dum->gadget); - // spin_lock (&dum->lock); - //} - } - - if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) != 0 - && time_after (jiffies, dum->re_timeout)) { - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_C_RESET); - dum->port_status[rhport] &= ~(1 << USB_PORT_FEAT_RESET); - dum->re_timeout = 0; - - if (dum->vdev[rhport].ud.status == VDEV_ST_NOTASSIGNED) { - dbg_vhci_rh(" enable rhport %d (status %u)\n", rhport, dum->vdev[rhport].ud.status); - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - } -#if 0 - if (dum->driver) { - - dum->port_status[rhport] |= USB_PORT_STAT_ENABLE; - /* give it the best speed we agree on */ - dum->gadget.speed = dum->driver->speed; - dum->gadget.ep0->maxpacket = 64; - switch (dum->gadget.speed) { - case USB_SPEED_HIGH: - dum->port_status[rhport] |= - USB_PORT_STAT_HIGH_SPEED; - break; - case USB_SPEED_LOW: - dum->gadget.ep0->maxpacket = 8; - dum->port_status[rhport] |= - USB_PORT_STAT_LOW_SPEED; - break; - default: - dum->gadget.speed = USB_SPEED_FULL; - break; - } - } -#endif - - } - ((u16 *) buf)[0] = cpu_to_le16 (dum->port_status[rhport]); - ((u16 *) buf)[1] = cpu_to_le16 (dum->port_status[rhport] >> 16); - - dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0], ((u16 *)buf)[1] ); - break; - case SetHubFeature: - dbg_vhci_rh(" SetHubFeature\n"); - retval = -EPIPE; - break; - case SetPortFeature: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_SUSPEND\n"); - uerr(" not yet\n"); -#if 0 - dum->port_status[rhport] |= (1 << USB_PORT_FEAT_SUSPEND); - if (dum->driver->suspend) { - spin_unlock (&dum->lock); - dum->driver->suspend (&dum->gadget); - spin_lock (&dum->lock); - } -#endif - break; - case USB_PORT_FEAT_RESET: - dbg_vhci_rh(" SetPortFeature: USB_PORT_FEAT_RESET\n"); - /* if it's already running, disconnect first */ - if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) { - dum->port_status[rhport] &= ~(USB_PORT_STAT_ENABLE - | USB_PORT_STAT_LOW_SPEED - | USB_PORT_STAT_HIGH_SPEED); -#if 0 - if (dum->driver) { - dev_dbg (hardware, "disconnect\n"); - stop_activity (dum, dum->driver); - } -#endif - - /* FIXME test that code path! */ - } - /* 50msec reset signaling */ - dum->re_timeout = jiffies + msecs_to_jiffies(50); - - /* FALLTHROUGH */ - default: - dbg_vhci_rh(" SetPortFeature: default %d\n", wValue); - dum->port_status[rhport] |= (1 << wValue); - } - break; - - default: - uerr(" default: no such request\n"); - //dev_dbg (hardware, - // "hub control req%04x v%04x i%04x l%d\n", - // typeReq, wValue, wIndex, wLength); - - /* "protocol stall" on error */ - retval = -EPIPE; - } - - if (dbg_flag_vhci_rh) { - printk("port %d\n", rhport); - dump_port_status(prev_port_status[rhport]); - dump_port_status(dum->port_status[rhport]); - } - dbg_vhci_rh(" bye\n"); - - spin_unlock_irqrestore (&dum->lock, flags); - - return retval; -} - - - -/*----------------------------------------------------------------------*/ - -static struct vhci_device *get_vdev(struct usb_device *udev) -{ - int i; - - if (!udev) - return NULL; - - for (i=0; i < VHCI_NPORTS; i++) - if (the_controller->vdev[i].udev == udev) - return port_to_vdev(i); - - return NULL; -} - -static void vhci_tx_urb(struct urb *urb) -{ - struct vhci_device *vdev = get_vdev(urb->dev); - struct vhci_priv *priv; - unsigned long flag; - - if (!vdev) - BUG(); - - spin_lock_irqsave(&vdev->priv_lock, flag); - - priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC); - if (!priv) { - uerr("malloc vhci_priv\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flag); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return; - } - - priv->seqnum = atomic_inc_return(&the_controller->seqnum); - if (priv->seqnum == 0xffff) - uinfo("seqnum max\n"); - - priv->vdev = vdev; - priv->urb = urb; - - urb->hcpriv = (void *) priv; - - - list_add_tail(&priv->list, &vdev->priv_tx); - - wake_up(&vdev->waitq_tx); - spin_unlock_irqrestore(&vdev->priv_lock, flag); -} - -static int vhci_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct urb *urb, gfp_t mem_flags) -{ - int ret = 0; - unsigned long flags; - - dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); - - - - /* patch to usb_sg_init() is in 2.5.60 */ - BUG_ON (!urb->transfer_buffer && urb->transfer_buffer_length); - - spin_lock_irqsave (&the_controller->lock, flags); - - /* check HC is active or not */ - if (!HC_IS_RUNNING(hcd->state)) { - uerr("HC is not running\n"); - spin_unlock_irqrestore(&the_controller->lock, flags); - return -ENODEV; - } - - if (urb->status != -EINPROGRESS) { - uerr("URB already unlinked!, status %d\n", urb->status); - spin_unlock_irqrestore(&the_controller->lock, flags); - return urb->status; - } - - /* - * The enumelation process is as follows; - * - * 1. Get_Descriptor request to DevAddrs(0) EndPoint(0) - * to get max packet length of default pipe - * - * 2. Set_Address request to DevAddr(0) EndPoint(0) - * - */ - - if (usb_pipedevice(urb->pipe) == 0) { - __u8 type = usb_pipetype(urb->pipe); - struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; - struct vhci_device *vdev = port_to_vdev(the_controller->pending_port); - - if (type != PIPE_CONTROL || !ctrlreq ) { - uerr("invalid request to devnum 0\n"); - ret = EINVAL; - goto no_need_xmit; - } - - switch (ctrlreq->bRequest) { - - case USB_REQ_SET_ADDRESS: - vdev->udev = urb->dev; - dbg_vhci_hc("SetAddress Request (%d) to port %d\n", - ctrlreq->wValue, vdev->rhport); - - spin_lock(&vdev->ud.lock); - vdev->ud.status = VDEV_ST_USED; - spin_unlock(&vdev->ud.lock); - - spin_lock (&urb->lock); - if (urb->status == -EINPROGRESS) { - /* This request is successfully completed. */ - /* If not -EINPROGRESS, possibly unlinked. */ - urb->status = 0; - } - spin_unlock (&urb->lock); - - goto no_need_xmit; - - case USB_REQ_GET_DESCRIPTOR: - if (ctrlreq->wValue == (USB_DT_DEVICE << 8)) - dbg_vhci_hc("Not yet?: Get_Descriptor to device 0 (get max pipe size)\n"); - - vdev->udev = urb->dev; - goto out; - - default: - /* NOT REACHED */ - uerr("invalid request to devnum 0 bRequest %u, wValue %u\n", - ctrlreq->bRequest, ctrlreq->wValue); - ret = -EINVAL; - goto no_need_xmit; - } - - } - -out: - - - vhci_tx_urb(urb); - - - spin_unlock_irqrestore (&the_controller->lock, flags); - - return 0; - - -no_need_xmit: - - spin_unlock_irqrestore(&the_controller->lock, flags); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - return 0; -} - - -/* - * vhci_rx gives back the urb after recieving the reply of the urb. If an - * unlink pdu is sent or not, vhci_rx recieves a normal return pdu and gives - * back its urb. For the driver unlinking the urb, the content of the urb is - * not important, but the calling to its completion handler is important; the - * completion of unlinking is notified by the completion handler. - * - * - * CLIENT SIDE - * - * - When vhci_hcd recieves RET_SUBMIT, - * - * - case 1a). the urb of the pdu is not unlinking. - * - normal case - * => just give back the urb - * - * - case 1b). the urb of the pdu is unlinking. - * - usbip.ko will return a reply of the unlinking request. - * => give back the urb now and go to case 2b). - * - * - When vhci_hcd recieves RET_UNLINK, - * - * - case 2a). a submit request is still pending in vhci_hcd. - * - urb was really pending in usbip.ko and urb_unlink_urb() was - * completed there. - * => free a pending submit request - * => notify unlink completeness by giving back the urb - * - * - case 2b). a submit request is *not* pending in vhci_hcd. - * - urb was already given back to the core driver. - * => do not give back the urb - * - * - * SERVER SIDE - * - * - When usbip recieves CMD_UNLINK, - * - * - case 3a). the urb of the unlink request is now in submission. - * => do usb_unlink_urb(). - * => after the unlink is completed, send RET_UNLINK. - * - * - case 3b). the urb of the unlink request is not in submission. - * - may be already completed or never be recieved - * => send RET_UNLINK - * - */ -static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -{ - unsigned long flags; - struct vhci_priv *priv; - struct vhci_device *vdev; - - uinfo("vhci_hcd: dequeue a urb %p\n", urb); - - - spin_lock_irqsave(&the_controller->lock, flags); - - priv = urb->hcpriv; - if (!priv) { - /* URB was never linked! or will be soon given back by vhci_rx. */ - spin_unlock_irqrestore(&the_controller->lock, flags); - return 0; - } - - /* send unlink request here? */ - vdev = priv->vdev; - - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - unsigned long flags2; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - uinfo("vhci_hcd: device %p seems to be disconnected\n", vdev); - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - - } else { - /* tcp connection is alive */ - unsigned long flags2; - struct vhci_unlink *unlink; - - spin_lock_irqsave(&vdev->priv_lock, flags2); - - /* setup CMD_UNLINK pdu */ - unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); - if (!unlink) { - uerr("malloc vhci_unlink\n"); - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - spin_unlock_irqrestore(&the_controller->lock, flags); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); - return -ENOMEM; - } - - unlink->seqnum = atomic_inc_return(&the_controller->seqnum); - if (unlink->seqnum == 0xffff) - uinfo("seqnum max\n"); - - unlink->unlink_seqnum = priv->seqnum; - - uinfo("vhci_hcd: device %p seems to be still connected\n", vdev); - - /* send cmd_unlink and try to cancel the pending URB in the peer */ - list_add_tail(&unlink->list, &vdev->unlink_tx); - wake_up(&vdev->waitq_tx); - - spin_unlock_irqrestore(&vdev->priv_lock, flags2); - } - - spin_unlock_irqrestore(&the_controller->lock, flags); - - /* - * If tcp connection is alive, we have sent CMD_UNLINK. - * vhci_rx will recieve RET_UNLINK and giveb back the URB. - * Otherwise, we give back it here. - */ - if (!vdev->ud.tcp_socket) { - /* tcp connection is closed */ - uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n", urb); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - dbg_vhci_hc("leave\n"); - return 0; -} - - -static void vhci_device_unlink_cleanup(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - list_del(&unlink->list); - kfree(unlink); - } - - spin_unlock(&vdev->priv_lock); -} - -/* - * The important thing is that only one context begins cleanup. - * This is why error handling and cleanup become simple. - * We do not want to consider race condition as possible. - */ -static void vhci_shutdown_connection(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - /* need this? see stub_dev.c */ - if (ud->tcp_socket) { - udbg("shutdown tcp_socket %p\n", ud->tcp_socket); - ud->tcp_socket->ops->shutdown(ud->tcp_socket, - RCV_SHUTDOWN|SEND_SHUTDOWN); - } - - usbip_stop_threads(&vdev->ud); - uinfo("stop threads\n"); - - /* active connection is closed */ - if (vdev->ud.tcp_socket != NULL) { - sock_release(vdev->ud.tcp_socket); - vdev->ud.tcp_socket = NULL; - } - uinfo("release socket\n"); - - vhci_device_unlink_cleanup(vdev); - - /* - * rh_port_disconnect() is a trigger of ... - * usb_disable_device(): - * disable all the endpoints for a USB device. - * usb_disable_endpoint(): - * disable endpoints. pending urbs are unlinked(dequeued). - * - * NOTE: After calling rh_port_disconnect(), the USB device driver of a - * deteched device should release used urbs in a cleanup function(i.e. - * xxx_disconnect()). Therefore, vhci_hcd does not need to release - * pushed urbs and their private data in this function. - * - * NOTE: vhci_dequeue() must be considered carefully. When shutdowning - * a connection, vhci_shutdown_connection() expects vhci_dequeue() - * gives back pushed urbs and frees their private data by request of - * the cleanup function of a USB driver. When unlinking a urb with an - * active connection, vhci_dequeue() does not give back the urb which - * is actually given back by vhci_rx after recieving its return pdu. - * - */ - rh_port_disconnect(vdev->rhport); - - uinfo("disconnect device\n"); -} - - -static void vhci_device_reset(struct usbip_device *ud) -{ - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - spin_lock(&ud->lock); - - vdev->busnum = 0; - vdev->devnum = 0; - vdev->speed = 0; - - ud->tcp_socket = NULL; - - ud->status = VDEV_ST_NULL; - - spin_unlock(&ud->lock); -} - -static void vhci_device_unusable(struct usbip_device* ud) -{ - spin_lock(&ud->lock); - - ud->status = VDEV_ST_ERROR; - - spin_unlock(&ud->lock); -} - -static void vhci_device_init(struct vhci_device *vdev) -{ - memset(vdev, 0, sizeof(*vdev)); - - usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop); - usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop); - - vdev->ud.side = USBIP_VHCI; - vdev->ud.status = VDEV_ST_NULL; - vdev->ud.lock = SPIN_LOCK_UNLOCKED; - - INIT_LIST_HEAD(&vdev->priv_rx); - INIT_LIST_HEAD(&vdev->priv_tx); - INIT_LIST_HEAD(&vdev->unlink_tx); - INIT_LIST_HEAD(&vdev->unlink_rx); - vdev->priv_lock = SPIN_LOCK_UNLOCKED; - - init_waitqueue_head(&vdev->waitq_tx); - - vdev->ud.eh_ops.shutdown = vhci_shutdown_connection; - vdev->ud.eh_ops.reset = vhci_device_reset; - vdev->ud.eh_ops.unusable= vhci_device_unusable; - - usbip_start_eh(&vdev->ud); -} - - -/*----------------------------------------------------------------------*/ - -static int vhci_start(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport; - - dbg_vhci_hc("enter vhci_start\n"); - - - /* initialize private data of usb_hcd */ - - for(rhport=0; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - vhci_device_init(vdev); - vdev->rhport = rhport; - } - - atomic_set(&vhci->seqnum, 0); - spin_lock_init(&vhci->lock); - - - - //hcd->power_budget = 0; /* no limit ? */ - hcd->state = HC_STATE_RUNNING; - //hcd->uses_new_polling = 1; - - - /* vhci_hcd is now ready to be controlled through sysfs */ - sysfs_create_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - return 0; -} - -static void vhci_stop(struct usb_hcd *hcd) -{ - struct vhci_hcd *vhci = hcd_to_vhci(hcd); - int rhport = 0; - - dbg_vhci_hc("stop VHCI controller\n"); - - - /* 1. remove the userland interface of vhci_hcd */ - sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group); - - /* 2. shutdown all the ports of vhci_hcd */ - for(rhport = 0 ; rhport < VHCI_NPORTS; rhport++) { - struct vhci_device *vdev = &vhci->vdev[rhport]; - - usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED); - usbip_stop_eh(&vdev->ud); - } - - - uinfo("vhci_stop done\n"); -} - -/*----------------------------------------------------------------------*/ - -static int vhci_get_frame_number(struct usb_hcd *hcd) -{ - uerr("Not yet implemented\n"); - return 0; -} - - -#ifdef CONFIG_PM - -static int vhci_bus_suspend(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -static int vhci_bus_resume(struct usb_hcd *hcd) -{ - dbg("%s\n", __FUNCTION__); - return 0; -} - -#else - -#define vhci_bus_suspend NULL -#define vhci_bus_resume NULL -#endif - - - -static struct hc_driver vhci_hc_driver = { - .description = driver_name, - .product_desc = driver_desc, - .hcd_priv_size = sizeof(struct vhci_hcd), - - .flags = HCD_USB2, - - .start = vhci_start, - .stop = vhci_stop, - - .urb_enqueue = vhci_urb_enqueue, - .urb_dequeue = vhci_urb_dequeue, - - .get_frame_number = vhci_get_frame_number, - - .hub_status_data = vhci_hub_status, - .hub_control = vhci_hub_control, - .bus_suspend = vhci_bus_suspend, - .bus_resume = vhci_bus_resume, -}; - -static int vhci_hcd_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - int ret; - - uinfo("proving...\n"); - - dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id); - - - /* will be removed */ - if (pdev->dev.dma_mask) { - info("vhci_hcd DMA not supported\n"); - return -EINVAL; - } - - - /* - * Allocate and initialize hcd. - * Our private data is also allocated automatically. - */ - hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, pdev->dev.bus_id); - if (!hcd) { - uerr("create hcd failed\n"); - return -ENOMEM; - } - - - /* this is private data for vhci_hcd */ - the_controller = hcd_to_vhci(hcd); - - /* - * Finish generic HCD structure initialization and register. - * Call the driver's reset() and start() routines. - */ - ret = usb_add_hcd(hcd, 0, 0); - if (ret != 0) { - uerr("usb_add_hcd failed %d\n", ret); - usb_put_hcd(hcd); - the_controller = NULL; - return ret; - } - - - dbg_vhci_hc("bye\n"); - return 0; -} - - -static int vhci_hcd_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - - - hcd = platform_get_drvdata(pdev); - if(!hcd) - return 0; - - /* - * Disconnects the root hub, - * then reverses the effects of usb_add_hcd(), - * invoking the HCD's stop() methods. - */ - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - the_controller = NULL; - - - return 0; -} - - - -#ifdef CONFIG_PM - -/* what should happen for USB/IP under suspend/resume? */ -static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = state; - - return 0; -} - -static int vhci_hcd_resume(struct platform_device *pdev) -{ - dev_dbg(pdev->dev, "%s\n", __FUNCTION__); - - pdev->dev.power.power_state = PMSG_ON; - - return 0; -} - -#else - -#define vhci_hcd_suspend NULL -#define vhci_hcd_resume NULL - -#endif - - -static struct platform_driver vhci_driver = { - .probe = vhci_hcd_probe, - .remove = __devexit_p(vhci_hcd_remove), - .suspend = vhci_hcd_suspend, - .resume = vhci_hcd_resume, - .driver = { - .name = (char *) driver_name, - .owner = THIS_MODULE, - }, -}; - -/*----------------------------------------------------------------------*/ - -/* - * The VHCI 'device' is 'virtual'; not a real plug&play hardware. - * We need to add this virtual device as a platform device arbitrarily: - * 1. platform_device_register() - */ -static void the_pdev_release(struct device *dev) -{ - return; -} - -static struct platform_device the_pdev = { - /* should be the same name as driver_name */ - .name = (char *) driver_name, - .id = -1, - .dev = { - //.driver = &vhci_driver, - .release = the_pdev_release, - }, -}; - -static int __init vhci_init(void) -{ - int ret; - - dbg_vhci_hc("enter\n"); - if (usb_disabled()) - return -ENODEV; - - info("driver %s, %s\n", driver_name, DRIVER_VERSION); - - ret = platform_driver_register(&vhci_driver); - if (ret < 0) - goto err_driver_register; - - ret = platform_device_register(&the_pdev); - if (ret < 0) - goto err_platform_device_register; - - - dbg_vhci_hc("bye\n"); - return ret; - - - - /* error occurred */ - -err_platform_device_register: - platform_driver_unregister(&vhci_driver); - -err_driver_register: - - dbg_vhci_hc("bye\n"); - return ret; -} -module_init(vhci_init); - - -static void __exit vhci_cleanup(void) -{ - dbg_vhci_hc("enter\n"); - - platform_device_unregister(&the_pdev); - platform_driver_unregister(&vhci_driver); - - dbg_vhci_hc("bye\n"); -} -module_exit(vhci_cleanup); diff -Naur usbip-0.1.4/drivers/2.6.18/vhci_rx.c trunk/drivers/2.6.18/vhci_rx.c --- usbip-0.1.4/drivers/2.6.18/vhci_rx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/vhci_rx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,239 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - - -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) -{ - struct vhci_priv *priv, *tmp; - struct urb *urb = NULL; - - - spin_lock(&vdev->priv_lock); - - - list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { - if (priv->seqnum == seqnum) { - urb = priv->urb; - dbg_vhci_rx("find urb %p vurb %p seqnum %u\n", urb, priv, seqnum); - - - if (urb->status != -EINPROGRESS) { - if (urb->status == -ENOENT || urb->status == -ECONNRESET) { - uinfo("urb %p was unlinked %ssynchronuously.\n", - urb, urb->status == -ENOENT ? "" : "a"); - } else { - uinfo("urb %p may be in a error, status %d\n", - urb, urb->status); - } - } - - - list_del(&priv->list); - kfree(priv); - urb->hcpriv = NULL; - - - break; - } - } - - spin_unlock(&vdev->priv_lock); - - - return urb; -} - -static void vhci_recv_ret_submit(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct usbip_device *ud = &vdev->ud; - struct urb *urb; - - - urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); - - - if (!urb) { - uerr("cannot find a urb of seqnum %u\n", pdu->base.seqnum); - uinfo("max seqnum %d\n", atomic_read(&the_controller->seqnum)); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - - /* unpack the pdu to a urb */ - usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0); - - - /* recv transfer buffer */ - if (usbip_recv_xbuff(ud, urb) < 0) - return; - - - /* recv iso_packet_descriptor */ - if (usbip_recv_iso(ud, urb) < 0) - return; - - - if (dbg_flag_vhci_rx) - usbip_dump_urb(urb); - - - dbg_vhci_rx("now giveback urb %p\n", urb); - - - - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - - - dbg_vhci_rx("Leave\n"); - - return; -} - - -static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, - struct usbip_header *pdu) -{ - struct vhci_unlink *unlink, *tmp; - - spin_lock(&vdev->priv_lock); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { - uinfo("unlink->seqnum %lu\n", unlink->seqnum); - if (unlink->seqnum == pdu->base.seqnum) { - dbg_vhci_rx("found pending unlink, %lu\n", unlink->seqnum); - list_del(&unlink->list); - - spin_unlock(&vdev->priv_lock); - return unlink; - } - } - - spin_unlock(&vdev->priv_lock); - - return NULL; -} - - -static void vhci_recv_ret_unlink(struct vhci_device *vdev, struct usbip_header *pdu) -{ - struct vhci_unlink *unlink; - struct urb *urb; - - usbip_dump_header(pdu); - - unlink = dequeue_pending_unlink(vdev, pdu); - if (!unlink) { - uinfo("cannot find the pending unlink %u\n", pdu->base.seqnum); - return; - } - - urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); - if (!urb) { - /* - * I get the result of a unlink request. But, it seems that I - * already recieved the result of its submit result and gave - * back the URB. - */ - uinfo("the urb (seqnum %d) was already given backed\n", pdu->base.seqnum); - } else { - dbg_vhci_rx("now giveback urb %p\n", urb); - - /* If unlink is succeed, status is -ECONNRESET */ - urb->status = pdu->u.ret_unlink.status; - uinfo("%d\n", urb->status); - usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, NULL); - } - - kfree(unlink); - - return; -} - -/* recv a pdu */ -static void vhci_rx_pdu(struct usbip_device *ud) -{ - int ret; - struct usbip_header pdu; - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - - dbg_vhci_rx("Enter\n"); - - memset(&pdu, 0, sizeof(pdu)); - - - /* 1. recieve a pdu header */ - ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); - if (ret != sizeof(pdu)) { - uerr("recv a header, %d\n", ret); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - return; - } - - usbip_header_correct_endian(&pdu, 0); - - if (dbg_flag_vhci_rx) - usbip_dump_header(&pdu); - - switch(pdu.base.command) { - case USBIP_RET_SUBMIT: - vhci_recv_ret_submit(vdev, &pdu); - break; - - case USBIP_RET_UNLINK: - vhci_recv_ret_unlink(vdev, &pdu); - break; - default: - /* NOTREACHED */ - uerr("unknown pdu %u\n", pdu.base.command); - usbip_dump_header(&pdu); - usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); - } -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_rx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx); - - - while (1) { - if (signal_pending(current)) { - dbg_vhci_rx("signal catched!\n"); - break; - } - - - if (usbip_event_happend(ud)) break; - - vhci_rx_pdu(ud); - } -} - diff -Naur usbip-0.1.4/drivers/2.6.18/vhci_sysfs.c trunk/drivers/2.6.18/vhci_sysfs.c --- usbip-0.1.4/drivers/2.6.18/vhci_sysfs.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/vhci_sysfs.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,286 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* TODO: refine locking ?*/ - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to show port status */ - -static ssize_t show_status(struct device *dev, struct device_attribute *attr, - char *out) -{ - char *s = out; - int i = 0; - - if (!the_controller || !out) - BUG(); - - spin_lock(&the_controller->lock); - - /* - * output example: - * prt sta bus dev socket local_busid - * 000 004 000 000 c5a7bb80 1-2.3 - * 001 004 000 000 d8cee980 2-3.4 - * - * IP address can be retrieved from a socket pointer address by looking - * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a - * port number and its peer IP address. - */ - out += sprintf(out, "prt sta spd bus dev socket local_busid\n"); - - for (i=0; i < VHCI_NPORTS; i++) { - struct vhci_device *vdev = port_to_vdev(i); - - spin_lock(&vdev->ud.lock); - - out += sprintf(out, "%03u %03u ", i, vdev->ud.status); - - if (vdev->ud.status == VDEV_ST_USED) { - out += sprintf(out, "%03u %03u %03u ", - vdev->speed, vdev->busnum, vdev->devnum); - out += sprintf(out, "%16p ", vdev->ud.tcp_socket); - out += sprintf(out, "%s", vdev->udev->dev.bus_id); - - } else - out += sprintf(out, "000 000 000 0000000000000000 0-0"); - - out += sprintf(out, "\n"); - - spin_unlock(&vdev->ud.lock); - } - - spin_unlock(&the_controller->lock); - - return out - s ; -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to shutdown a virtual connection */ - -static int vhci_port_disconnect(__u32 rhport) -{ - struct vhci_device *vdev; - - dbg_vhci_sysfs("enter\n"); - - /* lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - if (vdev->ud.status == VDEV_ST_NULL) { - uerr("not connected %d\n", vdev->ud.status); - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - return -EINVAL; - } - - /* unlock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); - - return 0; -} - -static ssize_t store_detach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) { - int err; - __u32 rhport = 0; - - sscanf(buf, "%u", &rhport); - - /* check rhport */ - if (rhport >= VHCI_NPORTS) { - uerr("invalid port %u\n", rhport); - return -EINVAL; - } - - err = vhci_port_disconnect(rhport); - if (err < 0) { - return -EINVAL; - } - - dbg_vhci_sysfs("Leave\n"); - return count; -} - -static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach); - - - -/*-------------------------------------------------------------------------*/ - -/* Sysfs entry to establish a virtual connection */ - -static int valid_args(__u32 rhport, __u32 busnum, __u32 devnum, - enum usb_device_speed speed) -{ - /* check rhport */ - if ((rhport < 0) || (rhport >= VHCI_NPORTS)) { - uerr("port %u\n", rhport); - return -EINVAL; - } - - /* check busnum & devnum */ - if ((busnum <= 0) || (busnum >= 128) || (devnum <= 0) || (devnum >= 128)) { - uerr("busnum %u devnum %u\n", busnum, devnum); - return -EINVAL; - } - - /* check speed */ - switch(speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - case USB_SPEED_HIGH: - case USB_SPEED_VARIABLE: - break; - - default: - uerr("speed %d\n", speed); - return -EINVAL; - } - - return 0; -} - -/* - * To start a new USB/IP attachment, a userland program needs to setup a TCP - * connection and then write its socket descriptor with remote device - * information into this sysfs file. - * - * A remote device is virtually attached to the root-hub port of @rhport with - * @speed. @busnum and @devnum are used to convert URBs between a client host - * and a server host. - * - * write() returns 0 on success, else negative errno. - */ -static ssize_t store_attach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vhci_device *vdev; - struct socket *socket; - int sockfd = 0; - __u32 rhport=0, busnum=0, devnum=0, speed=0; - - - /* - * @rhport: port number of vhci_hcd - * @sockfd: socket descriptor of an established TCP connection - * @busnum: usb bus number in a remote host - * @devnum: usb device number in a remote host - * @speed: usb device speed in a remote host - */ - sscanf(buf, "%u %u %u %u %u", &rhport, &sockfd, &busnum, &devnum, &speed); - - dbg_vhci_sysfs("rhport(%u) sockfd(%u) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - - /* check recieved parameters */ - if (valid_args(rhport, busnum, devnum, speed) < 0) - return -EINVAL; - - /* check sockfd */ - socket = sockfd_to_socket(sockfd); - if (!socket) - return -EINVAL; - - setnodelay(socket); - - - /* now need lock until setting vdev status as used */ - - /* begin a lock */ - spin_lock(&the_controller->lock); - - vdev = port_to_vdev(rhport); - - spin_lock(&vdev->ud.lock); - - if (vdev->ud.status != VDEV_ST_NULL) { - /* end of the lock */ - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - - uerr("port %d already used\n", rhport); - return -EINVAL; - } - - uinfo("rhport(%u) sockfd(%d) busnum(%u) devnum(%u) speed(%u)\n", - rhport, sockfd, busnum, devnum, speed); - - vdev->busnum = busnum; - vdev->devnum = devnum; - vdev->speed = speed; - vdev->ud.tcp_socket = socket; - vdev->ud.status = VDEV_ST_NOTASSIGNED; - - spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); - /* end the lock */ - - /* - * this function will sleep, so should be out of the lock. but, it's ok - * because we already marked vdev as being used. really? - */ - usbip_start_threads(&vdev->ud); - - rh_port_connect(rhport, speed); - - return count; -} - -static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach); - - - -/*-------------------------------------------------------------------------*/ - -static struct attribute *dev_attrs[] = { - &dev_attr_status.attr, - &dev_attr_detach.attr, - &dev_attr_attach.attr, - &dev_attr_usbip_debug.attr, - NULL, -}; - -struct attribute_group dev_attr_group = { - .attrs = dev_attrs, -}; diff -Naur usbip-0.1.4/drivers/2.6.18/vhci_tx.c trunk/drivers/2.6.18/vhci_tx.c --- usbip-0.1.4/drivers/2.6.18/vhci_tx.c 2007-05-18 11:37:49.000000000 +0200 +++ trunk/drivers/2.6.18/vhci_tx.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,264 +0,0 @@ -/* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ - * - * Copyright (C) 2003-2006 Takahiro Hirofuchi - * - * - * This 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 of the License, or - * (at your option) any later version. - * - * This 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "usbip_common.h" -#include "vhci.h" - - -/* @p: pipe whose dev number modified - * @pdev: new devive number */ -static unsigned long tweak_pipe_devnum(__u32 p, __u8 pdev) -{ - __u32 oldp; - oldp = p; - - if (pdev > 0x7f) - uerr("invalid devnum %u\n", pdev); - - pdev &= 0x7f; // 0XXX XXXX confirm MSB be 0 - - p &= 0xffff80ff; /* clear p's devnum */ - - p |= (pdev << 8); - - dbg_vhci_tx("return new pipe, devnum %u -> %u \n", - usb_pipedevice(oldp), usb_pipedevice(p)); - dbg_vhci_tx(" pipe %08x -> %08x\n", oldp, p); - - return p; -} - -static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) -{ - struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv); - struct vhci_device *vdev = priv->vdev; - - dbg_vhci_tx("URB, local devnum(%u), busnum(%u) devnum(%u)\n", - usb_pipedevice(urb->pipe), vdev->busnum, vdev->devnum); - - pdup->base.command = USBIP_CMD_SUBMIT; - pdup->base.busnum = vdev->busnum; - pdup->base.devnum = vdev->devnum; - pdup->base.seqnum = priv->seqnum; - pdup->base.pipe = tweak_pipe_devnum(urb->pipe, vdev->devnum); - - usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1); - - if (urb->setup_packet) - memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8); -} - -static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_priv *priv, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { - list_move_tail(&priv->list, &vdev->priv_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return priv; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - - - -static int vhci_send_cmd_submit(struct vhci_device *vdev) -{ - struct vhci_priv *priv = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((priv = dequeue_from_priv_tx(vdev)) != NULL) { - int ret; - struct urb *urb = priv->urb; - struct usbip_header pdu_header; - void *iso_buffer = NULL; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup txdata urb %p\n", urb); - - - /* 1. setup usbip_header */ - setup_cmd_submit_pdu(&pdu_header, urb); - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - /* 2. setup transfer buffer */ - if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) { - iov[1].iov_base = urb->transfer_buffer; - iov[1].iov_len = urb->transfer_buffer_length; - txsize += urb->transfer_buffer_length; - } - - /* 3. setup iso_packet_descriptor */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - ssize_t len = 0; - - iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len); - if (!iso_buffer) { - usbip_event_add(&vdev->ud, SDEV_EVENT_ERROR_MALLOC); - return -1; - } - - iov[2].iov_base = iso_buffer; - iov[2].iov_len = len; - txsize += len; - } - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - if (iso_buffer) - kfree(iso_buffer); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - if (iso_buffer) - kfree(iso_buffer); - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) -{ - unsigned long flags; - struct vhci_unlink *unlink, *tmp; - - spin_lock_irqsave(&vdev->priv_lock, flags); - - list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { - list_move_tail(&unlink->list, &vdev->unlink_rx); - spin_unlock_irqrestore(&vdev->priv_lock, flags); - return unlink; - } - - spin_unlock_irqrestore(&vdev->priv_lock, flags); - - return NULL; -} - -static int vhci_send_cmd_unlink(struct vhci_device *vdev) -{ - struct vhci_unlink *unlink = NULL; - - struct msghdr msg; - struct kvec iov[3]; - size_t txsize; - - size_t total_size = 0; - - while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) { - int ret; - struct usbip_header pdu_header; - - txsize = 0; - memset(&pdu_header, 0, sizeof(pdu_header)); - memset(&msg, 0, sizeof(msg)); - memset(&iov, 0, sizeof(iov)); - - dbg_vhci_tx("setup cmd unlink, %lu \n", unlink->seqnum); - - - /* 1. setup usbip_header */ - pdu_header.base.command = USBIP_CMD_UNLINK; - pdu_header.base.busnum = vdev->busnum; - pdu_header.base.devnum = vdev->devnum; - pdu_header.base.seqnum = unlink->seqnum; - pdu_header.base.pipe = 0; - pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum; - - usbip_header_correct_endian(&pdu_header, 1); - - iov[0].iov_base = &pdu_header; - iov[0].iov_len = sizeof(pdu_header); - txsize += sizeof(pdu_header); - - ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize); - if (ret != txsize) { - uerr("sendmsg failed!, retval %d for %zd\n", ret, txsize); - usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP); - return -1; - } - - - dbg_vhci_tx("send txdata\n"); - - total_size += txsize; - } - - return total_size; -} - - -/*-------------------------------------------------------------------------*/ - -void vhci_tx_loop(struct usbip_task *ut) -{ - struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx); - struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); - - while (1) { - if (signal_pending(current)) { - uinfo("vhci_tx signal catched\n"); - break; - } - - if (vhci_send_cmd_submit(vdev) < 0) - break; - - if (vhci_send_cmd_unlink(vdev) < 0) - break; - - wait_event_interruptible(vdev->waitq_tx, - (!list_empty(&vdev->priv_tx) || - !list_empty(&vdev->unlink_tx))); - - dbg_vhci_tx("pending urbs ?, now wake up\n"); - } -} diff -Naur usbip-0.1.4/drivers/2.6.19/Makefile trunk/drivers/2.6.19/Makefile --- usbip-0.1.4/drivers/2.6.19/Makefile 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/Makefile 2007-05-18 11:10:08.000000000 +0200 @@ -1,6 +1,6 @@ # Makefile for the USB/IP driver # -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ +# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ # # Copyright (C) 2003-2006 Takahiro Hirofuchi # @@ -51,7 +51,11 @@ default: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` modules + make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} M=`pwd` modules + +check: + #make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} C=1 M=`pwd` modules checkstack namespacecheck headers_check + make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} C=1 M=`pwd` modules .PHONY: cscope cscope: @@ -59,5 +63,5 @@ .PHONY: clean clean: - make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} SUBDIRS=`pwd` clean + make -C $(KSOURCE) LANG=C KBUILD_VERBOSE=${KBUILD_VERBOSE} M=`pwd` clean rm -f *.x *~ diff -Naur usbip-0.1.4/drivers/2.6.19/stub_dev.c trunk/drivers/2.6.19/stub_dev.c --- usbip-0.1.4/drivers/2.6.19/stub_dev.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/stub_dev.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -62,7 +62,7 @@ .name = "usbip", .probe = stub_probe, - .disconnect = stub_disconnect, + .disconnect = stub_disconnect, .id_table = stub_table, }; @@ -134,9 +134,11 @@ return -EINVAL; } +#if 0 setnodelay(socket); setkeepalive(socket); setreuse(socket); +#endif sdev->ud.tcp_socket = socket; @@ -330,7 +332,8 @@ sdev->ud.side = USBIP_STUB; sdev->ud.status = SDEV_ST_AVAILABLE; - sdev->ud.lock = SPIN_LOCK_UNLOCKED; + // sdev->ud.lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&sdev->ud.lock); sdev->ud.tcp_socket = NULL; INIT_LIST_HEAD(&sdev->priv_init); @@ -338,7 +341,8 @@ INIT_LIST_HEAD(&sdev->priv_free); INIT_LIST_HEAD(&sdev->unlink_free); INIT_LIST_HEAD(&sdev->unlink_tx); - sdev->priv_lock = SPIN_LOCK_UNLOCKED; + // sdev->priv_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&sdev->priv_lock); init_waitqueue_head(&sdev->tx_waitq); @@ -368,9 +372,12 @@ /* * If a usb device has multiple active interfaces, this driver is bound to all - * the active interfaces. However, usbip exports *a* usb device (i.e. not *an* + * the active interfaces. However, usbip exports *a* usb device (i.e., not *an* * active interface). Currently, a userland program must ensure that it * looks at the usbip's sysfs entries of only the first active interface. + * + * TODO: use "struct usb_device_driver" to bind a usb device. + * However, it seems it is not fully supported in mainline kerenel yet (2.6.19.2). */ static int stub_probe(struct usb_interface *interface, const struct usb_device_id *id) { diff -Naur usbip-0.1.4/drivers/2.6.19/stub.h trunk/drivers/2.6.19/stub.h --- usbip-0.1.4/drivers/2.6.19/stub.h 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/stub.h 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -38,9 +38,9 @@ * It is allocated as stub_priv_cache and assigned to urb->context. * * stub_priv is always linked to any one of 3 lists; - * priv_init: linked to this until the comletion of a urb. - * priv_tx : linked to this after the completion of a urb. - * priv_free: linked to this after the sending of the result. + * priv_init: linked to this until the comletion of a urb. + * priv_tx : linked to this after the completion of a urb. + * priv_free: linked to this after the sending of the result. * * Any of these list operations should be locked by priv_lock. */ @@ -74,7 +74,7 @@ }; -extern kmem_cache_t *stub_priv_cache; +extern struct kmem_cache *stub_priv_cache; /*-------------------------------------------------------------------------*/ diff -Naur usbip-0.1.4/drivers/2.6.19/stub_main.c trunk/drivers/2.6.19/stub_main.c --- usbip-0.1.4/drivers/2.6.19/stub_main.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/stub_main.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -25,14 +25,14 @@ #include "stub.h" /* Version Information */ -#define DRIVER_VERSION "$Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $" +#define DRIVER_VERSION "$Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $" #define DRIVER_AUTHOR "Takahiro Hirofuchi " #define DRIVER_DESC "Stub Driver for USB/IP" /* stub_priv is allocated from stub_priv_cache */ -kmem_cache_t *stub_priv_cache = NULL; +struct kmem_cache *stub_priv_cache = NULL; /*-------------------------------------------------------------------------*/ @@ -47,7 +47,7 @@ */ #define MAX_BUSID 16 static char busid_table[MAX_BUSID][BUS_ID_SIZE]; -spinlock_t busid_table_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t busid_table_lock; int match_busid(char *busid) @@ -261,6 +261,7 @@ info(DRIVER_DESC "" DRIVER_VERSION); memset(busid_table, 0, sizeof(busid_table)); + spin_lock_init(&busid_table_lock); ret = driver_create_file(&stub_driver.drvwrap.driver, &driver_attr_match_busid); if (ret) { diff -Naur usbip-0.1.4/drivers/2.6.19/stub_rx.c trunk/drivers/2.6.19/stub_rx.c --- usbip-0.1.4/drivers/2.6.19/stub_rx.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/stub_rx.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -67,7 +67,7 @@ /* * The stalled endpoint is specified in the wIndex value. The endpoint - * of the urb is the target of this clear_halt request (i.e. control + * of the urb is the target of this clear_halt request (i.e., control * endpoint). */ target_endp = le16_to_cpu(req->wIndex) & 0x000f; @@ -145,7 +145,7 @@ return; if (is_clear_halt_cmd(urb)) - /* treak clear_halt */ + /* tweak clear_halt */ tweak_clear_halt_cmd(urb); else if (is_set_interface_cmd(urb)) @@ -187,11 +187,11 @@ uinfo("unlink urb %p\n", priv->urb); /* - * This matched urb is not completed yet (i.e. be in + * This matched urb is not completed yet (i.e., be in * flight in usb hcd hardware/driver). Now we are * cancelling it. The unlinking flag means that we are * now not going to return the normal result pdu of a - * submittion request, but going to return a result pdu + * submission request, but going to return a result pdu * of the unlink request. */ priv->unlinking = 1; @@ -217,6 +217,10 @@ * though submission is completed and actual unlinking * is not executed. OK? */ + /* In the above case, urb->status is not -ECONNRESET, + * so a driver in a client host will know the failure + * of the unlink request ? + */ ret = usb_unlink_urb(priv->urb); if (ret != -EINPROGRESS) uerr("faild to unlink a urb %p, ret %d\n", priv->urb, ret); @@ -352,6 +356,7 @@ if (usbip_recv_iso(ud, priv->urb) < 0) return; + /* no need to submit an intercepted request, but harmless? */ tweak_special_requests(priv->urb); /* urb is now ready to submit */ @@ -364,7 +369,7 @@ /* * Pessimistic. - * This connection will be discared. + * This connection will be discarded. */ usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT); } @@ -386,7 +391,7 @@ memset(&pdu, 0, sizeof(pdu)); - /* 1. recieve a pdu header */ + /* 1. receive a pdu header */ ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); if (ret != sizeof(pdu)) { uerr("recv a header, %d\n", ret); @@ -429,7 +434,7 @@ while (1) { if (signal_pending(current)) { - dbg_stub_rx("signal catched!\n"); + dbg_stub_rx("signal caught!\n"); break; } diff -Naur usbip-0.1.4/drivers/2.6.19/stub_tx.c trunk/drivers/2.6.19/stub_tx.c --- usbip-0.1.4/drivers/2.6.19/stub_tx.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/stub_tx.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -350,10 +350,10 @@ /* * send_ret_submit comes earlier than send_ret_unlink. stub_rx * looks at only priv_init queue. If the completion of a URB is - * earlier than the recieve of CMD_UNLINK, priv is moved to + * earlier than the receive of CMD_UNLINK, priv is moved to * priv_tx queue and stub_rx does not find the target priv. In - * this case, vhci_rx recieves the result of the submit request - * and then recieves the result of the unlink request. The + * this case, vhci_rx receives the result of the submit request + * and then receives the result of the unlink request. The * result of the submit is given back to the usbcore as the * completion of the unlink request. The request of the * unlink is ignored. This is ok because a driver who calls diff -Naur usbip-0.1.4/drivers/2.6.19/usbip_common.c trunk/drivers/2.6.19/usbip_common.c --- usbip-0.1.4/drivers/2.6.19/usbip_common.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/usbip_common.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -523,6 +523,9 @@ return result; } + +/* now a usrland utility should set options. */ +#if 0 int setquickack(struct socket *socket) { mm_segment_t oldfs; @@ -572,6 +575,7 @@ { socket->sk->sk_reuse = 1; } +#endif struct socket *sockfd_to_socket(unsigned int sockfd) { @@ -791,7 +795,7 @@ BUG(); } } - + static void usbip_iso_pakcet_correct_endian(struct usbip_iso_packet_descriptor *iso, int send) { /* does not need all members. but copy all simply. */ diff -Naur usbip-0.1.4/drivers/2.6.19/usbip_common.h trunk/drivers/2.6.19/usbip_common.h --- usbip-0.1.4/drivers/2.6.19/usbip_common.h 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/usbip_common.h 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -43,11 +43,11 @@ #ifdef CONFIG_USB_DEBUG #define udbg(fmt, args...) \ - do{ \ + do { \ printk(KERN_DEBUG "%-10s:(%s,%d) %s: " fmt, \ (in_interrupt() ? "interrupt" : (current)->comm),\ __FILE__, __LINE__, __FUNCTION__ , ##args); \ - }while(0) + } while(0) #else /* CONFIG_USB_DEBUG */ @@ -88,7 +88,7 @@ #define dbg_with_flag(flag, fmt, args...) \ do { \ - if(flag & usbip_debug_flag) \ + if(flag & usbip_debug_flag) \ udbg(fmt , ##args); \ } while(0) @@ -254,14 +254,16 @@ return interface->cur_altsetting->desc.bInterfaceNumber; } +#if 0 int setnodelay(struct socket *); int setquickack(struct socket *); int setkeepalive(struct socket *socket); void setreuse(struct socket *); +#endif + struct socket *sockfd_to_socket(unsigned int); int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss); - void usbip_dump_urb (struct urb *purb); void usbip_dump_header(struct usbip_header *pdu); @@ -316,15 +318,15 @@ #define USBIP_EH_RESET (1 << 2) #define USBIP_EH_UNUSABLE (1 << 3) -#define SDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE ) -#define SDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define SDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) +#define SDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE ) +#define SDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) +#define SDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) #define SDEV_EVENT_ERROR_SUBMIT ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) #define SDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE ) -#define VDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_BYE ) -#define VDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) -#define VDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) +#define VDEV_EVENT_REMOVED ( USBIP_EH_SHUTDOWN | USBIP_EH_BYE ) +#define VDEV_EVENT_DOWN ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) +#define VDEV_EVENT_ERROR_TCP ( USBIP_EH_SHUTDOWN | USBIP_EH_RESET ) #define VDEV_EVENT_ERROR_MALLOC ( USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) unsigned long event; diff -Naur usbip-0.1.4/drivers/2.6.19/usbip_event.c trunk/drivers/2.6.19/usbip_event.c --- usbip-0.1.4/drivers/2.6.19/usbip_event.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/usbip_event.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * diff -Naur usbip-0.1.4/drivers/2.6.19/vhci_hcd.c trunk/drivers/2.6.19/vhci_hcd.c --- usbip-0.1.4/drivers/2.6.19/vhci_hcd.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/vhci_hcd.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -24,7 +24,7 @@ #include "usbip_common.h" #include "vhci.h" -#define DRIVER_VERSION " $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ " +#define DRIVER_VERSION " $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ " #define DRIVER_AUTHOR "HIROFUCHI Takahiro " #define DRIVER_DESC "Virtual Host Controller Interface Driver for USB/IP" #define DRIVER_LICENCE "GPL" @@ -36,12 +36,12 @@ /* * TODO - * - update root hub emulation - * - move the emulation code to userland ? - * poring to other operating systems - * minimize kernel code - * - add suspend/resume code - * - clean up everything + * - update root hub emulation + * - move the emulation code to userland ? + * poring to other operating systems + * minimize kernel code + * - add suspend/resume code + * - clean up everything */ @@ -611,7 +611,7 @@ vhci_tx_urb(urb); - spin_unlock_irqrestore (&the_controller->lock, flags); + spin_unlock_irqrestore(&the_controller->lock, flags); return 0; @@ -626,8 +626,8 @@ /* - * vhci_rx gives back the urb after recieving the reply of the urb. If an - * unlink pdu is sent or not, vhci_rx recieves a normal return pdu and gives + * vhci_rx gives back the urb after receiving the reply of the urb. If an + * unlink pdu is sent or not, vhci_rx receives a normal return pdu and gives * back its urb. For the driver unlinking the urb, the content of the urb is * not important, but the calling to its completion handler is important; the * completion of unlinking is notified by the completion handler. @@ -635,7 +635,7 @@ * * CLIENT SIDE * - * - When vhci_hcd recieves RET_SUBMIT, + * - When vhci_hcd receives RET_SUBMIT, * * - case 1a). the urb of the pdu is not unlinking. * - normal case @@ -645,29 +645,29 @@ * - usbip.ko will return a reply of the unlinking request. * => give back the urb now and go to case 2b). * - * - When vhci_hcd recieves RET_UNLINK, + * - When vhci_hcd receives RET_UNLINK, * - * - case 2a). a submit request is still pending in vhci_hcd. - * - urb was really pending in usbip.ko and urb_unlink_urb() was - * completed there. - * => free a pending submit request - * => notify unlink completeness by giving back the urb - * - * - case 2b). a submit request is *not* pending in vhci_hcd. - * - urb was already given back to the core driver. - * => do not give back the urb + * - case 2a). a submit request is still pending in vhci_hcd. + * - urb was really pending in usbip.ko and urb_unlink_urb() was + * completed there. + * => free a pending submit request + * => notify unlink completeness by giving back the urb + * + * - case 2b). a submit request is *not* pending in vhci_hcd. + * - urb was already given back to the core driver. + * => do not give back the urb * * * SERVER SIDE * - * - When usbip recieves CMD_UNLINK, + * - When usbip receives CMD_UNLINK, * * - case 3a). the urb of the unlink request is now in submission. * => do usb_unlink_urb(). * => after the unlink is completed, send RET_UNLINK. * * - case 3b). the urb of the unlink request is not in submission. - * - may be already completed or never be recieved + * - may be already completed or never be received * => send RET_UNLINK * */ @@ -736,12 +736,12 @@ spin_unlock_irqrestore(&vdev->priv_lock, flags2); } - + spin_unlock_irqrestore(&the_controller->lock, flags); /* * If tcp connection is alive, we have sent CMD_UNLINK. - * vhci_rx will recieve RET_UNLINK and giveb back the URB. + * vhci_rx will receive RET_UNLINK and giveb back the URB. * Otherwise, we give back it here. */ if (!vdev->ud.tcp_socket) { @@ -805,11 +805,11 @@ /* * rh_port_disconnect() is a trigger of ... * usb_disable_device(): - * disable all the endpoints for a USB device. + * disable all the endpoints for a USB device. * usb_disable_endpoint(): - * disable endpoints. pending urbs are unlinked(dequeued). + * disable endpoints. pending urbs are unlinked(dequeued). * - * NOTE: After calling rh_port_disconnect(), the USB device driver of a + * NOTE: After calling rh_port_disconnect(), the USB device drivers of a * deteched device should release used urbs in a cleanup function(i.e. * xxx_disconnect()). Therefore, vhci_hcd does not need to release * pushed urbs and their private data in this function. @@ -819,7 +819,7 @@ * gives back pushed urbs and frees their private data by request of * the cleanup function of a USB driver. When unlinking a urb with an * active connection, vhci_dequeue() does not give back the urb which - * is actually given back by vhci_rx after recieving its return pdu. + * is actually given back by vhci_rx after receiving its return pdu. * */ rh_port_disconnect(vdev->rhport); @@ -863,13 +863,15 @@ vdev->ud.side = USBIP_VHCI; vdev->ud.status = VDEV_ST_NULL; - vdev->ud.lock = SPIN_LOCK_UNLOCKED; + // vdev->ud.lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&vdev->ud.lock); INIT_LIST_HEAD(&vdev->priv_rx); INIT_LIST_HEAD(&vdev->priv_tx); INIT_LIST_HEAD(&vdev->unlink_tx); INIT_LIST_HEAD(&vdev->unlink_rx); - vdev->priv_lock = SPIN_LOCK_UNLOCKED; + // vdev->priv_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&vdev->priv_lock); init_waitqueue_head(&vdev->waitq_tx); @@ -1037,7 +1039,7 @@ the_controller = NULL; return ret; } - + dbg_vhci_hc("bye\n"); return 0; @@ -1113,7 +1115,7 @@ /* * The VHCI 'device' is 'virtual'; not a real plug&play hardware. * We need to add this virtual device as a platform device arbitrarily: - * 1. platform_device_register() + * 1. platform_device_register() */ static void the_pdev_release(struct device *dev) { diff -Naur usbip-0.1.4/drivers/2.6.19/vhci_rx.c trunk/drivers/2.6.19/vhci_rx.c --- usbip-0.1.4/drivers/2.6.19/vhci_rx.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/vhci_rx.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -143,7 +143,7 @@ { struct vhci_unlink *unlink; struct urb *urb; - + usbip_dump_header(pdu); unlink = dequeue_pending_unlink(vdev, pdu); @@ -156,7 +156,7 @@ if (!urb) { /* * I get the result of a unlink request. But, it seems that I - * already recieved the result of its submit result and gave + * already received the result of its submit result and gave * back the URB. */ uinfo("the urb (seqnum %d) was already given backed\n", pdu->base.seqnum); @@ -187,7 +187,7 @@ memset(&pdu, 0, sizeof(pdu)); - /* 1. recieve a pdu header */ + /* 1. receive a pdu header */ ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu),0); if (ret != sizeof(pdu)) { uerr("recv a header, %d\n", ret); diff -Naur usbip-0.1.4/drivers/2.6.19/vhci_sysfs.c trunk/drivers/2.6.19/vhci_sysfs.c --- usbip-0.1.4/drivers/2.6.19/vhci_sysfs.c 2007-05-18 11:10:10.000000000 +0200 +++ trunk/drivers/2.6.19/vhci_sysfs.c 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + * $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ * * Copyright (C) 2003-2006 Takahiro Hirofuchi * @@ -213,7 +213,7 @@ rhport, sockfd, busnum, devnum, speed); - /* check recieved parameters */ + /* check received parameters */ if (valid_args(rhport, busnum, devnum, speed) < 0) return -EINVAL; @@ -222,8 +222,9 @@ if (!socket) return -EINVAL; +#if 0 setnodelay(socket); - +#endif /* now need lock until setting vdev status as used */ diff -Naur usbip-0.1.4/NEWS trunk/NEWS --- usbip-0.1.4/NEWS 2007-05-18 11:10:10.000000000 +0200 +++ trunk/NEWS 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,20 @@ # vim:tw=78:ts=4:expandtab:ai:sw=4 -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ +# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + +usbip-0.1.5 + - Fix: "make dist" works. + - Cleanup: use autoreconf instead. + - Cleanup: change vhci_driver as a global value in libusbip. + - Cleanup: change stub_driver as a global value in libusbip. + - Cleanup: trim unused spaces. + - Add: version info in configure.ac + - Fix: auto detection of "glib-2.0 >= 2.6.0" + - Add: mailing list information in README + - Cleanup: use daemon(3), instead. + - Add: usb.ids + - setsockopt in userland + - Add: 2.6.20 support? + - Fix: use spin_lock_init() instead of SPIN_... usbip-0.1.4 - Fix: compile error & warning fix for 2.6.19 diff -Naur usbip-0.1.4/README trunk/README --- usbip-0.1.4/README 2007-05-18 11:10:10.000000000 +0200 +++ trunk/README 2007-05-18 11:10:08.000000000 +0200 @@ -1,6 +1,6 @@ # vim:tw=78:ts=4:expandtab:ai:sw=4 # -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ +# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ # # Copyright (C) 2003-2006 Takahiro Hirofuchi @@ -84,8 +84,21 @@ A. No. +Public Forum and Mailing List + They are available in the project page on sourceforge.net. + Forums + http://sourceforge.net/forum/forum.php?forum_id=418509 + Mailing List + http://sourceforge.net/mail/?group_id=122798 + + +RSS feeds (e.g., the latest file releases) + http://sourceforge.net/export/rss2_project.php?group_id=122798 + + Contact Bug reports, feature requests, and your comments are welcome. + Please use the above forums and the mailing list, or contact me. Nara Institute of Science and Technology Takahiro Hirofuchi diff -Naur usbip-0.1.4/src/autogen.sh trunk/src/autogen.sh --- usbip-0.1.4/src/autogen.sh 1970-01-01 01:00:00.000000000 +0100 +++ trunk/src/autogen.sh 2007-05-18 11:10:08.000000000 +0200 @@ -0,0 +1,9 @@ +#!/bin/sh -x + +#aclocal +#autoheader +#libtoolize --copy --force +#automake-1.9 -acf +#autoconf + +autoreconf -i -f -v diff -Naur usbip-0.1.4/src/cleanup trunk/src/cleanup --- usbip-0.1.4/src/cleanup 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/cleanup 2007-05-18 11:10:08.000000000 +0200 @@ -5,6 +5,6 @@ make distclean fi -FILES="configure cscope.out Makefile.in depcomp compile config.guess config.sub config.h.in~ config.log config.status libtool config.h.in autom4te.cache missing aclocal.m4 install-sh cmd/Makefile.in lib/Makefile.in" +FILES="configure cscope.out Makefile.in depcomp compile config.guess config.sub config.h.in~ config.log config.status ltmain.sh libtool config.h.in autom4te.cache missing aclocal.m4 install-sh cmd/Makefile.in lib/Makefile.in Makefile lib/Makefile cmd/Makefile" rm -Rf $FILES diff -Naur usbip-0.1.4/src/cmd/bind-driver.c trunk/src/cmd/bind-driver.c --- usbip-0.1.4/src/cmd/bind-driver.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/bind-driver.c 2007-05-18 11:10:07.000000000 +0200 @@ -8,6 +8,8 @@ {"usbip", required_argument, NULL, 'u'}, {"other", required_argument, NULL, 'o'}, {"list", no_argument, NULL, 'l'}, + {"scriptlist", no_argument, NULL, 's'}, + {"autobind", no_argument, NULL, 'a'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; @@ -60,7 +62,7 @@ snprintf(unbind_path, sizeof(unbind_path), unbind_path_format, busid); fd = open(unbind_path, O_WRONLY); - if (fd < 0) + if (fd < 0) return -1; ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE)); @@ -95,7 +97,7 @@ snprintf(bind_path, sizeof(bind_path), bind_path_format, driver); fd = open(bind_path, O_WRONLY); - if (fd < 0) + if (fd < 0) return -1; ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE)); @@ -139,11 +141,11 @@ g_message("skip unbinding of hub"); return -1; } - + for (i = 0; i < ninterface; i++) { char driver[PATH_MAX]; int ret; - + bzero(&driver, sizeof(driver)); getdriver(busid, configvalue, i, driver, PATH_MAX-1); @@ -188,7 +190,7 @@ g_debug("read config and ninf value, removed?"); return -1; } - + for (i = 0; i < ninterface; i++) { int ret; @@ -207,7 +209,7 @@ return 0; } - + static int use_device_by_usbip(char *busid) { int ret; @@ -289,7 +291,7 @@ g_error("regcomp: %s\n", strerror(errno)); ret = regexec(®ex, busid, 0, pmatch, 0); - if (ret) + if (ret) return 0; /* not matched */ return 1; @@ -342,6 +344,104 @@ return 0; } +static int show_devices_script(void) +{ + DIR *dir; + + dir = opendir("/sys/bus/usb/devices/"); + if (!dir) + g_error("opendir: %s", strerror(errno)); + + for (;;) { + struct dirent *dirent; + char *busid; + + dirent = readdir(dir); + if (!dirent) + break; + + busid = dirent->d_name; + + if (is_usb_device(busid)) { + char name[100] = {'\0'}; + char driver[100] = {'\0'}; + int conf, ninf = 0; + int i; + int islocal = 0; + + conf = read_bConfigurationValue(busid); + ninf = read_bNumInterfaces(busid); + + getdevicename(busid, name, sizeof(name)); + + for (i = 0; i < ninf; i++) { + getdriver(busid, conf, i, driver, sizeof(driver)); + + if (strncmp(driver, "usbhid", 6) == 0 || strncmp(driver, "usb-storage", 11) == 0) { + islocal = 1; + break; + } + } + + if (islocal == 0) + printf("%s|%s|%s\n", busid, driver, name); + } + } + + closedir(dir); + + return 0; +} + +static int auto_bind(void) +{ + DIR *dir; + + dir = opendir("/sys/bus/usb/devices/"); + if (!dir) + g_error("opendir: %s", strerror(errno)); + + for (;;) { + struct dirent *dirent; + char *busid; + + dirent = readdir(dir); + if (!dirent) + break; + + busid = dirent->d_name; + + if (is_usb_device(busid)) { + char name[100] = {'\0'}; + char driver[100] = {'\0'}; + int conf, ninf = 0; + int i; + int islocal = 0; + + conf = read_bConfigurationValue(busid); + ninf = read_bNumInterfaces(busid); + + getdevicename(busid, name, sizeof(name)); + + for (i = 0; i < ninf; i++) { + getdriver(busid, conf, i, driver, sizeof(driver)); + + if (strncmp(driver, "usbhid", 6) == 0 || strncmp(driver, "usb-storage", 11) == 0) { + islocal = 1; + break; + } + } + + if (islocal == 0) + use_device_by_usbip(busid); + } + } + + closedir(dir); + + return 0; +} + static void show_help(void) { printf("Usage: bind-driver [OPTION]\n"); @@ -349,25 +449,29 @@ printf(" --usbip busid make a device exportable by USB/IP\n"); printf(" --other busid use a device by a local driver\n"); printf(" --list print usb devices and their drivers\n"); + printf(" --scriptlist print usb devices and their drivers. handy for scripts\n"); + printf(" --autobind make all devices exportable by USB/IP\n"); } int main(int argc, char **argv) { - char *busid = NULL; + char *busid = NULL; enum { cmd_unknown = 0, cmd_use_by_usbip, cmd_use_by_other, cmd_list, + cmd_scriptlist, + cmd_autobind, cmd_help } cmd = cmd_unknown; - for(;;) { + for (;;) { int c; int index = 0; - c = getopt_long(argc, argv, "u:o:hl", longopts, &index); + c = getopt_long(argc, argv, "u:o:hlsa", longopts, &index); if (c == -1) break; @@ -383,6 +487,12 @@ case 'l' : cmd = cmd_list; break; + case 's' : + cmd = cmd_scriptlist; + break; + case 'a' : + cmd = cmd_autobind; + break; case 'h': case '?': cmd = cmd_help; @@ -405,6 +515,12 @@ case cmd_list: show_devices(); break; + case cmd_scriptlist: + show_devices_script(); + break; + case cmd_autobind: + auto_bind(); + break; case cmd_help: case cmd_unknown: show_help(); diff -Naur usbip-0.1.4/src/cmd/Makefile.am trunk/src/cmd/Makefile.am --- usbip-0.1.4/src/cmd/Makefile.am 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/Makefile.am 2007-05-18 11:10:07.000000000 +0200 @@ -1,12 +1,15 @@ bin_PROGRAMS = usbip usbipd bind_driver + usbip_SOURCES = vhci_attach.c usbip_network.c usbip_network.h usbipd_SOURCES = stub_server.c usbip_network.c usbip_network.h bind_driver_SOURCES = bind-driver.c utils.c utils.h -bind_driver_CFLAGS = -Wall -g @PACKAGE_CFLAGS@ -bind_driver_LDADD = @PACKAGE_LIBS@ -AM_CPPFLAGS = -I../include -Wall -std=gnu99 -#INCLUDES = -I../include -LDADD = ../lib/libusbip.la + +#bind_driver_CFLAGS = -Wall -W -Wstrict-prototypes @PACKAGE_CFLAGS@ +#bind_driver_LDADD = @PACKAGE_LIBS@ + +#AM_CPPFLAGS = -I../include -Wall -std=gnu99 +INCLUDES = -I$(top_srcdir)/lib +LDADD = ../lib/libusbip.la @PACKAGE_LIBS@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ -AM_CFLAGS = -Wall -W -Wstrict-prototypes $(EXTRA_CFLAGS) +AM_CFLAGS = -Wall -W -Wstrict-prototypes -std=gnu99 $(EXTRA_CFLAGS) @PACKAGE_CFLAGS@ diff -Naur usbip-0.1.4/src/cmd/stub_server.c trunk/src/cmd/stub_server.c --- usbip-0.1.4/src/cmd/stub_server.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/stub_server.c 2007-05-18 11:10:07.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Takahiro Hirofuchi + * Copyright (C) 2005-2007 Takahiro Hirofuchi */ #ifdef HAVE_CONFIG_H @@ -27,12 +27,13 @@ #include "usbip.h" #include "usbip_network.h" +#include + static const char version[] = PACKAGE_STRING " ($Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $)"; -static struct usbip_stub_driver *StubDriver; -static int send_reply_devlist(struct usbip_stub_driver *driver, int sockfd) +static int send_reply_devlist(int sockfd) { int ret; struct usbip_exported_device *edev; @@ -42,14 +43,14 @@ reply.ndev = 0; /* how many devices are exported ? */ - dlist_for_each_data(driver->edev_list, edev, struct usbip_exported_device) { + dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) { reply.ndev += 1; } dbg("%d devices are exported", reply.ndev); ret = usbip_send_op_common(sockfd, OP_REP_DEVLIST, ST_OK); - if(ret < 0) { + if (ret < 0) { err("send op_common"); return ret; } @@ -57,12 +58,12 @@ PACK_OP_DEVLIST_REPLY(1, &reply); ret = usbip_send(sockfd, (void *) &reply, sizeof(reply)); - if(ret < 0) { + if (ret < 0) { err("send op_devlist_reply"); return ret; } - dlist_for_each_data(driver->edev_list, edev, struct usbip_exported_device) { + dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) { struct usb_device pdu_udev; dump_usb_device(&edev->udev); @@ -70,12 +71,12 @@ pack_usb_device(1, &pdu_udev); ret = usbip_send(sockfd, (void *) &pdu_udev, sizeof(pdu_udev)); - if(ret < 0) { + if (ret < 0) { err("send pdu_udev"); return ret; } - for(int i=0; i < edev->udev.bNumInterfaces; i++) { + for (int i=0; i < edev->udev.bNumInterfaces; i++) { struct usb_interface pdu_uinf; dump_usb_interface(&edev->uinf[i]); @@ -83,7 +84,7 @@ pack_usb_interface(1, &pdu_uinf); ret = usbip_send(sockfd, (void *) &pdu_uinf, sizeof(pdu_uinf)); - if(ret < 0) { + if (ret < 0) { err("send pdu_uinf"); return ret; } @@ -102,13 +103,13 @@ bzero(&req, sizeof(req)); ret = usbip_recv(sockfd, (void *) &req, sizeof(req)); - if(ret < 0) { + if (ret < 0) { err("recv devlist request"); return -1; } - ret = send_reply_devlist(StubDriver, sockfd); - if(ret < 0) { + ret = send_reply_devlist(sockfd); + if (ret < 0) { err("send devlist reply"); return -1; } @@ -130,25 +131,28 @@ bzero(&reply, sizeof(reply)); ret = usbip_recv(sockfd, (void *) &req, sizeof(req)); - if(ret < 0) { + if (ret < 0) { err("recv import request"); return -1; } PACK_OP_IMPORT_REQUEST(0, &req); - dlist_for_each_data(StubDriver->edev_list, edev, struct usbip_exported_device) { - if(!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { + dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) { + if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { dbg("found requested device %s", req.busid); found = 1; break; } } - if(found) { + if (found) { + /* should set TCP_NODELAY for usbip */ + usbip_set_nodelay(sockfd); + /* export_device needs a TCP/IP socket descriptor */ - ret = usbip_stub_export_device(StubDriver, edev, sockfd); - if(ret < 0) + ret = usbip_stub_export_device(edev, sockfd); + if (ret < 0) error = 1; } else { info("not found requested device %s", req.busid); @@ -157,19 +161,19 @@ ret = usbip_send_op_common(sockfd, OP_REP_IMPORT, (!error ? ST_OK : ST_NA)); - if(ret < 0) { + if (ret < 0) { err("send import reply"); return -1; } - if(!error) { + if (!error) { struct usb_device pdu_udev; memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); pack_usb_device(1, &pdu_udev); ret = usbip_send(sockfd, (void *) &pdu_udev, sizeof(pdu_udev)); - if(ret < 0) { + if (ret < 0) { err("send devinfo"); return -1; } @@ -187,14 +191,14 @@ ret = usbip_recv_op_common(sockfd, &code); - if(ret < 0) { + if (ret < 0) { err("recv op_common, %d", ret); return ret; } - ret = usbip_stub_refresh_device_list(StubDriver); - if(ret < 0) + ret = usbip_stub_refresh_device_list(); + if (ret < 0) return -1; switch(code) { @@ -229,10 +233,10 @@ ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); - if(ret) + if (ret) err("getnameinfo, %s", gai_strerror(ret)); - dbg("listen at [%s]:%s", hbuf, sbuf); + info("listen at [%s]:%s", hbuf, sbuf); } static struct addrinfo *my_getaddrinfo(char *host, int ai_family) @@ -242,12 +246,13 @@ bzero(&hints, sizeof(hints)); + hints.ai_family = ai_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(host, USBIP_PORT_STRING, &hints, &ai_head); - if (ret){ - err("%s: %s", USBIP_PORT_STRING, gai_strerror(ret) ); + if (ret) { + err("%s: %s", USBIP_PORT_STRING, gai_strerror(ret)); return NULL; } @@ -255,36 +260,36 @@ } #define MAXSOCK 20 -static int listen_all_addrinfo(struct addrinfo *ai_head, int lsock[], int *maxfd) +static int listen_all_addrinfo(struct addrinfo *ai_head, int lsock[]) { struct addrinfo *ai; int n = 0; /* number of sockets */ - *maxfd = -1; /* maximum descriptor number */ - for(ai = ai_head; ai && n < MAXSOCK; ai = ai->ai_next){ + for (ai = ai_head; ai && n < MAXSOCK; ai = ai->ai_next) { int ret; lsock[n] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if(lsock[n] < 0) + if (lsock[n] < 0) continue; usbip_set_reuseaddr(lsock[n]); + usbip_set_nodelay(lsock[n]); - if(lsock[n] >= FD_SETSIZE){ + if (lsock[n] >= FD_SETSIZE) { close(lsock[n]); lsock[n] = -1; continue; } ret = bind(lsock[n], ai->ai_addr, ai->ai_addrlen); - if(ret < 0){ + if (ret < 0) { close(lsock[n]); lsock[n] = -1; continue; } ret = listen(lsock[n], SOMAXCONN); - if(ret < 0){ + if (ret < 0) { close(lsock[n]); lsock[n] = -1; continue; @@ -292,13 +297,11 @@ log_addrinfo(ai); - if(lsock[n] > *maxfd) - *maxfd = lsock[n]; - + /* next if succeed */ n++; } - if(n == 0){ + if (n == 0) { err("no socket to listen to"); return -1; } @@ -319,10 +322,10 @@ fromhost(&request); ret = hosts_access(&request); - if(!ret) + if (!ret) return -1; - return 0; + return 0; } #endif @@ -337,21 +340,23 @@ bzero(&ss, sizeof(ss)); csock = accept(lsock, (struct sockaddr *) &ss, &len); - if(csock < 0) { + if (csock < 0) { err("accept"); return -1; } - ret = getnameinfo((struct sockaddr *)&ss, len, + ret = getnameinfo((struct sockaddr *) &ss, len, host, sizeof(host), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - if(ret) + (NI_NUMERICHOST | NI_NUMERICSERV)); + if (ret) err("getnameinfo, %s", gai_strerror(ret)); #ifdef HAVE_LIBWRAP ret = tcpd_auth(csock); - if(ret < 0) { - info("deny %s", host); + if (ret < 0) { + info("deny access from %s", host); + close(csock); + return -1; } #endif @@ -360,138 +365,123 @@ return csock; } -static int loop_standalone = 1; + +GMainLoop *main_loop; static void signal_handler(int i) { - dbg("signal catched %d", i); - loop_standalone = 0; + dbg("signal catched, code %d", i); + + if (main_loop) + g_main_loop_quit(main_loop); } -static void daemon_init(void) +static void set_signal(void) { - pid_t pid; + struct sigaction act; - usbip_use_stderr = 0; - usbip_use_syslog = 1; + bzero(&act, sizeof(act)); + act.sa_handler = signal_handler; + sigemptyset(&act.sa_mask); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGINT, &act, NULL); +} - pid = fork(); - if(pid < 0) { - err("fork"); - exit(EXIT_FAILURE); - } else if(pid > 0) - /* bye parent */ - exit(EXIT_SUCCESS); - setsid(); +gboolean process_comming_request(GIOChannel *gio, GIOCondition condition, gpointer data) +{ + int ret; - signal(SIGHUP, SIG_IGN); + if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) + g_error("unknown condition"); - pid = fork(); - if(pid < 0) { - err("fork"); - exit(EXIT_FAILURE); - } else if(pid > 0) - /* bye parent */ - exit(EXIT_SUCCESS); - chdir("/"); - umask(0); + if (condition & G_IO_IN) { + int lsock; + int csock; - for(int i=0; i < 3; i++) - close(i); + lsock = g_io_channel_unix_get_fd(gio); -} + csock = my_accept(lsock); + if (csock < 0) + return TRUE; -static void set_signal(void) -{ - struct sigaction act; + ret = recv_pdu(csock); + if (ret < 0) + err("process recieved pdu"); - bzero(&act, sizeof(act)); - act.sa_handler = signal_handler; - sigemptyset(&act.sa_mask); - sigaction(SIGTERM, &act, NULL); - sigaction(SIGINT, &act, NULL); + close(csock); + } + + return TRUE; } -static void do_standalone_mode(void) + +static void do_standalone_mode(gboolean daemonize) { int ret; int lsock[MAXSOCK]; struct addrinfo *ai_head; int n; - int maxfd; - if(!usbip_use_debug) - daemon_init(); + + + ret = usbip_names_init(USBIDS_FILE); + if (ret) + err("open usb.ids"); + + ret = usbip_stub_driver_open(); + if (ret < 0) + g_error("driver open failed"); + + if (daemonize) { + if (daemon(0,0) < 0) + g_error("daemonizing failed: %s", g_strerror(errno)); + + usbip_use_syslog = 1; + } set_signal(); ai_head = my_getaddrinfo(NULL, PF_UNSPEC); - if(!ai_head) + if (!ai_head) return; - n = listen_all_addrinfo(ai_head, lsock, &maxfd); - if(n <= 0) { + n = listen_all_addrinfo(ai_head, lsock); + if (n <= 0) err("no socket to listen to"); - goto err; - } - StubDriver = usbip_stub_driver_open(); - if(!StubDriver) - goto err_driver_open; + for (int i = 0; i < n; i++) { + GIOChannel *gio; - ret = names_init(USBIDS_FILE); - if(ret) - err("open usb.ids"); + gio = g_io_channel_unix_new(lsock[i]); + g_io_add_watch(gio, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), + process_comming_request, NULL); + } - info("usbipd start (%s)", version); - /* setup fd_set */ - fd_set rfd0; - FD_ZERO(&rfd0); - for(int i = 0; i < n; i++) - FD_SET(lsock[i], &rfd0); - - while(loop_standalone){ - fd_set rfd = rfd0; - ret = select(maxfd + 1, &rfd, NULL, NULL, NULL); - if(ret < 0){ - if(!(errno == EINTR)) - err("select"); - break; - } + info("usbipd start (%s)", version); - for(int i = 0; i < n; i++){ - if(FD_ISSET(lsock[i], &rfd)){ - int csock; - - csock = my_accept(lsock[i]); - if(csock < 0) - continue; - - ret = recv_pdu(csock); - if(ret < 0) - err("process recieved pdu"); - close(csock); - } - } - } + main_loop = g_main_loop_new(FALSE, FALSE); + g_main_loop_run(main_loop); -err: - usbip_stub_driver_close(StubDriver); -err_driver_open: info("shutdown"); + freeaddrinfo(ai_head); - names_deinit(); + usbip_names_free(); + usbip_stub_driver_close(); + return; } -const char help_message[] = "\ +static const char help_message[] = "\ Usage: usbipd [options] \n\ - -D, --debug \n\ + -D, --daemon \n\ + Run as a daemon process. \n\ + \n\ + -d, --debug \n\ Print debugging information. \n\ \n\ -v, --version \n\ @@ -506,14 +496,17 @@ } static const struct option longopts[] = { + {"daemon", no_argument, NULL, 'D'}, + {"debug", no_argument, NULL, 'd'}, {"version", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, - {"debug", no_argument, NULL, 'D'}, {NULL, 0, NULL, 0} }; int main(int argc, char *argv[]) { + gboolean daemonize = FALSE; + enum { cmd_standalone_mode = 1, cmd_help, @@ -521,21 +514,23 @@ } cmd = cmd_standalone_mode; - usbip_use_stderr = 1; usbip_use_syslog = 0; - while(1){ + for (;;) { int c; int index = 0; - c = getopt_long(argc, argv, "vhD", longopts, &index); + c = getopt_long(argc, argv, "vhdD", longopts, &index); - if(c == -1) + if (c == -1) break; - switch(c){ + switch (c) { + case 'd': + usbip_use_debug = 1; + continue; case 'v': cmd = cmd_version; break; @@ -543,7 +538,7 @@ cmd = cmd_help; break; case 'D': - usbip_use_debug = 1; + daemonize = TRUE; break; case '?': break; @@ -552,9 +547,9 @@ } } - switch(cmd) { + switch (cmd) { case cmd_standalone_mode: - do_standalone_mode(); + do_standalone_mode(daemonize); break; case cmd_version: printf("%s\n", version); diff -Naur usbip-0.1.4/src/cmd/usbip_network.c trunk/src/cmd/usbip_network.c --- usbip-0.1.4/src/cmd/usbip_network.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/usbip_network.c 2007-05-18 11:10:07.000000000 +0200 @@ -1,26 +1,66 @@ /* - * Copyright (C) 2005-2006 Takahiro Hirofuchi + * Copyright (C) 2005-2007 Takahiro Hirofuchi */ #include "usbip_network.h" +void pack_uint32_t(int pack, uint32_t *num) +{ + uint32_t i; + + if (pack) + i = htonl(*num); + else + i = ntohl(*num); + + *num = i; +} + +void pack_uint16_t(int pack, uint16_t *num) +{ + uint16_t i; + + if (pack) + i = htons(*num); + else + i = ntohs(*num); + + *num = i; +} + +void pack_usb_device(int pack, struct usb_device *udev) +{ + pack_uint32_t(pack, &udev->busnum); + pack_uint32_t(pack, &udev->devnum); + pack_uint32_t(pack, &udev->speed ); + + pack_uint16_t(pack, &udev->idVendor ); + pack_uint16_t(pack, &udev->idProduct); + pack_uint16_t(pack, &udev->bcdDevice); +} + +void pack_usb_interface(int pack, struct usb_interface *udev) +{ + /* uint8_t members need nothing */ +} + static ssize_t usbip_xmit(int sockfd, void *buff, size_t bufflen, int sending) { ssize_t total = 0; - if(!bufflen) + if (!bufflen) return 0; do { ssize_t nbytes; - if(sending) + if (sending) nbytes = send(sockfd, buff, bufflen, 0); else nbytes = recv(sockfd, buff, bufflen, MSG_WAITALL); - if(nbytes <= 0) + if (nbytes <= 0) return -1; buff = (void *) ((intptr_t) buff + nbytes); @@ -57,7 +97,7 @@ PACK_OP_COMMON(1, &op_common); ret = usbip_send(sockfd, (void *) &op_common, sizeof(op_common)); - if(ret < 0) { + if (ret < 0) { err("send op_common"); return -1; } @@ -73,14 +113,14 @@ bzero(&op_common, sizeof(op_common)); ret = usbip_recv(sockfd, (void *) &op_common, sizeof(op_common)); - if(ret < 0) { + if (ret < 0) { err("recv op_common, %d", ret); goto err; } PACK_OP_COMMON(0, &op_common); - if(op_common.version != USBIP_VERSION) { + if (op_common.version != USBIP_VERSION) { err("version mismatch, %d %d", op_common.version, USBIP_VERSION); goto err; } @@ -89,13 +129,13 @@ case OP_UNSPEC: break; default: - if(op_common.code != *code) { + if (op_common.code != *code) { info("unexpected pdu %d for %d", op_common.code, *code); goto err; } } - if(op_common.status != ST_OK) { + if (op_common.status != ST_OK) { info("request failed at peer, %d", op_common.status); goto err; } @@ -107,40 +147,39 @@ return -1; } -/* IPv6 ready */ -void usbip_peername(char *host, char *port, int sockfd) + +int usbip_set_reuseaddr(int sockfd) { + const int val = 1; int ret; - struct sockaddr_storage ss; - socklen_t len = sizeof(ss); + ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + if (ret < 0) + err("setsockopt SO_REUSEADDR"); - bzero(&ss, sizeof(ss)); + return ret; +} - ret = getpeername(sockfd, (struct sockaddr *) &ss, &len); - if(ret < 0) { - err("getpeername, %s", gai_strerror(ret)); - return; +int usbip_set_nodelay(int sockfd) +{ + const int val = 1; + int ret; - } + ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); + if (ret < 0) + err("setsockopt TCP_NODELAY"); - ret = getnameinfo((struct sockaddr *)&ss, len, - host, sizeof(host), port, sizeof(port), - NI_NUMERICHOST | NI_NUMERICSERV); - - if(ret){ - err("getnameinfo, %s", gai_strerror(ret)); - return; - } + return ret; } - -void usbip_set_reuseaddr(int sockfd) +int usbip_set_keepalive(int sockfd) { const int val = 1; int ret; - ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); - if(ret < 0) - err("setsockopt"); + ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); + if (ret < 0) + err("setsockopt SO_KEEPALIVE"); + + return ret; } diff -Naur usbip-0.1.4/src/cmd/usbip_network.h trunk/src/cmd/usbip_network.h --- usbip-0.1.4/src/cmd/usbip_network.h 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/usbip_network.h 2007-05-18 11:10:06.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Takahiro Hirofuchi + * Copyright (C) 2005-2007 Takahiro Hirofuchi */ #ifndef _USBIP_NETWORK_H @@ -8,6 +8,7 @@ #include "usbip.h" #include #include +#include /* -------------------------------------------------- */ @@ -24,7 +25,7 @@ #define OP_REPLY (0x00 << 8) uint16_t code; - /* add more error code */ + /* add more error code */ #define ST_OK 0x00 #define ST_NA 0x01 uint32_t status; /* op_code status (for reply) */ @@ -35,7 +36,7 @@ pack_uint16_t(pack, &(op_common)->version);\ pack_uint16_t(pack, &(op_common)->code );\ pack_uint32_t(pack, &(op_common)->status );\ -} while(0) +} while (0) /* ---------------------------------------------------------------------- */ @@ -76,11 +77,11 @@ } __attribute__((packed)); #define PACK_OP_IMPORT_REQUEST(pack, request) do {\ -} while(0) +} while (0) #define PACK_OP_IMPORT_REPLY(pack, reply) do {\ pack_usb_device(pack, &(reply)->udev);\ -} while(0) +} while (0) /* ---------------------------------------------------------------------- */ /* Negotiate IPSec encryption key. (still not used) */ @@ -118,23 +119,29 @@ } __attribute__((packed)); #define PACK_OP_DEVLIST_REQUEST(pack, request) do {\ -} while(0) +} while (0) #define PACK_OP_DEVLIST_REPLY(pack, reply) do {\ pack_uint32_t(pack, &(reply)->ndev);\ -} while(0) +} while (0) /* -------------------------------------------------- */ /* Declare Prototype Function */ /* -------------------------------------------------- */ +void pack_uint32_t(int pack, uint32_t *num); +void pack_uint16_t(int pack, uint16_t *num); +void pack_usb_device(int pack, struct usb_device *udev); +void pack_usb_interface(int pack, struct usb_interface *uinf); + ssize_t usbip_recv(int sockfd, void *buff, size_t bufflen); ssize_t usbip_send(int sockfd, void *buff, size_t bufflen); int usbip_send_op_common(int sockfd, uint32_t code, uint32_t status); int usbip_recv_op_common(int sockfd, uint16_t *code); -void usbip_peername(char *host, char *port, int sockfd); -void usbip_set_reuseaddr(int sockfd); +int usbip_set_reuseaddr(int sockfd); +int usbip_set_nodelay(int sockfd); +int usbip_set_keepalive(int sockfd); #define USBIP_PORT 3240 #define USBIP_PORT_STRING "3240" diff -Naur usbip-0.1.4/src/cmd/utils.c trunk/src/cmd/utils.c --- usbip-0.1.4/src/cmd/utils.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/utils.c 2007-05-18 11:10:07.000000000 +0200 @@ -176,7 +176,7 @@ /* end of line */ buff[index-1] = '\0'; /* get rid of delimitor */ return index; - } else + } else index++; } @@ -191,7 +191,7 @@ int len; char buff[MAXLINE]; - if (strlen + 3 > MAXLINE) + if (strlen + 3 > MAXLINE) return -1; strncpy(buff, str, strlen); diff -Naur usbip-0.1.4/src/cmd/utils.h trunk/src/cmd/utils.h --- usbip-0.1.4/src/cmd/utils.h 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/utils.h 2007-05-18 11:10:07.000000000 +0200 @@ -23,7 +23,7 @@ /* Be sync to kernel header */ -#define BUS_ID_SIZE 20 +#define BUS_ID_SIZE 20 int read_string(char *path, char *, size_t len); int read_integer(char *path); diff -Naur usbip-0.1.4/src/cmd/vhci_attach.c trunk/src/cmd/vhci_attach.c --- usbip-0.1.4/src/cmd/vhci_attach.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/cmd/vhci_attach.c 2007-05-18 11:10:07.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Takahiro Hirofuchi + * Copyright (C) 2005-2007 Takahiro Hirofuchi */ #ifdef HAVE_CONFIG_H @@ -18,36 +18,36 @@ /* /sys/devices/platform/vhci_hcd/usb6/6-1/6-1:1.1 -> 1 */ -static int get_interface_number(struct usbip_vhci_driver *driver, char *path) +static int get_interface_number(char *path) { char *c; - c = strstr(path, driver->hc_device->bus_id); - if(!c) + c = strstr(path, vhci_driver->hc_device->bus_id); + if (!c) return -1; /* hc exist? */ c++; /* -> usb6/6-1/6-1:1.1 */ c = strchr(c, '/'); - if(!c) + if (!c) return -1; /* hc exist? */ c++; /* -> 6-1/6-1:1.1 */ c = strchr(c, '/'); - if(!c) + if (!c) return -1; /* no interface path */ c++; /* -> 6-1:1.1 */ c = strchr(c, ':'); - if(!c) + if (!c) return -1; /* no configuration? */ c++; /* -> 1.1 */ c = strchr(c, '.'); - if(!c) + if (!c) return -1; /* no interface? */ c++; /* -> 1 */ @@ -66,7 +66,7 @@ udev->busid, udev->bConfigurationValue, i); suinf = sysfs_open_device("usb", busid); - if(!suinf) + if (!suinf) err("sysfs_open_device %s", busid); return suinf; @@ -89,7 +89,7 @@ if (fd < 0) return -1; - snprintf(buff, MAX_BUFF, "%s %s %s\n", + snprintf(buff, MAX_BUFF, "%s %s %s\n", host, port, busid); ret = write(fd, buff, strlen(buff)); @@ -124,7 +124,7 @@ } -void usbip_vhci_imported_device_dump(struct usbip_vhci_driver *driver, struct usbip_imported_device *idev) +void usbip_vhci_imported_device_dump(struct usbip_imported_device *idev) { char product_name[100]; char host[NI_MAXHOST] = "unknown host"; @@ -132,19 +132,19 @@ char remote_busid[SYSFS_BUS_ID_SIZE]; int ret; - if(idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) { + if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) { info("Port %02d: <%s>", idev->port, usbip_status_string(idev->status)); return; } ret = read_record(idev->port, host, serv, remote_busid); - if(ret) + if (ret) err("red_record"); info("Port %02d: <%s> at %s", idev->port, usbip_status_string(idev->status), usbip_speed_string(idev->udev.speed)); - usbip_product_name(product_name, sizeof(product_name), + usbip_names_get_product(product_name, sizeof(product_name), idev->udev.idVendor, idev->udev.idProduct); info(" %s", product_name); @@ -153,13 +153,14 @@ idev->udev.busid, host, serv, remote_busid, idev->busnum, idev->devnum); - for(int i=0; i < idev->udev.bNumInterfaces; i++) { + for (int i=0; i < idev->udev.bNumInterfaces; i++) { /* show interface information */ struct sysfs_device *suinf; suinf = open_usb_interface(&idev->udev, i); - if(!suinf) + if (!suinf) continue; + info(" %6s used by %-17s", suinf->bus_id, suinf->driver_name); sysfs_close_device(suinf); @@ -167,8 +168,8 @@ struct class_device *cdev; dlist_for_each_data(idev->cdev_list, cdev, struct class_device) { - int ifnum = get_interface_number(driver, cdev->devpath); - if(ifnum == i) { + int ifnum = get_interface_number(cdev->devpath); + if (ifnum == i) { info(" %s", cdev->clspath); } } @@ -188,18 +189,18 @@ /* get all possible addresses */ err = getaddrinfo(hostname, service, &hints, &res0); - if(err) { + if (err) { err("%s %s: %s", hostname, service, gai_strerror(err)); return -1; } /* try all the addresses */ - for(res = res0; res; res = res->ai_next) { + for (res = res0; res; res = res->ai_next) { char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; err = getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); - if(err) { + if (err) { err("%s %s: %s", hostname, service, gai_strerror(err)); continue; } @@ -207,13 +208,18 @@ dbg("trying %s port %s\n", hbuf, sbuf); sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if(sockfd < 0) { + if (sockfd < 0) { err("socket"); continue; } + /* should set TCP_NODELAY for usbip */ + usbip_set_nodelay(sockfd); + /* TODO: write code for heatbeat */ + usbip_set_keepalive(sockfd); + err = connect(sockfd, res->ai_addr, res->ai_addrlen); - if(err < 0) { + if (err < 0) { close(sockfd); continue; } @@ -242,19 +248,19 @@ bzero(&rep, sizeof(rep)); ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0); - if(ret < 0) { + if (ret < 0) { err("send op_common"); return -1; } ret = usbip_recv_op_common(sockfd, &code); - if(ret < 0) { + if (ret < 0) { err("recv op_common"); return -1; } ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep)); - if(ret < 0) { + if (ret < 0) { err("recv op_devlist"); return -1; } @@ -262,7 +268,7 @@ PACK_OP_DEVLIST_REPLY(0, &rep); dbg("exportable %d devices", rep.ndev); - for(unsigned int i=0; i < rep.ndev; i++) { + for (unsigned int i=0; i < rep.ndev; i++) { char product_name[100]; char class_name[100]; struct usb_device udev; @@ -270,32 +276,32 @@ bzero(&udev, sizeof(udev)); ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev)); - if(ret < 0) { + if (ret < 0) { err("recv usb_device[%d]", i); return -1; } pack_usb_device(0, &udev); - usbip_product_name(product_name, sizeof(product_name), + usbip_names_get_product(product_name, sizeof(product_name), udev.idVendor, udev.idProduct); - usbip_class_name(class_name, sizeof(class_name), udev.bDeviceClass, + usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass, udev.bDeviceSubClass, udev.bDeviceProtocol); info("%8s: %s", udev.busid, product_name); info("%8s: %s", " ", udev.path); info("%8s: %s", " ", class_name); - for(int j=0; j < udev.bNumInterfaces; j++) { + for (int j=0; j < udev.bNumInterfaces; j++) { struct usb_interface uinf; ret = usbip_recv(sockfd, (void *) &uinf, sizeof(uinf)); - if(ret < 0) { + if (ret < 0) { err("recv usb_interface[%d]", j); return -1; } pack_usb_interface(0, &uinf); - usbip_class_name(class_name, sizeof(class_name), uinf.bInterfaceClass, + usbip_names_get_class(class_name, sizeof(class_name), uinf.bInterfaceClass, uinf.bInterfaceSubClass, uinf.bInterfaceProtocol); info("%8s: %2d - %s", " ", j, class_name); @@ -310,30 +316,30 @@ static int import_device(int sockfd, struct usb_device *udev) { int ret; - struct usbip_vhci_driver *driver; int port; - driver = usbip_vhci_driver_open(); - if(!driver) { + ret = usbip_vhci_driver_open(); + if (ret < 0) { err("open vhci_driver"); return -1; } - port = usbip_vhci_get_free_port(driver); - if(port < 0) { + port = usbip_vhci_get_free_port(); + if (port < 0) { err("no free port"); - usbip_vhci_driver_close(driver); + usbip_vhci_driver_close(); return -1; } - ret = usbip_vhci_import_device(driver, port, sockfd, udev); - if(ret < 0) { + ret = usbip_vhci_attach_device(port, sockfd, udev->busnum, + udev->devnum, udev->speed); + if (ret < 0) { err("import device"); - usbip_vhci_driver_close(driver); + usbip_vhci_driver_close(); return -1; } - usbip_vhci_driver_close(driver); + usbip_vhci_driver_close(); return port; } @@ -352,7 +358,7 @@ /* send a request */ ret = usbip_send_op_common(sockfd, OP_REQ_IMPORT, 0); - if(ret < 0) { + if (ret < 0) { err("send op_common"); return -1; } @@ -362,7 +368,7 @@ PACK_OP_IMPORT_REQUEST(0, &request); ret = usbip_send(sockfd, (void *) &request, sizeof(request)); - if(ret < 0) { + if (ret < 0) { err("send op_import_request"); return -1; } @@ -370,13 +376,13 @@ /* recieve a reply */ ret = usbip_recv_op_common(sockfd, &code); - if(ret < 0) { + if (ret < 0) { err("recv op_common"); return -1; } ret = usbip_recv(sockfd, (void *) &reply, sizeof(reply)); - if(ret < 0) { + if (ret < 0) { err("recv op_import_reply"); return -1; } @@ -385,7 +391,7 @@ /* check the reply */ - if(strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) { + if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) { err("recv different busid %s", reply.udev.busid); return -1; } @@ -402,13 +408,13 @@ int rhport; sockfd = tcp_connect(host, USBIP_PORT_STRING); - if(sockfd < 0) { + if (sockfd < 0) { err("tcp connect"); return; } rhport = query_import_device(sockfd, busid); - if(rhport < 0) { + if (rhport < 0) { err("query"); return; } @@ -417,7 +423,7 @@ ret = record_connection(host, USBIP_PORT_STRING, busid, rhport); - if (ret < 0) + if (ret < 0) err("record connection"); return; @@ -425,11 +431,11 @@ static void detach_port(char *port) { - struct usbip_vhci_driver *driver; + int ret; uint8_t portnum; - for(unsigned int i=0; i < strlen(port); i++) - if(!isdigit(port[i])) { + for (unsigned int i=0; i < strlen(port); i++) + if (!isdigit(port[i])) { err("invalid port %s", port); return; } @@ -438,15 +444,15 @@ portnum = atoi(port); - driver = usbip_vhci_driver_open(); - if(!driver) { + ret = usbip_vhci_driver_open(); + if (ret < 0) { err("open vhci_driver"); return; } - usbip_vhci_detach_device(driver, portnum); + usbip_vhci_detach_device(portnum); - usbip_vhci_driver_close(driver); + usbip_vhci_driver_close(); } static void show_exported_devices(char *host) @@ -455,7 +461,7 @@ int sockfd; sockfd = tcp_connect(host, USBIP_PORT_STRING); - if(sockfd < 0) { + if (sockfd < 0) { info("- %s failed", host); return; } @@ -463,6 +469,82 @@ info("- %s", host); ret = query_exported_devices(sockfd); + if (ret < 0) { + err("query"); + } + + close(sockfd); +} + +static int attach_exported_devices(char *host, int sockfd) +{ + int ret; + struct op_devlist_reply rep; + uint16_t code = OP_REP_DEVLIST; + + bzero(&rep, sizeof(rep)); + + ret = usbip_send_op_common(sockfd, OP_REQ_DEVLIST, 0); + if(ret < 0) { + err("send op_common"); + return -1; + } + + ret = usbip_recv_op_common(sockfd, &code); + if(ret < 0) { + err("recv op_common"); + return -1; + } + + ret = usbip_recv(sockfd, (void *) &rep, sizeof(rep)); + if(ret < 0) { + err("recv op_devlist"); + return -1; + } + + PACK_OP_DEVLIST_REPLY(0, &rep); + dbg("exportable %d devices", rep.ndev); + + for(unsigned int i=0; i < rep.ndev; i++) { + char product_name[100]; + char class_name[100]; + struct usb_device udev; + + bzero(&udev, sizeof(udev)); + + ret = usbip_recv(sockfd, (void *) &udev, sizeof(udev)); + if(ret < 0) { + err("recv usb_device[%d]", i); + return -1; + } + pack_usb_device(0, &udev); + + usbip_names_get_product(product_name, sizeof(product_name), + udev.idVendor, udev.idProduct); + usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass, + udev.bDeviceSubClass, udev.bDeviceProtocol); + + dbg("Attaching usb port %s from host %s on usbip, with deviceid: %s", udev.busid, host, product_name); + attach_device(host, udev.busid); + } + + return rep.ndev; +} + +static void attach_devices_all(char *host) +{ + int ret; + int sockfd; + + sockfd = tcp_connect(host, USBIP_PORT_STRING); + if(sockfd < 0) { + info("- %s failed", host); + return; + } + + info("- %s", host); + + ret = attach_exported_devices(host, sockfd); if(ret < 0) { err("query"); } @@ -476,6 +558,9 @@ -a, --attach [host] [bus_id] \n\ Attach a remote USB device. \n\ \n\ + -x, --attachall [host] \n\ + Attach all remote USB devices on the specific host. \n\ + \n\ -d, --detach [ports] \n\ Detach an imported USB device. \n\ \n\ @@ -499,29 +584,30 @@ printf("%s", help_message); } -static void show_port_status(void) +static void show_port_status(void) { + int ret; struct usbip_imported_device *idev; - struct usbip_vhci_driver *driver; - driver = usbip_vhci_driver_open(); - if(!driver) { + ret = usbip_vhci_driver_open(); + if (ret < 0) return; - } - for(int i = 0; i < driver->nports; i++) { - idev = &driver->idev[i]; - usbip_vhci_imported_device_dump(driver, idev); + for (int i = 0; i < vhci_driver->nports; i++) { + idev = &vhci_driver->idev[i]; + + usbip_vhci_imported_device_dump(idev); } - usbip_vhci_driver_close(driver); + usbip_vhci_driver_close(); } #define _GNU_SOURCE #include static const struct option longopts[] = { {"attach", no_argument, NULL, 'a'}, + {"attachall", no_argument, NULL, 'x'}, {"detach", no_argument, NULL, 'd'}, {"port", no_argument, NULL, 'p'}, {"list", no_argument, NULL, 'l'}, @@ -538,6 +624,7 @@ enum { cmd_attach = 1, + cmd_attachall, cmd_detach, cmd_port, cmd_list, @@ -547,49 +634,55 @@ usbip_use_stderr = 1; - ret = names_init(USBIDS_FILE); - if(ret) + ret = usbip_names_init(USBIDS_FILE); + if (ret) err("open usb.ids"); - while(1) { + for (;;) { int c; int index = 0; - c = getopt_long(argc, argv, "adplvhDS", longopts, &index); + c = getopt_long(argc, argv, "adplvhDSx", longopts, &index); - if(c == -1) + if (c == -1) break; switch(c) { case 'a': - if(!cmd) + if (!cmd) cmd = cmd_attach; else cmd = cmd_help; break; case 'd': - if(!cmd) + if (!cmd) cmd = cmd_detach; else cmd = cmd_help; break; case 'p': - if(!cmd) + if (!cmd) cmd = cmd_port; else cmd = cmd_help; break; case 'l': - if(!cmd) + if (!cmd) cmd = cmd_list; else cmd = cmd_help; break; case 'v': - if(!cmd) + if (!cmd) cmd = cmd_version; else cmd = cmd_help; break; + case 'x': + if(!cmd) + cmd = cmd_attachall; + else + cmd = cmd_help; + break; case 'h': cmd = cmd_help; break; @@ -610,22 +703,26 @@ switch(cmd) { case cmd_attach: - if(optind == argc - 2) + if (optind == argc - 2) attach_device(argv[optind], argv[optind+1]); else show_help(); break; case cmd_detach: - while(optind < argc) + while (optind < argc) detach_port(argv[optind++]); break; case cmd_port: show_port_status(); break; case cmd_list: - while(optind < argc) + while (optind < argc) show_exported_devices(argv[optind++]); break; + case cmd_attachall: + while(optind < argc) + attach_devices_all(argv[optind++]); + break; case cmd_version: printf("%s\n", version); break; @@ -637,7 +734,7 @@ } - names_deinit(); + usbip_names_free(); return 0; } diff -Naur usbip-0.1.4/src/configure.ac trunk/src/configure.ac --- usbip-0.1.4/src/configure.ac 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/configure.ac 2007-05-18 11:10:08.000000000 +0200 @@ -2,8 +2,9 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT(usbip, 0.1.4, taka-hir@is.naist.jp) -AC_DEFINE(USBIP_VERSION, 0x000104, Numeric version number) +AC_REVISION($Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $) +AC_INIT(usbip, 0.1.5, taka-hir@is.naist.jp) +AC_DEFINE(USBIP_VERSION, 0x000105, Numeric version number) AC_CONFIG_SRCDIR([config.h.in]) AM_INIT_AUTOMAKE @@ -38,44 +39,62 @@ AC_CHECK_HEADER(sysfs/libsysfs.h, [AC_CHECK_LIB(sysfs, sysfs_open_directory_list, [LIBS="$LIBS -lsysfs"], - [AC_MSG_ERROR([Missing sysfs2 library!])])], + [AC_MSG_ERROR([Missing sysfs2 library!])])], [AC_MSG_ERROR([Missing /usr/include/sysfs/libsysfs.h])]) # get from stunnel dnl Check for libwrap library. AC_MSG_CHECKING([whether to use the libwrap (TCP wrappers) library]) + AC_ARG_WITH(tcp-wrappers, - [ --with-tcp-wrappers Use the libwrap (TCP wrappers) library ], - [ - saved_LIBS="$LIBS" - if test "$withval" = "yes"; then - AC_MSG_RESULT([yes]) - AC_MSG_CHECKING([for hosts_access in -lwrap]) - LIBS="-lwrap $LIBS" - AC_TRY_LINK([int hosts_access(); int allow_severity, deny_severity;], - [hosts_access()], - [AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_LIBWRAP, 1, use tcp wrapper) wrap_LIB="-lwrap"], - [AC_MSG_RESULT([not found]); exit 1]) - else - AC_MSG_RESULT([no]) - fi - LIBS="$saved_LIBS" - ], - [ - AC_MSG_RESULT([(default)]) - AC_MSG_CHECKING([for hosts_access in -lwrap]) - saved_LIBS="$LIBS" - LIBS="-lwrap $saved_LIBS" - AC_TRY_LINK([int hosts_access(); int allow_severity, deny_severity;], - [hosts_access()], - [AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_LIBWRAP, 1, use tcp wrapper)], - [AC_MSG_RESULT([no]); LIBS="$saved_LIBS"]) - ] - ) +[ --with-tcp-wrappers Use the libwrap (TCP wrappers) library ], +[saved_LIBS="$LIBS" + if test "$withval" = "yes"; then + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([for hosts_access in -lwrap]) + LIBS="-lwrap $LIBS" + AC_TRY_LINK( + [int hosts_access(); int allow_severity, deny_severity;], + [hosts_access()], + [AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_LIBWRAP, 1, use tcp wrapper) wrap_LIB="-lwrap"], + [AC_MSG_RESULT([not found]); exit 1]) + else + AC_MSG_RESULT([no]) + fi + LIBS="$saved_LIBS"], +[AC_MSG_RESULT([(default)]) + AC_MSG_CHECKING([for hosts_access in -lwrap]) + saved_LIBS="$LIBS" + LIBS="-lwrap $saved_LIBS" + AC_TRY_LINK( + [int hosts_access(); int allow_severity, deny_severity;], + [hosts_access()], + [AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_LIBWRAP, 1, use tcp wrapper)], + [AC_MSG_RESULT([no]); LIBS="$saved_LIBS"]) +]) + + + +USBIDS_DIR='${datadir}/usbip' +AC_ARG_WITH(usbids-dir, [ --with-usbids-dir=DIR where usb.ids is found (default ${datadir}/usbip)], [USBIDS_DIR=$withval]) +AC_SUBST(USBIDS_DIR) + +dnl FIXME: when disabled, empty directry is created +usbids=install +AC_ARG_ENABLE(usbids-install, +[ --enable-usbids-install install usb.ids (default)], +[case "${enableval}" in + yes) usbids=install ;; + no) usbids=notinstall ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-usbids-install) ;; + esac]) +AM_CONDITIONAL(INSTALL_USBIDS, test x$usbids = xinstall) + + -pkg_modules="glib-2.0" -PKG_CHECK_MODULES(PACKAGE, [$pkg_modules]) +GLIB2_REQUIRED=2.6.0 +PKG_CHECK_MODULES(PACKAGE, glib-2.0 >= $GLIB2_REQUIRED) AC_SUBST(PACKAGE_CFLAGS) AC_SUBST(PACKAGE_LIBS) diff -Naur usbip-0.1.4/src/include/names.h trunk/src/include/names.h --- usbip-0.1.4/src/include/names.h 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/include/names.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,57 +0,0 @@ -/*****************************************************************************/ - -/* - * names.h -- USB name database manipulation routines - * - * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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 of the License, 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. - * - * - */ - -/* - * Copyright (C) 2005 Takahiro Hirofuchi - * - names_deinit() is added. - */ - -/*****************************************************************************/ - -#ifndef _NAMES_H -#define _NAMES_H - -#include - -/* ---------------------------------------------------------------------- */ - -extern const char *names_vendor(u_int16_t vendorid); -extern const char *names_product(u_int16_t vendorid, u_int16_t productid); -extern const char *names_class(u_int8_t classid); -extern const char *names_subclass(u_int8_t classid, u_int8_t subclassid); -extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid); -extern const char *names_audioterminal(u_int16_t termt); -extern const char *names_hid(u_int8_t hidd); -extern const char *names_reporttag(u_int8_t rt); -extern const char *names_huts(unsigned int data); -extern const char *names_hutus(unsigned int data); -extern const char *names_langid(u_int16_t langid); -extern const char *names_physdes(u_int8_t ph); -extern const char *names_bias(u_int8_t b); -extern const char *names_countrycode(unsigned int countrycode); -extern int names_init(char *n); -extern void names_deinit(void); - -/* ---------------------------------------------------------------------- */ -#endif /* _NAMES_H */ diff -Naur usbip-0.1.4/src/include/stub_driver.h trunk/src/include/stub_driver.h --- usbip-0.1.4/src/include/stub_driver.h 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/include/stub_driver.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2005-2006 Takahiro Hirofuchi - */ - -#ifndef _USBIP_STUB_DRIVER_H -#define _USBIP_STUB_DRIVER_H - -#include "usbip.h" - - -struct usbip_stub_driver { - int ndevs; - struct sysfs_driver *sysfs_driver; - - struct dlist *edev_list; /* list of exported device */ -}; - -struct usbip_exported_device { - struct sysfs_device *sudev; - - int32_t status; - struct usb_device udev; - struct usb_interface uinf[]; -}; - - - -struct usbip_stub_driver *usbip_stub_driver_open(void); -void usbip_stub_driver_close(struct usbip_stub_driver *driver); -int usbip_stub_refresh_device_list(struct usbip_stub_driver *driver); -int usbip_stub_export_device(struct usbip_stub_driver *driver, - struct usbip_exported_device *edev, int sockfd); - -/* add for SWIG */ -struct usbip_exported_device *usbip_stub_get_device(struct usbip_stub_driver *, int num); -#endif diff -Naur usbip-0.1.4/src/include/usbip_common.h trunk/src/include/usbip_common.h --- usbip-0.1.4/src/include/usbip_common.h 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/include/usbip_common.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2005-2006 Takahiro Hirofuchi - */ - -#ifndef _USBIP_COMMON_H -#define _USBIP_COMMON_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define USBIDS_FILE "/usr/share/hwdata/usb.ids" - -extern int usbip_use_syslog; -extern int usbip_use_stderr; -extern int usbip_use_debug ; - -//#include -enum usb_device_speed { - USB_SPEED_UNKNOWN = 0, /* enumerating */ - USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ - USB_SPEED_HIGH, /* usb 2.0 */ - USB_SPEED_VARIABLE /* wireless (usb 2.5) */ -}; - -/* FIXME: how to sync with drivers/usbip_common.h ? */ -enum usbip_device_status{ - /* sdev is available. */ - SDEV_ST_AVAILABLE = 0x01, - /* sdev is now used. */ - SDEV_ST_USED, - /* sdev is unusable because of a fatal error. */ - SDEV_ST_ERROR, - - /* vdev does not connect a remote device. */ - VDEV_ST_NULL, - /* vdev is used, but the USB address is not assigned yet */ - VDEV_ST_NOTASSIGNED, - VDEV_ST_USED, - VDEV_ST_ERROR -}; - -#define err(fmt, args...) do { \ - if(usbip_use_syslog) { \ - syslog(LOG_ERR, "usbip err: %13s:%4d (%-12s) " fmt " [%s]", \ - __FILE__, __LINE__, __FUNCTION__, ##args, strerror(errno)); \ - } \ - if(usbip_use_stderr) { \ - fprintf(stderr, "usbip err: %13s:%4d (%-12s) " fmt " [%s]\n", \ - __FILE__, __LINE__, __FUNCTION__, ##args, strerror(errno)); \ - } \ -} while (0) - -#define notice(fmt, args...) do { \ - if(usbip_use_syslog) { \ - syslog(LOG_DEBUG, "usbip: " fmt, ##args); \ - } \ - if(usbip_use_stderr) { \ - fprintf(stderr, "usbip: " fmt "\n", ##args); \ - } \ -} while (0) - -#define info(fmt, args...) do { \ - if(usbip_use_syslog) { \ - syslog(LOG_DEBUG, fmt, ##args); \ - } \ - if(usbip_use_stderr) { \ - fprintf(stderr, fmt "\n", ##args); \ - } \ -} while (0) - -#define dbg(fmt, args...) do { \ - if(usbip_use_debug) { \ - if(usbip_use_syslog) { \ - syslog(LOG_DEBUG, "usbip dbg: %13s:%4d (%-12s) " fmt, \ - __FILE__, __LINE__, __FUNCTION__, ##args); \ - } \ - if(usbip_use_stderr) { \ - fprintf(stderr, "usbip dbg: %13s:%4d (%-12s) " fmt "\n", \ - __FILE__, __LINE__, __FUNCTION__, ##args); \ - } \ - } \ -} while (0) - - -#define BUG() do { err("sorry, it's a bug"); abort(); } while(0) - -struct usb_interface { - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; -} __attribute__((packed)); - - - -struct usb_device { - char path[SYSFS_PATH_MAX]; - char busid[SYSFS_BUS_ID_SIZE]; - - uint32_t busnum; - uint32_t devnum; - uint32_t speed; - - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bConfigurationValue; - uint8_t bNumConfigurations; - uint8_t bNumInterfaces; -} __attribute__((packed)); - -#define to_string(s) #s - -void dump_usb_interface(struct usb_interface *); -void dump_usb_device(struct usb_device *); -int read_usb_device(struct sysfs_device *sdev, struct usb_device *udev); -int read_attr_value(struct sysfs_device *dev, const char *name, const char *format); -int read_usb_interface(struct usb_device *udev, int i, struct usb_interface *uinf); - -const char *usbip_speed_string(int num); -const char *usbip_status_string(int32_t status); - -void usbip_product_name(char *buff, size_t size, uint16_t vendor, uint16_t product); -void usbip_class_name(char *buff, size_t size, uint8_t class, uint8_t subclass, uint8_t protocol); - -void pack_uint32_t(int pack, uint32_t *num); -void pack_uint16_t(int pack, uint16_t *num); -void pack_usb_device(int pack, struct usb_device *udev); -void pack_usb_interface(int pack, struct usb_interface *uinf); - -#endif diff -Naur usbip-0.1.4/src/include/usbip.h trunk/src/include/usbip.h --- usbip-0.1.4/src/include/usbip.h 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/include/usbip.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2005-2006 Takahiro Hirofuchi - */ - -#ifndef _USBIP_H -#define _USBIP_H - -#ifdef HAVE_CONFIG_H -#include "../config.h" -#endif - -#include "names.h" -#include "usbip_common.h" -#include "stub_driver.h" -#include "vhci_driver.h" -#ifdef DMALLOC -#include -#endif - -#endif diff -Naur usbip-0.1.4/src/include/vhci_driver.h trunk/src/include/vhci_driver.h --- usbip-0.1.4/src/include/vhci_driver.h 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/include/vhci_driver.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2005-2006 Takahiro Hirofuchi - */ - -#ifndef _VHCI_DRIVER_H -#define _VHCI_DRIVER_H - -#include "usbip.h" - - -extern const char *portst_str[]; - - -#define MAXNPORT 128 - -struct class_device { - char clspath[SYSFS_PATH_MAX]; - char devpath[SYSFS_PATH_MAX]; -}; - -struct usbip_imported_device { - uint8_t port; - uint32_t status; - - uint8_t busnum; - uint8_t devnum; - - - struct dlist *cdev_list; /* list of class device */ - struct usb_device udev; -}; - -struct usbip_vhci_driver { - char sysfs_mntpath[SYSFS_PATH_MAX]; - struct sysfs_device *hc_device; /* /sys/devices/platform/vhci_hcd */ - - struct dlist *cdev_list; /* list of class device */ - - int nports; - struct usbip_imported_device idev[MAXNPORT]; -}; - - - -struct usbip_vhci_driver *usbip_vhci_driver_open(void); -void usbip_vhci_driver_close(struct usbip_vhci_driver *driver); -int usbip_vhci_refresh_device_list(struct usbip_vhci_driver *driver); - - -int usbip_vhci_get_free_port(struct usbip_vhci_driver *driver); -int usbip_vhci_import_device(struct usbip_vhci_driver *driver, - uint8_t port, int sockfd, struct usb_device *udev); -int usbip_vhci_import_device2(struct usbip_vhci_driver *driver, - uint8_t port, int sockfd, uint8_t busnum, - uint8_t devnum, uint32_t speed); -int usbip_vhci_detach_device(struct usbip_vhci_driver *driver, uint8_t port); -#endif diff -Naur usbip-0.1.4/src/INSTALL trunk/src/INSTALL --- usbip-0.1.4/src/INSTALL 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/INSTALL 2007-05-18 11:10:08.000000000 +0200 @@ -1,8 +1,8 @@ Installation Instructions ************************* -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free -Software Foundation, Inc. +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. @@ -10,7 +10,10 @@ Basic Installation ================== -These are generic installation instructions. +Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -23,9 +26,9 @@ It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is +the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale -cache files.) +cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail @@ -35,20 +38,17 @@ may remove or edit it. The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. + `./configure' to configure the package for your system. - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. 2. Type `make' to compile the package. @@ -78,7 +78,7 @@ by setting variables in the command line or in the environment. Here is an example: - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. @@ -87,17 +87,15 @@ You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the +own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. Installation Names ================== @@ -190,12 +188,12 @@ ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). Here is a another example: +overridden in the site shell script). - /bin/bash ./configure CONFIG_SHELL=/bin/bash +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: -Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent -configuration-related scripts to be executed by `/bin/bash'. + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== diff -Naur usbip-0.1.4/src/lib/Makefile.am trunk/src/lib/Makefile.am --- usbip-0.1.4/src/lib/Makefile.am 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/lib/Makefile.am 2007-05-18 11:10:07.000000000 +0200 @@ -1,8 +1,10 @@ # AM_CFLAGS = -Wall -std=gnu99 lib_LTLIBRARIES = libusbip.la libusbip_la_SOURCES = names.c names.h stub_driver.c stub_driver.h usbip.h usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h -AM_CPPFLAGS = -I../include -Wall -std=gnu99 +#libusbip_la_SOURCES = names.c names.h stub_driver.c usbip_common.c vhci_driver.c +#INCLUDES = -I../include +#AM_CPPFLAGS = -I../include -Wall -std=gnu99 libusbip_la_LDFLAGS = -version-info 0:1:0 EXTRA_CFLAGS = @EXTRA_CLFAGS@ -libusbip_la_CFLAGS = -Wall -W -Wstrict-prototypes $(EXTRA_CLFAGS) +libusbip_la_CFLAGS = -Wall -W -Wstrict-prototypes -std=gnu99 $(EXTRA_CLFAGS) -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"' diff -Naur usbip-0.1.4/src/lib/names.c trunk/src/lib/names.c --- usbip-0.1.4/src/lib/names.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/lib/names.c 2007-05-18 11:10:07.000000000 +0200 @@ -239,27 +239,27 @@ } /* ---------------------------------------------------------------------- */ +/* add a cleanup function by takahiro */ -/* add a cleanup function */ struct pool { struct pool *next; void *mem; }; -struct pool *pool_head = NULL; +static struct pool *pool_head = NULL; static void *my_malloc(size_t size) { struct pool *p; p = calloc(1, sizeof(struct pool)); - if(!p) { + if (!p) { free(p); return NULL; } p->mem = calloc(1, size); - if(!p->mem) + if (!p->mem) return NULL; p->next = pool_head; @@ -268,17 +268,17 @@ return p->mem; } -void names_deinit(void) +void names_free(void) { struct pool *pool; - if(!pool_head) + if (!pool_head) return; - for(pool = pool_head; pool != NULL; ) { + for (pool = pool_head; pool != NULL; ) { struct pool *tmp; - if(pool->mem) + if (pool->mem) free(pool->mem); tmp = pool; @@ -411,7 +411,7 @@ { struct genericstrtable *g; unsigned int h = hashnum(index); - + for (g = t[h]; g; g = g->next) if (g->num == index) return -1; @@ -466,7 +466,7 @@ /* ---------------------------------------------------------------------- */ -#define DBG(x) +#define DBG(x) static void parse(FILE *f) { @@ -769,7 +769,7 @@ DBG(printf("line %5u Report type %02x %s\n", linectr, u, cp)); continue; - } + } if (buf[0] == 'V' && buf[1] == 'T') { /* add here */ continue; @@ -783,7 +783,7 @@ int names_init(char *n) { FILE *f; - + if (!(f = fopen(n, "r"))) { return errno; } diff -Naur usbip-0.1.4/src/lib/names.h trunk/src/lib/names.h --- usbip-0.1.4/src/lib/names.h 1970-01-01 01:00:00.000000000 +0100 +++ trunk/src/lib/names.h 2007-05-18 11:10:07.000000000 +0200 @@ -0,0 +1,57 @@ +/*****************************************************************************/ + +/* + * names.h -- USB name database manipulation routines + * + * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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 of the License, 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. + * + * + */ + +/* + * Copyright (C) 2005 Takahiro Hirofuchi + * - names_free() is added. + */ + +/*****************************************************************************/ + +#ifndef _NAMES_H +#define _NAMES_H + +#include + +/* ---------------------------------------------------------------------- */ + +extern const char *names_vendor(u_int16_t vendorid); +extern const char *names_product(u_int16_t vendorid, u_int16_t productid); +extern const char *names_class(u_int8_t classid); +extern const char *names_subclass(u_int8_t classid, u_int8_t subclassid); +extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid); +extern const char *names_audioterminal(u_int16_t termt); +extern const char *names_hid(u_int8_t hidd); +extern const char *names_reporttag(u_int8_t rt); +extern const char *names_huts(unsigned int data); +extern const char *names_hutus(unsigned int data); +extern const char *names_langid(u_int16_t langid); +extern const char *names_physdes(u_int8_t ph); +extern const char *names_bias(u_int8_t b); +extern const char *names_countrycode(unsigned int countrycode); +extern int names_init(char *n); +extern void names_free(void); + +/* ---------------------------------------------------------------------- */ +#endif /* _NAMES_H */ diff -Naur usbip-0.1.4/src/lib/stub_driver.c trunk/src/lib/stub_driver.c --- usbip-0.1.4/src/lib/stub_driver.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/lib/stub_driver.c 2007-05-18 11:10:07.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Takahiro Hirofuchi + * Copyright (C) 2005-2007 Takahiro Hirofuchi */ #include "usbip.h" @@ -7,6 +7,7 @@ static const char *usbip_stub_driver_name = "usbip"; +struct usbip_stub_driver *stub_driver; static struct sysfs_driver *open_sysfs_stub_driver(void) { @@ -18,7 +19,7 @@ ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); - if(ret < 0) { + if (ret < 0) { err("sysfs must be mounted"); return NULL; } @@ -28,7 +29,7 @@ usbip_stub_driver_name); stub_driver = sysfs_open_driver_path(stub_driver_path); - if(!stub_driver) { + if (!stub_driver) { err("stub.ko must be loaded"); return NULL; } @@ -36,19 +37,6 @@ return stub_driver; } -#if 0 -static void unshift_if_new(struct dlist *dlist, struct sysfs_device *target) -{ - struct sysfs_device *dev; - - dlist_for_each_data(dlist, dev, struct sysfs_device) { - if(!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE)) - return; - } - - dlist_unshift(dlist, (void *) target); -} -#endif /* only the first interface value is true! */ @@ -61,17 +49,17 @@ snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status", udev->path, udev->busid, - udev->bConfigurationValue, + udev->bConfigurationValue, 0); attr = sysfs_open_attribute(attrpath); - if(!attr) { + if (!attr) { err("open %s", attrpath); return -1; } ret = sysfs_read_attribute(attr); - if(ret) { + if (ret) { err("read %s", attrpath); sysfs_close_attribute(attr); return -1; @@ -87,7 +75,7 @@ static void usbip_exported_device_delete(void *dev) { - struct usbip_exported_device *edev = + struct usbip_exported_device *edev = (struct usbip_exported_device *) dev; sysfs_close_device(edev->sudev); @@ -100,13 +88,13 @@ struct usbip_exported_device *edev = NULL; edev = (struct usbip_exported_device *) calloc(1, sizeof(*edev)); - if(!edev) { + if (!edev) { err("alloc device"); return NULL; } edev->sudev = sysfs_open_device_path(sdevpath); - if(!edev->sudev) { + if (!edev->sudev) { err("open %s", sdevpath); goto err; } @@ -114,26 +102,26 @@ read_usb_device(edev->sudev, &edev->udev); edev->status = read_attr_usbip_status(&edev->udev); - if(edev->status < 0) + if (edev->status < 0) goto err; /* reallocate buffer to include usb interface data */ size_t size = sizeof(*edev) + edev->udev.bNumInterfaces * sizeof(struct usb_interface); edev = (struct usbip_exported_device *) realloc(edev, size); - if(!edev) { + if (!edev) { err("alloc device"); goto err; } - for(int i=0; i < edev->udev.bNumInterfaces; i++) + for (int i=0; i < edev->udev.bNumInterfaces; i++) read_usb_interface(&edev->udev, i, &edev->uinf[i]); return edev; err: - if(edev && edev->sudev) + if (edev && edev->sudev) sysfs_close_device(edev->sudev); - if(edev) + if (edev) free(edev); return NULL; } @@ -144,7 +132,7 @@ struct sysfs_device *dev; dlist_for_each_data(dlist, dev, struct sysfs_device) { - if(!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE)) + if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE)) /* found. not new */ return 0; } @@ -157,19 +145,19 @@ /* do not delete anything. but, its container will be deleted. */ } -static int refresh_exported_devices(struct usbip_stub_driver *driver) +static int refresh_exported_devices(void) { struct sysfs_device *suinf; /* sysfs_device of usb_interface */ struct dlist *suinf_list; struct sysfs_device *sudev; /* sysfs_device of usb_device */ - struct dlist *sudev_list; + struct dlist *sudev_list; sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing); - suinf_list = sysfs_get_driver_devices(driver->sysfs_driver); - if(!suinf_list) { + suinf_list = sysfs_get_driver_devices(stub_driver->sysfs_driver); + if (!suinf_list) { printf("Bind usbip.ko to a usb device to be exportable!\n"); goto bye; } @@ -179,27 +167,27 @@ /* get usb device of this usb interface */ sudev = sysfs_get_device_parent(suinf); - if(!sudev) { + if (!sudev) { err("get parent dev of %s", suinf->name); continue; - } + } - if(check_new(sudev_list, sudev)) { + if (check_new(sudev_list, sudev)) { dlist_unshift(sudev_list, sudev); } } dlist_for_each_data(sudev_list, sudev, struct sysfs_device) { - struct usbip_exported_device *edev; + struct usbip_exported_device *edev; edev = usbip_exported_device_new(sudev->path); - if(!edev) { + if (!edev) { err("usbip_exported_device new"); continue; } - dlist_unshift(driver->edev_list, (void *) edev); - driver->ndevs++; + dlist_unshift(stub_driver->edev_list, (void *) edev); + stub_driver->ndevs++; } @@ -210,91 +198,95 @@ return 0; } -int usbip_stub_refresh_device_list(struct usbip_stub_driver *driver) +int usbip_stub_refresh_device_list(void) { int ret; - if(driver->edev_list) - dlist_destroy(driver->edev_list); + if (stub_driver->edev_list) + dlist_destroy(stub_driver->edev_list); - driver->ndevs = 0; + stub_driver->ndevs = 0; - driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device), + stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device), usbip_exported_device_delete); - if(!driver->edev_list) { + if (!stub_driver->edev_list) { err("alloc dlist"); return -1; } - ret = refresh_exported_devices(driver); - if(ret < 0) + ret = refresh_exported_devices(); + if (ret < 0) return ret; return 0; } -struct usbip_stub_driver *usbip_stub_driver_open(void) +int usbip_stub_driver_open(void) { int ret; - struct usbip_stub_driver *driver; - - driver = (struct usbip_stub_driver *) calloc(1, sizeof(*driver)); - if(!driver) { - err("alloc driver"); - return NULL; + + stub_driver = (struct usbip_stub_driver *) calloc(1, sizeof(*stub_driver)); + if (!stub_driver) { + err("alloc stub_driver"); + return -1; } - driver->ndevs = 0; + stub_driver->ndevs = 0; - driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device), + stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device), usbip_exported_device_delete); - if(!driver->edev_list) { + if (!stub_driver->edev_list) { err("alloc dlist"); goto err; } - driver->sysfs_driver = open_sysfs_stub_driver(); - if(!driver->sysfs_driver) + stub_driver->sysfs_driver = open_sysfs_stub_driver(); + if (!stub_driver->sysfs_driver) goto err; - ret = refresh_exported_devices(driver); - if(ret < 0) + ret = refresh_exported_devices(); + if (ret < 0) goto err; - return driver; + return 0; err: - if(driver->sysfs_driver) - sysfs_close_driver(driver->sysfs_driver); - if(driver->edev_list) - dlist_destroy(driver->edev_list); - free(driver); + if (stub_driver->sysfs_driver) + sysfs_close_driver(stub_driver->sysfs_driver); + if (stub_driver->edev_list) + dlist_destroy(stub_driver->edev_list); + free(stub_driver); - return NULL; + stub_driver = NULL; + return -1; } -void usbip_stub_driver_close(struct usbip_stub_driver *driver) +void usbip_stub_driver_close(void) { - if(driver->edev_list) - dlist_destroy(driver->edev_list); - if(driver->sysfs_driver) - sysfs_close_driver(driver->sysfs_driver); - free(driver); + if (!stub_driver) + return; + + if (stub_driver->edev_list) + dlist_destroy(stub_driver->edev_list); + if (stub_driver->sysfs_driver) + sysfs_close_driver(stub_driver->sysfs_driver); + free(stub_driver); + + stub_driver = NULL; } -int usbip_stub_export_device(struct usbip_stub_driver *driver, - struct usbip_exported_device *edev, int sockfd) +int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; char sockfd_buff[30]; - int ret; + int ret; - if(edev->status != SDEV_ST_AVAILABLE) { + if (edev->status != SDEV_ST_AVAILABLE) { info("device not available, %s", edev->udev.busid); return -1; } @@ -307,7 +299,7 @@ "usbip_sockfd"); attr = sysfs_open_attribute(attrpath); - if(!attr) { + if (!attr) { err("open %s", attrpath); return -1; } @@ -317,7 +309,7 @@ dbg("write: %s", sockfd_buff); ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff)); - if(ret < 0) { + if (ret < 0) { err("write sockfd %s to %s", sockfd_buff, attrpath); goto err_write_sockfd; } @@ -330,15 +322,14 @@ return ret; } -struct usbip_exported_device *usbip_stub_get_device(struct usbip_stub_driver *driver, - int num) +struct usbip_exported_device *usbip_stub_get_device(int num) { - struct usbip_exported_device *edev; - struct dlist *dlist = driver->edev_list; + struct usbip_exported_device *edev; + struct dlist *dlist = stub_driver->edev_list; int count = 0; dlist_for_each_data(dlist, edev, struct usbip_exported_device) { - if(num == count) + if (num == count) return edev; else count++ ; diff -Naur usbip-0.1.4/src/lib/stub_driver.h trunk/src/lib/stub_driver.h --- usbip-0.1.4/src/lib/stub_driver.h 1970-01-01 01:00:00.000000000 +0100 +++ trunk/src/lib/stub_driver.h 2007-05-18 11:10:07.000000000 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2007 Takahiro Hirofuchi + */ + +#ifndef _USBIP_STUB_DRIVER_H +#define _USBIP_STUB_DRIVER_H + +#include "usbip.h" + + +struct usbip_stub_driver { + int ndevs; + struct sysfs_driver *sysfs_driver; + + struct dlist *edev_list; /* list of exported device */ +}; + +struct usbip_exported_device { + struct sysfs_device *sudev; + + int32_t status; + struct usb_device udev; + struct usb_interface uinf[]; +}; + + +extern struct usbip_stub_driver *stub_driver; + +int usbip_stub_driver_open(void); +void usbip_stub_driver_close(void); + +int usbip_stub_refresh_device_list(void); +int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd); + +struct usbip_exported_device *usbip_stub_get_device(int num); +#endif diff -Naur usbip-0.1.4/src/lib/usbip_common.c trunk/src/lib/usbip_common.c --- usbip-0.1.4/src/lib/usbip_common.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/lib/usbip_common.c 2007-05-18 11:10:07.000000000 +0200 @@ -1,8 +1,9 @@ /* - * Copyright (C) 2005-2006 Takahiro Hirofuchi + * Copyright (C) 2005-2007 Takahiro Hirofuchi */ #include "usbip.h" +#include "names.h" int usbip_use_syslog = 0; int usbip_use_stderr = 0; @@ -40,8 +41,8 @@ const char *usbip_status_string(int32_t status) { - for(int i=0; portst_strings[i].desc != NULL; i++) - if(portst_strings[i].num == status) + for (int i=0; portst_strings[i].desc != NULL; i++) + if (portst_strings[i].num == status) return portst_strings[i].desc; return "Unknown Status"; @@ -49,53 +50,13 @@ const char *usbip_speed_string(int num) { - for(int i=0; speed_strings[i].speed != NULL; i++) - if(speed_strings[i].num == num) + for (int i=0; speed_strings[i].speed != NULL; i++) + if (speed_strings[i].num == num) return speed_strings[i].desc; return "Unknown Speed"; } -void pack_uint32_t(int pack, uint32_t *num) -{ - uint32_t i; - - if(pack) - i = htonl(*num); - else - i = ntohl(*num); - - *num = i; -} - -void pack_uint16_t(int pack, uint16_t *num) -{ - uint16_t i; - - if(pack) - i = htons(*num); - else - i = ntohs(*num); - - *num = i; -} - -void pack_usb_device(int pack, struct usb_device *udev) -{ - pack_uint32_t(pack, &udev->busnum); - pack_uint32_t(pack, &udev->devnum); - pack_uint32_t(pack, &udev->speed ); - - pack_uint16_t(pack, &udev->idVendor ); - pack_uint16_t(pack, &udev->idProduct); - pack_uint16_t(pack, &udev->bcdDevice); -} - -void pack_usb_interface(int pack, struct usb_interface *udev) -{ - /* uint8_t members need nothing */ -} - #define DBG_UDEV_INTEGER(name)\ dbg("%-20s = %x", to_string(name), (int) udev->name) @@ -106,7 +67,7 @@ void dump_usb_interface(struct usb_interface *uinf) { char buff[100]; - usbip_class_name(buff, sizeof(buff), + usbip_names_get_class(buff, sizeof(buff), uinf->bInterfaceClass, uinf->bInterfaceSubClass, uinf->bInterfaceProtocol); @@ -121,7 +82,7 @@ dbg("%-20s = %s", "path", udev->path); dbg("%-20s = %s", "busid", udev->busid); - usbip_class_name(buff, sizeof(buff), + usbip_names_get_class(buff, sizeof(buff), udev->bDeviceClass, udev->bDeviceSubClass, udev->bDeviceProtocol); @@ -129,7 +90,7 @@ DBG_UDEV_INTEGER(bcdDevice); - usbip_product_name(buff, sizeof(buff), + usbip_names_get_product(buff, sizeof(buff), udev->idVendor, udev->idProduct); dbg("%-20s = %s", "Vendor/Product", buff); @@ -137,7 +98,7 @@ DBG_UDEV_INTEGER(bNumConfigurations); DBG_UDEV_INTEGER(bNumInterfaces); - dbg("%-20s = %s", "speed", + dbg("%-20s = %s", "speed", usbip_speed_string(udev->speed)); DBG_UDEV_INTEGER(busnum); @@ -155,19 +116,19 @@ snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, name); attr = sysfs_open_attribute(attrpath); - if(!attr) { + if (!attr) { err("open attr %s", attrpath); return 0; } ret = sysfs_read_attribute(attr); - if(ret < 0) { + if (ret < 0) { err("read attr"); goto err; } ret = sscanf(attr->value, format, &num); - if(ret < 1) { + if (ret < 1) { err("sscanf"); goto err; } @@ -189,27 +150,27 @@ snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, "speed"); attr = sysfs_open_attribute(attrpath); - if(!attr) { + if (!attr) { err("open attr"); return 0; } ret = sysfs_read_attribute(attr); - if(ret < 0) { + if (ret < 0) { err("read attr"); goto err; } ret = sscanf(attr->value, "%s\n", speed); - if(ret < 1) { + if (ret < 1) { err("sscanf"); goto err; } err: sysfs_close_attribute(attr); - for(int i=0; speed_strings[i].speed != NULL; i++) { - if(!strcmp(speed, speed_strings[i].speed)) + for (int i=0; speed_strings[i].speed != NULL; i++) { + if (!strcmp(speed, speed_strings[i].speed)) return speed_strings[i].num; } @@ -217,7 +178,7 @@ } #define READ_ATTR(object, type, dev, name, format)\ - do { (object)->name = (type) read_attr_value(dev, to_string(name), format); } while(0) + do { (object)->name = (type) read_attr_value(dev, to_string(name), format); } while (0) int read_usb_device(struct sysfs_device *sdev, struct usb_device *udev) @@ -256,7 +217,7 @@ sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i); sif = sysfs_open_device("usb", busid); - if(!sif) { + if (!sif) { err("open sif of %s", busid); return -1; } @@ -270,24 +231,33 @@ return 0; } +int usbip_names_init(char *f) +{ + return names_init(f); +} + +void usbip_names_free() +{ + names_free(); +} -void usbip_product_name(char *buff, size_t size, uint16_t vendor, uint16_t product) +void usbip_names_get_product(char *buff, size_t size, uint16_t vendor, uint16_t product) { const char *prod, *vend; prod = names_product(vendor, product); - if(!prod) + if (!prod) prod = "unknown product"; vend = names_vendor(vendor); - if(!vend) + if (!vend) vend = "unknown vendor"; snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product); } -void usbip_class_name(char *buff, size_t size, uint8_t class, uint8_t subclass, uint8_t protocol) +void usbip_names_get_class(char *buff, size_t size, uint8_t class, uint8_t subclass, uint8_t protocol) { const char *c, *s, *p; @@ -297,15 +267,15 @@ } p = names_protocol(class, subclass, protocol); - if(!p) + if (!p) p = "unknown protocol"; s = names_subclass(class, subclass); - if(!s) + if (!s) s = "unknown subclass"; c = names_class(class); - if(!c) + if (!c) c = "unknown class"; snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol); diff -Naur usbip-0.1.4/src/lib/usbip_common.h trunk/src/lib/usbip_common.h --- usbip-0.1.4/src/lib/usbip_common.h 1970-01-01 01:00:00.000000000 +0100 +++ trunk/src/lib/usbip_common.h 2007-05-18 11:10:07.000000000 +0200 @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2005-2007 Takahiro Hirofuchi + */ + +#ifndef _USBIP_COMMON_H +#define _USBIP_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef USBIDS_FILE +#define USBIDS_FILE "/usr/share/hwdata/usb.ids" +#endif + +extern int usbip_use_syslog; +extern int usbip_use_stderr; +extern int usbip_use_debug ; + +//#include +enum usb_device_speed { + USB_SPEED_UNKNOWN = 0, /* enumerating */ + USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ + USB_SPEED_HIGH, /* usb 2.0 */ + USB_SPEED_VARIABLE /* wireless (usb 2.5) */ +}; + +/* FIXME: how to sync with drivers/usbip_common.h ? */ +enum usbip_device_status{ + /* sdev is available. */ + SDEV_ST_AVAILABLE = 0x01, + /* sdev is now used. */ + SDEV_ST_USED, + /* sdev is unusable because of a fatal error. */ + SDEV_ST_ERROR, + + /* vdev does not connect a remote device. */ + VDEV_ST_NULL, + /* vdev is used, but the USB address is not assigned yet */ + VDEV_ST_NOTASSIGNED, + VDEV_ST_USED, + VDEV_ST_ERROR +}; + +#define err(fmt, args...) do { \ + if (usbip_use_syslog) { \ + syslog(LOG_ERR, "usbip err: %13s:%4d (%-12s) " fmt "\n", \ + __FILE__, __LINE__, __FUNCTION__, ##args); \ + } \ + if (usbip_use_stderr) { \ + fprintf(stderr, "usbip err: %13s:%4d (%-12s) " fmt "\n", \ + __FILE__, __LINE__, __FUNCTION__, ##args); \ + } \ +} while (0) + +#define notice(fmt, args...) do { \ + if (usbip_use_syslog) { \ + syslog(LOG_DEBUG, "usbip: " fmt, ##args); \ + } \ + if (usbip_use_stderr) { \ + fprintf(stderr, "usbip: " fmt "\n", ##args); \ + } \ +} while (0) + +#define info(fmt, args...) do { \ + if (usbip_use_syslog) { \ + syslog(LOG_DEBUG, fmt, ##args); \ + } \ + if (usbip_use_stderr) { \ + fprintf(stderr, fmt "\n", ##args); \ + } \ +} while (0) + +#define dbg(fmt, args...) do { \ + if (usbip_use_debug) { \ + if (usbip_use_syslog) { \ + syslog(LOG_DEBUG, "usbip dbg: %13s:%4d (%-12s) " fmt, \ + __FILE__, __LINE__, __FUNCTION__, ##args); \ + } \ + if (usbip_use_stderr) { \ + fprintf(stderr, "usbip dbg: %13s:%4d (%-12s) " fmt "\n", \ + __FILE__, __LINE__, __FUNCTION__, ##args); \ + } \ + } \ +} while (0) + + +#define BUG() do { err("sorry, it's a bug"); abort(); } while (0) + +struct usb_interface { + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t padding; /* alignment */ +} __attribute__((packed)); + + + +struct usb_device { + char path[SYSFS_PATH_MAX]; + char busid[SYSFS_BUS_ID_SIZE]; + + uint32_t busnum; + uint32_t devnum; + uint32_t speed; + + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bConfigurationValue; + uint8_t bNumConfigurations; + uint8_t bNumInterfaces; +} __attribute__((packed)); + +#define to_string(s) #s + +void dump_usb_interface(struct usb_interface *); +void dump_usb_device(struct usb_device *); +int read_usb_device(struct sysfs_device *sdev, struct usb_device *udev); +int read_attr_value(struct sysfs_device *dev, const char *name, const char *format); +int read_usb_interface(struct usb_device *udev, int i, struct usb_interface *uinf); + +const char *usbip_speed_string(int num); +const char *usbip_status_string(int32_t status); + +int usbip_names_init(char *); +void usbip_names_free(void); +void usbip_names_get_product(char *buff, size_t size, uint16_t vendor, uint16_t product); +void usbip_names_get_class(char *buff, size_t size, uint8_t class, uint8_t subclass, uint8_t protocol); + +#endif diff -Naur usbip-0.1.4/src/lib/usbip.h trunk/src/lib/usbip.h --- usbip-0.1.4/src/lib/usbip.h 1970-01-01 01:00:00.000000000 +0100 +++ trunk/src/lib/usbip.h 2007-05-18 11:10:07.000000000 +0200 @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2005-2007 Takahiro Hirofuchi + */ + +#ifndef _USBIP_H +#define _USBIP_H + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include "usbip_common.h" +#include "stub_driver.h" +#include "vhci_driver.h" +#ifdef DMALLOC +#include +#endif + +#endif diff -Naur usbip-0.1.4/src/lib/vhci_driver.c trunk/src/lib/vhci_driver.c --- usbip-0.1.4/src/lib/vhci_driver.c 2007-05-18 11:10:09.000000000 +0200 +++ trunk/src/lib/vhci_driver.c 2007-05-18 11:10:07.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2006 Takahiro Hirofuchi + * Copyright (C) 2005-2007 Takahiro Hirofuchi */ @@ -8,55 +8,14 @@ static const char vhci_driver_name[] = "vhci_hcd"; +struct usbip_vhci_driver *vhci_driver; -#if 0 -static struct sockaddr_storage *get_sockaddr_s(char *ipaddr, char *ipport, struct sockaddr_storage *ss) -{ - struct addrinfo hints, *res; - int ret; - - /* kernel api should be changed to be simpler */ - while(*ipaddr == '0' && *ipaddr != '\0') - ipaddr += 1; - - while(*ipport == '0' && *ipport != '\0') - ipport += 1; - - bzero(&hints, sizeof(hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICHOST; - - ret = getaddrinfo(ipaddr, ipport, &hints, &res); - if(ret) { - err("getaddrinfo %s", gai_strerror(ret)); - } - - if(res->ai_addrlen > sizeof(*ss)) { - err("sockaddr too large"); - freeaddrinfo(res); - return NULL; - } - - memcpy(ss, res->ai_addr, res->ai_addrlen); - - freeaddrinfo(res); - - return ss; -} -#endif - - - - - - -static struct usbip_imported_device *imported_device_init(struct usbip_vhci_driver *driver, - struct usbip_imported_device *idev, char *busid) +static struct usbip_imported_device *imported_device_init(struct usbip_imported_device *idev, char *busid) { struct sysfs_device *sudev; sudev = sysfs_open_device("usb", busid); - if(!sudev) { + if (!sudev) { err("sysfs_open_device %s", busid); goto err; } @@ -65,13 +24,13 @@ /* add class devices of this imported device */ struct class_device *cdev; - dlist_for_each_data(driver->cdev_list, cdev, struct class_device) { - if(!strncmp(cdev->devpath, idev->udev.path, strlen(idev->udev.path))) { + dlist_for_each_data(vhci_driver->cdev_list, cdev, struct class_device) { + if (!strncmp(cdev->devpath, idev->udev.path, strlen(idev->udev.path))) { struct class_device *new_cdev; /* alloc and copy because dlist is linked from only one list */ new_cdev = calloc(1, sizeof(*new_cdev)); - if(!new_cdev) + if (!new_cdev) goto err; memcpy(new_cdev, cdev, sizeof(*new_cdev)); @@ -87,29 +46,29 @@ -static int parse_status(char *value, struct usbip_vhci_driver *driver) +static int parse_status(char *value) { int ret = 0; char *c; - - for(int i = 0; i < driver->nports; i++) - bzero(&driver->idev[i], sizeof(struct usbip_imported_device)); + + for (int i = 0; i < vhci_driver->nports; i++) + bzero(&vhci_driver->idev[i], sizeof(struct usbip_imported_device)); /* skip a header line */ c = strchr(value, '\n') + 1; - while(*c != '\0') { + while (*c != '\0') { int port, status, speed, busnum, devnum; unsigned long socket; char lbusid[SYSFS_BUS_ID_SIZE]; - ret = sscanf(c, "%d %d %d %d %d %lx %s\n", + ret = sscanf(c, "%d %d %d %d %d %lx %s\n", &port, &status, &speed, &busnum, &devnum, &socket, lbusid); - if(ret < 5) { + if (ret < 5) { err("scanf %d", ret); BUG(); } @@ -121,7 +80,7 @@ /* if a device is connected, look at it */ { - struct usbip_imported_device *idev = &driver->idev[port]; + struct usbip_imported_device *idev = &vhci_driver->idev[port]; idev->port = port; idev->status = status; @@ -129,14 +88,14 @@ idev->devnum = devnum; idev->cdev_list = dlist_new(sizeof(struct class_device)); - if(!idev->cdev_list) { + if (!idev->cdev_list) { err("init new device"); return -1; } - if(idev->status != VDEV_ST_NULL && idev->status != VDEV_ST_NOTASSIGNED) { - idev = imported_device_init(driver, idev, lbusid); - if(!idev) { + if (idev->status != VDEV_ST_NULL && idev->status != VDEV_ST_NOTASSIGNED) { + idev = imported_device_init(idev, lbusid); + if (!idev) { err("init new device"); return -1; } @@ -154,7 +113,7 @@ } -static int check_usbip_device(struct usbip_vhci_driver *driver, struct sysfs_class_device *cdev) +static int check_usbip_device(struct sysfs_class_device *cdev) { char clspath[SYSFS_PATH_MAX]; /* /sys/class/video4linux/video0/device */ char devpath[SYSFS_PATH_MAX]; /* /sys/devices/platform/vhci_hcd/usb6/6-1:1.1 */ @@ -164,18 +123,18 @@ snprintf(clspath, sizeof(clspath), "%s/device", cdev->path); ret = sysfs_get_link(clspath, devpath, SYSFS_PATH_MAX); - if(!ret) { - if(!strncmp(devpath, driver->hc_device->path, - strlen(driver->hc_device->path))) { + if (!ret) { + if (!strncmp(devpath, vhci_driver->hc_device->path, + strlen(vhci_driver->hc_device->path))) { /* found usbip device */ struct class_device *cdev; - cdev = calloc(1, sizeof*cdev); - if(!cdev) { + cdev = calloc(1, sizeof(*cdev)); + if (!cdev) { err("calloc cdev"); return -1; } - dlist_unshift(driver->cdev_list, (void*) cdev); + dlist_unshift(vhci_driver->cdev_list, (void*) cdev); strncpy(cdev->clspath, clspath, sizeof(cdev->clspath)); strncpy(cdev->devpath, devpath, sizeof(cdev->clspath)); dbg(" found %s %s", clspath, devpath); @@ -186,7 +145,7 @@ } -static int search_class_for_usbip_device(struct usbip_vhci_driver *driver, char *cname) +static int search_class_for_usbip_device(char *cname) { struct sysfs_class *class; struct dlist *cdev_list; @@ -194,7 +153,7 @@ int ret = 0; class = sysfs_open_class(cname); - if(!class) { + if (!class) { err("open class"); return -1; } @@ -202,14 +161,14 @@ dbg("class %s", class->name); cdev_list = sysfs_get_class_devices(class); - if(!cdev_list) + if (!cdev_list) /* nothing */ goto out; dlist_for_each_data(cdev_list, cdev, struct sysfs_class_device) { dbg(" cdev %s", cdev->name); - ret = check_usbip_device(driver, cdev); - if(ret < 0) + ret = check_usbip_device(cdev); + if (ret < 0) goto out; } @@ -220,7 +179,7 @@ } -static int refresh_class_device_list(struct usbip_vhci_driver *driver) +static int refresh_class_device_list(void) { int ret; struct dlist *cname_list; @@ -228,14 +187,14 @@ /* search under /sys/class */ cname_list = sysfs_open_directory_list("/sys/class"); - if(!cname_list) { + if (!cname_list) { err("open class directory"); return -1; } dlist_for_each_data(cname_list, cname, char) { - ret = search_class_for_usbip_device(driver, cname); - if(ret < 0) { + ret = search_class_for_usbip_device(cname); + if (ret < 0) { sysfs_close_list(cname_list); return -1; } @@ -244,22 +203,22 @@ sysfs_close_list(cname_list); /* seach under /sys/block */ - ret = search_class_for_usbip_device(driver, SYSFS_BLOCK_NAME); - if(ret < 0) + ret = search_class_for_usbip_device(SYSFS_BLOCK_NAME); + if (ret < 0) return -1; return 0; } -static int refresh_imported_device_list(struct usbip_vhci_driver *driver) +static int refresh_imported_device_list(void) { struct sysfs_attribute *attr_status; - attr_status = sysfs_get_device_attr(driver->hc_device, "status"); - if(!attr_status) { - err("get attr %s of %s", "status", driver->hc_device->name); + attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status"); + if (!attr_status) { + err("get attr %s of %s", "status", vhci_driver->hc_device->name); return -1; } @@ -268,17 +227,17 @@ dbg("%s", attr_status->value); - return parse_status(attr_status->value, driver); + return parse_status(attr_status->value); } -static int get_nports(struct usbip_vhci_driver *driver) +static int get_nports(void) { int nports = 0; struct sysfs_attribute *attr_status; - attr_status = sysfs_get_device_attr(driver->hc_device, "status"); - if(!attr_status) { - err("get attr %s of %s", "status", driver->hc_device->name); + attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status"); + if (!attr_status) { + err("get attr %s of %s", "status", vhci_driver->hc_device->name); return -1; } @@ -293,7 +252,7 @@ /* skip a header line */ c = strchr(attr_status->value, '\n') + 1; - while(*c != '\0') { + while (*c != '\0') { /* go to the next line */ c = strchr(c, '\n') + 1; nports += 1; @@ -312,25 +271,25 @@ struct dlist *hc_devs; int found = 0; - + snprintf(sdriver_path, SYSFS_PATH_MAX, "%s/%s/platform/%s/%s", sysfs_mntpath, SYSFS_BUS_NAME, SYSFS_DRIVERS_NAME, vhci_driver_name); - + sdriver = sysfs_open_driver_path(sdriver_path); - if(!sdriver) { + if (!sdriver) { info("%s is not found", sdriver_path); info("load vhci-hcd.ko !"); return -1; } hc_devs = sysfs_get_driver_devices(sdriver); - if(!hc_devs) { + if (!hc_devs) { err("get hc list"); goto err; } - /* only vhci_hcd */ + /* assume only one vhci_hcd */ dlist_for_each_data(hc_devs, hc_dev, struct sysfs_device) { strncpy(hc_busid, hc_dev->bus_id, SYSFS_BUS_ID_SIZE); found = 1; @@ -339,7 +298,7 @@ err: sysfs_close_driver(sdriver); - if(found) + if (found) return 0; err("not found usbip hc"); @@ -349,110 +308,115 @@ /* ---------------------------------------------------------------------- */ -struct usbip_vhci_driver *usbip_vhci_driver_open(void) +int usbip_vhci_driver_open(void) { int ret; char hc_busid[SYSFS_BUS_ID_SIZE]; - struct usbip_vhci_driver *driver; - - driver = (struct usbip_vhci_driver *) calloc(1, sizeof(*driver)); - if(!driver) { - err("alloc driver"); - return NULL; + vhci_driver = (struct usbip_vhci_driver *) calloc(1, sizeof(*vhci_driver)); + if (!vhci_driver) { + err("alloc vhci_driver"); + return -1; } - ret = sysfs_get_mnt_path(driver->sysfs_mntpath, SYSFS_PATH_MAX); - if(ret < 0) { + ret = sysfs_get_mnt_path(vhci_driver->sysfs_mntpath, SYSFS_PATH_MAX); + if (ret < 0) { err("sysfs must be mounted"); goto err; } - ret = get_hc_busid(driver->sysfs_mntpath, hc_busid); - if(ret < 0) + ret = get_hc_busid(vhci_driver->sysfs_mntpath, hc_busid); + if (ret < 0) goto err; /* will be freed in usbip_driver_close() */ - driver->hc_device = sysfs_open_device("platform", hc_busid); - if(!driver->hc_device) { - err("get sysfs driver"); + vhci_driver->hc_device = sysfs_open_device("platform", hc_busid); + if (!vhci_driver->hc_device) { + err("get sysfs vhci_driver"); goto err; } - driver->nports = get_nports(driver); + vhci_driver->nports = get_nports(); - info("%d ports available\n", driver->nports); + info("%d ports available\n", vhci_driver->nports); - driver->cdev_list = dlist_new(sizeof(struct class_device)); - if(!driver->cdev_list) + vhci_driver->cdev_list = dlist_new(sizeof(struct class_device)); + if (!vhci_driver->cdev_list) goto err; - if(refresh_class_device_list(driver)) + if (refresh_class_device_list()) goto err; - if(refresh_imported_device_list(driver)) + if (refresh_imported_device_list()) goto err; - return driver; + return 0; err: - if(driver->cdev_list) - dlist_destroy(driver->cdev_list); - if(driver->hc_device) - sysfs_close_device(driver->hc_device); - if(driver) - free(driver); - return NULL; + if (vhci_driver->cdev_list) + dlist_destroy(vhci_driver->cdev_list); + if (vhci_driver->hc_device) + sysfs_close_device(vhci_driver->hc_device); + if (vhci_driver) + free(vhci_driver); + + vhci_driver = NULL; + return -1; } -void usbip_vhci_driver_close(struct usbip_vhci_driver *driver) +void usbip_vhci_driver_close() { - if(driver->cdev_list) - dlist_destroy(driver->cdev_list); + if (!vhci_driver) + return; + + if (vhci_driver->cdev_list) + dlist_destroy(vhci_driver->cdev_list); - for(int i = 0; i < driver->nports; i++) { - if(driver->idev[i].cdev_list) - dlist_destroy(driver->idev[i].cdev_list); + for (int i = 0; i < vhci_driver->nports; i++) { + if (vhci_driver->idev[i].cdev_list) + dlist_destroy(vhci_driver->idev[i].cdev_list); } - if(driver->hc_device) - sysfs_close_device(driver->hc_device); - free(driver); + if (vhci_driver->hc_device) + sysfs_close_device(vhci_driver->hc_device); + free(vhci_driver); + + vhci_driver = NULL; } -int usbip_vhci_refresh_device_list(struct usbip_vhci_driver *driver) +int usbip_vhci_refresh_device_list(void) { - if(driver->cdev_list) - dlist_destroy(driver->cdev_list); + if (vhci_driver->cdev_list) + dlist_destroy(vhci_driver->cdev_list); - for(int i = 0; i < driver->nports; i++) { - if(driver->idev[i].cdev_list) - dlist_destroy(driver->idev[i].cdev_list); + for (int i = 0; i < vhci_driver->nports; i++) { + if (vhci_driver->idev[i].cdev_list) + dlist_destroy(vhci_driver->idev[i].cdev_list); } - driver->cdev_list = dlist_new(sizeof(struct class_device)); - if(!driver->cdev_list) + vhci_driver->cdev_list = dlist_new(sizeof(struct class_device)); + if (!vhci_driver->cdev_list) goto err; - if(refresh_class_device_list(driver)) + if (refresh_class_device_list()) goto err; - if(refresh_imported_device_list(driver)) + if (refresh_imported_device_list()) goto err; return 0; err: - if(driver->cdev_list) - dlist_destroy(driver->cdev_list); + if (vhci_driver->cdev_list) + dlist_destroy(vhci_driver->cdev_list); - for(int i = 0; i < driver->nports; i++) { - if(driver->idev[i].cdev_list) - dlist_destroy(driver->idev[i].cdev_list); + for (int i = 0; i < vhci_driver->nports; i++) { + if (vhci_driver->idev[i].cdev_list) + dlist_destroy(vhci_driver->idev[i].cdev_list); } err("refresh device list"); @@ -460,11 +424,10 @@ } -int usbip_vhci_get_free_port(struct usbip_vhci_driver *driver) +int usbip_vhci_get_free_port(void) { - - for(int i = 0; i < driver->nports; i++) { - if(driver->idev[i].status == VDEV_ST_NULL) + for (int i = 0; i < vhci_driver->nports; i++) { + if (vhci_driver->idev[i].status == VDEV_ST_NULL) return i; } @@ -472,26 +435,25 @@ } -int usbip_vhci_import_device2(struct usbip_vhci_driver *driver, - uint8_t port, int sockfd, uint8_t busnum, +int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum, uint8_t devnum, uint32_t speed) { struct sysfs_attribute *attr_attach; - char newvalue[200]; /* what size should be ? */ + char buff[200]; /* what size should be ? */ int ret; - attr_attach = sysfs_get_device_attr(driver->hc_device, "attach"); - if(!attr_attach) { + attr_attach = sysfs_get_device_attr(vhci_driver->hc_device, "attach"); + if (!attr_attach) { err("get attach"); return -1; } - snprintf(newvalue, 200, "%u %u %u %u %u", + snprintf(buff, sizeof(buff), "%u %u %u %u %u", port, sockfd, busnum, devnum, speed); - dbg("writing: %s", newvalue); + dbg("writing: %s", buff); - ret = sysfs_write_attribute(attr_attach, newvalue, strlen(newvalue)); - if(ret < 0) { + ret = sysfs_write_attribute(attr_attach, buff, strlen(buff)); + if (ret < 0) { err("write to attach failed"); return -1; } @@ -501,39 +463,24 @@ return 0; } - -int usbip_vhci_import_device(struct usbip_vhci_driver *driver, uint8_t port, - int sockfd, struct usb_device *udev) -{ - int ret; - - ret = usbip_vhci_import_device2(driver, port, sockfd, - udev->busnum, udev->devnum, udev->speed); - if(ret < 0) - err("import device"); - - return ret; -} - - -int usbip_vhci_detach_device(struct usbip_vhci_driver *driver, uint8_t port) +int usbip_vhci_detach_device(uint8_t port) { struct sysfs_attribute *attr_detach; - char newvalue[200]; /* what size should be ? */ + char buff[200]; /* what size should be ? */ int ret; - attr_detach = sysfs_get_device_attr(driver->hc_device, "detach"); - if(!attr_detach) { + attr_detach = sysfs_get_device_attr(vhci_driver->hc_device, "detach"); + if (!attr_detach) { err("get detach"); return -1; } - snprintf(newvalue, 200, "%u", port); + snprintf(buff, sizeof(buff), "%u", port); dbg("writing to detach"); - dbg("writing: %s", newvalue); + dbg("writing: %s", buff); - ret = sysfs_write_attribute(attr_detach, newvalue, strlen(newvalue)); - if(ret < 0) { + ret = sysfs_write_attribute(attr_detach, buff, strlen(buff)); + if (ret < 0) { err("write to detach failed"); return -1; } @@ -542,5 +489,3 @@ return 0; } - - diff -Naur usbip-0.1.4/src/lib/vhci_driver.h trunk/src/lib/vhci_driver.h --- usbip-0.1.4/src/lib/vhci_driver.h 1970-01-01 01:00:00.000000000 +0100 +++ trunk/src/lib/vhci_driver.h 2007-05-18 11:10:07.000000000 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2005-2007 Takahiro Hirofuchi + */ + +#ifndef _VHCI_DRIVER_H +#define _VHCI_DRIVER_H + +#include "usbip.h" + + + +#define MAXNPORT 128 + +struct class_device { + char clspath[SYSFS_PATH_MAX]; + char devpath[SYSFS_PATH_MAX]; +}; + +struct usbip_imported_device { + uint8_t port; + uint32_t status; + + uint8_t busnum; + uint8_t devnum; + + + struct dlist *cdev_list; /* list of class device */ + struct usb_device udev; +}; + +struct usbip_vhci_driver { + char sysfs_mntpath[SYSFS_PATH_MAX]; + struct sysfs_device *hc_device; /* /sys/devices/platform/vhci_hcd */ + + struct dlist *cdev_list; /* list of class device */ + + int nports; + struct usbip_imported_device idev[MAXNPORT]; +}; + + +extern struct usbip_vhci_driver *vhci_driver; + +int usbip_vhci_driver_open(void); +void usbip_vhci_driver_close(void); + +int usbip_vhci_refresh_device_list(void); + + +int usbip_vhci_get_free_port(void); +int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum, + uint8_t devnum, uint32_t speed); +int usbip_vhci_detach_device(uint8_t port); +#endif diff -Naur usbip-0.1.4/src/ltmain.sh trunk/src/ltmain.sh --- usbip-0.1.4/src/ltmain.sh 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/ltmain.sh 1970-01-01 01:00:00.000000000 +0100 @@ -1,6871 +0,0 @@ -# ltmain.sh - Provide generalized library-building support services. -# NOTE: Changing this file will not affect anything until you rerun configure. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# Originally by Gordon Matzigkeit , 1996 -# -# 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 of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -basename="s,^.*/,,g" - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" - -# The name of this program: -progname=`echo "$progpath" | $SED $basename` -modename="$progname" - -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 - -PROGRAM=ltmain.sh -PACKAGE=libtool -VERSION="1.5.22 Debian 1.5.22-4" -TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" - -# See if we are running on zsh, and set the options which allow our -# commands through without removal of \ escapes. -if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - -# Check that we have a working $echo. -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then - # Yippee, $echo works! - : -else - # Restart under the correct shell, and then maybe $echo will work. - exec $SHELL "$progpath" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit $EXIT_FAILURE -fi - -# Global variables. -mode=$default_mode -nonopt= -prev= -prevopt= -run= -show="$echo" -show_help= -execute_dlfiles= -duplicate_deps=no -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" - -##################################### -# Shell function definitions: -# This seems to be the best place for them - -# func_mktempdir [string] -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. -func_mktempdir () -{ - my_template="${TMPDIR-/tmp}/${1-$progname}" - - if test "$run" = ":"; then - # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" - else - - # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` - - if test ! -d "$my_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" - - save_mktempdir_umask=`umask` - umask 0077 - $mkdir "$my_tmpdir" - umask $save_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || { - $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 - exit $EXIT_FAILURE - } - fi - - $echo "X$my_tmpdir" | $Xsed -} - - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -func_win32_libid () -{ - win32_libid_type="unknown" - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ - $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then - win32_nmres=`eval $NM -f posix -A $1 | \ - $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $echo $win32_libid_type -} - - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - CC_quoted="$CC_quoted $arg" - done - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - CC_quoted="$CC_quoted $arg" - done - case "$@ " in - " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - $echo "$modename: unable to infer tagged configuration" - $echo "$modename: specify a tag with \`--tag'" 1>&2 - exit $EXIT_FAILURE -# else -# $echo "$modename: using $tagname tagged configuration" - fi - ;; - esac - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - - $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" - $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 - exit $EXIT_FAILURE - fi -} - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - my_gentop="$1"; shift - my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" - my_status="" - - $show "${rm}r $my_gentop" - $run ${rm}r "$my_gentop" - $show "$mkdir $my_gentop" - $run $mkdir "$my_gentop" - my_status=$? - if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then - exit $my_status - fi - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` - my_xdir="$my_gentop/$my_xlib" - - $show "${rm}r $my_xdir" - $run ${rm}r "$my_xdir" - $show "$mkdir $my_xdir" - $run $mkdir "$my_xdir" - exit_status=$? - if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then - exit $exit_status - fi - case $host in - *-darwin*) - $show "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - if test -z "$run"; then - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` - darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` - if test -n "$darwin_arches"; then - darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - $show "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" - cd "$darwin_curdir" - $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" - done # $darwin_arches - ## Okay now we have a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` - lipo -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - ${rm}r unfat-$$ - cd "$darwin_orig_dir" - else - cd "$darwin_orig_dir" - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - fi # $run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done - func_extract_archives_result="$my_oldobjs" -} -# End of Shell function definitions -##################################### - -# Darwin sucks -eval std_shrext=\"$shrext_cmds\" - -disable_libs=no - -# Parse our command line options once, thoroughly. -while test "$#" -gt 0 -do - arg="$1" - shift - - case $arg in - -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - execute_dlfiles) - execute_dlfiles="$execute_dlfiles $arg" - ;; - tag) - tagname="$arg" - preserve_args="${preserve_args}=$arg" - - # Check whether tagname contains only valid characters - case $tagname in - *[!-_A-Za-z0-9,/]*) - $echo "$progname: invalid tag name: $tagname" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - case $tagname in - CC) - # Don't test for the "default" C tag, as we know, it's there, but - # not specially marked. - ;; - *) - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then - taglist="$taglist $tagname" - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" - else - $echo "$progname: ignoring unknown tag $tagname" 1>&2 - fi - ;; - esac - ;; - *) - eval "$prev=\$arg" - ;; - esac - - prev= - prevopt= - continue - fi - - # Have we seen a non-optional argument yet? - case $arg in - --help) - show_help=yes - ;; - - --version) - $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" - $echo - $echo "Copyright (C) 2005 Free Software Foundation, Inc." - $echo "This is free software; see the source for copying conditions. There is NO" - $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - exit $? - ;; - - --config) - ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath - # Now print the configurations for the tags. - for tagname in $taglist; do - ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" - done - exit $? - ;; - - --debug) - $echo "$progname: enabling shell trace mode" - set -x - preserve_args="$preserve_args $arg" - ;; - - --dry-run | -n) - run=: - ;; - - --features) - $echo "host: $host" - if test "$build_libtool_libs" = yes; then - $echo "enable shared libraries" - else - $echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - $echo "enable static libraries" - else - $echo "disable static libraries" - fi - exit $? - ;; - - --finish) mode="finish" ;; - - --mode) prevopt="--mode" prev=mode ;; - --mode=*) mode="$optarg" ;; - - --preserve-dup-deps) duplicate_deps="yes" ;; - - --quiet | --silent) - show=: - preserve_args="$preserve_args $arg" - ;; - - --tag) - prevopt="--tag" - prev=tag - preserve_args="$preserve_args --tag" - ;; - --tag=*) - set tag "$optarg" ${1+"$@"} - shift - prev=tag - preserve_args="$preserve_args --tag" - ;; - - -dlopen) - prevopt="-dlopen" - prev=execute_dlfiles - ;; - - -*) - $echo "$modename: unrecognized option \`$arg'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - - *) - nonopt="$arg" - break - ;; - esac -done - -if test -n "$prevopt"; then - $echo "$modename: option \`$prevopt' requires an argument" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE -fi - -case $disable_libs in -no) - ;; -shared) - build_libtool_libs=no - build_old_libs=yes - ;; -static) - build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` - ;; -esac - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -if test -z "$show_help"; then - - # Infer the operation mode. - if test -z "$mode"; then - $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 - $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 - case $nonopt in - *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) - mode=link - for arg - do - case $arg in - -c) - mode=compile - break - ;; - esac - done - ;; - *db | *dbx | *strace | *truss) - mode=execute - ;; - *install*|cp|mv) - mode=install - ;; - *rm) - mode=uninstall - ;; - *) - # If we have no mode, but dlfiles were specified, then do execute mode. - test -n "$execute_dlfiles" && mode=execute - - # Just use the default operation mode. - if test -z "$mode"; then - if test -n "$nonopt"; then - $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 - else - $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 - fi - fi - ;; - esac - fi - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$execute_dlfiles" && test "$mode" != execute; then - $echo "$modename: unrecognized option \`-dlopen'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$modename --help --mode=$mode' for more information." - - # These modes are in order of execution frequency so that they run quickly. - case $mode in - # libtool compile mode - compile) - modename="$modename: compile" - # Get the compilation command and the source file. - base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg="$arg" - arg_mode=normal - ;; - - target ) - libobj="$arg" - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - if test -n "$libobj" ; then - $echo "$modename: you cannot specify \`-o' more than once" 1>&2 - exit $EXIT_FAILURE - fi - arg_mode=target - continue - ;; - - -static | -prefer-pic | -prefer-non-pic) - later="$later $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` - lastarg= - save_ifs="$IFS"; IFS=',' - for arg in $args; do - IFS="$save_ifs" - - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - lastarg="$lastarg $arg" - done - IFS="$save_ifs" - lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` - - # Add the arguments to base_compile. - base_compile="$base_compile $lastarg" - continue - ;; - - * ) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg="$srcfile" - srcfile="$arg" - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` - - case $lastarg in - # Double-quote args containing other shell metacharacters. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, and some SunOS ksh mistreat backslash-escaping - # in scan sets (worked around with variable expansion), - # and furthermore cannot handle '|' '&' '(' ')' in scan sets - # at all, so we specify them separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - lastarg="\"$lastarg\"" - ;; - esac - - base_compile="$base_compile $lastarg" - done # for arg - - case $arg_mode in - arg) - $echo "$modename: you must specify an argument for -Xcompile" - exit $EXIT_FAILURE - ;; - target) - $echo "$modename: you must specify a target with \`-o'" 1>&2 - exit $EXIT_FAILURE - ;; - *) - # Get the name of the library object. - [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - xform='[cCFSifmso]' - case $libobj in - *.ada) xform=ada ;; - *.adb) xform=adb ;; - *.ads) xform=ads ;; - *.asm) xform=asm ;; - *.c++) xform=c++ ;; - *.cc) xform=cc ;; - *.ii) xform=ii ;; - *.class) xform=class ;; - *.cpp) xform=cpp ;; - *.cxx) xform=cxx ;; - *.f90) xform=f90 ;; - *.for) xform=for ;; - *.java) xform=java ;; - esac - - libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` - - case $libobj in - *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; - *) - $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -static) - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` - case $qlibobj in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - qlibobj="\"$qlibobj\"" ;; - esac - test "X$libobj" != "X$qlibobj" \ - && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." - objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` - xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$obj"; then - xdir= - else - xdir=$xdir/ - fi - lobj=${xdir}$objdir/$objname - - if test -z "$base_compile"; then - $echo "$modename: you must specify a compilation command" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - $run $rm $removelist - trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2*) - pic_mode=default - ;; - esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" - removelist="$removelist $output_obj $lockfile" - trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until $run ln "$progpath" "$lockfile" 2>/dev/null; do - $show "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - $echo "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit $EXIT_FAILURE - fi - $echo "$srcfile" > "$lockfile" - fi - - if test -n "$fix_srcfile_path"; then - eval srcfile=\"$fix_srcfile_path\" - fi - qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` - case $qsrcfile in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - qsrcfile="\"$qsrcfile\"" ;; - esac - - $run $rm "$libobj" "${libobj}T" - - # Create a libtool object file (analogous to a ".la" file), - # but don't create it if we're doing a dry run. - test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then - $echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - $show "$mv $output_obj $lobj" - if $run $mv $output_obj $lobj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Append the name of the PIC object to the libtool object file. - test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then - $echo "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $run $rm $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - $show "$mv $output_obj $obj" - if $run $mv $output_obj $obj; then : - else - error=$? - $run $rm $removelist - exit $error - fi - fi - - # Append the name of the non-PIC object the libtool object file. - # Only append if the libtool object file exists. - test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - else - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - fi - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg="$1" - shift - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test - ;; - *) qarg=$arg ;; - esac - libtool_args="$libtool_args $qarg" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - compile_command="$compile_command @OUTPUT@" - finalize_command="$finalize_command @OUTPUT@" - ;; - esac - - case $prev in - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - compile_command="$compile_command @SYMFILE@" - finalize_command="$finalize_command @SYMFILE@" - preload=yes - fi - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - dlfiles="$dlfiles $arg" - else - dlprefiles="$dlprefiles $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols="$arg" - if test ! -f "$arg"; then - $echo "$modename: symbol file \`$arg' does not exist" - exit $EXIT_FAILURE - fi - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - inst_prefix) - inst_prefix_dir="$arg" - prev= - continue - ;; - precious_regex) - precious_files_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat $save_arg` - do -# moreargs="$moreargs $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - pic_object= - non_pic_object= - - # Read the .lo file - # If there is no directory component, then add one. - case $arg in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - if test -z "$pic_object" || \ - test -z "$non_pic_object" || - test "$pic_object" = none && \ - test "$non_pic_object" = none; then - $echo "$modename: cannot find name of object for \`$arg'" 1>&2 - exit $EXIT_FAILURE - fi - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" - prev= - fi - - # A PIC object. - libobjs="$libobjs $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if test -z "$run"; then - $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 - exit $EXIT_FAILURE - else - # Dry-run case. - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` - non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - fi - done - else - $echo "$modename: link input file \`$save_arg' does not exist" - exit $EXIT_FAILURE - fi - arg=$save_arg - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit $EXIT_FAILURE - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) rpath="$rpath $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) xrpath="$xrpath $arg" ;; - esac - fi - prev= - continue - ;; - xcompiler) - compiler_flags="$compiler_flags $qarg" - prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" - continue - ;; - xlinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $wl$qarg" - prev= - compile_command="$compile_command $wl$qarg" - finalize_command="$finalize_command $wl$qarg" - continue - ;; - xcclinker) - linker_flags="$linker_flags $qarg" - compiler_flags="$compiler_flags $qarg" - prev= - compile_command="$compile_command $qarg" - finalize_command="$finalize_command $qarg" - continue - ;; - shrext) - shrext_cmds="$arg" - prev= - continue - ;; - darwin_framework|darwin_framework_skip) - test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - prev= - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg="$arg" - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - compile_command="$compile_command $link_static_flag" - finalize_command="$finalize_command $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 - continue - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: more than one -exported-symbols argument is not allowed" - exit $EXIT_FAILURE - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework|-arch|-isysroot) - case " $CC " in - *" ${arg} ${1} "* | *" ${arg} ${1} "*) - prev=darwin_framework_skip ;; - *) compiler_flags="$compiler_flags $arg" - prev=darwin_framework ;; - esac - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - ;; - esac - continue - ;; - - -L*) - dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 - absdir="$dir" - notinst_path="$notinst_path $dir" - fi - dir="$absdir" - ;; - esac - case "$deplibs " in - *" -L$dir "*) ;; - *) - deplibs="$deplibs -L$dir" - lib_search_path="$lib_search_path $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - *) dllsearchpath="$dllsearchpath:$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - *) dllsearchpath="$dllsearchpath:$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - deplibs="$deplibs -framework System" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test "X$arg" = "X-lc" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue - ;; - esac - elif test "X$arg" = "X-lc_r"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - deplibs="$deplibs $arg" - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - -model) - compile_command="$compile_command $arg" - compiler_flags="$compiler_flags $arg" - finalize_command="$finalize_command $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) - compiler_flags="$compiler_flags $arg" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - continue - ;; - - -module) - module=yes - continue - ;; - - # -64, -mips[0-9] enable 64-bit mode on the SGI compiler - # -r[0-9][0-9]* specifies the processor on the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler - # +DA*, +DD* enable 64-bit mode on the HP compiler - # -q* pass through compiler args for the IBM compiler - # -m* pass through architecture-specific compiler args for GCC - # -m*, -t[45]*, -txscale* pass through architecture-specific - # compiler args for GCC - # -pg pass through profiling flag for GCC - # @file GCC response files - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ - -t[45]*|-txscale*|@*) - - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - compiler_flags="$compiler_flags $arg" - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - # The PATH hackery in wrapper scripts is required on Windows - # in order for the loader to find any dlls it needs. - $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 - $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - $echo "$modename: only absolute run-paths are allowed" 1>&2 - exit $EXIT_FAILURE - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - continue - ;; - - -static) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -Wc,*) - args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - case $flag in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - flag="\"$flag\"" - ;; - esac - arg="$arg $wl$flag" - compiler_flags="$compiler_flags $flag" - done - IFS="$save_ifs" - arg=`$echo "X$arg" | $Xsed -e "s/^ //"` - ;; - - -Wl,*) - args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - case $flag in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - flag="\"$flag\"" - ;; - esac - arg="$arg $wl$flag" - compiler_flags="$compiler_flags $wl$flag" - linker_flags="$linker_flags $flag" - done - IFS="$save_ifs" - arg=`$echo "X$arg" | $Xsed -e "s/^ //"` - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # Some other compiler flag. - -* | +*) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - ;; - - *.$objext) - # A standard object. - objs="$objs $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - pic_object= - non_pic_object= - - # Read the .lo file - # If there is no directory component, then add one. - case $arg in - */* | *\\*) . $arg ;; - *) . ./$arg ;; - esac - - if test -z "$pic_object" || \ - test -z "$non_pic_object" || - test "$pic_object" = none && \ - test "$non_pic_object" = none; then - $echo "$modename: cannot find name of object for \`$arg'" 1>&2 - exit $EXIT_FAILURE - fi - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - dlfiles="$dlfiles $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - dlprefiles="$dlprefiles $pic_object" - prev= - fi - - # A PIC object. - libobjs="$libobjs $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - non_pic_objects="$non_pic_objects $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if test -z "$run"; then - $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 - exit $EXIT_FAILURE - else - # Dry-run case. - - # Extract subdirectory from the argument. - xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` - if test "X$xdir" = "X$arg"; then - xdir= - else - xdir="$xdir/" - fi - - pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` - non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` - libobjs="$libobjs $pic_object" - non_pic_objects="$non_pic_objects $non_pic_object" - fi - fi - ;; - - *.$libext) - # An archive. - deplibs="$deplibs $arg" - old_deplibs="$old_deplibs $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - if test "$prev" = dlfiles; then - # This library was specified with -dlopen. - dlfiles="$dlfiles $arg" - prev= - elif test "$prev" = dlprefiles; then - # The library was specified with -dlpreopen. - dlprefiles="$dlprefiles $arg" - prev= - else - deplibs="$deplibs $arg" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - done # argument parsing loop - - if test -n "$prev"; then - $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - compile_command="$compile_command $arg" - finalize_command="$finalize_command $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` - libobjs_save="$libobjs" - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` - if test "X$output_objdir" = "X$output"; then - output_objdir="$objdir" - else - output_objdir="$output_objdir/$objdir" - fi - # Create the object directory. - if test ! -d "$output_objdir"; then - $show "$mkdir $output_objdir" - $run $mkdir $output_objdir - exit_status=$? - if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then - exit $exit_status - fi - fi - - # Determine the type of output - case $output in - "") - $echo "$modename: you must specify an output file" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - case $host in - *cygwin* | *mingw* | *pw32*) - # don't eliminate duplications in $postdeps and $predeps - duplicate_compiler_generated_deps=yes - ;; - *) - duplicate_compiler_generated_deps=$duplicate_deps - ;; - esac - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if test "X$duplicate_deps" = "Xyes" ; then - case "$libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - libs="$libs $deplib" - done - - if test "$linkmode" = lib; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; - esac - pre_post_deps="$pre_post_deps $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - case $linkmode in - lib) - passes="conv link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 - exit $EXIT_FAILURE - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=no - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - for pass in $passes; do - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" - deplibs= - fi - if test "$linkmode" = prog; then - case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; - link) - libs="$deplibs %DEPLIBS%" - test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" - ;; - esac - fi - if test "$pass" = dlopen; then - # Collect dlpreopened libraries - save_deplibs="$deplibs" - deplibs= - fi - for deplib in $libs; do - lib= - found=no - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - compiler_flags="$compiler_flags $deplib" - fi - continue - ;; - -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 - continue - fi - name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` - for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" - if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes - else - found=no - fi - break 2 - fi - done - done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $deplib "*) - if (${SED} -e '2q' $lib | - grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - library_names= - old_library= - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - for l in $old_library $library_names; do - ll="$l" - done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no - ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` - test "X$ladir" = "X$lib" && ladir="." - lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - fi - ;; # -l - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test "$pass" = conv && continue - newdependency_libs="$deplib $newdependency_libs" - newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` - ;; - prog) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - if test "$pass" = scan; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` - ;; - *) - $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test "$pass" = link; then - dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) xrpath="$xrpath $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) lib="$deplib" ;; - *.$libext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - valid_a_lib=no - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method - match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` - if eval $echo \"$deplib\" 2>/dev/null \ - | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes - fi - ;; - pass_all) - valid_a_lib=yes - ;; - esac - if test "$valid_a_lib" != yes; then - $echo - $echo "*** Warning: Trying to link with static lib archive $deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because the file extensions .$libext of this argument makes me believe" - $echo "*** that it is just a static archive that I should not used here." - else - $echo - $echo "*** Warning: Linking the shared library $output against the" - $echo "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi - continue - ;; - prog) - if test "$pass" != link; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - newdlprefiles="$newdlprefiles $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - newdlfiles="$newdlfiles $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=yes - continue - ;; - esac # case $deplib - if test "$found" = yes || test -f "$lib"; then : - else - $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 - exit $EXIT_FAILURE - fi - - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - - ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` - test "X$ladir" = "X$lib" && ladir="." - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && dlfiles="$dlfiles $dlopen" - test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" - fi - - if test "$pass" = conv; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - # It is a libtool convenience library, so add in its objects. - convenience="$convenience $ladir/$objdir/$old_library" - old_convenience="$old_convenience $ladir/$objdir/$old_library" - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done - elif test "$linkmode" != prog && test "$linkmode" != lib; then - $echo "$modename: \`$lib' is not a convenience library" 1>&2 - exit $EXIT_FAILURE - fi - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - for l in $old_library $library_names; do - linklib="$l" - done - if test -z "$linklib"; then - $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - - # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - dlprefiles="$dlprefiles $lib $dependency_libs" - else - newdlfiles="$newdlfiles $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 - $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 - abs_ladir="$ladir" - fi - ;; - esac - laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - - # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then - if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - $echo "$modename: warning: library \`$lib' was moved." 1>&2 - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" - else - dir="$libdir" - absdir="$libdir" - fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" - # Remove this search path later - notinst_path="$notinst_path $abs_ladir" - else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - notinst_path="$notinst_path $abs_ladir" - fi - fi # $installed = yes - name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - - # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir"; then - $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 - exit $EXIT_FAILURE - fi - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - newdlprefiles="$newdlprefiles $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - newdlprefiles="$newdlprefiles $dir/$dlname" - else - newdlprefiles="$newdlprefiles $dir/$linklib" - fi - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test "$linkmode" = lib; then - deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test "$linkmode" = prog && test "$pass" != link; then - newlib_search_path="$newlib_search_path $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test - esac - # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test "$linkmode,$pass" = "prog,link"; then - if test -n "$library_names" && - { test "$prefer_static_libs" = no || test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath " in - *" $dir "*) ;; - *" $absdir "*) ;; - *) temp_rpath="$temp_rpath $absdir" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes ; then - use_static_libs=no - fi - if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then - if test "$installed" = no; then - notinst_deplibs="$notinst_deplibs $lib" - need_relink=yes - fi - # This is a shared library - - # Warn about portability, can't link against -module's on - # some systems (darwin) - if test "$shouldnotlink" = yes && test "$pass" = link ; then - $echo - if test "$linkmode" = prog; then - $echo "*** Warning: Linking the executable $output against the loadable module" - else - $echo "*** Warning: Linking the shared library $output against the loadable module" - fi - $echo "*** $linklib is not portable!" - fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) compile_rpath="$compile_rpath $absdir" - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - realname="$2" - shift; shift - libname=`eval \\$echo \"$libname_spec\"` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname="$dlname" - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw*) - major=`expr $current - $age` - versuffix="-$major" - ;; - esac - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" - soname=`$echo $soroot | ${SED} -e 's/^.*\///'` - newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - $show "extracting exported symbol list from \`$soname'" - save_ifs="$IFS"; IFS='~' - cmds=$extract_expsyms_cmds - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - $show "generating import library for \`$soname'" - save_ifs="$IFS"; IFS='~' - cmds=$old_archive_from_expsyms_cmds - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test "$linkmode" = prog || test "$mode" != relink; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" - case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; - *-*-darwin* ) - # if the lib is a module then we can not link against - # it, someone is ignoring the new warnings I added - if /usr/bin/file -L $add 2> /dev/null | - $EGREP ": [^:]* bundle" >/dev/null ; then - $echo "** Warning, lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - $echo - $echo "** And there doesn't seem to be a static archive available" - $echo "** The link will probably fail, sorry" - else - add="$dir/$old_library" - fi - fi - esac - elif test "$hardcode_minus_L" = no; then - case $host in - *-*-sunos*) add_shlibpath="$dir" ;; - esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - relink) - if test "$hardcode_direct" = yes; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$dir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test "$lib_linked" != yes; then - $echo "$modename: configuration error: unsupported hardcode properties" - exit $EXIT_FAILURE - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; - esac - fi - if test "$linkmode" = prog; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && \ - test "$hardcode_minus_L" != yes && \ - test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; - esac - fi - fi - fi - - if test "$linkmode" = prog || test "$mode" = relink; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; - esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" - else - add="$libdir/$linklib" - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - add_dir="$add_dir -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - fi - - if test "$linkmode" = prog; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test "$linkmode" = prog; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test "$build_libtool_libs" = yes; then - # Not a shared library - if test "$deplibs_check_method" != pass_all; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - $echo - $echo "*** Warning: This system can not link to static lib archive $lib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then - $echo "*** But as you try to build a module library, libtool will still create " - $echo "*** a static module, that should work as long as the dlopening application" - $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - $echo - $echo "*** However, this would only work if libtool was able to extract symbol" - $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - $echo "*** not find such a program. So, this module is probably useless." - $echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test "$linkmode" = lib; then - if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) xrpath="$xrpath $temp_xrpath";; - esac;; - *) temp_deplibs="$temp_deplibs $libdir";; - esac - done - dependency_libs="$temp_deplibs" - fi - - newlib_search_path="$newlib_search_path $absdir" - # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - if test "X$duplicate_deps" = "Xyes" ; then - case "$tmp_libs " in - *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; - esac - fi - tmp_libs="$tmp_libs $deplib" - done - - if test "$link_all_deplibs" != no; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - case $deplib in - -L*) path="$deplib" ;; - *.la) - dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$deplib" && dir="." - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 - absdir="$dir" - fi - ;; - esac - if grep "^installed=no" $deplib > /dev/null; then - path="$absdir/$objdir" - else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - if test -z "$libdir"; then - $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - if test "$absdir" != "$libdir"; then - $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 - fi - path="$absdir" - fi - depdepl= - case $host in - *-*-darwin*) - # we do not want to link against static libs, - # but need to link against shared - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do - depdepl=$tmp - done - if test -f "$path/$depdepl" ; then - depdepl="$path/$depdepl" - fi - # do not add paths which are already there - case " $newlib_search_path " in - *" $path "*) ;; - *) newlib_search_path="$newlib_search_path $path";; - esac - fi - path="" - ;; - *) - path="-L$path" - ;; - esac - ;; - -l*) - case $host in - *-*-darwin*) - # Again, we only want to link against shared libraries - eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` - for tmp in $newlib_search_path ; do - if test -f "$tmp/lib$tmp_libs.dylib" ; then - eval depdepl="$tmp/lib$tmp_libs.dylib" - break - fi - done - path="" - ;; - *) continue ;; - esac - ;; - *) continue ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - case " $deplibs " in - *" $depdepl "*) ;; - *) deplibs="$depdepl $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) lib_search_path="$lib_search_path $dir" ;; - esac - done - newlib_search_path= - fi - - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else - vars="compile_deplibs finalize_deplibs" - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) tmp_libs="$tmp_libs $deplib" ;; - esac - ;; - *) tmp_libs="$tmp_libs $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs ; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i="" - ;; - esac - if test -n "$i" ; then - tmp_libs="$tmp_libs $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" - dlprefiles="$newdlprefiles" - fi - - case $linkmode in - oldlib) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 - fi - - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 - fi - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - objs="$objs$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form `libNAME.la'. - case $outputname in - lib*) - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - if test "$module" = no; then - $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` - fi - ;; - esac - - if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 - exit $EXIT_FAILURE - else - $echo - $echo "*** Warning: Linking the shared library $output against the non-libtool" - $echo "*** objects $objs is not portable!" - libobjs="$libobjs $objs" - fi - fi - - if test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 - fi - - set dummy $rpath - if test "$#" -gt 2; then - $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 - fi - install_libdir="$2" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 - fi - else - - # Parse the version information argument. - save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - IFS="$save_ifs" - - if test -n "$8"; then - $echo "$modename: too many parameters to \`-version-info'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major="$2" - number_minor="$3" - number_revision="$4" - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # which has an extra 1 added just for fun - # - case $version_type in - darwin|linux|osf|windows) - current=`expr $number_major + $number_minor` - age="$number_minor" - revision="$number_revision" - ;; - freebsd-aout|freebsd-elf|sunos) - current="$number_major" - revision="$number_minor" - age="0" - ;; - irix|nonstopux) - current=`expr $number_major + $number_minor - 1` - age="$number_minor" - revision="$number_minor" - ;; - *) - $echo "$modename: unknown library version type \`$version_type'" 1>&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit $EXIT_FAILURE - ;; - esac - ;; - no) - current="$2" - revision="$3" - age="$4" - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - if test "$age" -gt "$current"; then - $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 - $echo "$modename: \`$vinfo' is not valid version information" 1>&2 - exit $EXIT_FAILURE - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - minor_current=`expr $current + 1` - verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current"; - ;; - - irix | nonstopux) - major=`expr $current - $age + 1` - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring="$verstring_prefix$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test "$loop" -ne 0; do - iface=`expr $revision - $loop` - loop=`expr $loop - 1` - verstring="$verstring_prefix$major.$iface:$verstring" - done - - # Before this point, $major must not contain `.'. - major=.$major - versuffix="$major.$revision" - ;; - - linux) - major=.`expr $current - $age` - versuffix="$major.$age.$revision" - ;; - - osf) - major=.`expr $current - $age` - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test "$loop" -ne 0; do - iface=`expr $current - $loop` - loop=`expr $loop - 1` - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - verstring="$verstring:${current}.0" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. - major=`expr $current - $age` - versuffix="-$major" - ;; - - *) - $echo "$modename: unknown library version type \`$version_type'" 1>&2 - $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 - exit $EXIT_FAILURE - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring="0.0" - ;; - esac - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - fi - - if test "$mode" != relink; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$echo "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then - if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - removelist="$removelist $p" - ;; - *) ;; - esac - done - if test -n "$removelist"; then - $show "${rm}r $removelist" - $run ${rm}r $removelist - fi - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - oldlibs="$oldlibs $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - for path in $notinst_path; do - lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` - deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` - dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` - done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - temp_xrpath="$temp_xrpath -R$libdir" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) dlfiles="$dlfiles $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) dlprefiles="$dlprefiles $lib" ;; - esac - done - - if test "$build_libtool_libs" = yes; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - deplibs="$deplibs -framework System" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then - deplibs="$deplibs -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $rm conftest.c - cat > conftest.c </dev/null` - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null \ - | grep " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ - | ${SED} 10q \ - | $EGREP "$file_magic_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - $echo - $echo "*** Warning: linker path does not have real file for library $a_deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $echo "*** with $libname but no candidates were found. (...for file magic test)" - else - $echo "*** with $libname and none of the candidates passed a file format test" - $echo "*** using a file magic. Last file checked: $potlib" - fi - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method - match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` - for a_deplib in $deplibs; do - name=`expr $a_deplib : '-l\(.*\)'` - # If $name is empty we are operating on a -L argument. - if test -n "$name" && test "$name" != "0"; then - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $a_deplib "*) - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - ;; - esac - fi - if test -n "$a_deplib" ; then - libname=`eval \\$echo \"$libname_spec\"` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test - if eval $echo \"$potent_lib\" 2>/dev/null \ - | ${SED} 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - newdeplibs="$newdeplibs $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - $echo - $echo "*** Warning: linker path does not have real file for library $a_deplib." - $echo "*** I have the capability to make that library automatically link in when" - $echo "*** you link to this library. But I can only do this if you have a" - $echo "*** shared version of the library, which you do not appear to have" - $echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $echo "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $echo "*** with $libname and none of the candidates passed a file format test" - $echo "*** using a regex pattern. Last file checked: $potlib" - fi - fi - else - # Add a -L argument. - newdeplibs="$newdeplibs $a_deplib" - fi - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ - -e 's/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` - done - fi - if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ - | grep . >/dev/null; then - $echo - if test "X$deplibs_check_method" = "Xnone"; then - $echo "*** Warning: inter-library dependencies are not supported in this platform." - else - $echo "*** Warning: inter-library dependencies are not known to be supported." - fi - $echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - fi - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` - ;; - esac - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - $echo - $echo "*** Warning: libtool could not satisfy all declared inter-library" - $echo "*** dependencies of module $libname. Therefore, libtool will create" - $echo "*** a static module, that should work as long as the dlopening" - $echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - $echo - $echo "*** However, this would only work if libtool was able to extract symbol" - $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - $echo "*** not find such a program. So, this module is probably useless." - $echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - $echo "*** The inter-library dependencies that have been dropped here will be" - $echo "*** automatically added whenever a program is linked with this library" - $echo "*** or is declared to -dlopen it." - - if test "$allow_undefined" = no; then - $echo - $echo "*** Since this library must not contain undefined symbols," - $echo "*** because either the platform does not support them or" - $echo "*** it was explicitly requested with -no-undefined," - $echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - new_libs="$new_libs -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$new_libs $deplib" ;; - esac - ;; - *) new_libs="$new_libs $deplib" ;; - esac - done - deplibs="$new_libs" - - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - if test "$hardcode_into_libs" = yes; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath="$finalize_rpath" - test "$mode" != relink && rpath="$compile_rpath$rpath" - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - dep_rpath="$dep_rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - if test -n "$hardcode_libdir_flag_spec_ld"; then - eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" - else - eval dep_rpath=\"$hardcode_libdir_flag_spec\" - fi - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath="$finalize_shlibpath" - test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - realname="$2" - shift; shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib="$output_objdir/$realname" - linknames= - for link - do - linknames="$linknames $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - if len=`expr "X$cmd" : ".*"` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - $show "$cmd" - $run eval "$cmd" || exit $? - skipped_export=false - else - # The command line is too long to execute in one step. - $show "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS="$save_ifs" - if test -n "$export_symbols_regex"; then - $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" - $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - $show "$mv \"${export_symbols}T\" \"$export_symbols\"" - $run eval '$mv "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - tmp_deplibs="$tmp_deplibs $test_deplib" - ;; - esac - done - deplibs="$tmp_deplibs" - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" - - func_extract_archives $gentop $convenience - libobjs="$libobjs $func_extract_archives_result" - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - linker_flags="$linker_flags $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test "X$skipped_export" != "X:" && - len=`expr "X$test_cmds" : ".*" 2>/dev/null` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise. - $echo "creating reloadable object files..." - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - output_la=`$echo "X$output" | $Xsed -e "$basename"` - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - delfiles= - last_robj= - k=1 - output=$output_objdir/$output_la-${k}.$objext - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - eval test_cmds=\"$reload_cmds $objlist $last_robj\" - if test "X$objlist" = X || - { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && - test "$len" -le "$max_cmd_len"; }; then - objlist="$objlist $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - eval concat_cmds=\"$reload_cmds $objlist $last_robj\" - else - # All subsequent reloadable object files will link in - # the last one created. - eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" - fi - last_robj=$output_objdir/$output_la-${k}.$objext - k=`expr $k + 1` - output=$output_objdir/$output_la-${k}.$objext - objlist=$obj - len=1 - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" - - if ${skipped_export-false}; then - $show "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $run $rm $export_symbols - libobjs=$output - # Append the command to create the export file. - eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" - fi - - # Set up a command to remove the reloadable object files - # after they are used. - i=0 - while test "$i" -lt "$k" - do - i=`expr $i + 1` - delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" - done - - $echo "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' - for cmd in $concat_cmds; do - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - - # Append the command to remove the reloadable object files - # to the just-reset $cmds. - eval cmds=\"\$cmds~\$rm $delfiles\" - fi - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - # Restore the uninstalled library and exit - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - obj) - if test -n "$deplibs"; then - $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 - fi - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 - fi - - if test -n "$rpath"; then - $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 - fi - - if test -n "$xrpath"; then - $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 - fi - - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 - fi - - case $output in - *.lo) - if test -n "$objs$old_deplibs"; then - $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 - exit $EXIT_FAILURE - fi - libobj="$output" - obj=`$echo "X$output" | $Xsed -e "$lo2o"` - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $run $rm $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" - else - gentop="$output_objdir/${obj}x" - generated="$generated $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # Create the old-style object. - reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - - output="$obj" - cmds=$reload_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit $EXIT_SUCCESS - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $run eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - fi - - if test -n "$pic_flag" || test "$pic_mode" != default; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - cmds=$reload_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - fi - - if test -n "$gentop"; then - $show "${rm}r $gentop" - $run ${rm}r $gentop - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; - esac - if test -n "$vinfo"; then - $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 - fi - - if test -n "$release"; then - $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 - fi - - if test "$preload" = yes; then - if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && - test "$dlopen_self_static" = unknown; then - $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." - fi - fi - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` - finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` - ;; - esac - - case $host in - *darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - if test "$tagname" = CXX ; then - compile_command="$compile_command ${wl}-bind_at_load" - finalize_command="$finalize_command ${wl}-bind_at_load" - fi - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - new_libs="$new_libs -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$new_libs $deplib" ;; - esac - ;; - *) new_libs="$new_libs $deplib" ;; - esac - done - compile_deplibs="$new_libs" - - - compile_command="$compile_command $compile_deplibs" - finalize_command="$finalize_command $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) finalize_rpath="$finalize_rpath $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) perm_rpath="$perm_rpath $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) - testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - *) dllsearchpath="$dllsearchpath:$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - *) dllsearchpath="$dllsearchpath:$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - rpath="$rpath $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - fi - - dlsyms= - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - dlsyms="${outputname}S.c" - else - $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 - fi - fi - - if test -n "$dlsyms"; then - case $dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${outputname}.nm" - - $show "$rm $nlist ${nlist}S ${nlist}T" - $run $rm "$nlist" "${nlist}S" "${nlist}T" - - # Parse the name list into a source file. - $show "creating $output_objdir/$dlsyms" - - test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ -/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ -/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -/* Prevent the only kind of declaration conflicts we can make. */ -#define lt_preloaded_symbols some_other_symbol - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - $show "generating symbol list for \`$output'" - - test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - for arg in $progfiles; do - $show "extracting global C symbols from \`$arg'" - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - if test -n "$export_symbols_regex"; then - $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - $run eval '$mv "$nlist"T "$nlist"' - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" - $run $rm $export_symbols - $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* ) - $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - else - $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - $run eval 'mv "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* ) - $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - fi - fi - - for arg in $dlprefiles; do - $show "extracting global C symbols from \`$arg'" - name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` - $run eval '$echo ": $name " >> "$nlist"' - $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" - done - - if test -z "$run"; then - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $mv "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if grep -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - grep -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' - else - $echo '/* NONE */' >> "$output_objdir/$dlsyms" - fi - - $echo >> "$output_objdir/$dlsyms" "\ - -#undef lt_preloaded_symbols - -#if defined (__STDC__) && __STDC__ -# define lt_ptr void * -#else -# define lt_ptr char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -" - - case $host in - *cygwin* | *mingw* ) - $echo >> "$output_objdir/$dlsyms" "\ -/* DATA imports from DLLs on WIN32 can't be const, because - runtime relocations are performed -- see ld's documentation - on pseudo-relocs */ -struct { -" - ;; - * ) - $echo >> "$output_objdir/$dlsyms" "\ -const struct { -" - ;; - esac - - - $echo >> "$output_objdir/$dlsyms" "\ - const char *name; - lt_ptr address; -} -lt_preloaded_symbols[] = -{\ -" - - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" - - $echo >> "$output_objdir/$dlsyms" "\ - {0, (lt_ptr) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - fi - - pic_flag_for_symtable= - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; - esac;; - *-*-hpux*) - case "$compile_command " in - *" -static "*) ;; - *) pic_flag_for_symtable=" $pic_flag";; - esac - esac - - # Now compile the dynamic symbol file. - $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" - $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? - - # Clean up the generated files. - $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" - $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" - - # Transform the symbol file into the correct name. - case $host in - *cygwin* | *mingw* ) - if test -f "$output_objdir/${outputname}.def" ; then - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` - else - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - fi - ;; - * ) - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - ;; - esac - ;; - *) - $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 - exit $EXIT_FAILURE - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` - fi - - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - # Replace the output file specification. - compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - $show "$link_command" - $run eval "$link_command" - exit_status=$? - - # Delete the generated files. - if test -n "$dlsyms"; then - $show "$rm $output_objdir/${outputname}S.${objext}" - $run $rm "$output_objdir/${outputname}S.${objext}" - fi - - exit $exit_status - fi - - if test -n "$shlibpath_var"; then - # We should set the shlibpath_var - rpath= - for dir in $temp_rpath; do - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) - # Absolute path. - rpath="$rpath$dir:" - ;; - *) - # Relative path: add a thisdir entry. - rpath="$rpath\$thisdir/$dir:" - ;; - esac - done - temp_rpath="$rpath" - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - rpath="$rpath$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - rpath="$rpath$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$no_install" = yes; then - # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $run $rm $output - # Link the executable and exit - $show "$link_command" - $run eval "$link_command" || exit $? - exit $EXIT_SUCCESS - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 - $echo "$modename: \`$output' will be relinked during installation" 1>&2 - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname - - $show "$link_command" - $run eval "$link_command" || exit $? - - # Now create the wrapper script. - $show "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` - relink_command="$var=\"$var_value\"; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` - fi - - # Quote $echo for shipping. - if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then - case $progpath in - [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; - *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; - esac - qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` - else - qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` - fi - - # Only actually do things if our run command is non-null. - if test -z "$run"; then - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - output_name=`basename $output` - output_path=`dirname $output` - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" - $rm $cwrappersource $cwrapper - trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - cat > $cwrappersource <> $cwrappersource<<"EOF" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(PATH_MAX) -# define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) -# define HAVE_DOS_BASED_FILE_SYSTEM -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ -} while (0) - -/* -DDEBUG is fairly common in CFLAGS. */ -#undef DEBUG -#if defined DEBUGWRAPPER -# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) -#else -# define DEBUG(format, ...) -#endif - -const char *program_name = NULL; - -void * xmalloc (size_t num); -char * xstrdup (const char *string); -const char * base_name (const char *name); -char * find_executable(const char *wrapper); -int check_executable(const char *path); -char * strendzap(char *str, const char *pat); -void lt_fatal (const char *message, ...); - -int -main (int argc, char *argv[]) -{ - char **newargz; - int i; - - program_name = (char *) xstrdup (base_name (argv[0])); - DEBUG("(main) argv[0] : %s\n",argv[0]); - DEBUG("(main) program_name : %s\n",program_name); - newargz = XMALLOC(char *, argc+2); -EOF - - cat >> $cwrappersource <> $cwrappersource <<"EOF" - newargz[1] = find_executable(argv[0]); - if (newargz[1] == NULL) - lt_fatal("Couldn't find %s", argv[0]); - DEBUG("(main) found exe at : %s\n",newargz[1]); - /* we know the script has the same name, without the .exe */ - /* so make sure newargz[1] doesn't end in .exe */ - strendzap(newargz[1],".exe"); - for (i = 1; i < argc; i++) - newargz[i+1] = xstrdup(argv[i]); - newargz[argc+1] = NULL; - - for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" - return 127; -} - -void * -xmalloc (size_t num) -{ - void * p = (void *) malloc (num); - if (!p) - lt_fatal ("Memory exhausted"); - - return p; -} - -char * -xstrdup (const char *string) -{ - return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL -; -} - -const char * -base_name (const char *name) -{ - const char *base; - -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - /* Skip over the disk name in MSDOS pathnames. */ - if (isalpha ((unsigned char)name[0]) && name[1] == ':') - name += 2; -#endif - - for (base = name; *name; name++) - if (IS_DIR_SEPARATOR (*name)) - base = name + 1; - return base; -} - -int -check_executable(const char * path) -{ - struct stat st; - - DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); - if ((!path) || (!*path)) - return 0; - - if ((stat (path, &st) >= 0) && - ( - /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ -#if defined (S_IXOTH) - ((st.st_mode & S_IXOTH) == S_IXOTH) || -#endif -#if defined (S_IXGRP) - ((st.st_mode & S_IXGRP) == S_IXGRP) || -#endif - ((st.st_mode & S_IXUSR) == S_IXUSR)) - ) - return 1; - else - return 0; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise */ -char * -find_executable (const char* wrapper) -{ - int has_slash = 0; - const char* p; - const char* p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - int tmp_len; - char* concat_name; - - DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - } -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char* path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char* q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR(*q)) - break; - p_len = q - p; - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); - tmp_len = strlen(tmp); - concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); - tmp_len = strlen(tmp); - concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable(concat_name)) - return concat_name; - XFREE(concat_name); - return NULL; -} - -char * -strendzap(char *str, const char *pat) -{ - size_t len, patlen; - - assert(str != NULL); - assert(pat != NULL); - - len = strlen(str); - patlen = strlen(pat); - - if (patlen <= len) - { - str += len - patlen; - if (strcmp(str, pat) == 0) - *str = '\0'; - } - return str; -} - -static void -lt_error_core (int exit_status, const char * mode, - const char * message, va_list ap) -{ - fprintf (stderr, "%s: %s: ", program_name, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, "FATAL", message, ap); - va_end (ap); -} -EOF - # we should really use a build-platform specific compiler - # here, but OTOH, the wrappers (shell script and this C one) - # are only useful if you want to execute the "real" binary. - # Since the "real" binary is built for $host, then this - # wrapper might as well be built for $host, too. - $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource - ;; - esac - $rm $output - trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 - - $echo > $output "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='${SED} -e 1s/^X//' -sed_quote_subst='$sed_quote_subst' - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variable: - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$echo are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - echo=\"$qecho\" - file=\"\$0\" - # Make sure echo works. - if test \"X\$1\" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then - # Yippee, \$echo works! - : - else - # Restart under the correct shell, and then maybe \$echo will work. - exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} - fi - fi\ -" - $echo >> $output "\ - - # Find the directory that this script lives in. - thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` - done - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - $echo >> $output "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || \\ - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $mkdir \"\$progdir\" - else - $rm \"\$progdir/\$file\" - fi" - - $echo >> $output "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - $echo \"\$relink_command_output\" >&2 - $rm \"\$progdir/\$file\" - exit $EXIT_FAILURE - fi - fi - - $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $rm \"\$progdir/\$program\"; - $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $rm \"\$progdir/\$file\" - fi" - else - $echo >> $output "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $echo >> $output "\ - - if test -f \"\$progdir/\$program\"; then" - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $echo >> $output "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` - - export $shlibpath_var -" - fi - - # fixup the dll searchpath if we need to. - if test -n "$dllsearchpath"; then - $echo >> $output "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - $echo >> $output "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2*) - $echo >> $output "\ - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $echo >> $output "\ - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $echo >> $output "\ - \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" - exit $EXIT_FAILURE - fi - else - # The program doesn't exist. - \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 - \$echo \"This script is just a wrapper for \$program.\" 1>&2 - $echo \"See the $PACKAGE documentation for more information.\" 1>&2 - exit $EXIT_FAILURE - fi -fi\ -" - chmod +x $output - fi - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$old_deplibs $non_pic_objects" - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" - - func_extract_archives $gentop $addlibs - oldobjs="$oldobjs $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds - else - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - $echo "X$obj" | $Xsed -e 's%^.*/%%' - done | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "copying selected object files to avoid basename conflicts..." - - if test -z "$gentop"; then - gentop="$output_objdir/${outputname}x" - generated="$generated $gentop" - - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - exit_status=$? - if test "$exit_status" -ne 0 && test ! -d "$gentop"; then - exit $exit_status - fi - fi - - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - counter=`expr $counter + 1` - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - $run ln "$obj" "$gentop/$newobj" || - $run cp "$obj" "$gentop/$newobj" - oldobjs="$oldobjs $gentop/$newobj" - ;; - *) oldobjs="$oldobjs $obj" ;; - esac - done - fi - - eval cmds=\"$old_archive_cmds\" - - if len=`expr "X$cmds" : ".*"` && - test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - $echo "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - for obj in $save_oldobjs - do - oldobjs="$objlist $obj" - objlist="$objlist $obj" - eval test_cmds=\"$old_archive_cmds\" - if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && - test "$len" -le "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - eval cmd=\"$cmd\" - IFS="$save_ifs" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$generated"; then - $show "${rm}r$generated" - $run ${rm}r$generated - fi - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - $show "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` - relink_command="$var=\"$var_value\"; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then - relink_command= - fi - - - # Only create the output if not a dry run. - if test -z "$run"; then - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - if test -z "$libdir"; then - $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdependency_libs="$newdependency_libs $libdir/$name" - ;; - *) newdependency_libs="$newdependency_libs $deplib" ;; - esac - done - dependency_libs="$newdependency_libs" - newdlfiles= - for lib in $dlfiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdlfiles="$newdlfiles $libdir/$name" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - if test -z "$libdir"; then - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - exit $EXIT_FAILURE - fi - newdlprefiles="$newdlprefiles $libdir/$name" - done - dlprefiles="$newdlprefiles" - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - newdlfiles="$newdlfiles $abs" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - newdlprefiles="$newdlprefiles $abs" - done - dlprefiles="$newdlprefiles" - fi - $rm $output - # place dlname in correct position for cygwin - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; - esac - $echo > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then - $echo >> $output "\ -relink_command=\"$relink_command\"" - fi - done - fi - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" - $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? - ;; - esac - exit $EXIT_SUCCESS - ;; - - # libtool install mode - install) - modename="$modename: install" - - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || - # Allow the use of GNU shtool's install command. - $echo "X$nonopt" | grep shtool > /dev/null; then - # Aesthetically quote it. - arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - install_prog="$arg " - arg="$1" - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog$arg" - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - for arg - do - if test -n "$dest"; then - files="$files $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=yes ;; - -f) - case " $install_prog " in - *[\\\ /]cp\ *) ;; - *) prev=$arg ;; - esac - ;; - -g | -m | -o) prev=$arg ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` - case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - arg="\"$arg\"" - ;; - esac - install_prog="$install_prog $arg" - done - - if test -z "$install_prog"; then - $echo "$modename: you must specify an install program" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - if test -n "$prev"; then - $echo "$modename: the \`$prev' option requires an argument" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - if test -z "$files"; then - if test -z "$dest"; then - $echo "$modename: no file or destination specified" 1>&2 - else - $echo "$modename: you must specify a destination" 1>&2 - fi - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Strip any trailing slash from the destination. - dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` - test "X$destdir" = "X$dest" && destdir=. - destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` - - # Not a directory, so check to see that there is only one file specified. - set dummy $files - if test "$#" -gt 2; then - $echo "$modename: \`$dest' is not a directory" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - staticlibs="$staticlibs $file" - ;; - - *.la) - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - library_names= - old_library= - relink_command= - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) current_libdirs="$current_libdirs $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) future_libdirs="$future_libdirs $libdir" ;; - esac - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ - test "X$dir" = "X$file/" && dir= - dir="$dir$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - if test "$inst_prefix_dir" = "$destdir"; then - $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 - exit $EXIT_FAILURE - fi - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - $echo "$modename: warning: relinking \`$file'" 1>&2 - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - exit $EXIT_FAILURE - fi - fi - - # See the names of the shared library. - set dummy $library_names - if test -n "$2"; then - realname="$2" - shift - shift - - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T - - # Install the shared library and build the symlinks. - $show "$install_prog $dir/$srcname $destdir/$realname" - $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? - if test -n "$stripme" && test -n "$striplib"; then - $show "$striplib $destdir/$realname" - $run eval "$striplib $destdir/$realname" || exit $? - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - if test "$linkname" != "$realname"; then - $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" - $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" - fi - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - cmds=$postinstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$mode" = relink; then - $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - fi - - # Install the pseudo-library for information purposes. - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - instname="$dir/$name"i - $show "$install_prog $instname $destdir/$name" - $run eval "$install_prog $instname $destdir/$name" || exit $? - - # Maybe install the static library, too. - test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` - ;; - *.$objext) - staticdest="$destfile" - destfile= - ;; - *) - $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - # Install the libtool object if requested. - if test -n "$destfile"; then - $show "$install_prog $file $destfile" - $run eval "$install_prog $file $destfile" || exit $? - fi - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` - - $show "$install_prog $staticobj $staticdest" - $run eval "$install_prog \$staticobj \$staticdest" || exit $? - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - destfile="$destdir/$destfile" - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext="" - case $file in - *.exe) - if test ! -f "$file"; then - file=`$echo $file|${SED} 's,.exe$,,'` - stripped_ext=".exe" - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin*|*mingw*) - wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` - ;; - *) - wrapper=$file - ;; - esac - if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then - notinst_deplibs= - relink_command= - - # Note that it is not necessary on cygwin/mingw to append a dot to - # foo even if both foo and FILE.exe exist: automatic-append-.exe - # behavior happens only for exec(3), not for open(2)! Also, sourcing - # `FILE.' does not work on cygwin managed mounts. - # - # If there is no directory component, then add one. - case $wrapper in - */* | *\\*) . ${wrapper} ;; - *) . ./${wrapper} ;; - esac - - # Check the variables that should have been set. - if test -z "$notinst_deplibs"; then - $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 - exit $EXIT_FAILURE - fi - - finalize=yes - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - # If there is no directory component, then add one. - case $lib in - */* | *\\*) . $lib ;; - *) . ./$lib ;; - esac - fi - libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test - if test -n "$libdir" && test ! -f "$libfile"; then - $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 - finalize=no - fi - done - - relink_command= - # Note that it is not necessary on cygwin/mingw to append a dot to - # foo even if both foo and FILE.exe exist: automatic-append-.exe - # behavior happens only for exec(3), not for open(2)! Also, sourcing - # `FILE.' does not work on cygwin managed mounts. - # - # If there is no directory component, then add one. - case $wrapper in - */* | *\\*) . ${wrapper} ;; - *) . ./${wrapper} ;; - esac - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - if test "$finalize" = yes && test -z "$run"; then - tmpdir=`func_mktempdir` - file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` - - $show "$relink_command" - if $run eval "$relink_command"; then : - else - $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 - ${rm}r "$tmpdir" - continue - fi - file="$outputname" - else - $echo "$modename: warning: cannot relink \`$file'" 1>&2 - fi - else - # Install the binary that we compiled earlier. - file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` - ;; - esac - ;; - esac - $show "$install_prog$stripme $file $destfile" - $run eval "$install_prog\$stripme \$file \$destfile" || exit $? - test -n "$outputname" && ${rm}r "$tmpdir" - ;; - esac - done - - for file in $staticlibs; do - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - - $show "$install_prog $file $oldlib" - $run eval "$install_prog \$file \$oldlib" || exit $? - - if test -n "$stripme" && test -n "$old_striplib"; then - $show "$old_striplib $oldlib" - $run eval "$old_striplib $oldlib" || exit $? - fi - - # Do each command in the postinstall commands. - cmds=$old_postinstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || exit $? - done - IFS="$save_ifs" - done - - if test -n "$future_libdirs"; then - $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 - fi - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - test -n "$run" && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi - ;; - - # libtool finish mode - finish) - modename="$modename: finish" - libdirs="$nonopt" - admincmds= - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for dir - do - libdirs="$libdirs $dir" - done - - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - cmds=$finish_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" || admincmds="$admincmds - $cmd" - done - IFS="$save_ifs" - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $run eval "$cmds" || admincmds="$admincmds - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - test "$show" = : && exit $EXIT_SUCCESS - - $echo "X----------------------------------------------------------------------" | $Xsed - $echo "Libraries have been installed in:" - for libdir in $libdirs; do - $echo " $libdir" - done - $echo - $echo "If you ever happen to want to link against installed libraries" - $echo "in a given directory, LIBDIR, you must either use libtool, and" - $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" - $echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - $echo " during execution" - fi - if test -n "$runpath_var"; then - $echo " - add LIBDIR to the \`$runpath_var' environment variable" - $echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $echo " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $echo " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - $echo - $echo "See any operating system documentation about shared libraries for" - $echo "more information, such as the ld(1) and ld.so(8) manual pages." - $echo "X----------------------------------------------------------------------" | $Xsed - exit $EXIT_SUCCESS - ;; - - # libtool execute mode - execute) - modename="$modename: execute" - - # The first argument is the command name. - cmd="$nonopt" - if test -z "$cmd"; then - $echo "$modename: you must specify a COMMAND" 1>&2 - $echo "$help" - exit $EXIT_FAILURE - fi - - # Handle -dlopen flags immediately. - for file in $execute_dlfiles; do - if test ! -f "$file"; then - $echo "$modename: \`$file' is not a file" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - dir= - case $file in - *.la) - # Check to see that this really is a libtool archive. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : - else - $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Read the libtool library. - dlname= - library_names= - - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" - continue - fi - - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - - if test -f "$dir/$objdir/$dlname"; then - dir="$dir/$objdir" - else - $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 - exit $EXIT_FAILURE - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - test "X$dir" = "X$file" && dir=. - ;; - - *) - $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -*) ;; - *) - # Do a test to see if this is really a libtool program. - if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - # If there is no directory component, then add one. - case $file in - */* | *\\*) . $file ;; - *) . ./$file ;; - esac - - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` - args="$args \"$file\"" - done - - if test -z "$run"; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - if test "${save_LC_ALL+set}" = set; then - LC_ALL="$save_LC_ALL"; export LC_ALL - fi - if test "${save_LANG+set}" = set; then - LANG="$save_LANG"; export LANG - fi - - # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" - $echo "export $shlibpath_var" - fi - $echo "$cmd$args" - exit $EXIT_SUCCESS - fi - ;; - - # libtool clean and uninstall mode - clean | uninstall) - modename="$modename: $mode" - rm="$nonopt" - files= - rmforce= - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - for arg - do - case $arg in - -f) rm="$rm $arg"; rmforce=yes ;; - -*) rm="$rm $arg" ;; - *) files="$files $arg" ;; - esac - done - - if test -z "$rm"; then - $echo "$modename: you must specify an RM program" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - fi - - rmdirs= - - origobjdir="$objdir" - for file in $files; do - dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` - if test "X$dir" = "X$file"; then - dir=. - objdir="$origobjdir" - else - objdir="$dir/$origobjdir" - fi - name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` - test "$mode" = uninstall && objdir="$dir" - - # Remember objdir for removal later, being careful to avoid duplicates - if test "$mode" = clean; then - case " $rmdirs " in - *" $objdir "*) ;; - *) rmdirs="$rmdirs $objdir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if (test -L "$file") >/dev/null 2>&1 \ - || (test -h "$file") >/dev/null 2>&1 \ - || test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif test "$rmforce" = yes; then - continue - fi - - rmfiles="$file" - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - . $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - rmfiles="$rmfiles $objdir/$n" - done - test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" - - case "$mode" in - clean) - case " $library_names " in - # " " in the beginning catches empty $dlname - *" $dlname "*) ;; - *) rmfiles="$rmfiles $objdir/$dlname" ;; - esac - test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - cmds=$postuninstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" - if test "$?" -ne 0 && test "$rmforce" != yes; then - exit_status=1 - fi - done - IFS="$save_ifs" - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - cmds=$old_postuninstall_cmds - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $show "$cmd" - $run eval "$cmd" - if test "$?" -ne 0 && test "$rmforce" != yes; then - exit_status=1 - fi - done - IFS="$save_ifs" - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - - # Read the .lo file - . $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" \ - && test "$pic_object" != none; then - rmfiles="$rmfiles $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" \ - && test "$non_pic_object" != none; then - rmfiles="$rmfiles $dir/$non_pic_object" - fi - fi - ;; - - *) - if test "$mode" = clean ; then - noexename=$name - case $file in - *.exe) - file=`$echo $file|${SED} 's,.exe$,,'` - noexename=`$echo $name|${SED} 's,.exe$,,'` - # $file with .exe has already been added to rmfiles, - # add $file without .exe - rmfiles="$rmfiles $file" - ;; - esac - # Do a test to see if this is a libtool program. - if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then - relink_command= - . $dir/$noexename - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then - rmfiles="$rmfiles $objdir/lt-$name" - fi - if test "X$noexename" != "X$name" ; then - rmfiles="$rmfiles $objdir/lt-${noexename}.c" - fi - fi - fi - ;; - esac - $show "$rm $rmfiles" - $run $rm $rmfiles || exit_status=1 - done - objdir="$origobjdir" - - # Try to remove the ${objdir}s in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - $show "rmdir $dir" - $run rmdir $dir >/dev/null 2>&1 - fi - done - - exit $exit_status - ;; - - "") - $echo "$modename: you must specify a MODE" 1>&2 - $echo "$generic_help" 1>&2 - exit $EXIT_FAILURE - ;; - esac - - if test -z "$exec_cmd"; then - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$generic_help" 1>&2 - exit $EXIT_FAILURE - fi -fi # test -z "$show_help" - -if test -n "$exec_cmd"; then - eval exec $exec_cmd - exit $EXIT_FAILURE -fi - -# We need to display help for each of the modes. -case $mode in -"") $echo \ -"Usage: $modename [OPTION]... [MODE-ARG]... - -Provide generalized library-building support services. - - --config show all configuration variables - --debug enable verbose shell tracing --n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --finish same as \`--mode=finish' - --help display this help message and exit - --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] - --quiet same as \`--silent' - --silent don't print informational messages - --tag=TAG use configuration variables from tag TAG - --version print version information - -MODE must be one of the following: - - clean remove files from the build directory - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for -a more detailed description of MODE. - -Report bugs to ." - exit $EXIT_SUCCESS - ;; - -clean) - $echo \ -"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - -compile) - $echo \ -"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -prefer-pic try to building PIC objects only - -prefer-non-pic try to building non-PIC objects only - -static always build a \`.o' file suitable for static linking - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - -execute) - $echo \ -"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - -finish) - $echo \ -"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - -install) - $echo \ -"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - -link) - $echo \ -"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -static do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - -uninstall) - $echo \ -"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - -*) - $echo "$modename: invalid operation mode \`$mode'" 1>&2 - $echo "$help" 1>&2 - exit $EXIT_FAILURE - ;; -esac - -$echo -$echo "Try \`$modename --help' for more information about other modes." - -exit $? - -# The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -disable_libs=shared -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -disable_libs=static -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: diff -Naur usbip-0.1.4/src/Makefile.am trunk/src/Makefile.am --- usbip-0.1.4/src/Makefile.am 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/Makefile.am 2007-05-18 11:10:08.000000000 +0200 @@ -1,3 +1,8 @@ SUBDIRS = lib cmd includedir=@includedir@/usbip +include_HEADERS = lib/usbip.h lib/usbip_common.h lib/vhci_driver.h lib/stub_driver.h +if INSTALL_USBIDS +pkgdata_DATA = usb.ids +EXTRA_DIST = $(pkgdata_DATA) +endif diff -Naur usbip-0.1.4/src/NEWS trunk/src/NEWS --- usbip-0.1.4/src/NEWS 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/NEWS 2007-05-18 11:10:08.000000000 +0200 @@ -1,5 +1,20 @@ # vim:tw=78:ts=4:expandtab:ai:sw=4 -# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ +# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ + +usbip-0.1.5 + - Fix: "make dist" works. + - Cleanup: use autoreconf instead. + - Cleanup: change vhci_driver as a global value in libusbip. + - Cleanup: change stub_driver as a global value in libusbip. + - Cleanup: trim unused spaces. + - Add: version info in configure.ac + - Fix: auto detection of "glib-2.0 >= 2.6.0" + - Add: mailing list information in README + - Cleanup: use daemon(3), instead. + - Add: usb.ids + - setsockopt in userland + - Add: 2.6.20 support? + - Fix: use spin_lock_init() instead of SPIN_... usbip-0.1.4 - Fix: compile error & warning fix for 2.6.19 diff -Naur usbip-0.1.4/src/README trunk/src/README --- usbip-0.1.4/src/README 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/README 2007-05-18 11:10:08.000000000 +0200 @@ -2,7 +2,7 @@ # # README for usbip-utils # -# Copyright (C) 2005-2006 Takahiro Hirofuchi +# Copyright (C) 2005-2007 Takahiro Hirofuchi [Note] @@ -17,24 +17,18 @@ - libwrap0-dev tcp wrapper library - - hwdata - /usr/share/hwdata/usb.ids - - usbip device drivers For mainline kernels, it is included under usbip-utils/drivers/. - gcc >= 4.0 - - libglib2.0-dev + - libglib2.0-dev >= 2.6.0 - libtool, automake-1.9, autoconf >= 2.5.0, pkg-config [Install] 0. Skip here if you see a configure script. - $ aclocal - $ autoheader - $ automake-1.9 -a -c -f - $ autoconf + $ ./autogen.sh 1. Compile & install. $ ./configure diff -Naur usbip-0.1.4/src/setup trunk/src/setup --- usbip-0.1.4/src/setup 2007-05-18 11:10:10.000000000 +0200 +++ trunk/src/setup 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +0,0 @@ -#!/bin/sh -x - -aclocal -autoheader -automake-1.9 -acf -autoconf diff -Naur usbip-0.1.4/src/usb.ids trunk/src/usb.ids --- usbip-0.1.4/src/usb.ids 1970-01-01 01:00:00.000000000 +0100 +++ trunk/src/usb.ids 2007-05-18 11:10:08.000000000 +0200 @@ -0,0 +1,5971 @@ +# +# List of USB ID's +# +# Maintained by Vojtech Pavlik +# If you have any new entries, send them to the maintainer. +# Send entries as patches (diff -u old new). +# The latest version can be obtained from +# http://www.linux-usb.org/usb.ids +# +# $Id: usbip-svn-20070518-1.patch,v 1.1 2007-05-18 09:40:34 niro Exp $ +# + +# Vendors, devices and interfaces. Please keep sorted. + +# Syntax: +# vendor vendor_name +# device device_name <-- single tab +# interface interface_name <-- two tabs + +0001 Fry's Electronics +0002 Ingram +0003 Club Mac +0004 Nebraska Furniture Mart +0386 LTS + 0001 PSX for USB Converter +03e8 EndPoints, Inc. + 0004 SE401 WebCam + 0008 101 Ethernet [klsi] +03e9 Thesys Microelectronics +03ea Data Broadcasting Corp. +03eb Atmel Corp. + 2002 Mass Storage Device + 2015 at90usbkey sample firmware (HID keyboard) + 2018 at90usbkey sample firmware (CDC ACM) + 2019 stk525 sample firmware (microphone) + 201c at90usbkey sample firmware (HID mouse) + 201d at90usbkey sample firmware (HID generic) + 2022 at90usbkey sample firmware (composite device) + 2103 JTAG ICE mkII + 2104 AVR ISP mkII + 2107 AVR Dragon + 2ffb at90usb AVR DFU bootloader + 2ffd at89c5130/c5131 DFU bootloader + 2fff at89c5132/c51snd1c DFU bootloader + 3301 at43301 4-port Hub + 3312 4-port Hub + 5601 at76c510 Prism-II 802.11b Access Point + 5603 Cisco 7920 WiFi IP Phone + 6124 at91sam SAMBA bootloader + 7603 at76c503a D-Link DWL-120 802.11b Adapter + 7605 at76c503a 802.11b Adapter + 7606 at76c505 802.11b Adapter + 7611 at76c510 rfmd2948 802.11b Access Point +03ec Iwatsu America, Inc. +03ed Mitel Corp. +03ee Mitsumi + 0000 CD-R/RW Drive + 641f WIF-0402C Bluetooth Adapter + 6440 WML-C52APR Bluetooth Adapter + 6901 SmartDisk FDD +03f0 Hewlett-Packard + 0004 DeskJet 895c + 0101 ScanJet 4100c + 0102 PhotoSmart S20 + 0104 DeskJet 880c/970c + 0105 ScanJet 4200c + 0107 CD-Writer Plus + 010c Multimedia Keyboard Hub + 0111 G55xi Printer/Scanner/Copier + 011c hn210w 802.11b Adapter + 0121 HP49g+ Calculator + 0201 ScanJet 6200c + 0202 PhotoSmart S20 + 0204 DeskJet 815c + 0205 ScanJet 3300c + 0207 CD-Writer Plus 8200e + 020c Multimedia Keyboard + 0304 DeskJet 810c/812c + 0305 ScanJet 4300c + 0311 OfficeJet G85xi + 0317 LaserJet 1200 + 0401 ScanJet 5200c + 0404 DeskJet 830c/832c + 0405 ScanJet 3400cse + 0504 DeskJet 885c + 0505 ScanJet 2100c + 050c 5219 Wireless Keyboard + 0517 LaserJet 1000 + 0601 ScanJet 6300c + 0604 DeskJet 840c + 0605 ScanJet 2200c + 0701 ScanJet 5300c/5370c + 0704 DeskJet 825c + 0705 ScanJet 4400c + 0712 DeskJet 1180c + 0801 ScanJet 7400c + 0804 DeskJet 816c + 0901 ScanJet 2300c + 0904 DeskJet 845c + 1004 DeskJet 970c/970cse + 1005 ScanJet 5400c + 1016 Jornada 548 / iPAQ HW6515 Pocket PC + 1104 DeskJet 959c + 1105 ScanJet 5470c + 1116 Jornada 568 Pocket PC + 1151 750xi Printer/Scanner/Copier + 1204 DeskJet 930c + 1305 ScanJet 4570c + 1317 LaserJet 1005 + 1405 Scanjet 3670 + 1504 DeskJet 920c + 1604 DeskJet 940c + 1904 DeskJet 3820 + 1c17 Color LaserJet 2550l + 1e11 PSC-950 + 2002 Hub + 2004 DeskJet 640c + 2005 ScanJet 3570c + 2104 DeskJet 630c + 2205 ScanJet 3500c + 2304 DeskJet 656c + 2305 ScanJet 3970c + 2811 PSC-2100 + 2d11 OfficeJet 6110 + 3102 PhotoSmart P1100 Printer w/ Card Reader + 3104 DeskJet 960c + 3304 DeskJet 990c + 3404 DeskJet 6122 + 3504 DeskJet 6127c + 3c02 PhotoSmart 7350 + 3d11 OfficeJet 4215 + 3f11 PSC-1315/PSC-1317 + 4002 PhotoSmart 720 / PhotoSmart 935 (storage) + 4102 PhotoSmart 618 + 4202 PhotoSmart 812 + 4302 PhotoSmart 850 (ptp) + 4402 PhotoSmart 935 (ptp) + 5004 DeskJet 995c + 6004 DeskJet 5550 + 6104 DeskJet 5650c + 6202 PhotoSmart 215 + 6204 DeskJet 5150c + 6302 PhotoSmart 318/612 + 6402 PhotoSmart 715 (ptp) + 6502 PhotoSmart 120 (ptp) + 6602 PhotoSmart 320 + 6702 PhotoSmart 720 (ptp) + 6802 PhotoSmart 620 (ptp) + 6a02 PhotoSmart 735 (ptp) + 7004 DeskJet 3320c + 7104 DeskJet 3420c + 7202 PhotoSmart 43x (ptp) + 7204 DeskJet 36xx + 7304 DeskJet 35xx + a004 DeskJet 5850c + bef4 NEC Picty760 + efbe NEC Picty900 + f0be NEC Picty920 + f1be NEC Picty800 +03f1 Genoa Technology +03f2 Oak Technology, Inc. +03f3 Adaptec, Inc. +03f4 Diebold, Inc. +03f5 Siemens Electromechanical +03f8 Epson Imaging Technology Center +03f9 KeyTronic Corp. +03fb OPTi, Inc. +03fc Elitegroup Computer Systems +03fd Xilinx, Inc. +03fe Farallon Comunications +0400 National Semiconductor Corp. + 0807 Bluetooth Dongle + 1000 Mustek BearPaw 1200 Scanner + 1001 Mustek BearPaw 2400 Scanner +0401 National Registry, Inc. +0402 ALi Corp. + 5462 M5462 IDE Controller + 5603 USB 2.0 Q-tec Webcam 300 + 5621 USB 2.0 Storage Device + 5632 USB 2.0 Host-to-Host Link + 5637 M5637 IDE Controller +0403 Future Technology Devices International, Ltd + 0000 H4SMK 7 Port Hub + 6001 8-bit FIFO + 8040 4 Port Hub + 8070 7 Port Hub + 8370 7 Port Hub + 8371 PS/2 Keyboard And Mouse + 8372 FT8U100AX Serial Port + ea90 Eclo 1-Wire Adapter + f208 Papenmeier Braille-Display + fd48 ShipModul MiniPlex-4xUSB NMEA Multiplexer + ff08 ToolHouse LoopBack Adapter +0404 NCR Corp. + 0310 K590 Printer, Self-Service + 0311 7167 Printer, Receipt/Slip + 0312 7197 Printer Receipt + 0320 5932-USB Keyboard + 0321 5953-USB Dynakey + 0322 5932-USB Enhanced Keyboard + 0323 5932-USB Enhanced Keyboard, Flash-Recovery/Download + 0324 5953-USB Enhanced Dynakey + 0325 5953-USB Enhanced Dynakey Flash-Recovery/Download + 0328 K016: USB-MSR ISO 3-track MSR: POS Standard (See HID pages) + 0329 K018: USB-MSR JIS 2-Track MSR: POS Standard + 032a K016: USB-MSR ISO 3-Track MSR: HID Keyboard Mode + 032b K016/K018: USB-MSR Flash-Recovery/Download +0405 Synopsys, Inc. +0406 Fujitsu-ICL Computers +0407 Fujitsu Personal Systems, Inc. +0408 Quanta Computer, Inc. +0409 NEC Corp. + 0012 ATerm IT75DSU ISDN TA + 0014 Japanese Keyboard + 0027 MultiSync Monitor + 0058 HighSpeed Hub + 0059 HighSpeed Hub + 006a Conceptronic USB Harddisk Box + 011d e228 Mobile Phone + 55aa Hub + 55ab Hub [iMac/iTouch kbd] + efbe P!cty 900 [HP DJ] + f0be P!cty 920 [HP DJ 812c] +040a Kodak Co. + 0001 DVC-323 + 0002 DVC-325 + 0100 DC-220 + 0110 DC-260 + 0111 DC-265 + 0112 DC-290 + 0120 DC-240 + 0121 DC-240 (PTP firmware) + 0130 DC-280 + 0131 DC-5000 + 0132 DC-3400 + 0140 DC-4800 + 0160 DC4800 + 0170 DX3900 + 0300 EZ-200 + 0400 MC3 + 0500 DX3500 + 0510 DX3600 + 0525 DX3215 + 0530 DX3700 + 0535 EasyShare CX4230 Camera + 0540 LS420 + 0550 DX4900 + 0555 DX4330 + 0560 CX4200 + 0565 CX4210 + 0566 CX4300 + 0568 LS443 + 0569 LS663 + 0570 DX6340 + 0571 CX6330 + 0572 DX6440 + 0573 CX6230 + 0574 CX6200 + 0575 DX6490 + 0576 DX4530 + 057c CX7530 + 057f DX7590 + 5010 Wireless Adapter +040b Weltrend Semiconductor + 6510 Weltrend Bar Code Reader + 6520 XBOX Xploder +040c VTech Computers, Ltd +040d VIA Technologies, Inc. +040e MCCI +040f Echo Speech Corp. +0411 MelCo., Inc. + 0001 LUA-TX Ethernet [pegasus] + 0016 WLI-USB-S11 802.11b Adapter + 0027 WLI-USB-KS11G 802.11b Adapter +0412 Award Software International +0413 Leadtek Research, Inc. + 6025 WinFast DTV Dongle (cold state) + 6026 WinFast DTV Dongle (warm state) + 6f00 WinFast DTV Dongle (STK7700P based) +0414 Giga-Byte Technology Co., Ltd +0416 Winbond Electronics Corp. + 0961 AVL Flash Card Reader + 5518 4-Port Hub + 551a PC Sync Keypad + 551b PC Async Keypad + 551c Sync Tenkey + 551d Async Tenkey + 551e Keyboard + 551f Keyboard w/ Sys and Media + 5521 Keyboard + 7723 SD Card Reader + 6481 16-bit Scanner +0417 Symbios Logic +0418 AST Research +0419 Samsung Info. Systems America, Inc. + 0001 IrDA Remote Controller + 3001 Xerox P1202 Laser Printer + 8002 SyncMaster 757DFX HID Device +041a Phoenix Technologies, Ltd +041b d'TV +041d S3, Inc. +041e Creative Technology, Ltd + 1002 Nomad II + 1003 Blaster GamePad Cobra + 1050 GamePad Cobra + 3010 SoundBlaster MP3+ + 3020 SoundBlaster Audigy 2 NX + 4003 VideoBlaster WebCam Go Plus [W9967CF] + 4004 Nomad II MG + 4005 WebCam Blaster Go ES + 400a PC-Cam 300 + 400b PC-Cam 600 + 400c WebCam 5 [pwc] + 400d WebCam PD1001 + 4011 WebCam PRO eX + 4013 PC-Cam 750 + 4015 CardCam Value + 4017 WebCam Mobile + 4018 WebCam Vista + 401c WebCam NX [PD1110] + 401d WebCam NX Ultra + 401e WebCam NX Pro + 401f Webcam Notebook + 4036 Webcam Live!/Live! Pro + 403a WebCam NX Pro 2 + 403c WebCam Live! Ultra + 403d WebCam Notebook Ultra + 4100 Nomad Jukebox 2 + 4101 Nomad Jukebox 3 + 4106 Nomad MuVo + 4108 Nomad Jukebox Zen + 4109 Nomad Jukebox Zen NX + 410b Nomad Jukebox Zen USB 2.0 + 410c Nomad MuVo NX + 4110 Nomad Jukebox Zen Xtra + 4111 Dell Digital Jukebox + 4116 MuVo^2 + 4117 Nomad MuVo TX + 411b Zen Touch + 411d Zen + 411e Zen Micro + 4123 Zen Portable Media Center + 4126 Dell DJ (2nd gen) + 4127 Dell DJ + 412b MuVo N200 with FM radio + 4134 Zen Neeon + 4136 Zen Sleek + 4139 Zen Nano Plus + 413c Zen MicroPhoto +041f LCS Telegraphics +0420 Chips and Technologies +0421 Nokia Mobile Phones + 0401 6650 GSM Phone + 0405 9500 GSM Communicator + 040b N-Gage GSM Phone + 040f 6230 GSM Phone + 0410 6630 Imaging Smartphone + 0415 9300 GSM Smartphone + 0418 E-70 (PC-Suite mode) + 041a 9500 GSM Communicator (RNDIS) + 041b 9300 GSM Smartphone (RNDIS) + 0429 6230i Camera Phone + 0435 E-70 (IP Passthrough/RNDIS mode) + 0800 Connectivity Cable DKU-5 +0422 ADI Systems, Inc. +0423 Computer Access Technology Corp. + 000a NetMate Ethernet + 000c NetMate2 Ethernet + 000d USB Chief Analyzer + 1237 Andromeda Hub +0424 Standard Microsystems Corp. + 20fc 6-in-1 Card Reader + 223a 8-in-1 Card Reader +0425 Motorola Semiconductors HK, Ltd + 0101 G-Tech Wireless Mouse & Keyboard +0426 Integrated Device Technology, Inc. +0427 Motorola Electronics Taiwan, Ltd +0428 Advanced Gravis Computer Tech, Ltd + 4001 GamePad Pro +0429 Cirrus Logic +042a Ericsson Austrian, AG +042b Intel Corp. +042c Innovative Semiconductors, Inc. +042d Micronics +042e Acer, Inc. +042f Molex, Inc. +0430 Sun Microsystems, Inc. + 0005 Type 6 Keyboard + 0100 3-button Mouse +0431 Itac Systems, Inc. +0432 Unisys Corp. +0433 Alps Electric, Inc. + 1101 IBM Game Controller +0434 Samsung Info. Systems America, Inc. +0435 Hyundai Electronics America +0436 Taugagreining HF +0437 Framatome Connectors USA +0438 Advanced Micro Devices, Inc. +0439 Voice Technologies Group +043d Lexmark International, Inc. + 0002 Optra E310 Printer + 0009 Optra S2450 Printer + 000c Optra E312 Printer + 0017 Z32 printer + 0018 Z52 Printer + 001a Z65 Printer + 001c Kodak Personal Picture Maker 200 Printer + 001f Kodak Personal Picture Maker 200 Card Reader + 0020 Z51 Printer + 0021 Z33 Printer + 002d X70/X73 Scan/Print/Copy + 003d X83 Scan/Print/Copy + 0057 Z35 Printer + 0060 X74/X75 Scanner + 0061 X74 Hub + 0069 X74/X75 Printer + 0072 X6170 Printer +043e LG Electronics USA, Inc. + 42bd Flatron 795FT Plus Monitor + 4a4d Flatron 915FT Plus Monitor + 7001 MF-PD100 Soul Digital MP3 Player + 8484 LPC-U30 Webcam II + 8585 LPC-UC35 Webcam +043f RadiSys Corp. +0440 Eizo Nanao Corp. +0441 Winbond Systems Lab. + 1456 Hub +0442 Ericsson, Inc. +0443 Gateway, Inc. +0445 Lucent Technologies, Inc. +0446 NMB Technologies Corp. +0447 Momentum Microsystems +044a Shamrock Tech. Co., Ltd +044b WSI +044c CCL/ITRI +044d Siemens Nixdorf AG +044e Alps Electric Co., Ltd + 2002 MD-5500 Printer + 3001 UGTZ4 Bluetooth +044f ThrustMaster, Inc. + 0400 HOTAS Cougar + a0a3 Fusion Digital GamePad + b203 360 Modena Pro Wheel + b300 Firestorm Dual Power + b304 Firestorm Dual Power +0450 DFI, Inc. +0451 Texas Instruments, Inc. + 1428 Hub + 1446 TUSB2040/2070 Hub + 2036 TUSB2036 Hub + 2046 TUSB2046 Hub + 2077 TUSB2077 Hub + 3410 TUSB3410 Microcontroller + 5409 Frontier Labs NEX IA+ Digital Audio Player + 6000 AU5 ADSL Modem (pre-reenum) + 6001 AU5 ADSL Modem + e001 GraphLink + e004 TI-89 Titanium Calculator + e008 TI-84 Plus Silver Calculator +0452 Mitsubishi Electronics America, Inc. + 0050 Diamond Pro 900u CRT Monitor + 0051 Integrated Hub +0453 CMD Technology +0454 Vobis Microcomputer AG +0455 Telematics International, Inc. +0456 Analog Devices, Inc. +0457 Silicon Integrated Systems Corp. + 0150 Super Talent 1GB Flash Drive + 0151 Super Flash 1GB Flash Drive +0458 KYE Systems Corp. (Mouse Systems) + 0001 Mouse + 0002 Genius NetMouse Pro + 0003 Genius NetScroll+ + 000e VideoCAM Web + 001a Genius WebScroll+ + 004c Slimstar Pro Keyboard + 0100 EasyPen Tablet + 0101 CueCat + 1003 Genius VideoCam + 1004 Flight2000 F-23 Joystick + 100a Aashima Technology Trust Sight Fighter Vibration Feedback Joystick + 2001 ColorPage-Vivid Pro Scanner + 2007 ColorPage-HR6 V2 Scanner + 2008 ColorPage-HR6 V2 Scanner + 2009 ColorPage-HR6A Scanner + 2011 ColorPage-Vivid3x Scanner + 2013 ColorPage-HR7 Scanner + 2015 ColorPage-HR7LE Scanner + 2016 ColorPage-HR6X Scanner + 301d Genius MaxFire MiniPad + 7004 VideoCAM Express + 7007 VideoCAM Web + 7012 WebCAM USB2.0 +0459 Adobe Systems, Inc. +045a SONICblue, Inc. + 0b4a SupraMax 2890 56K Modem [Lucent Atlas] + 0b68 SupraMax 56K Modem + 5210 Rio Karma Music Player + 5220 Rio Nitrus MP3 Player +045b Hitachi, Ltd +045d Nortel Networks, Ltd +045e Microsoft Corp. + 0007 SideWinder Game Pad + 0008 SideWinder Precision Pro + 0009 IntelliMouse + 000b Natural Keyboard Elite + 0014 Digital Sound System 80 + 001a SideWinder Precision Racing Wheel + 001b SideWinder Force Feedback 2 Joystick + 001d Natural Keyboard Pro + 001e IntelliMouse Explorer + 0023 Trackball Optical + 0024 Trackball Explorer + 0025 IntelliEye Mouse + 0026 SideWinder GamePad Pro + 0027 SideWinder PnP GamePad + 0028 SideWinder Dual Strike + 0029 IntelliMouse Optical + 002b Internet Keyboard Pro + 0033 Sidewinder Strategic Commander + 0034 SideWinder Force Feedback Wheel + 0038 SideWinder Precision 2 + 0039 IntelliMouse Optical + 003b SideWinder Game Voice + 003c SideWinder Joystick + 0040 Wheel Mouse Optical + 0047 IntelliMouse Explorer 3.0 + 0059 Wireless IntelliMouse Explorer + 006e MN510 802.11b Adapter + 007d Notebook Optical Mouse + 007e Wireless Transceiver for Bluetooth + 0083 Basic Optical Mouse + 008a Wireless Keyboard and Mouse + 008c Wireless Intellimouse Explorer 2.0 + 00b9 Wireless Optical Mouse 3.0 + 00bd Fingerprint Reader + 0284 Xbox DVD Playback Kit + 0288 Xbox Controller S Hub + 0289 Xbox Controller S +0460 Ace Cad Enterprise Co., Ltd +0461 Primax Electronics, Ltd + 0300 G2-300 Scanner + 0301 G2E-300 Scanner + 0302 G2-300 #2 Scanner + 0303 G2E-300 #2 Scanner + 0340 Colorado 9600 Scanner + 0341 Colorado 600u Scanner + 0345 Visioneer 6200 Scanner + 0346 Memorex Maxx 6136u Scanner + 0347 Primascan Colorado 2600u/Visioneer 4400 Scanner + 0360 Colorado 19200 Scanner + 0361 Colorado 1200u Scanner + 0364 LG Electronics Scanworks 600U Scanner + 0371 Visioneer Onetouch 8920 Scanner + 0377 Medion MD 5345 Scanner + 037b Medion MD 6190 Scanner + 0380 G2-600 Scanner + 0381 ReadyScan 636i Scanner + 0382 G2-600 #2 Scanner + 0383 G2E-600 Scanner + 0813 IBM UltraPort Camera + 0815 Micro Innovations WebCam + 0819 Fujifilm IX-30 Camera [webcam mode] + 081a Fujifilm IX-30 Camera [storage mode] + 081c Elitegroup ECS-C11 Camera + 081d Elitegroup ECS-C11 Storage + 4d01 Comfort Keyboard + 4d02 Mouse-in-a-Box + 4d03 Kensington Mouse-in-a-box + 4d04 Mouse +0463 MGE UPS Systems + 0001 UPS + ffff UPS +0464 AMP/Tycoelectronics Corp. +0467 AT&T Paradyne +0468 Wieson Technologies Co., Ltd +046a Cherry GmbH + 0001 My3000 Keyboard + 0003 My3000 Hub + 0005 XX33 SmartCard Reader Keyboard + 0023 Cymotion Master Linux Keyboard +046b American Megatrends, Inc. +046c Toshiba Corp., Digital Media Equipment +046d Logitech, Inc. + 0203 M2452 Keyboard + 0301 M4848 Mouse + 0401 HP PageScan + 0402 NEC PageScan + 040f Logitech/Storm PageScan + 0801 QuickCam Home + 0810 QuickCam Pro + 0840 QuickCam Express + 0850 QuickCam Web + 0870 QuickCam Express + 0890 QuickCam Traveler + 08a0 QuickCam IM + 08a2 Labtec WebCam Pro + 08b0 QuickCam 3000 Pro [pwc] + 08b1 QuickCam Notebook Pro + 08b2 QuickCam Pro 4000 + 08b3 QuickCam Zoom + 08b4 QuickCam Zoom + 08da QuickCam Messanger + 08f0 QuickCam Messenger + 0900 ClickSmart 310 + 0901 ClickSmart 510 + 0903 ClickSmart 820 + 0905 ClickSmart 820 + 0920 QuickCam Express + 0921 Labtec WebCam + 0928 Quickcam Express + 092a QuickCam for Notebooks + 0950 Pocket Camera + 0960 ClickSmart 420 + 0970 Pocket750 + c000 N43 [Pilot Mouse] + c001 N48/M-BB48 [FirstMouse Plus] + c002 M-BA47 [MouseMan Plus] + c004 WingMan Gaming Mouse + c00b MouseMan Wheel + c00c Optical Wheel Mouse + c00e M-BJ69 Optical Wheel Mouse + c012 Optical Mouse + c016 M-UV69a Optical Wheel Mouse + c01b MX310 Optical Mouse + c01e MX518 Optical Mouse + c025 MX500 Optical Mouse + c030 iFeel Mouse + c032 MouseMan iFeel + c03e Premium Optical Wheel Mouse + c202 WingMan Formula + c207 WingMan Extreme Digital 3D + c208 WingMan Gamepad Extreme + c209 WingMan Gamepad + c20a WingMan RumblePad + c20c WingMan Precision + c211 iTouch Cordless Reciever + c216 Dual Action Gamepad + c281 WingMan Force + c283 WingMan Force 3D + c285 WingMan Strike Force 3D + c291 WingMan Formula Force + c293 WingMan Formula Force GP + c295 Momo Force Steering Wheel + c2a0 Wingman Force Feedback Mouse + c303 iTouch Keyboard + c308 Internet Navigator Keyboard + c309 Internet Keyboard + c401 TrackMan Marble Wheel + c402 Marble Mouse (2-button) + c404 TrackMan Wheel + c408 Marble Mouse (4-button) + c501 Cordless Mouse Receiver + c503 Cordless Mouse+Keyboard Receiver + c504 Cordless Mouse+Keyboard Receiver + c505 Cordless Mouse+Keyboard Receiver + c506 MX-700 Cordless Mouse Receiver + c50b Cordless Desktop Optical + c50e MX-1000 Cordless Mouse Receiver + d001 QuickCam Pro +046e Behavior Tech. Computer Corp. + 6782 BTC 7932 mouse+keyboard +046f Crystal Semiconductor +0471 Philips + 0101 DSS350 Digital Speaker System + 0104 DSS330 Digital Speaker System [uda1321] + 0201 Hub + 0222 Creative Nomad Jukebox + 0302 PCA645VC WebCam [pwc] + 0303 PCA646VC WebCam [pwc] + 0304 Askey VC010 WebCam [pwc] + 0307 PCVC675K WebCam [pwc] + 0308 PCVC680K WebCam [pwc] + 030c PCVC690K WebCam [pwc] + 0310 PCVC730K WebCam [pwc] + 0311 PCVC740K ToUcam Pro [pwc] + 0312 PCVC750K WebCam [pwc] + 0471 Digital Speaker System + 0601 OVU1020 IR Dongle (Kbd+Mouse) + 0701 150P1 TFT Display + 0811 JR24 CDRW + 1120 Creative Rhomba MP3 player + 1801 Diva MP3 player +0472 Chicony Electronics Co., Ltd + 0065 PFU-65 Keyboard +0473 Sanyo Information Business Co., Ltd +0474 Sanyo Electric Co., Ltd + 0701 SCP-4900 Cellphone +0475 Relisys/Teco Information System +0476 AESP +0477 Seagate Technology, Inc. +0478 Connectix Corp. + 0001 QuickCam + 0002 QuickClip +0479 Advanced Peripheral Laboratories +047a Semtech Corp. +047b Silitek Corp. + 0002 Keyboard and Mouse + 0101 BlueTooth Keyboard and Mouse + 020b SK-3105 SmartCard Reader + 1002 HP ScanJet 4300c Parallel Port +047c Dell Computer Corp. +047d Kensington + 1003 Orbit TrackBall + 1005 TurboBall + 1009 Orbit TrackBall for Mac + 101f PocketMouse Pro + 2010 Wireless Presentation Remote + 4005 Gravis Eliminator GamePad Pro + 4006 Gravis Eliminator AfterShock + 4008 Gravis Destroyer TiltPad + 5002 VideoCam CABO II + 5003 VideoCam +047e Agere Systems, Inc. (Lucent) + 1001 USS720 Parallel Port + f101 Atlas Modem +047f Plantronics, Inc. +0480 Toshiba America Info. Systems, Inc. +0481 Zenith Data Systems +0482 Kyocera Corp. + 000e FS-1020D Printer +0483 SGS Thomson Microelectronics + 1307 Cytronix 6in1 card reader + 163d Cool Icam Digi-MP3 + 2016 Fingerprint Reader + 2017 Biometric Smart Card Reader + 7554 56k SoftModem +0484 Specialix +0485 Nokia Monitors +0486 ASUS Computers, Inc. +0487 Stewart Connector +0488 Cirque Corp. +0489 Foxconn / Hon Hai + 0502 SmartMedia Card Reader Firmware Loader + 0503 SmartMedia Card Reader +048a S-MOS Systems, Inc. +048c Alps Electric Ireland, Ltd +048d Integrated Technology Express, Inc. +048f Eicon Tech. +0490 United Microelectronics Corp. +0491 Capetronic +0492 Samsung SemiConductor, Inc. +0493 MAG Technology Co., Ltd +0495 ESS Technology, Inc. +0496 Micron Electronics +0497 Smile International +0498 Capetronic (Kaohsiung) Corp. +0499 Yamaha Corp. + 6001 CRW2200UX Lightspeed 2 External CD-RW Drive +049a Gandalf Technologies, Ltd +049b Curtis Computer Products +049c Acer Advanced Labs, Inc. + 0002 Keyboard (???) +049d VLSI Technology +049f Compaq Computer Corp. + 0003 iPAQ PocketPC + 000e Internet Keyboard + 0018 PA-1/PA-2 MP3 Player + 001a S4 100 Scanner + 0021 S200 Scanner + 0033 801.11b Adapter [orinoco] + 0051 KU-0133 Easy Access Interner Keyboard + 505a Linux-USB "CDC Subset" Device, or Itsy (experimental) + 8511 iPAQ Networking 10/100 Ethernet [pegasus2] +04a0 Digital Equipment Corp. +04a1 SystemSoft Corp. +04a2 FirePower Systems +04a3 Trident Microsystems, Inc. +04a4 Hitachi, Ltd +04a5 Acer Peripherals Inc. (now BenQ Corp.) + 0001 Keyboard + 12a6 AcerScan C310U + 1a20 Prisa 310U + 1a2a Prisa 620U + 2022 Prisa 320U/340U + 2040 Prisa 620UT + 2060 Prisa 620U+/640U + 207e Prisa 640BU + 20b0 S2W 3300U/4300U + 20be Prisa 640BT + 20c0 Prisa 1240UT + 20de S2W 4300U+ + 20fc Benq 5000 + 20fe SW2 5300U + 3003 Benq WebCam + 3008 Benq 1500 + 300a Benq 3410 + 300c Benq 1016 + 9213 Kbd Hub +04a6 Nokia Display Products +04a7 Visioneer + 0211 OneTouch 7600 Scanner + 0221 OneTouch 5300 Scanner + 0224 OneTouch 4800 USB/Microtek Scanport 3000 + 0226 OneTouch 5300 USB + 0231 6100 Scanner + 0311 6200 EPP/USB Scanner + 0321 OneTouch 8100 EPP/USB Scanner + 0331 OneTouch 8600 EPP/USB Scanner +04a8 Multivideo Labs, Inc. +04a9 Canon, Inc. + 1051 BJC-3000 Color Printer + 1056 BJC-2110 Color Printer + 105b S600 Printer + 105d S450 Printer + 1062 S500 Printer + 1064 S300 Printer + 106b S520 Printer + 106d S750 Printer + 1072 I850 Printer + 1073 I550 Printer + 1074 S330 Printer + 1094 PIXMA iP3000x Printer + 2201 CanoScan FB320U + 2202 CanoScan FB620U + 2204 CanoScan FB630U + 2205 CanoScan FB1210U + 2206 CanoScan N650U/N656U + 2207 CanoScan 1220U + 2208 CanoScan D660U + 220a CanoScan D2400UF + 220b CanoScan D646U + 220c CanoScan D1250U2 + 220d CanoScan N670U/N676U/LiDE 20 + 220e CanoScan N1240U/LiDE 30 + 220f CanoScan 8000F + 2210 CanoScan 9900F + 2212 CanoScan 5000F + 2213 LiDE 50/LiDE 35 + 2215 CanoScan 3000/3000F/3000ex + 2216 CanoScan 3200F + 2217 CanoScan 5200F + 221e CanoScan 8400F + 2611 SmartBase MPC400 + 262b LaserShot LBP-1120 Printer + 3041 PowerShot S10 + 3042 CanoScan FS4000US Film Scanner + 3043 PowerShot S20 + 3044 EOS D30 + 3045 PowerShot S100 + 3046 IXY Digital + 3047 Digital IXUS + 3048 PowerShot G1 + 3049 PowerShot Pro90 IS + 304b IXY Digital 300 + 304c PowerShot S300 + 304d Digital IXUS 300 + 304e PowerShot A20 + 304f PowerShot A10 + 3051 PowerShot S110 + 3052 Digital IXUS V + 3055 PowerShot G2 + 3056 PowerShot S40 + 3057 PowerShot S30 + 3058 PowerShot A40 + 3059 PowerShot A30 + 305b ZR45MC Digital Camcorder + 3060 EOS D60 + 3061 PowerShot A100 + 3062 PowerShot A200 + 3065 PowerShot S200 + 3066 Digital IXUS 330 + 3067 MV550i Digital Video Camera + 3069 PowerShot G3 + 306b MVX2i Digital Video Camera + 306c PowerShot S45 + 306d PowerShot S45 PtP Mode + 306f PowerShot G3 (ptp) + 3070 PowerShot S230 + 3071 PowerShot S230 (ptp) + 3072 PowerShot SD100 / Digital IXUS 2 (ptp) + 3073 PowerShot A70 (ptp) + 3074 PowerShot A60 (ptp) + 3075 IXUS 400 Camera + 3076 PowerShot A300 + 3077 PowerShot S50 + 3078 ZR70MC Digital Camcorder + 307b MV630i Difital Video Camera + 307f Optura 20 + 3081 Optura 10 + 3083 EOS 10D + 3084 EOS 300D / EOS Digital Rebel + 3085 PowerShot G5 + 3099 EOS 300D (ptp) + 309a PowerShot A80 + 309b Digital IXUS (ptp) + 309c PowerShot S1 IS + 30b4 PowerShot S500 + 30b5 PowerShot A75 + 30b9 Powershot A85 + 30ba PowerShot S410 Digital Elph + 30bb PowerShot A95 + 30bf Digital IXUS 40 + 30eb EOS 20D + 30ec EOS 20D (ptp) + 30ee EOS 350D + 30ef EOS 350D (ptp) + 3138 PowerShot A710 IS +04aa DaeWoo Telecom, Ltd +04ab Chromatic Research +04ac Micro Audiometrics Corp. +04ad Dooin Electronics +04af Winnov L.P. +04b0 Nikon Corp. + 0102 Coolpix 990 + 0103 Coolpix 880 + 0104 Coolpix 995 + 0106 Coolpix 775 + 0107 Coolpix 5000 + 0108 Coolpix 2500 + 0109 Coolpix 2500 (ptp) + 010a Coolpix 4500 + 010b Coolpix 4500 (ptp) + 010d Coolpix 5700 (ptp) + 010e Coolpix 4300 (storage) + 010f Coolpix 4300 (ptp) + 0111 Coolpix 3500 (ptp) + 0112 Coolpix 885 (ptp) + 0113 Coolpix 5000 (ptp) + 0114 Coolpix 3100 (storage) + 0115 Coolpix 3100 (ptp) + 0117 Coolpix 2100 (ptp) + 0119 Coolpix 5400 (ptp) + 011d Coolpix 3700 (ptp) + 012c Coolpix 4100 (storage) + 0136 Coolpix 7900 (storage) + 0137 Coolpix 7900 (ptp) + 0202 Coolpix SQ (ptp) + 0205 Coolpix 5200 (storage) + 0206 Coolpix 5200 (ptp) + 0301 Coolpix 2000 (storage) + 0302 Coolpix 2000 (ptp) + 0402 DSC D100 (ptp) + 4000 Coolscan LS 40 ED +04b1 Pan International +04b3 IBM Corp. + 3004 Media Access Pro Keyboard + 3016 UltraNav Keyboard Hub + 3018 UltraNav Keyboard + 3100 NetVista Mouse + 3103 ScrollPoint Pro Mouse + 3107 ThinkPad 800dpi Optical Travel Mouse + 3108 800dpi Optical Mouse w/ Scroll Point + 3109 Optical ScrollPoint Pro Mouse + 310b Red Wheel Mouse + 4427 Portable CD ROM + 4525 Double sided CRT + 4550 NVRAM (128 KB) + 4554 Cash Drawer + 4580 Hub w/ NVRAM + 4581 4800-2xx Hub w/ Cash Drawer + 4604 Keyboard w/ Card Reader + 4671 4820 LCD w/ MSR/KB +04b4 Cypress Semiconductor Corp. + 0000 Dacal DC-101 CD Library + 0001 Mouse + 0002 CY7C63x0x Thermometer + 1002 CY7C63001 R100 FM Radio + 5500 HID->COM RS232 Adapter + 6560 CY7C65640 USB-2.0 "TetraHub" + 6830 USB-2.0 IDE Adapter + 7417 Wireless PC Lock + 8613 CY7C68013 EZ-USB FX2 USB 2.0 Development Kit + d5d5 CY7C63x0x Zoltrix Z-Boxer GamePad + f000 CY30700 Licorice evaluation board +04b5 ROHM LSI Systems USA, LLC +04b6 Hint Corp. +04b7 Compal Electronics, Inc. +04b8 Seiko Epson Corp. + 0001 Stylus Color 740 / Photo 750 + 0002 ISD Smart Cable for Mac + 0003 ISD Smart Cable + 0005 Stylus Printer + 0101 Perfection 636 + 0102 GT-2200 + 0103 Perfection 610 + 0104 Perfection 1200 + 0105 StylusScan 2000 + 0106 Stylus Scan 2500 + 0107 Expression 1600U + 0109 Expression 1640 XL + 010a Perfection 1640SU + 010b Perfection 1240 + 010c Perfection 640 + 010e Perfection 1680 + 010f Perfection 1250 + 0110 Perfection 1650 + 0112 Perfection 2450 + 0114 Perfection 660 + 011b Perfection 2400 Photo + 011c Perfection 3200 + 011d Perfection 1260 Photo + 011e Perfection 1660 Photo + 011f Perfection 1670 + 0202 Receipt Printer M129C + 0601 Stylus Photo 875DC Card Reader + 0602 Stylus Photo 895 Card Reader + 0801 Stylus CX5200 + 0802 Stylus CX3200 +04b9 Rainbow Technologies, Inc. + 1000 iKey 1000 Token + 1001 iKey 1200 Token + 1200 iKey 2000 Token + 1202 iKey 2032 Token + 1300 iKey 3000 Token +04ba Toucan Systems, Ltd +04bb I-O Data Device, Inc. + 0904 ET/TX Ethernet [pegasus] + 0913 ET/TX-S Ethernet [pegasus2] + 0922 IOData AirPort WN-B11/USBS 802.11b +04bd Toshiba Electronics Taiwan Corp. +04be Telia Research AB +04bf TDK Corp. + 0100 MediaReader CF +04c1 U.S. Robotics (3Com) + 0082 OfficeConnect Analog Modem + 008f Pro ISDN TA + 009d HomeConnect WebCam [vicam] + 3021 56k Voice FaxModem Pro +04c2 Methode Electronics Far East PTE, Ltd +04c3 Maxi Switch, Inc. +04c4 Lockheed Martin Energy Research +04c5 Fujitsu, Ltd + 1029 fi-4010c Scanner + 1041 fi-4120c Scanner + 1042 fi-4220c Scanner +04c6 Toshiba America Electronic Components +04c7 Micro Macro Technologies +04c8 Konica Corp. + 0720 Digital Color Camera + 0721 e-miniD Camera + 0723 KD-200Z Camera + 0726 KD-310Z Camera +04ca Lite-On Technology Corp. +04cb Fuji Photo Film Co., Ltd + 0100 FinePix 1300 / 1400 / 4700 Zoom digital camera + 0103 FinePix NX-700 printer + 0104 FinePix A101/2600 Zoom (PC-Cam Mode) + 0108 FinePix F601 Zoom (Disk mode) + 0109 FinePix F601 Zoom (PC-Cam mode) + 010a FinePix S602 Zoom (Disk mode) + 010b FinePix S602 Zoom (PC-Cam mode) + 0114 FinePix F401 Zoom (Disk mode) + 0115 FinePix F401 Zoom (PC-Cam mode) + 0116 FinePix A203 (Disk mode) + 0117 FinePix A203 (PC-Cam mode) + 011a FinePix S304/3800 (Disk mode) + 011b FinePix S304/3800 (PC-Cam mode) + 011c FinePix 2650 (Disk mode) + 012c FinePix S7000 Zoom (Disk mode) + 0130 Finepix S5000 Camera (Disk mode) + 0131 Finepix S5000 Camera (PC-Cam mode) + 0177 Finepix F10 Camera (Disk mode) + 0179 Finepix F10 Camera (PTP mode) +04cc Philips Semiconductors + 1122 Hub + 1521 USB 2.0 Hub + 8116 Camera +04cd Tatung Co. Of America +04ce ScanLogic Corp. + 0002 SL11R-IDE IDE Bridge +04cf Myson Century, Inc. + 8818 Fast 3.5" External Storage +04d0 Digi International +04d1 ITT Canon +04d2 Altec Lansing Technologies + 0311 ADA-310 Speakers + ff05 ADA-305 Speakers +04d3 VidUS, Inc. +04d4 LSI Logic, Inc. +04d5 Forte Technologies, Inc. +04d6 Mentor Graphics +04d7 Oki Semiconductor +04d8 Microchip Technology, Inc. + 8000 In-Circuit Debugger +04d9 Holtek Semiconductor, Inc. +04da Panasonic (Matsushita) + 2372 Lumix DMC-FZ10 Camera +04db Hypertec Pty, Ltd +04dc Huan Hsin Holdings, Ltd +04dd Sharp Corp. + 7004 VE-CG40U Digital Still Camera + 7005 VE-CG30 Digital Still Camera + 7007 VL-Z7S Digital Camcorder + 8004 Zaurus SL-5000D/SL-5500 PDA + 8005 Zaurus A-300 + 8006 Zaurus SL-B500/SL-5600 PDA + 8007 Zaurus C-700 PDA + 9014 IM-DR80 Portable NetMD Player + 9031 Zaurus C-750/C-760/C-860/SL-C3000 PDA + 9032 Zaurus SL-6000 + 9050 Zaurus C-860 PDA +04de MindShare, Inc. +04df Interlink Electronics +04e1 Iiyama North America, Inc. + 0201 Monitor Hub +04e2 Exar Corp. +04e3 Zilog, Inc. +04e4 ACC Microelectronics +04e5 Promise Technology +04e6 SCM Microsystems, Inc. + 0001 E-USB ATA Bridge + 0002 eUSCSI SCSI Bridge + 0003 eUSB SmartMedia Card Reader + 0005 eUSB SmartMedia/CompactFlash Card Reader + 0006 eUSB SmartMedia Card Reader + 0007 Hifd + 0101 eUSB ATA Bridge + 0325 eUSB ORCA Quad Reader + 0500 Veridicom 5thSense Fingerprint Sensor and eUSB SmartCard + 1010 USBAT-2 CompactFlash Card Reader + 5111 SCR331-DI SmartCard Reader + 5113 SCR333 SmartCard Reader + 5115 SCR335 SmartCard Reader + 5116 SCR331-LC1 SmartCard Reader + e001 SCR331 SmartCard Reader + e003 SPR532 PinPad SmartCard Reader +04e7 Elo TouchSystems + 0001 TouchScreen +04e8 Samsung Electronics Co., Ltd + 0110 Connect3D Flash Drive + 0111 Connect3D Flash Drive + 1003 MP3 Player and Recorder + 300c ML-1210 Printer + 324c ML-1740 Printer + 3260 CLP-510 Color Laser Printer + 5a03 Yepp MP3 Player + 6601 Z100 Mobile Phone +04e9 PC-Tel, Inc. +04ea Brooktree Corp. +04eb Northstar Systems, Inc. +04ec Tokyo Electron Device, Ltd +04ed Annabooks +04ef Pacific Electronic International, Inc. +04f0 Daewoo Electronics Co., Ltd +04f1 Victor Company of Japan, Ltd + 0001 GC-QX3 Digital Still Camera + 0004 GR-DVL815U Digital Video Camera + 0009 GR-DX25EK Digital Video Camera + 000a GR-D72 Digital Video Camera +04f2 Chicony Electronics Co., Ltd + 0001 KU-8933 Keyboard + 0002 NT68P81 Keyboard + 0110 KU-2971 Keyboard + 0112 KU-8933 Keyboard with PS/2 Mouse port + 0116 KU-2971 German Keyboard +04f3 Elan Microelectronics Corp. +04f4 Harting Elektronik, Inc. +04f5 Fujitsu-ICL Systems, Inc. +04f6 Norand Corp. +04f7 Newnex Technology Corp. +04f8 FuturePlus Systems +04f9 Brother Industries, Ltd + 0002 HL-1050 Laser Printer + 0006 HL-1240 Laser Printer + 0007 HL-1250 Laser Printer + 0008 HL-1270 Laser Printer + 000d HL-1440 Laser Printer + 010f MFC 5100C + 0111 MFC 6800 + 2004 PT-2300/2310 p-Touch Laber Printer +04fa Dallas Semiconductor + 2490 DS1490F 2-in-1 Fob, 1-Wire adapter + 4201 DS4201 Audio DAC +04fb Biostar Microtech International Corp. +04fc Sunplus Technology Co., Ltd + 0003 CM1092 Optical Scroller Mouse + 0561 Flexcam 100 + 504a SPCA504a Digital Camera + 504b Aiptek, 1.3 mega PockerCam + 7333 Finet Technology Palmpix DC-85 +04fd Soliton Systems, K.K. +04fe PFU, Ltd +04ff E-CMOS Corp. +0500 Siam United Hi-Tech +0501 Fujikura DDK, Ltd +0502 Acer, Inc. + d001 Divio NW801/DVC-V6+ Digital Camera +0503 Hitachi America, Ltd +0504 Hayes Microcomputer Products +0506 3Com Corp. + 00a0 3CREB96 Bluetooth Adapter + 03e8 3C19250 Ethernet [klsi] + 0a11 3CRWE254G72 802.11g Adapter + 00df 3Com Home Connect lite + 4601 3C460B 10/100 Ethernet Adapter + f002 3CP4218 ADSL Modem (pre-init) + f003 3CP4218 ADSL Modem + f100 3CP4218 ADSL Modem (pre-init) +0507 Hosiden Corp. + 0011 Konami ParaParaParadise Controller +0508 Clarion Co., Ltd +0509 Aztech Systems, Ltd +050a Cinch Connectors +050b Cable System International +050c InnoMedia, Inc. +050d Belkin Components + 0103 F5U103 Serial Adapter [etek] + 0108 F1DE108B KVM + 0109 F5U109/F5U409 PDA Adapter + 0115 SCSI Adapter + 0121 F5D5050 100Mbps Ethernet + 0208 USBView II Video Adapter [nt1004] + 0224 F5U224 USB 2.0 4-Port Hub + 0234 F5U234 USB 2.0 4-Port Hub + 0803 Nostromo 1745 GamePad + 0805 Nostromo N50 GamePad + 1203 F5U120-PC Serial Port + 7050 F5D7050 ver 1000 WiFi +050e Neon Technology, Inc. +050f KC Technology, Inc. + 0003 KC82C160S Hub + 0180 KC-180 IrDA Dongle + 0190 KC2190 USB Host-to-Host cable +0510 Sejin Electron, Inc. +0511 N'Able (DataBook) Technologies, Inc. +0512 Hualon Microelectronics Corp. +0513 digital-X, Inc. +0514 FCI Electronics +0515 ACTC +0516 Longwell Electronics +0517 Butterfly Communications +0518 EzKEY Corp. +0519 Star Micronics Co., Ltd + c002 Xlive Bluetooth XBM-100S MP3 Player +051a WYSE Technology +051b Silicon Graphics +051c Shuttle, Inc. +051d American Power Conversion + 0002 Back-UPS Pro 500/1000/1500 +051e Scientific Atlanta, Inc. +051f IO Systems (Elite Electronics), Inc. +0520 Taiwan Semiconductor Manufacturing Co. +0521 Airborn Connectors +0522 Advanced Connectek, Inc. +0523 ATEN GmbH +0524 Sola Electronics +0525 Netchip Technology, Inc. + 1080 NET1080 USB-USB Bridge + a4a0 Linux-USB "Gadget Zero" + a4a1 Linux-USB Ethernet Gadget + a4a2 Linux-USB Ethernet/RNDIS Gadget + a4a3 Linux-USB user-mode isochronous source/sink + a4a4 Linux-USB user-mode bulk source/sink + a4a5 Linux-USB File Storage Gadget + a4a6 Linux-USB Serial Gadget + a4a7 Linux-USB Serial Gadget (CDC ACM mode) +0526 Temic MHS S.A. +0527 ALTRA +0528 ATI Technologies, Inc. + 7561 TV Wonder +0529 Aladdin Knowledge Systems + 0001 HASP v0.06 + 030b eToken R1 v3.1.3.x + 0313 eToken R1 v3.2.3.x + 031b eToken R1 v3.3.3.x + 0323 eToken R1 v3.4.3.x + 0412 eToken R2 v2.2.4.x + 041a eToken R2 v2.2.4.x + 0422 eToken R2 v2.4.4.x + 042a eToken R2 v2.5.4.x + 050c eToken Pro v4.1.5.x + 0514 eToken Pro v4.2.5.4 +052a Crescent Heart Software +052b Tekom Technologies, Inc. + 1513 Aosta CX100 WebCam + 1514 Aosta CX100 WebCam Storage +052c Canon Information Systems, Inc. +052d Avid Electronics Corp. +052e Standard Microsystems Corp. +052f Unicore Software, Inc. +0530 American Microsystems, Inc. +0531 Wacom Technology Corp. +0532 Systech Corp. +0533 Alcatel Mobile Phones +0534 Motorola, Inc. +0535 LIH TZU Electric Co., Ltd +0536 Hand Held Products (Welch Allyn, Inc.) +0537 Inventec Corp. +0538 Caldera International, Inc. (SCO) +0539 Shyh Shiun Terminals Co., Ltd +053a Preh Werke GmbH & Co. KG +053b Global Village Communication +053c Institut of Microelectronic & Mechatronic Systems +053d Silicon Architect +053e Mobility Electronics +053f Synopsys, Inc. +0540 UniAccess AB + 0101 Panache Surf ISDN TA +0541 Sirf Technology, Inc. +0543 ViewSonic Corp. + 00fe G773 Monitor Hub + 00ff P815 Monitor Hub + 4153 ViewSonic G773 Control (?) +0544 Cristie Electronics, Ltd +0545 Xirlink, Inc. + 8002 IBM NetCamera + 800c Veo StingRay + 8080 IBM C-It WebCam + 810a Veo Advanced Connect WebCam +0546 Polaroid Corp. + 1bed PDC 1320 Camera +0547 Anchor Chips, Inc. + 2131 AN2131 EZUSB Microcontroller + 2235 AN2235 EZUSB-FX Microcontroller + 2720 AN2720 USB-USB Bridge + 2727 Xircom PGUNET USB-USB Bridge + 2810 Cypress USB ATAPI Bridge + 9999 AN2131 uninitialized (?) +0548 Tyan Computer Corp. + 1005 EZ Cart II GameBoy Flash Programmer +0549 Pixera Corp. +054a Fujitsu Microelectronics, Inc. +054b New Media Corp. +054c Sony Corp. + 0010 DSC-S30/S70/S75/F505V/F505/FD92 Cybershot/Mavica Digital Camera + 0023 CD Writer + 0024 Mavica CD-1000 Camera + 0025 NW-MS7 Walkman MemoryStick Reader + 002d MSAC-US1 MemoryStick Reader + 002e Sony HandyCam MemoryStick Reader + 0032 MemoryStick MSC-U01 Reader + 0038 Clie PEG-S300/D PalmOS PDA + 004e DSC-xxx (ptp) + 0058 Clie PEG-N7x0C PalmOS PDA Mass Storage + 0066 Clie PEG-N7x0C/PEG-T425 PalmOS PDA Serial + 0069 Memorystick MSC-U03 Reader + 006d Clie PEG-T425 PDA Mass Storage + 008b Micro Vault 64M Mass Storage + 0099 Clie NR70 PDA Mass Storage + 009a Clie NR70 PDA Serial + 00c0 Handycam DCR-30 + 00c8 MZ-N710 Minidisc Walkman + 00ca MZ-DN430 Minidisc Walkman + 00cb MSAC-US20 Memory Stick Reader + 0105 Micro Vault Hub + 0107 VCC-U01 Visual Communication Camera + 0144 Clie PEG-TH55 PDA + 014c Aiwa AM-NX9 Net MD Music Recorder MDLP + 014d Memory Stick Reader/Writer + 0169 Clie PEG-TJ35 PDA Serial + 016a Clie PEG-TJ35 PDA Mass Storage + 01c3 NW-E55 Network Walkman + 01d0 DVD+RW External Drive DRU-700A + 023b DVD+RW External Drive DRU-800UL +054d Try Corp. +054e Proside Corp. +054f WYSE Technology Taiwan +0550 Fuji Xerox Co., Ltd +0551 CompuTrend Systems, Inc. +0552 Philips Monitors +0553 STMicroelectronics Imaging Division (VLSI Vision) + 0002 CPiA WebCam + 0151 Digital Blue QX5 Microscope + 0202 Aiptek PenCam 1 +0554 Dictaphone Corp. +0555 ANAM S&T Co., Ltd +0556 Asahi Kasei Microsystems Co., Ltd + 0001 AK5370 I/F A/D Converter +0557 ATEN International Co., Ltd + 2001 UC-1284 Printer Port + 2002 10Mbps Ethernet [klsi] + 2004 UC-100KM PS/2 Mouse and Keyboard adapter + 2006 UC-1284B Printer Port + 2007 UC-110T 100Mbps Ethernet [pegasus] + 2008 UC-232A Serial Port [pl2303] + 2202 CS124U Miniview II KVM Switch + 2600 IDE Bridge + 4000 DSB-650 10Mbps Ethernet [klsi] +0558 Truevision, Inc. +0559 Cadence Design Systems, Inc. +055a Kenwood USA +055b KnowledgeTek, Inc. +055c Proton Electronic Ind. +055d Samsung Electro-Mechanics Co. + 9000 AnyCam [pwc] + 9001 MPC-C30 AnyCam Premium for Notebooks [pwc] +055e CTX Opto-Electronics Corp. +055f Mustek Systems, Inc. + 0001 ScanExpress 1200 CU + 0002 ScanExpress 600 CU + 0003 ScanExpress 1200 USB + 0006 ScanExpress 1200 UB + 0007 ScanExpress 1200 USB Plus + 0008 ScanExpress 1200 CU Plus + 0010 BearPaw 1200F + 0210 ScanExpress A3 USB + 0218 BearPaw 2400 TA + 0219 BearPaw 2400 TA Plus + 021a BearPaw 2448 TA Plus + 021c BearPaw 1200 CU Plus + 021d BearPaw 2400 CU Plus + 021e BearPaw 1200 TA/CS + 0400 BearPaw 2400 TA Pro + 0401 P 3600 A3 Pro + 0873 ScanExpress 600 USB + 1000 BearPaw 4800 TA Pro + a350 gSmart 350 + a800 MDC 800 Camera + b500 MDC 3000 Camera + c200 gSmart 300 + c220 gSmart mini + c360 Mustek DV 4000 + c420 gSmart mini 2 + c440 Mustek DV 3000 + c520 gSmart mini 3 + c530 Mustek Gsmart LCD 2 + c650 Mustek MDC5500Z + d001 WCam 300 +0560 Interface Corp. +0561 Oasis Design, Inc. +0562 Telex Communications, Inc. + 0001 Enhanced Microphone +0563 Immersion Corp. +0564 Chinon Industries, Inc. +0565 Peracom Networks, Inc. + 0001 Serial Port [etek] + 0002 Enet Ethernet [klsi] + 0003 @Home Networks Ethernet [klsi] + 0005 Enet2 Ethernet [klsi] +0566 Monterey International Corp. +0567 Xyratex International, Ltd +0568 Quartz Ingenierie +0569 SegaSoft +056a Wacom Co., Ltd + 0000 PenPartner + 0010 Graphire + 0011 Graphire 2 + 0020 Intuos 4x5 + 0021 Intuos 6x8 + 0022 Intuos 9x12 + 0023 Intuos 12x12 + 0024 Intuos 12x18 + 0031 PL500 + 0042 Intuos 2 6x8 + 0043 Intuos 2 +056b Decicon, Inc. +056c eTEK Labs + 8007 Kwik232 Serial Port + 8101 KwikLink USB-USB Bridge +056d EIZO Corp. + 0000 Hub + 0001 Monitor +056e Elecom Co., Ltd + 0002 29UO Mouse + 4002 Laneed 100Mbps Ethernet LD-USB/TX [pegasus] +056f Korea Data Systems Co., Ltd +0570 Epson America +0571 Interex, Inc. + 0002 echoFX InterView Lite +0572 Conexant Systems (Rockwell), Inc. + 0001 Ezcam II WebCam + 0002 Ezcam II WebCam + 0040 Wondereye CP-115 WebCam + 1232 V.90 modem + cafe AccessRunner ADSL Modem + cb00 E-Tech ADSL Modem v2 + cb01 GeekADSL Promax Q31 ADSL Modem +0573 Zoran Co. Personal Media Division (Nogatech) + 0003 USBGear USBG-V1 + 0400 D-Link V100 + 2000 X10 va10a Wireless Camera + 2101 Zoran Co. PMD (Nogatech) AV-grabber Manhattan + 2d00 Osprey 50 + 2d01 Hauppauge USB-Live Model 600 + 4100 USB-TV FM (NTSC) + 4110 PNY USB-TV (NTSC) FM + 4450 PixelView PlayTv-USB PRO (PAL) FM + 4550 ZTV ZT-721 2.4GHz USB A/V Receiver + 4d00 Hauppauge WinTV-USB USA + 4d01 Hauppauge WinTV-USB + 4d02 Hauppauge WinTV-USB UK + 4d03 Hauppauge WinTV-USB France + 4d10 Hauppauge WinTV-USB with FM USA radio + 4d11 Hauppauge WinTV-USB (PAL) with FM radio + 4d12 Hauppauge WinTV-USB UK with FM Radio + 4d20 Hauppauge WinTV-USB II (PAL) with FM radio + 4d21 Hauppauge WinTV-USB II (PAL) + 4d22 Hauppauge WinTV-USB II (PAL) Model 566 + 4d23 Hauppauge WinTV-USB France 4D23 + 4d25 Hauppauge WinTV-USB Model 40209 rev B234 + 4d26 Hauppauge WinTV-USB Model 40209 rev B243 + 4d27 Hauppauge WinTV-USB Model 40204 Rev B281 + 4d28 Hauppauge WinTV-USB Model 40204 rev B283 + 4d29 Hauppauge WinTV-USB Model 40205 rev B298 + 4d2a Hauppague WinTV-USB Model 602 Rev B285 + 4d2b Hauppague WinTV-USB Model 602 Rev B282 + 4d30 Hauppauge WinTV-USB FM Model 40211 Rev B123 + 4d31 Hauppauge WinTV-USB III (PAL) with FM radio Model 568 + 4d32 Hauppauge WinTV-USB III (PAL) FM Model 573 + 4d35 Hauppauge WinTV-USB III (PAL) FM Model 597 + 4d37 Hauppauge WinTV-USB Model 40219 rev E189 +0574 City University of Hong Kong +0575 Philips Creative Display Solutions +0576 BAFO/Quality Computer Accessories +0577 ELSA +0578 Intrinsix Corp. +0579 GVC Corp. +057a Samsung Electronics America +057b Y-E Data, Inc. + 0000 FlashBuster-U Floppy + 0001 Tri-Media Reader Floppy + 0006 Tri-Media Reader Card Reader + 0010 Memory Stick Reader Writer + 0020 HEXA Media Drive 6-in-1 Card Reader Writer + 0030 Memory Card Viewer (TV) +057c AVM GmbH + 2800 ISDN-Connector TA + 3800 BlueFRITZ! Bluetooth Stick + 3d00 Fritz!Box +057d Shark Multimedia, Inc. +057e Nintendo Co., Ltd +057f QuickShot, Ltd +0580 Denron, Inc. +0581 Racal Data Group +0582 Roland Corp. + 0002 MPU64 Midi Interface + 0003 Sound Canvas SC-8850 + 0005 Edirol UM-2 MIDI Adapter + 0011 Edirol UA-5 Sound Capture + 002d VX-2020 Synthesizer +0583 Padix Co., Ltd (Rockfire) + 2030 RM-203 USB Nest [mode 1] + 2031 RM-203 USB Nest [mode 2] + 2032 RM-203 USB Nest [mode 3] + 2033 RM-203 USB Nest [mode 4] + 2050 PX-205 PSX Bridge + 3050 QF-305u Gamepad + 688f QF-688uv Windstorm Pro Joystick + 7070 QF-707u Bazooka Joystick +0584 RATOC System, Inc. +0585 FlashPoint Technology, Inc. +0586 ZyXEL Communications Corp. + 1000 Omni NET Modem / ISDN TA +0587 America Kotobuki Electronics Industries, Inc. +0588 Sapien Design +0589 Victron +058a Nohau Corp. +058b Infineon Technologies +058c In Focus Systems +058d Micrel Semiconductor +058e Tripath Technology, Inc. +058f Alcor Micro Corp. + 2802 Monterey Keyboard + 5492 Hub + 6232 Hi-Speed 16-in-1 Flash Card Reader/Writer + 9213 MacAlly Kbd Hub + 9215 AU9814 Hub + 9254 Hub + 9330 SD Reader + 9380 Flash drive + 9382 Acer/Sweex Flash drive + 9410 Keyboard + 9472 Keyboard Hub +0590 Omron Corp. + 0004 Cable Modem +0591 Questra Consulting +0592 Powerware Corp. +0593 Incite +0594 Princeton Graphic Systems +0595 Zoran Microelectronics, Ltd +0596 MicroTouch Systems, Inc. + 0001 Touchscreen +0597 Trisignal Communications +0598 Niigata Canotec Co., Inc. +0599 Brilliance Semiconductor, Inc. +059a Spectrum Signal Processing, Inc. +059b Iomega Corp. + 0001 Zip 100 (Type 1) + 000b Zip 100 (Type 2) + 0030 Zip 250 (Ver 1) + 0031 Zip 100 (Type 3) + 0032 Zip 250 (Ver 2) + 0040 SCSI Bridge + 0050 Zip CD 650 Writer + 0053 CDRW55292EXT CD-RW External Drive + 006d HipZip MP3 Player + 015d Super DVD Writer + 1052 DVD+RW External Drive +059c A-Trend Technology Co., Ltd +059d Advanced Input Devices +059e Intelligent Instrumentation +059f LaCie, Ltd + 0211 PocketDrive + 0212 PocketDrive + a601 HardDrive +05a0 Vetronix Corp. +05a1 USC Corp. +05a2 Fuji Film Microdevices Co., Ltd +05a3 ARC International +05a4 Ortek Technology, Inc. + 9731 MCK-600W Keyboard +05a5 Sampo Technology Corp. +05a6 Cisco Systems, Inc. +05a7 Bose Corp. +05a8 Spacetec IMC Corp. +05a9 OmniVision Technologies, Inc. + 0511 OV511 WebCam + 0518 OV518 WebCam + a511 OV511+ WebCam +05aa Utilux South China, Ltd +05ab In-System Design + 0002 Parallel Port + 0031 ATA Bridge + 0060 USB 2.0 ATA Bridge + 0200 USS725 ATA Bridge + 0202 ATA Bridge + 081a ATA Bridge + 0cda ATA Bridge for CD-R/RW +05ac Apple Computer, Inc. + 0201 iMac Keyboard [ALPS M2452] + 0202 Apple Keyboard [ALPS] + 0205 Apple Extended Keyboard [Mitsumi] + 0206 Apple Extended Keyboard [Mitsumi] + 020e Apple Internal Keyboard/Trackpad + 020f Apple Internal Keyboard/Trackpad + 0301 iMac Mouse [Mitsumi/Logitech] + 0302 Apple Optical Mouse [Fujitsu] + 1001 Apple Keyboard Hub [ALPS] + 1002 Apple Extended Keyboard Hub [Mitsumi] + 1101 Speakers + 1201 3G iPod + 1300 iPod Shuffle + 8202 HCF V.90 Data/Fax Modem + 8203 Bluetooth HCI +05ad Y.C. Cable U.S.A., Inc. +05ae Synopsys, Inc. +05af Jing-Mold Enterprise Co., Ltd +05b0 Fountain Technologies, Inc. +05b1 First International Computer, Inc. +05b4 LG Semicon Co., Ltd + 4857 M-Any DAH-210 + 6001 Digisette DUO-MP3 AR-100 +05b5 Dialogic Corp. +05b6 Proxima Corp. +05b7 Medianix Semiconductor, Inc. +05b8 Agiler, Inc. + 3002 Scroll Mouse +05b9 Philips Research Laboratories +05ba DigitalPersona, Inc. +05bb Grey Cell Systems +05bc 3G Green Green Globe Co., Ltd + 0004 Trackball +05bd RAFI GmbH & Co. KG +05be Tyco Electronics (Raychem) +05bf S & S Research +05c0 Keil Software +05c1 Kawasaki Microelectronics, Inc. +05c2 Media Phonics (Suisse) S.A. +05c5 Digi International, Inc. +05c6 Qualcomm, Inc. + 3100 CDMA Wireless Modem/Phone + 3196 CDMA Wireless Modem + 3197 CDMA Wireless Modem/Phone +05c7 Qtronix Corp. + 1001 Lynx Mouse + 2011 SCorpius Keyboard +05c8 Cheng Uei Precision Industry Co., Ltd (Foxlink) +05c9 Semtech Corp. +05ca Ricoh Co., Ltd + 0101 RDC-5300 Camera + 2201 RDC-7 Camera + 2205 Caplio RR30 / Medion MD 6126 Camera + 2212 Caplio R1v Camera +05cb PowerVision Technologies, Inc. + 1483 PV8630 interface (scanners, webcams) +05cc ELSA AG + 2100 MicroLink ISDN Office + 2219 MicroLink ISDN + 2265 MicroLink 56k + 2267 MicroLink 56k (V.250) + 2280 MicroLink 56k Fun + 3000 Micolink USB2Ethernet [pegasus] + 3363 MicroLink ADSL Fun +05cd Silicom, Ltd +05ce sci-worx GmbH +05cf Sung Forn Co., Ltd +05d0 GE Medical Systems Lunar +05d1 Brainboxes, Ltd +05d2 Wave Systems Corp. +05d3 Tohoku Ricoh Co., Ltd +05d5 Super Gate Technology Co., Ltd +05d6 Philips Semiconductors, CICT +05d7 Thomas & Betts Corp. + 0099 10Mbps Ethernet [klsi] +05d8 Ultima Electronics Corp. + 4001 Artec Ultima 2000 + 4002 Artec Ultima 2000 (GT6801 based)/Lifetec LT9385 Scanner + 4003 Artec E+ 48U + 4004 Artec E+ Pro + 4008 Trust Easy Webscan 19200 + 4009 Umax Astraslim + 8105 Artec T1 USB TVBOX (cold) + 8106 Artec T1 USB TVBOX (warm) + 8107 Artec T1 USB TVBOX with AN2235 (cold) + 8108 Artec T1 USB TVBOX with AN2235 (warm) + 8109 Artec T1 USB2.0 TVBOX (cold +05d9 Axiohm Transaction Solutions +05da Microtek International, Inc. + 0093 ScanMaker V6USL + 0094 Phantom 336CX/C3 + 0099 ScanMaker X6/X6U + 009a Phantom C6 + 00a0 Phantom 336CX/C3 (#2) + 00b6 ScanMaker V6UPL + 1011 NHJ Che-ez! Kiss Digital Camera + 1018 Digital Dream Enigma 1.3 + 30ce ScanMaker 3800 + 30cf ScanMaker 4800 + 30e6 ScanMaker i320 + 40ca ScanMaker 3600 + 80a3 ScanMaker V6USL (#2) + 80ac ScanMaker V6UL/SpicyU +05db Sun Corp. (Suntac?) +05dc Lexar Media, Inc. + 0080 Jumpdrive Secure 64MB + 0200 JumpDrive 2.0 Pro + 0300 Jumpdrive Geysr + b018 Multi-Card Reader +05dd Delta Electronics, Inc. +05df Silicon Vision, Inc. +05e0 Symbol Technologies +05e1 Syntek Semiconductor Co., Ltd +05e2 ElecVision, Inc. +05e3 Genesys Logic, Inc. + 000a Keyboard with PS/2 Port + 000b Mouse + 0100 Nintendo Game Boy Advance SP + 0120 Pacific Image Electronics PrimeFilm 1800u slide/negative scanner + 0300 GLUSB98PT Parallel Port + 0406 Hub + 0502 GL620USB GeneLink USB-USB Bridge + 0604 USB 1.1 Hub + 0605 USB 2.0 Hub [ednet] + 0660 USB 2.0 Hub + 0700 SIIG US2256 CompactFlash Card Reader + 0701 USB 2.0 IDE Adapter + 0702 USB 2.0 IDE Adapter + 0703 Card Reader + 0710 USB 2.0 33-in-1 Card Reader + 0760 Card Reader + 07A0 Pen Flash + 1205 Afilias Optical Mouse H3003 +05e4 Red Wing Corp. +05e5 Fuji Electric Co., Ltd +05e6 Keithley Instruments +05e8 ICC, Inc. +05e9 Kawasaki LSI + 0008 KL5KUSB101B Ethernet [klsi] + 0009 Sony 10Mbps Ethernet [pegasus] +05eb FFC, Ltd +05ec COM21, Inc. +05ee Cytechinfo Inc. +05ef AVB, Inc. [anko?] + 020a Top Shot Pegasus Joystick + 8884 Mag Turbo Force Wheel + 8888 Top Shot Force Feedback Racing Wheel +05f0 Canopus Co., Ltd + 0101 DA-Port DAC +05f1 Compass Communications +05f2 Dexin Corp., Ltd +05f3 PI Engineering, Inc. + 0007 Kinesis Advantage PRO MPC/USB Keyboard + 0081 Kinesis Integrated Hub + 020b PS2 Adapter + 0232 X-Keys Switch Interface, Programming Mode + 0261 X-Keys Switch Interface, SPLAT Mode + 0264 X-Keys Switch Interface, Composite Mode +05f5 Unixtar Technology, Inc. +05f6 AOC International +05f7 RFC Distribution(s) PTE, Ltd +05f9 PSC Scanning, Inc. +05fa Siemens Telecommunications Systems, Ltd +05fc Harman Multimedia +05fd InterAct, Inc. + 0251 Raider Pro + 0253 ProPad 8 Digital + 262a 3dfx HammerHead FX + daae Game Shark +05fe Chic Technology Corp. + 0001 Mouse + 0005 Viewmaster 4D Browser Mouse + 0007 Twinhead Mouse + 0009 Inland Pro 4500/5000 Mouse + 0011 Browser Mouse +05ff LeCroy Corp. +0600 Barco Display Systems +0601 Jazz Hipster Corp. +0602 Vista Imaging, Inc. + 1001 ViCam WebCam +0603 Novatek Microelectronics Corp. + 00f1 Keyboard + 6871 Mouse +0604 Jean Co., Ltd +0605 Anchor C&C Co., Ltd +0606 Royal Information Electronics Co., Ltd +0607 Bridge Information Co., Ltd +0608 Genrad Ads +0609 SMK Manufacturing, Inc. +060a Worthington Data Solutions, Inc. +060b Solid Year + 0001 MacAlly Keyboard + 2101 Keyboard + 5811 ACK-571U Wireless Keyboard + a001 Maxwell Compact Pc PM3 +060c EEH Datalink GmbH +060d Auctor Corp. +060e Transmonde Technologies, Inc. +060f Joinsoon Electronics Mfg. Co., Ltd +0610 Costar Electronics, Inc. +0611 Totoku Electric Co., Ltd +0613 TransAct Technologies, Inc. +0614 Bio-Rad Laboratories +0615 Quabbin Wire & Cable Co., Inc. +0616 Future Techno Designs PVT, Ltd +0617 Swiss Federal Insitute of Technology +0618 MacAlly + 0101 Mouse +0619 Seiko Instruments, Inc. +061a Veridicom International, Inc. + 0110 5thSense Fingerprint Sensor + 0200 FPS200 Fingerprint Sensor + 8200 VKI-A Fingerprint Sensor/Flash Storage (dumb) + 9200 VKI-B Fingerprint Sensor/Flash Storage (smart) +061b Promptus Communications, Inc. +061c Act Labs, Ltd +061d Quatech, Inc. +061e Nissei Electric Co. +0620 Alaris, Inc. +0621 ODU-Steckverbindungssysteme GmbH & Co. KG +0622 Iotech, Inc. +0623 Littelfuse, Inc. +0624 Avocent Corp. +0625 TiMedia Technology Co., Ltd +0626 Nippon Systems Development Co., Ltd +0627 Adomax Technology Co., Ltd +0628 Tasking Software, Inc. +0629 Zida Technologies, Ltd +062a Creative Labs + 0001 Notebook Optical Mouse +062b Greatlink Electronics Taiwan, Ltd +062c Institute for Information Industry +062d Taiwan Tai-Hao Enterprises Co., Ltd +062e Mainsuper Enterprises Co., Ltd +062f Sin Sheng Terminal & Machine, Inc. +0631 JUJO Electronics Corp. +0633 Cyrix Corp. +0634 Micron Technology, Inc. +0635 Methode Electronics, Inc. +0636 Sierra Imaging, Inc. +0638 Avision, Inc. + 0268 iVina 1200U Scanner + 026a Minolta Dimage Scan Dual II + 0a10 iVina FB1600/UMAX Astra 4500 + 4004 Minolta Dimage Scan Elite II +0639 Chrontel, Inc. +063a Techwin Corp. +063b Taugagreining HF +063c Yamaichi Electronics Co., Ltd (Sakura) +063d Fong Kai Industrial Co., Ltd +063e RealMedia Technology, Inc. +063f New Technology Cable, Ltd +0640 Hitex Development Tools +0641 Woods Industries, Inc. +0642 VIA Medical Corp. +0644 TEAC Corp. + 0000 Floppy + 800D TASCAM Portastudio DP-01FX +0645 Who? Vision Systems, Inc. +0646 UMAX +0647 Acton Research Corp. + 0100 ARC SpectraPro UV/VIS/IR Monochromator/Spectrograph + 0101 ARC AM-VM Mono Airpath/Vacuum Monochromator/Spectrograph + 0102 ARC Inspectrum Mono + 0103 ARC Filterwheel + 03e9 Inspectrum 128x1024 F VIS Spectrograph + 03ea Inspectrum 256x1024 F VIS Spectrograph + 03eb Inspectrum 128x1024 B VIS Spectrograph + 03ec Inspectrum 256x1024 B VIS Spectrograph +0648 Inside Out Networks +0649 Weli Science Co., Ltd +064b White Mountain DSP, Inc. +064c Ji-Haw Industrial Co., Ltd +064d TriTech Microelectronics, Ltd +064e Suyin Corp. +064f WIBU-Systems AG +0650 Dynapro Systems +0651 Likom Technology Sdn. Bhd. +0652 Stargate Solutions, Inc. +0653 CNF, Inc. +0654 Granite Microsystems, Inc. +0655 Space Shuttle Hi-Tech Co., Ltd +0656 Glory Mark Electronic, Ltd +0657 Tekcon Electronics Corp. +0658 Sigma Designs, Inc. +0659 Aethra +065a Optoelectronics Co., Ltd + 0001 Barcode scanner +065b Tracewell Systems +065e Silicon Graphics +065f Good Way Technology Co., Ltd & GWC technology Inc. +0660 TSAY-E (BVI) International, Inc. +0661 Hamamatsu Photonics K.K. +0662 Kansai Electric Co., Ltd +0663 Topmax Electronic Co., Ltd + 0103 CobraPad +0667 Aiwa Co., Ltd + 0fa1 TD-U8000 Tape Drive +0668 WordWand +0669 Oce' Printing Systems GmbH +066a Total Technologies, Ltd +066b Linksys, Inc. + 0105 SCM eUSB SmartMedia Card Reader + 010a Melco MCR-U2 SmartMedia / CompactFlash Reader + 2202 USB10TX Ethernet [pegasus] + 2203 USB100TX Ethernet [pegasus] + 2204 USB100TX HomePNA Ethernet [pegasus] + 2206 USB Ethernet [pegasus] + 2211 WUSB11 802.11b Adapter + 2212 WUSB11v2.5 802.11b Adapter + 2213 WUSB12v1.1 802.11b Adapter +066d Entrega, Inc. +066e Acer Semiconductor America, Inc. +066f SigmaTel, Inc. + 004b A-Max PA11 MP3 Player + 3400 STMP3400 D-Major MP3 Player + 3410 STMP3410 D-Major MP3 Player + 4200 STIr4200 IrDA Bridge + 4210 STIr4210 IrDA Bridge + 8004 MSCNMMC MP3 Player + 8202 Jens of Sweden / I-BEAD 150M/150H MP3 player +0672 Labtec, Inc. + 1041 LCS1040 Speaker System + 5000 SpaceBall 4000 FLX +0673 HCL + 5000 Keyboard +0674 Key Mouse Electronic Enterprise Co., Ltd +0675 Draytech + 0110 Vigor 128 ISDN TA +0676 Teles AG +0677 Aiwa Co., Ltd + 0fa1 TD-U8000 Tape Drive +0678 ACard Technology Corp. +067b Prolific Technology, Inc. + 0000 PL2301 USB-USB Bridge + 0001 PL2302 USB-USB Bridge + 2303 PL2303 Serial Port + 2305 PL2305 Parallel Port + 2307 PL2307 USB-ATAPI4 Bridge + 2315 Flash Disk Embedded Hub + 2316 Flash Disk Security Device + 2317 Mass Storage Device + 2501 PL2501 USB-USB Bridge (USB 2.0) + 2515 Flash Disk Embedded Hub + 2517 Flash Disk Mass Storage Device + 3507 PL3507 ATAPI6 Bridge +067c Efficient Networks, Inc. + 1001 Siemens SpeedStream 100MBps Ethernet + 1022 Siemens SpeedStream 1022 802.11b Adapter + 4060 Alcatel Speedstream 4060 ADSL Modem +067d Hohner Corp. +067e Intermec +067f Virata, Ltd +0680 Realtek Semiconductor Corp., CPP Div. (Avance Logic) + 0002 Arowana Optical Wheel Mouse MSOP-01 +0681 Siemens Information and Communication Products + 0002 Gigaset 3075 Passive ISDN + 0005 Mouse with Fingerprint Reader + 0012 I-Gate 802.11b Adapter + 002b A-100-I ADSL Modem +0682 Victor Company of Japan, Ltd +0684 Actiontec Electronics, Inc. +0686 Minolta Co., Ltd + 4003 Dimage 2330 Zoom Camera + 4004 Scan Elite II + 4006 Dimage 7 Camera + 4007 Dimage S304 Camera + 4008 Dimage 5 Camera + 4009 Dimage X Camera + 400a Dimage S404 Camera + 400b Dimage 7i Camera + 400c Dimage F100 Camera + 400d Scan Dual III + 400f Dimage 7Hi Camera + 4010 Dimage Xi Camera + 4011 Dimage F300 Camera + 4012 Dimage F200 Camera + 4014 Dimage S414 Camera + 4015 Dimage XT Camera [storage] + 4016 Dimage XT Camera [remote mode] + 4018 Dimage Z1 Camera + 401a Dimage A1 Camera + 401c Dimage X20 Camera + 401e Dimage E323 Camera +068a Pertech, Inc. +068b Potrans International, Inc. +068e CH Products, Inc. + 00e2 HFX OEM Joystick + 00f2 Flight Sim Pedals + 00ff Flight Sim Yoke + 0500 GameStick 3D + 0501 CH Pro Pedals + 0504 F-16 Combat Stick +0690 Golden Bridge Electech, Inc. +0693 Hagiwara Sys-Com Co., Ltd + 0002 FlashGate SmartMedia Card Reader + 0003 FlashGate CompactFlash Card Reader + 0005 FlashGate +0694 Lego Group + 0001 Mindstorms Tower +0698 Chuntex (CTX) + 1786 1300ex Monitor + 9999 VLxxxx Monitor+Hub +0699 Tektronix, Inc. +069a Askey Computer Corp. + 0001 VC010 WebCam [pwc] + 0303 Cable Modem + 0321 Dynalink WLL013 / Compex WLU11A 802.11b Adapter + 0821 BT Voyager 1010 802.11b Adapter +069b Thomson, Inc. + 0704 DCM245 Cable Modem + 2220 RCA Kazoo RD1000 MP3 Player + 300a RCA Lyra MP3 Player +069d Hughes Network Systems (HNS) + 0002 Satellite Device +069e Marx + 0005 CryptoBox v1.2 +069f Allied Data Technologies BV + 0010 Tornado Speakerphone FaxModem 56.0 + 0011 Tornado Speakerphone FaxModem 56.0 +06a2 Topro Technology, Inc. +06a3 Saitek PLC + 0006 Cyborg Gold Joystick + 0200 Xbox Adrenalin Hub + 0241 Xbox Adrenalin Gamepad + 0422 ST90 Joystick + 052d P750 Gamepad + 053f X36F Flightstick + 100a SP550 Pad and Joystick Combo + 100b SP550 Pad + 3509 P3000 RF GamePad +06a4 Xiamen Doowell Electron Co., Ltd +06a5 Divio + 0000 Typhoon Webcam 100k [nw8000] + d001 ProLink DS3303u WebCam + d800 Chicony TwinkleCam +06a7 MicroStore, Inc. +06a8 Topaz Systems, Inc. + 0042 SignatureGem 1X5 Pad + 0043 SignatureGem 1X5-HID Pad +06a9 Westell +06aa Sysgration, Ltd +06ac Fujitsu Laboratories of America, Inc. +06ad Greatland Electronics Taiwan, Ltd +06ae Professional Multimedia Testing Centre +06af Harting, Inc. of North America +06b8 Pixela Corp. +06b9 Alcatel Telecom + 0121 SpeedTouch 121g Wireless Dongle + 4061 SpeedTouch ISDN or ADSL Modem + a5a5 DynaMiTe Modem +06ba Smooth Cord & Connector Co., Ltd +06bb EDA, Inc. +06bc Oki Data Corp. +06bd AGFA-Gevaert NV + 0001 SnapScan 1212U + 0002 SnapScan 1236U + 0100 SnapScan Touch + 0403 ePhoto CL18 Camera + 0404 ePhoto CL20 Camera + 2061 SnapScan 1212U (?) + 208d Snapscan e40 + 208f SnapScan e50 + 2091 SnapScan e20 + 2093 SnapScan e10 + 2095 SnapScan e25 + 2097 SnapScan e26 + 20fd SnapScan e52 + 20ff SnapScan e42 +06be AME Optimedia Technology Co., Ltd +06bf Leoco Corp. +06c2 Phidgets Inc. (formerly GLAB) + 0030 PhidgetRFID + 0038 4-Motor PhidgetServo v3.0 + 0039 1-Motor PhidgetServo v3.0 + 003a 8-Motor PhidgetAvancedServo + 0040 PhidgetInterface Kit 0-0-4 + 0044 PhidgetInterface Kit 0-16-16 + 0045 PhidgetInterface Kit 8-8-8 + 0048 PhidgetStepper (Under Development) + 0049 PhidgetTextLED Ver 1.0 + 004a PhidgetLED Ver 1.0 + 004b PhidgetEncoder Ver 1.0 + 0051 PhidgetInterface Kit 0-5-7 (Custom) + 0052 PhidgetTextLCD + 0053 PhidgetInterfaceKit 0-8-8 + 0058 PhidgetMotorControl Ver 1.0 + 0070 PhidgetTemperatureSensor Ver 1.0 + 0071 PhidgetAccelerometer Ver 1.0 + 0072 PhidgetWeightSensor Ver 1.0 + 0073 PhidgetHumiditySensor + 0074 PhidgetPHSensor + 0075 PhidgetGyroscope +06c4 Bizlink International Corp. +06c5 Hagenuk, GmbH +06c6 Infowave Software, Inc. +06c8 SIIG, Inc. +06c9 Taxan (Europe), Ltd +06ca Newer Technology, Inc. +06cb Synaptics, Inc. + 0009 Composite TouchPad and TrackPoint +06cc Terayon Communication Systems +06cd Keyspan + 0101 USA-28 PDA [preenum] + 0102 USA-28X PDA [preenum] + 0103 USA-19 PDA [preenum] + 0104 PDA [prerenum] + 0105 USA-18X PDA [preenum] + 0106 USA-19W PDA [preenum] + 0107 USA-19 PDA + 0108 USA-19W PDA + 010b USA-19Q PDA + 010f USA-28 PDA + 0110 USA-28X PDA + 0112 USA-18X PDA + 0114 USA-28X PDA + 0118 USA-19QW PDA + 0201 Digital Media Remote +06cf SpheronVR AG + 1010 PanoCam 10 + 1012 PanoCam 12/12X +06d0 LapLink, Inc. + 0622 LapLink Gold USB-USB Bridge [net1080] +06d1 Daewoo Electronics Co., Ltd +06d3 Mitsubishi Electric Corp. +06d4 Cisco Systems +06d5 Toshiba + 4000 Japanese Keyboard +06d6 Aashima Technology B.V. +06d7 Network Computing Devices (NCD) +06d8 Technical Marketing Research, Inc. +06da Phoenixtec Power Co., Ltd +06db Paradyne +06dc Foxlink Image Technology Co., Ltd + 0014 Prolink Winscan Pro 2448U +06de Heisei Electronics Co., Ltd +06e0 Multi-Tech Systems, Inc. + f101 MT5634ZBA-USB MultiModemUSB (old firmware) + f103 MT5634MU MultiMobileUSB + f104 MT5634ZBA-USB MultiModemUSB (new firmware) + f107 MT5634ZBA-USB-V92 MultiModemUSB +06e1 ADS Technologies, Inc. + 0008 UBS-10BT Ethernet [klsi] + a190 Instand VCD Usb Capture +06e4 Alcatel Microelectronics +06e6 Tiger Jet Network, Inc. +06ea Sirius Technologies + 0001 NetCom Roadster II 56k + 0002 Roadster II 56k +06eb PC Expert Tech. Co., Ltd +06ef I.A.C. Geometrische Ingenieurs B.V. +06f0 T.N.C Industrial Co., Ltd +06f1 Opcode Systems, Inc. +06f2 Emine Technology Co. +06f6 Wintrend Technology Co., Ltd +06f8 Guillemot Corp. + a300 Dual Analog Leader GamePad +06fa HSD S.r.L +06fc Motorola Semiconductor Products Sector +06fd Boston Acoustics +06fe Gallant Computer, Inc. +0701 Supercomal Wire & Cable SDN. BHD. +0703 Bvtech Industry, Inc. +0705 NKK Corp. +0706 Ariel Corp. +0707 Standard Microsystems Corp. + 0100 2202 Ethernet [klsi] + 0200 2202 Ethernet [pegasus] + ee06 EZ-Connect 802.11g Adapter + ee13 EZ-Connect 802.11g Adapter +0708 Putercom Co., Ltd +0709 Silicon Systems, Ltd (SSL) +070a Oki Electric Industry Co., Ltd +070d Comoss Electronic Co., Ltd +070e Excel Cell Electronic Co., Ltd +0710 Connect Tech, Inc. + 0001 WhiteHeat (fake ID) + 8001 WhiteHeat +0711 Magic Control Technology Corp. + 0100 Hub + 0200 BAY-3U1S1P Serial Port + 0210 MCT1S Serial Port + 0230 MCT-232 Serial Port + 0231 PS/2 Mouse Port + 0240 PS/2 to USB Converter + 0300 BAY-3U1S1P Parallel Port + 0302 Parallel Port + 0900 SVGA Adapter +0713 Interval Research Corp. +0714 NewMotion, Inc. + 0003 ADB to USB convertor +0717 ZNK Corp. +0718 Imation Corp. +0719 Tremon Enterprises Co., Ltd +071b Domain Technologies, Inc. + 0002 DTI-56362-USB Digital Interface Unit + 0101 Audio4-USB DSP Data Acquisition Unit + 0201 Audio4-5410 DSP Data Acquisition Unit + 0301 SB-USB JTAG Emulator +071c Xionics Document Technologies, Inc. +071d Eicon Networks Corp. + 1000 Diva ISDN TA +071e Ariston Technologies +0723 Centillium Communications Corp. +0726 Vanguard International Semiconductor-America +0729 Amitm + 1000 USC-1000 Serial Port +072e Sunix Co., Ltd +072f Advanced Card Systems, Ltd + 0001 AC1030-based SmartCard Reader + 9000 ACR38 AC1038-based Smart Card Reader + 90cc ACR38 SmartCard Reader +0731 Susteen, Inc. + 0528 SonyEricsson DCU-11 Cable +0732 Goldfull Electronics & Telecommunications Corp. +0733 ViewQuest Technologies, Inc. + 0110 VQ110 + 1311 Digital Dream Epsilon 1.3 + 2211 Jenoptik + 0401 CS330 WebCam + 0402 M-318B WebCam + 0430 Intel Pro Share WebCam +0734 Lasat Communications A/S + 0001 560V Modem +0735 Asuscom Network + c541 ISDN TA 280 +0736 Lorom Industrial Co., Ltd +0738 Mad Catz, Inc. +073b Suncom Technologies +073a Chaplet Systems, Inc. +073d Eutron S.p.a. + 0005 Crypto Token +073e NEC, Inc. + 0301 Game Pad +0745 Syntech Information Co., Ltd +0746 Onkyo Corp. +0747 Labway Corp. +0748 Strong Man Enterprise Co., Ltd +0749 EVer Electronics Corp. +074a Ming Fortune Industry Co., Ltd +074b Polestar Tech. Corp. +074c C-C-C Group PLC +074d Micronas GmbH +074e Digital Stream Corp. + 0001 PS/2 Adapter + 0002 PS/2 Adapter +0755 Aureal Semiconductor +0757 Network Technologies, Inc. +075b Sophisticated Circuits, Inc. + 0001 Kick-off! Watchdog +0763 Midiman + 1001 Midisport 2x2 + 1010 Midisport 1x1 + 1020 Midisport 4x4 + 1030 Midisport 8x8 +0764 Cyber Power System, Inc. + 0005 Cyber Power UPS +0765 X-Rite, Inc. +0766 Jess-Link Products Co., Ltd +0767 Tokheim Corp. +0768 Camtel Technology Corp. + 0006 Camtel Technology USB TV Genie Pro FM Model TVB330 +0769 Surecom Technology Corp. +076a Smart Technology Enablers, Inc. +076b OmniKey AG + 0596 CardMan 2020 + 1784 CardMan 6020 + 3021 CardMan 3121 +076c Partner Tech +076d Denso Corp. +076e Kuan Tech Enterprise Co., Ltd +076f Jhen Vei Electronic Co., Ltd +0774 AmTRAN Technology Co., Ltd +0775 Longshine Electronics Corp. +0776 Inalways Corp. +0777 Comda Enterprise Corp. +0778 Volex, Inc. +0779 Fairchild Semiconductor +077a Sankyo Seiki Mfg. Co., Ltd +077b Linksys + 2219 WUSB11 V2.6 802.11b Adapter + 2226 USB200M 100baseTX Adapter +077c Forward Electronics Co., Ltd + 0005 NEC Keyboard +077d Griffin Technology + 0410 PowerMate + 041a PowerWave + 0223 IMic Audio In/Out +077f Well Excellent & Most Corp. +0781 SanDisk Corp. + 0001 SDDR-05a ImageMate CompactFlash Reader + 0002 SDDR-31 ImageMate II CompactFlash Reader + 0005 SDDR-05b (CF II) ImageMate CompactFlash Reader + 0200 SDDR-09 (SSFDC) ImageMate SmartMedia Reader [eusb] + 0400 SecureMate SD/MMC Reader + 0621 SDDR-86 Imagemate 6-in-1 Reader + 0810 SDDR-75 ImageMate CF-SM Reader + 0830 ImageMate CF/MMC/SD Reader + 5150 SDCZ2 Cruzer Mini Flash Drive (thin) + 5151 Cruzer Micro 256/512MB Flash Drive + 7104 Cruzer Micro Mini 256MB Flash Drive + 7112 Cruzer Micro 128MB Flash Drive + 7113 Cruzer Micro 256MB Flash Drive + 8185 SDCZ2 Cruzer Mini Flash Drive (older, thick) + 8889 SDDR-88 Imagemate 8-in-1 Reader +0782 Trackerball +0783 C3PO + 0003 LTC31 SmartCard Reader +0784 Vivitar, Inc. + 0100 Vivicam 2655 + 1310 Vivicam 3305 + 1688 Vivicam 3665 + 2888 Polaroid DC700 + 3330 Nytec ND-3200 Camera + 5260 Werlisa Sport PX 100 / JVC GC-A33 Camera + 5300 Pretec dc530 +0785 NTT-ME + 0001 MN128mini-V ISDN TA + 0003 MN128mini-J ISDN TA +0789 Logitec Corp. +078b Happ Controls, Inc. + 0010 Driving UGCI + 0020 Flying UGCI + 0030 Fighting UGCI +078e Brincom, Inc. +0790 Pro-Image Manufacturing Co., Ltd +0791 Copartner Wire and Cable Mfg. Corp. +0792 Axis Communications AB +0793 Wha Yu Industrial Co., Ltd +0794 ABL Electronics Corp. +0795 RealChip, Inc. +0796 Certicom Corp. +0797 Grandtech Semiconductor Corp. + 8001 SmartCam + 801c Meade Binoculars/Camera +079b Sagem +079d Alfadata Computer Corp. + 0201 GamePort Adapter +07a1 Digicom S.p.A. + d952 Palladio USB V.92 Modem +07a2 National Technical Systems +07a3 Onnto Corp. +07a4 Be, Inc. +07a6 ADMtek, Inc. + 0986 AN986 Pegasus Ethernet + 8511 ADM8511 Pegasus II Ethernet +07aa Corega K.K. + 0001 Ether USB-T Ethernet [klsi] + 0004 FEther USB-TX Ethernet [pegasus] + 0012 Stick-11 802.11b Adapter + 7613 Stick-11 V2 802.11b Adapter +07ab Freecom Technologies + fc01 IDE bridge + fc03 USB2-IDE IDE bridge +07af Microtech + 0004 SCSI-DB25 SCSI Bridge [shuttle] + 0005 SCSI-HD50 SCSI Bridge [shuttle] + 0006 CameraMate SmartMedia and CompactFlash Card Reader [eusb/shuttle] +07b0 Trust Technologies + 0001 ISDN TA +07b1 IMP, Inc. +07b2 Motorola BCS, Inc. + 4100 SurfBoard SB4100 Cable Modem + 4200 SurfBoard SB4200 Cable Modem + 5100 SurfBoard SB5100 Cable Modem + 5120 Surfboard SB5120 Cable Modem (RNDIS) +07b3 Plustek, Inc. + 0001 OpticPro 1212U Scanner + 0010 OpticPro U12 Scanner + 0011 OpticPro U24 Scanner + 0013 OpticPro UT12 Scanner + 0015 OpticPro U24 Scanner + 0017 OpticPro UT12/16/24 Scanner + 0400 OpticPro 1248U Scanner + 0401 OpticPro 1248U Scanner #2 + 0403 OpticPro U16B Scanner +07b4 Olympus Optical Co., Ltd + 0100 Camedia C-2100/C-3000 Ultra Zoom Camera + 0102 Camedia E-10/C-220/C-50 Camera + 0105 Camedia C-310Z/C-700/C-750UZ/C-755/C-765UZ/C-3040/C-4000/C-5050Z/D-560 Zoom Camera + 0112 MAUSB-100 xD Card Reader + 0114 C-350Z Camera + 0203 Digital Voice Recorder DW-90 + 0206 Digital Voice Recorder DS-330 + 0207 Digital Voice Recorder & Camera W-10 + 020d Digital Voice Recorder VN-240PC +07b5 Mega World International, Ltd + 9902 GamePad +07b6 Marubun Corp. +07b7 TIME Interconnect, Ltd +07b8 D-Link Corp. + 4000 DU-E10 Ethernet [klsi] + 4002 DU-E100 Ethernet [pegasus] + abc1 DU-E10 Ethernet [pegasus] + f101 DSB-560 Modem [atlas] +07bc Canon Computer Systems, Inc. +07bd Webgear, Inc. +07be Veridicom +07c0 Code Mercenaries Hard- und Software GmbH + 1121 The Claw + 1500 IO-Warrior 40 + 1501 IO-Warrior 24 + 1502 IO-Warrior 48 + 1503 IO-Warrior 28 +07c4 Datafab Systems, Inc. + a000 CompactFlash Card Reader + a001 CompactFlash & SmartMedia Card Reader [eusb] + a002 Disk Drive + a005 CompactFlash & SmartMedia Card Reader + a006 SmartMedia Card Reader + a109 LC1 CompactFlash & SmartMedia Card Reader + a200 DF-UT-06 Hama MMC/SD Reader + a400 CompactFlash & Microdrive Reader + b004 MMC/SD Reader +07c5 APG Cash Drawer +07c6 ShareWave, Inc. +07c7 Powertech Industrial Co., Ltd +07c8 B.U.G., Inc. +07c9 Allied Telesyn International +07ca AVerMedia Technologies, Inc. +07cb Kingmax Technology, Inc. +07cc Carry Computer Eng., Co., Ltd + 0000 CF Card Reader + 0003 SM Card Reader + 0004 SM/CF/PCMCIA Card Reader + 0006 SM/CF/PCMCIA Card Reader + 000c SM/CF Card Reader + 000d SM/CF Card Reader + 0200 6-in-1 Card Reader + 0301 6-in-1 Card Reader +07cd Elektor + 0001 USBuart Serial Port +07cf Casio Computer Co., Ltd + 1001 QV-8000SX/5700/3000EX Digicam + 2002 E-125 Cassiopeia Pocket PC + 3801 WMP-1 MP3-Watch + 4001 Label Printer KL-P1000 + 4500 LV-20 Digital Camera +07d0 Dazzle + 0001 Digital Video Creator I + 0002 Global Village VideoFX Grabber + 0003 Fusion Model DVC-50 Rev 1 (NTSC) + 0004 DVC-800 (PAL) Grabber +07d1 D-Link System +07d2 Aptio Products, Inc. +07d3 Cyberdata Corp. +07d7 GCC Technologies, Inc. +07da Arasan Chip Systems +07df David Electronics Co., Ltd +07e1 Ambient Technologies, Inc. + 5201 V.90 Modem +07e2 Elmeg GmbH & Co., Ltd +07e3 Planex Communications, Inc. +07e4 Movado Enterprise Co., Ltd +07e5 QPS, Inc. + 5c01 Que! CDRW +07e6 Allied Cable Corp. +07e7 Mirvo Toys, Inc. +07e8 Labsystems +07ea Iwatsu Electric Co., Ltd +07eb Double-H Technology Co., Ltd +07ec Taiyo Electric Wire & Cable Co., Ltd +07ee Torex Retail (formerly Logware) + 0002 Cash Drawer I/F +07f6 Circuit Assembly Corp. +07f7 Century Corp. +07f9 Dotop Technology, Inc. +07fa Draytek + 0778 miniVigor 128 ISDN TA +07fd Mark of the Unicorn + 0000 FastLane MIDI Interface +0801 Mag-Tek +0802 Mako Technologies, LLC +0803 Zoom Telephonics, Inc. + 9700 2986L FaxModem +0809 Genicom Technology, Inc. +080a Evermuch Technology Co., Ltd +080c Datalogic S.p.A. + 0300 Gryphon D120 Barcode Scanner + 0400 Gryphon D120 Barcode Scanner + 0500 Gryphon D120 Barcode Scanner + 0600 Gryphon M100 Barcode Scanner +080d Teco Image Systems Co., Ltd + 0102 Hercules Scan@home 48 +0810 Personal Communication Systems, Inc. +0813 Mattel, Inc. + 0001 Intel Play QX3 Microscope +081a MG Logic + 1000 Duo Pen Tablet +081b Indigita Corp. +081c Mipsys +081e AlphaSmart, Inc. +0822 Reudo Corp. +0825 GC Protronics +0826 Data Transit +0827 BroadLogic, Inc. +0828 Sato Corp. +0829 DirecTV Broadband, Inc. (Telocity) +082d Handspring + 0100 Visor + 0300 Treo 600 +0830 Palm, Inc. + 0002 Palm M505 + 0003 Palm M515 + 0020 Palm I705 + 0040 Palm M125 + 0050 Palm M130 + 0060 Palm Tungsten T / Zire 71 + 0080 Palm +0832 Kouwell Electronics Corp. +0833 Sourcenext Corp. +0835 Action Star Enterprise Co., Ltd +0839 Samsung Techwin Co., Ltd + 0005 Digimax Camera + 0008 Digimax 230 Camera + 1003 Digimax 210SE + 1012 6500 Document Camera + 1542 Digimax 50 Duo +083a Accton Technology Corp. + 1046 10/100 Ethernet [pegasus] + 5046 SpeedStream 10/100 Ethernet [pegasus] +083f Global Village + b100 TelePort V.90 Fax/Modem +0840 Argosy Research, Inc. +0841 Rioport.com, Inc. + 0001 Rio 500 +0844 Welland Industrial Co., Ltd +0846 NetGear, Inc. + 1001 EA101 Ethernet [klsi] + 4110 MA111 WiFi (v1) + 4200 WG121 WiFi (v1) + 4210 WG121 WiFi (v2) + 4220 WG111 WiFi (v1) + 4230 MA111 WiFi + 4240 WG111 WiFi (v2) + 6a00 WG111 WiFi (v2) +084d Minton Optic Industry Co., Inc. + 0003 S-Cam F5 Digital Camera + 0011 Argus DC3500 Digital Camera +084e KB Gear + 1002 Pablo Tablet +084f Empeg + 0001 Empeg-Car Mark I/II Player +0850 Fast Point Technologies, Inc. +0851 Macronix International Co., Ltd + 1543 Maxell WS30 Slim Digital Camera +0852 CSEM +0854 ActiveWire, Inc. + 0100 I/O Board + 0101 I/O Board, rev1 +0856 B&B Electronics + AC01 uLinks USOTL4 RS422/485 Adapter +0858 Hitachi Maxell, Ltd +0859 Minolta Systems Laboratory, Inc. +085a Xircom + 0001 Portstation Dual Serial Port + 0003 Portstation Paraller Port + 000b Portstation Dual PS/2 Port + 0299 Colorvision, Inc. Monitor Spyder + 8027 PGSDB9 Serial Port +085c ColorVision, Inc. + 0200 Monitor Spyder +0862 Teletrol Systems, Inc. +0863 Filanet Corp. +0864 NetGear, Inc. + 4100 MA101 802.11b Adapter + 4102 MA101 802.11b Adapter +0867 Data Translation, Inc. + 9812 ECON Data acquisition unit +086a Emagic Soft-und Hardware GmbH +086c DeTeWe - Deutsche Telephonwerke AG & Co. + 1001 Eumex 504PC ISDN TA + 1003 TA33 ISDN TA + 1055 Eumex 220 ISDN TA +086e System TALKS, Inc. +086f MEC IMEX, Inc. +0870 Metricom +0871 SanDisk, Inc. + 0001 SDDR-01 Compact Flash Reader + 0002 SDDR-31 Compact Flash Reader + 0005 SDDR-05 Compact Flash Reader +0873 Xpeed, Inc. +0874 A-Tec Subsystem, Inc. +0879 Comtrol Corp. +087c Adesso/Kbtek America, Inc. +087d Jaton Corp. +087e Fujitsu Computer Products of America +087f Virtual IP Group, Inc. +0880 APT Technologies, Inc. +0883 Recording Industry Association of America (RIAA) +0885 Boca Research, Inc. +0886 XAC Automation Corp. +0887 Hannstar Electronics Corp. +088b MassWorks, Inc. + 4944 MassWorks ID-75 TouchScreen +0892 DioGraphy, Inc. +089c United Technologies Research Cntr. +089d Icron Technologies Corp. +089e NST Co., Ltd +089f Primex Aerospace Co. +08a5 e9, Inc. +08a8 Andrea Electronics +08ae Macally (Mace Group, Inc.) +08b4 Sorenson Vision, Inc. +08b8 J. Gordon Electronic Design, Inc. + 01f4 USBSIMM1 +08b9 RadioShack Corp. (Tandy) +08bb Texas Instruments Japan +08bd Citizen Watch Co., Ltd +08c3 Precise Biometrics + 0101 Precise 100 MC FingerPrint and SmartCard Reader +08c4 Proxim, Inc. +08c7 Key Nice Enterprise Co., Ltd +08c8 2Wire, Inc. +08c9 Nippon Telegraph and Telephone Corp. +08ca Aiptek International, Inc. + 0010 Tablet + 0020 APT-6000U Tablet + 0021 APT-2 Tablet + 0022 Tablet + 0023 Tablet + 0024 Tablet + 0102 DualCam + 0103 Pocket DV Digital Camera + 0104 Pocket DVII + 0106 Pocket DV3100+ + 0111 PenCam VGA Plus + 2008 Mini PenCam 2 + 2010 Pocket CAM 3 Mega (webcam) + 2011 Pocket CAM 3 Mega (storage) + 2018 Pencam SD 2 + 2024 Pocket DV3500 +08cd Jue Hsun Ind. Corp. +08ce Long Well Electronics Corp. +08cf Productivity Enhancement Products +08d1 smartBridges, Inc. + 0001 smartNIC Ethernet [catc] +08d3 Virtual Ink +08d4 Fujitsu Siemens Computers + 0009 SCR SmartCard Reader +08d9 Increment P Corp. +08dd Billionton Systems, Inc. + 0986 USB-100N Ethernet [pegasus] + 0987 USBLP-100 HomePNA Ethernet [pegasus] + 0988 USBEL-100 Ethernet [pegasus] + 8511 USBE-100 Ethernet [pegasus2] +08de ??? + 7a01 802.11b Adapter +08df Spyrus, Inc. +08e3 Olitec, Inc. + 0002 USB-RS232 Bridge +08e4 Pioneer Corp. +08e5 Litronic +08e6 Gemplus + 0430 GemPC430 SmartCard Reader + 0432 GemPC432 SmartCard Reader + 0435 GemPC435 SmartCard Reader + 0437 GemPC433 SL SmartCard Reader + 3437 GemPC Twin SmartCard Reader + 3438 GemPC Key SmartCard Reader +08e7 Pan-International Wire & Cable +08e8 Integrated Memory Logic +08e9 Extended Systems, Inc. + 0100 XTNDAccess IrDA Dongle +08ea Ericsson, Inc., Blue Ridge Labs +08ec M-Systems Flash Disk Pioneers + 0010 DiskOnKey +08ee CCSI/Hesso +08f0 Corex Technologies +08f1 CTI Electronics Corp. +08f5 SysTec Co., Ltd +08f6 Logic 3 International, Ltd +08f7 Vernier + 0001 LabPro + 0002 EasyTemp +08f8 Keen Top International Enterprise Co., Ltd +08f9 Wipro Technologies +08fa Caere +08fb Socket Communications +08fc Sicon Cable Technology Co., Ltd +08fd Digianswer A/S +08ff AuthenTec, Inc. +0900 Pinnacle Systems, Inc. +0901 VST Technologies +0906 Faraday Technology Corp. +0909 Audio-Technica Corp. +090a Trumpion Microelectronics, Inc. + 1540 Digitex Container Flash Disk +090b Neurosmith +090c Feiya Technology Corp. + 1000 Memory Bar +090d Multiport Computer Vertriebs GmbH +090e Shining Technology, Inc. +090f Fujitsu Devices, Inc. +0910 Alation Systems, Inc. +0911 Philips Speech Processing +0912 Voquette, Inc. +0915 GlobeSpan, Inc. +0917 SmartDisk Corp. +0919 Tiger Electronics + 0100 Fast Flicks Digital Camera +091e Garmin International + 0003 GPSmap (various models) +0920 Echelon Co. +0921 GoHubs, Inc. +0922 Dymo-CoStar Corp. + 0007 LabelWriter 330 + 0009 LabelWriter 310 +0923 IC Media Corp. + 010f SIIG MobileCam +0924 Xerox +0925 Lakeview Research + 8101 Phidgets, Inc., 1-Motor PhidgetServo v2.0 + 8104 Phidgets, Inc., 4-Motor PhidgetServo v2.0 + 8800 WiseGroup Ltd, MP-8800 Quad Joypad + 8866 WiseGroup Ltd, MP-8866 Dual Joypad +0927 Summus, Ltd +0928 Oxford Semiconductor, Ltd +0929 American Biometric Co. +092a Toshiba Information & Industrial Sys. And Services +092b Sena Technologies, Inc. +0930 Toshiba Corp. + 6519 Kingston DataTraveler 2.0 USB Stick + 6533 512M USB Stick +0931 Harmonic Data Systems, Ltd +0932 Crescentec Corp. +0933 Quantum Corp. +0934 Netcom Systems +0939 Lumberg, Inc. +093a Pixart Imaging, Inc. + 2468 Easy Snap Snake Eye WebCam +093b Plextor Corp. + 0042 PX-712UF DVD RW +093c Intrepid Control Systems, Inc. + 0601 ValueCAN +093d InnoSync, Inc. +093e J.S.T. Mfg. Co., Ltd +093f Olympia Telecom Vertriebs GmbH +0940 Japan Storage Battery Co., Ltd +0941 Photobit Corp. +0942 i2Go.com, LLC +0943 HCL Technologies India Private, Ltd +0944 KORG, Inc. +0945 Pasco Scientific +0948 Kronauer music in digital + 0301 USB Pro (24/48) + 0302 USB Pro (24/96 playback) + 0303 USB Pro (24/96 record) + 0304 USB Pro (16/48) + 1105 USB One +094b Linkup Systems Corp. +094d Cable Television Laboratories +0951 Kingston Technology + 000a KNU101TX 100baseTX Ethernet + 1600 Data Traveler II Pen Drive +0954 RPM Systems Corp. +0955 NVidia Corp. +0956 BSquare Corp. +0957 Agilent Technologies, Inc. +0958 CompuLink Research, Inc. +0959 Cologne Chip AG +095a Portsmith +095b Medialogic Corp. +095c K-Tec Electronics +095d Polycom, Inc. +0967 Acer (??) + 0204 WarpLink 802.11b Adapter +0968 Catalyst Enterprises, Inc. +0971 Gretag-Macbeth AG +0973 Schlumberger +0974 Datagraphix, a business unit of Anacomp +0975 OL'E Communications, Inc. +0976 Adirondack Wire & Cable +0977 Lightsurf Technologies +0978 Beckhoff GmbH +0979 Jeilin Technology Corp., Ltd +097a Minds At Work LLC +097b Knudsen Engineering, Ltd +097c Marunix Co., Ltd +097d Rosun Technologies, Inc. +097f Barun Electronics Co., Ltd +0981 Oak Technology, Ltd +0984 Apricorn +0985 cab Produkttechnik GmbH & Co KG + 00a3 A3/200 or A3/300 Label Printer +098c Vitana Corp. +098d INDesign +098e Integrated Intellectual Property, Inc. +098f Kenwood TMI Corp. +0993 Gemstar eBook Group, Ltd + 0001 REB1100 eBook Reader +0996 Integrated Telecom Express, Inc. +099a Zippy Technology Corp. + 610c EL-610 Super Mini Electron luminescent Keyboard +09a3 PairGain Technologies +09a4 Contech Research, Inc. +09a5 VCON Telecommunications +09a6 Poinchips +09a7 Data Transmission Network Corp. +09a8 Lin Shiung Enterprise Co., Ltd +09a9 Smart Card Technologies Co., Ltd +09aa Intersil Corp. + 1000 Prism GT 802.11b/g Adapter + 3642 Prism 2.x 802.11b Adapter +09ae Tripp Lite +09b2 Franklin Electronic Publishers, Inc. + 0001 eBookman Palm Computer +09b3 Altius Solutions, Inc. +09b4 MDS Telephone Systems +09b5 Celltrix Technology Co., Ltd +09bc Grundig + 0002 MPaxx MP150 MP3 Player +09be MySmart.Com + 0001 MySmartPad +09bf Auerswald GmbH & Co. KG + 00c0 COMpact 2104 ISDN PBX + 00db COMpact 4410/2206 ISDN ISDN + 00f1 COMfort System Telephones +09c1 Arris Interactive LLC +09c2 Nisca Corp. +09c3 ActivCard, Inc. + 0008 SmartCard Reader +09c4 ACTiSYS Corp. + 0011 ACT-IR2000U IrDA Dongle +09c5 Memory Corp. +09cc Workbit Corp. +09cd Psion Dacom Home Networks, Ltd +09ce City Electronics, Ltd +09cf Electronics Testing Center, Taiwan +09d1 NeoMagic, Inc. +09d2 Vreelin Engineering, Inc. +09d3 Com One + 0001 ISDN TA +09d9 KRF Tech, Ltd +09da A4 Tech Co., Ltd + 0006 Optical Mouse WOP-35 / Trust 450L Optical Mouse + 001a Wireless Mouse & RXM-15 Receiver + 002a Wireless Optical Mouse NB-30 +09db Measurement Computing Corp. + 0075 MiniLab 1008 + 0076 PMD-1024 + 007A PMD-1208LS +09dc Aimex Corp. +09dd Fellowes, Inc. +09df Addonics Technologies Corp. +09e1 Intellon Corp. +09e5 Jo-Dan International, Inc. +09e6 Silutia, Inc. +09e7 Real 3D, Inc. +09e8 AKAI Professional M.I. Corp. +09e9 Chen-Source, Inc. +09eb IM Networks, Inc. + 4331 iRhythm Tuner Remote +09ef Xitel + 0101 MD-Port DG2 MiniDisc Interface +09f5 AresCom +09f6 RocketChips, Inc. +09f7 Edu-Science (H.K.), Ltd +09f8 SoftConnex Technologies, Inc. +09f9 Bay Associates +09fa Mtek Vision +09fb Altera +09ff Gain Technology Corp. +0a00 Liquid Audio +0a01 ViA, Inc. +0a07 Ontrak Control Systems Inc. + 0064 ADU100 Data Acquisition Interface + 00c8 ADU200 Relay I/O Interface + 00d0 ADU208 Data Acquisition Interface +0a0b Cybex Computer Products Co. +0a11 Xentec, Inc. +0a12 Cambridge Silicon Radio, Ltd + 0001 Bluetooth Dongle (HCI mode) + 1000 Bluetooth Dongle (HID proxy mode) +0a13 Telebyte, Inc. +0a14 Spacelabs Medical, Inc. +0a15 Scalar Corp. +0a16 Trek Technology (S) PTE, Ltd + 9988 Trek2000 TD-G2 +0a17 Pentax Corp. + 0004 Pentax Optio 330 + 0006 Pentax Optio S + 0007 Pentax Optio 550 + 003d Pentax Optio S55 +0a18 Heidelberger Druckmaschinen AG +0a19 Hua Geng Technologies, Inc. +0a21 Medtronic Physio Control Corp. +0a22 Century Semiconductor USA, Inc. +0a2c AK-Modul-Bus Computer GmbH + 0008 GPIO Ports +0a39 Gilat Satellite Networks, Ltd +0a3a PentaMedia Co., Ltd +0a3c NTT DoCoMo, Inc. +0a3d Varo Vision +0a3f Swissonic AG +0a43 Boca Systems, Inc. +0a46 Davicom Semiconductor, Inc. +0a47 Hirose Electric +0a48 I/O Interconnect + 3258 Dane Elec zMate SD Reader + 3259 Dane Elec zMate CF Reader +0a4b Fujitsu Media Devices, Ltd +0a4c Computex Co., Ltd +0a4d Evolution Electronics, Ltd + 008e MK-249C MIDI Keyboard + 00a3 MK-461C MIDI Keyboard + 00f5 UC-33e MIDI Controller +0a4e Steinberg Soft-und Hardware GmbH +0a4f Litton Systems, Inc. +0a50 Mimaki Engineering Co., Ltd +0a51 Sony Electronics, Inc. +0a52 Jebsee Electronics Co., Ltd +0a53 Portable Peripheral Co., Ltd +0a5a Electronics For Imaging, Inc. +0a5b EAsics NV +0a5c Broadcom Corp. + 2033 BCM2033 Bluetooth + 2035 BCM2035 Bluetooth +0a5d Diatrend Corp. +0a5f Zebra + 0009 LP2844 Printer +0a62 MPMan + 0010 MPMan MP-F40 MP3 Player +0a66 ClearCube Technology +0a67 Medeli Electronics Co., Ltd +0a68 Comaide Corp. +0a69 Chroma ate, Inc. +0a6b Green House Co., Ltd + 0001 Compact Flash R/W with MP3 player +0a6c Integrated Circuit Systems, Inc. +0a6d UPS Manufacturing +0a6e Benwin +0a6f Core Technology, Inc. + 0400 Xanboo +0a70 International Game Technology +0a72 Sanwa Denshi +0a7d NSTL, Inc. +0a7e Octagon Systems Corp. +0a80 Rexon Technology Corp., Ltd +0a81 Chesen Electronics Corp. + 0101 Keyboard + 0103 Keyboard + 0203 Mouse + 0205 PS/2 Keyboard+Mouse Adapter +0a82 Syscan + 4600 TravelScan 460/464 +0a83 NextComm, Inc. +0a84 Maui Innovative Peripherals +0a85 Idexx Labs +0a86 NITGen Co., Ltd +0a8d Picturetel +0a8e Japan Aviation Electronics Industry, Ltd +0a90 Candy Technology Co., Ltd +0a91 Globlink Technology, Inc. +0a92 EGO SYStems, Inc. +0a93 C Technologies AB +0a94 Intersense +0aa3 Lava Computer Mfg., Inc. +0aa4 Develco Elektronik +0aa5 First International Digital +0aa6 Perception Digital, Ltd + 0101 Hercules Jukebox +0aa7 Wincor Nixdorf GmbH & Co KG + 0200 POS Display BA63 + 0201 POS Display BA66 + 0300 POS Printer TH210 + 0302 POS Printer TH220 + 0305 Lottery Printer XiPrintPlus + 0306 POS Printer TH320 + 0308 POS Printer TH420 + 4304 Banking Printer TP07 +0aa8 TriGem Computer, Inc. +0aa9 Baromtec Co. + f01b Medion MD 6242 MP3 Player +0aaa Japan CBM Corp. +0aab Vision Shape Europe SA +0aac iCompression, Inc. +0aad Rohde & Schwarz GmbH & Co. KG +0aae NEC infrontia Corp. (Nitsuko) +0aaf Digitalway Co., Ltd +0ab0 Arrow Strong Electronics Co., Ltd +0aba Ellisys + 8001 USB Tracker 110 Protocol Analyzer +0abe Stereo-Link + 0101 SL1200 DAC +0ac3 Sanyo Semiconductor Company Micro +0ac4 Leco Corp. +0ac5 I & C Corp. +0ac6 Singing Electrons, Inc. +0ac7 Panwest Corp. +0ac8 Z-Star Microelectronics Corp. + 0302 ZC0302 WebCam + 301b ZC0301 WebCam + 303b ZC0303 WebCam +0ac9 Micro Solutions, Inc. + 0000 Backpack CD-ReWriter + 0011 Backpack 40GB Hard Drive +0acc Koga Electronics Co. +0acd ID Tech +0ace ZyDAS + 1201 802.11b WiFi + 1211 802.11b/g USB2 WiFi +0acf Intoto, Inc. +0ad0 Intellix Corp. +0ad1 Remotec Technology, Ltd +0ad2 Service & Quality Technology Co., Ltd +0ae3 Allion Computer, Inc. +0ae4 Taito Corp. +0ae7 Neodym Systems, Inc. +0ae8 System Support Co., Ltd +0ae9 North Shore Circuit Design L.L.P. +0aea SciEssence, LLC +0aeb TTP Communications, Ltd +0aec Neodio Technologies Corp. + 3050 ND3050 8-in-1 Card Reader + 3260 7-in-1 Card Reader + 5010 ND5010 Card Reader +0af0 Option + 5000 UMTS Card +0af6 Silver I Co., Ltd +0af7 B2C2, Inc. + 0101 Digital TV USB Receiver (DVB-S/T/C / ATSC) +0af9 Hama, Inc. + 0010 USB SightCam 100 + 0011 Micro Innovations IC50C WebCam +0afc Zaptronix Ltd +0afd Tateno Dennou, Inc. +0afe Cummins Engine Co. +0aff Jump Zone Network Products, Inc. +0b05 ASUSTek Computer, Inc. +0b0c Todos Data System AB + 0009 Todos Argos Mini II Smart Card Reader +0b0e GN Netcom +0b0f AVID Technology +0b10 Pcally +0b11 I Tech Solutions Co., Ltd +0b1e Electronic Warfare Assoc., Inc. (EWA) +0b1f Insyde Software Corp. +0b20 TransDimension, Inc. +0b21 Yokogawa Electric Corp. +0b22 Japan System Development Co., Ltd +0b23 Pan-Asia Electronics Co., Ltd +0b24 Link Evolution Corp. +0b27 Ritek Corp. +0b28 Kenwood Corp. +0b2c Village Center, Inc. +0b30 PNY Technologies, Inc. + 0006 SM Media-Shuttle Card Reader +0b33 Contour Design, Inc. +0b37 Hitachi ULSI Systems Co., Ltd +0b39 Omnidirectional Control Technology, Inc. +0b3a IPaxess +0b3b Tekram Technology Co., Ltd + 1601 Allnet 0193 802.11b Adapter + 1602 ZyXEL ZyAIR B200 802.11b Adapter + 1612 AIR.Mate 2@net 802.11b Adapter +0b3c Olivetti Techcenter +0b3e Kikusui Electronics Corp. +0b41 Hal Corp. +0b43 Play.com, Inc. + 0003 PS2 Controller Converter +0b47 Sportbug.com, Inc. +0b48 TechnoTrend AG + 1003 Technotrend/Hauppauge USB-Nova + 1005 Technotrend/Hauppauge USB-Nova + 1006 Technotrend/Hauppauge DEC3000-s + 1008 Technotrend/Hauppauge DEC2000-t + 1009 Technotrend/Hauppauge DEC2540-t +0b49 ASCII Corp. + 064f Trance Vibrator +0b4b Pine Corp. Ltd. + 0100 D'music MP3 Player +0b4e Musical Electronics, Ltd +0b50 Dumpries Co., Ltd +0b51 Comfort Keyboard Co. + 0020 Comfort Keyboard +0b52 Colorado MicroDisplay, Inc. +0b54 Sinbon Electronics Co., Ltd +0b56 TYI Systems, Ltd +0b57 Beijing HanwangTechnology Co., Ltd +0b59 Lake Communications, Ltd +0b5a Corel Corp. +0b5f Green Electronics Co., Ltd +0b60 Nsine, Ltd +0b61 NEC Viewtechnology, Ltd +0b62 Orange Micro, Inc. + 0059 iBOT2 WebCam +0b63 ADLink Technology, Inc. +0b64 Wonderful Wire Cable Co., Ltd +0b65 Expert Magnetics Corp. +0b69 CacheVision +0b6a Maxim Integrated Products +0b6f Nagano Japan Radio Co., Ltd +0b70 PortalPlayer, Inc. +0b71 SHIN-EI Sangyo Co., Ltd +0b72 Embedded Wireless Technology Co., Ltd +0b73 Computone Corp. +0b75 Roland DG Corp. +0b79 Sunrise Telecom, Inc. +0b7a Zeevo, Inc. +0b7b Taiko Denki Co., Ltd +0b7c ITRAN Communications, Ltd +0b7d Astrodesign, Inc. +0b84 Rextron Technology, Inc. +0b85 Elkat Electronics, Sdn., Bhd. +0b86 Exputer Systems, Inc. +0b87 Plus-One I & T, Inc. +0b88 Sigma Koki Co., Ltd, Technology Center +0b89 Advanced Digital Broadcast, Ltd +0b95 ASIX Electronics Corp. +0b96 Sewon Telecom +0b97 O2 Micro, Inc. + 7762 Oz776 SmartCard Reader +0b98 Playmates Toys, Inc. +0b99 Audio International, Inc. +0b9b Dipl.-Ing. Stefan Kunde + 4012 Reflex RC-controller Interface +0b9d Softprotec Co. +0b9f Chippo Technologies +0baf U.S. Robotics + 00eb USR1120 802.11b Adapter + 0118 U5 802.11g Adapter + 6112 FaxModem Model 5633 +0bb0 Concord Camera Corp. +0bb1 Infinilink Corp. +0bb2 Ambit Microsystems Corp. + 6098 USB Cable Modem +0bb3 Ofuji Technology +0bb4 High Tech Computer Corp. + 00ce mmO2 XDA GSM/GPRS Pocket PC + 00cf SPV C500 Smart Phone + 0a02 Himalaya GSM/GPRS Pocket PC + 0a51 SPV C400 / T-Mobile SDA GSM/GPRS Pocket PC +0bb5 Murata Manufacturing Co., Ltd +0bb6 Network Alchemy +0bb7 Joytech Computer Co., Ltd +0bb8 Hitachi Semiconductor and Devices Sales Co., Ltd +0bb9 Eiger M&C Co., Ltd +0bba ZAccess Systems +0bbb General Meters Corp. +0bbc Assistive Technology, Inc. +0bbd System Connection, Inc. +0bc0 Knilink Technology, Inc. +0bc1 Fuw Yng Electronics Co., Ltd +0bc2 Seagate RSS LLC +0bc3 IPWireless, Inc. +0bc4 Microcube Corp. +0bc5 JCN Co., Ltd +0bc6 ExWAY, Inc. +0bc7 X10 Wireless Technology, Inc. + 0004 X10 Receiver +0bc8 Telmax Communications +0bc9 ECI Telecom, Ltd +0bca Startek Engineering, Inc. +0bcb Perfect Technic Enterprise Co., Ltd +0bda Realtek Semiconductor Corp. + 8150 RTL8150 Fast Ethernet Adapter + 8151 RTL8151 Adapteon Business Mobile Networks BV +0bdb Ericsson Business Mobile Networks BV +0bdc Y Media Corp. +0bdd Orange PCS +0be2 Kanda Tsushin Kogyo Co., Ltd +0be3 TOYO Corp. +0be4 Elka International, Ltd +0be5 DOME imaging systems, Inc. +0be6 Dong Guan Humen Wonderful Wire Cable Factory +0bee LTK Industries, Ltd +0bef Way2Call Communications +0bf0 Pace Micro Technology PLC +0bf1 Intracom S.A. +0bf2 Konexx +0bf6 Addonics Technologies, Inc. + a002 IDE Bridge +0bf7 Sunny Giken, Inc. +0bf8 Fujitsu Siemens Computers + 1001 Fujitsu Pocket Loox 600 PDA +0c04 MOTO Development Group, Inc. +0c05 Appian Graphics +0c06 Hasbro Games, Inc. +0c07 Infinite Data Storage, Ltd +0c08 Agate + 0378 Q 16MB Storage Device +0c09 Comjet Information System +0c0a Highpoint Technologies, Inc. +0c0b Dura Micro, Inc. (Acomdata) + 27cb 6-in-1 Flash Reader and Writer + a109 CF/SM Reader and Writer + a10c SD/MS Reader and Writer + b004 MMC/SD Reader and Writer +0c12 Zeroplus + 0005 PSX Vibration Feedback Converter + 8809 Red Octane Ignition Xbox DDR Pad +0c15 Iris Graphics +0c16 Gyration, Inc. +0c17 Cyberboard A/S +0c18 SynerTek Korea, Inc. +0c19 cyberPIXIE, Inc. +0c1a Silicon Motion, Inc. +0c1b MIPS Technologies +0c1c Hang Zhou Silan Electronics Co., Ltd +0c22 Tally Printer Corp. +0c23 Lernout + Hauspie +0c24 Taiyo Yuden +0c25 Sampo Corp. +0c2e Metro + 0200 Metrologic Scanner +0c35 Eagletron, Inc. +0c36 E Ink Corp. +0c37 e.Digital +0c38 Der An Electric Wire & Cable Co., Ltd +0c39 IFR +0c3a Furui Precise Component (Kunshan) Co., Ltd +0c3b Komatsu, Ltd +0c3c Radius Co., Ltd +0c3d Innocom, Inc. +0c3e Nextcell, Inc. +0c44 Motorola iDEN +0c45 Microdia + 1060 iFlash SM-Direct Card Reader + 6001 Genius VideoCAM NB + 6005 Sweex Mini WebCam + 6029 Triplex i-mini PC Camera + 602a Meade ETX-105EC Camera + 602c Clas Ohlson TWC-30XOP WebCam +0c46 WaveRider Communications, Inc. +0c4b Reiner SCT Kartensysteme GmbH + 0100 cyberJack e-com/pinpad + 0300 cyberJack pinpad(a) +0c52 Sealevel Systems, Inc. +0c53 ViewPLUS, Inc. +0c54 Glory, Ltd +0c55 Spectrum Digital, Inc. + 0510 Spectrum Digital XDS510 JTAG Debugger +0c56 Billion Bright, Ltd +0c57 Imaginative Design Operation Co., Ltd +0c58 Vidar Systems Corp. +0c59 Dong Guan Shinko Wire Co., Ltd +0c5a TRS International Mfg., Inc. +0c5e Xytronix Research & Design +0c62 Chant Sincere Co., Ltd +0c63 Toko, Inc. +0c64 Signality System Engineering Co., Ltd +0c65 Eminence Enterprise Co., Ltd +0c66 Rexon Electronics Corp. +0c67 Concept Telecom, Ltd +0c70 MCT Elektronikladen + 0000 USB08 Development board +0c74 Optronic Laboratories Inc. + 0002 OL 700-30 Goniometer +0c76 JMTek, LLC. + 0003 USBdisk + 0005 USBdisk + 0006 Transcend JetFlash +0c77 Sipix Group, Ltd +0c78 Detto Corp. +0c79 NuConnex Technologies Pte., Ltd +0c7a Wing-Span Enterprise Co., Ltd +0c86 NDA Technologies, Inc. +0c88 Kyocera Wireless Corp. +0c89 Honda Tsushin Kogyo Co., Ltd +0c8a Pathway Connectivity, Inc. +0c8b Wavefly Corp. +0c8c Coactive Networks +0c8d Tempo +0c8e Cesscom Co., Ltd +0c8f Applied Microsystems +0c99 Innochips Co., Ltd +0c9a Hanwool Robotics Corp. +0c9b Jobin Yvon, Inc. +0ca2 Zyfer +0ca3 Sega Corp. +0ca4 ST&T Instrument Corp. +0ca5 BAE Systems Canada, Inc. +0ca6 Castles Technology Co., Ltd +0ca7 Information Systems Laboratories +0cad Motorola CGISS +0cae Ascom Business Systems, Ltd +0caf Buslink + 2515 Flash Disk Embedded Hub + 2516 Flash Disk Security Device + 2517 Flash Disk Mass Storage Device + 3a00 Hard Drive +0cb0 Flying Pig Systems +0cb1 Innovonics, Inc. +0cb6 Celestix Networks, Pte., Ltd +0cb7 Singatron Enterprise Co., Ltd +0cb8 Opticis Co., Ltd +0cba Trust Electronic (Shanghai) Co., Ltd +0cbb Shanghai Darong Electronics Co., Ltd +0cbc Palmax Technology Co., Ltd +0cbd Pentel Co., Ltd (Electronics Equipment Div.) +0cbe Keryx Technologies, Inc. +0cbf Union Genius Computer Co., Ltd +0cc0 Kuon Yi Industrial Corp. +0cc1 Given Imaging, Ltd +0cc2 Timex Corp. +0cc3 Rimage Corp. +0cc4 emsys GmbH +0cc5 Sendo +0cc6 Intermagic Corp. +0cc7 Kontron Medical AG +0cc8 Technotools Corp. +0cc9 BroadMAX Technologies, Inc. +0cca Amphenol +0ccb SKNet Co., Ltd +0ccc Domex Technology Corp. +0ccd TerraTec Electronic GmbH + 0038 Cinergy T^2 DVB-T Receiver +0cd4 Bang Olufsen + 0101 BeolinkPC2 +0cd7 NewChip S.r.l. +0cd8 JS Digitech, Inc. +0cd9 Hitachi Shin Din Cable, Ltd +0cde Z-Com + 0002 XI-725/726 Prism2.5 802.11b Adapter + 0005 XI-735 Prism3 802.11b Adapter + 0006 Medion 40900 802.11b Adapter +0cf1 e-Conn Electronic Co., Ltd +0cf2 ENE Technology, Inc. +0cf3 Atheros Communications, Inc. +0cf4 Fomtex Corp. +0cf5 Cellink Co., Ltd +0cf6 Compucable Corp. +0cf7 ishoni Networks +0cf8 Clarisys, Inc. +0cf9 Central System Research Co., Ltd +0cfa Inviso, Inc. +0cfc Minolta-QMS, Inc. +0d06 telos EDV Systementwicklung GmbH +0d0b Contemporary Controls +0d0c Astron Electronics Co., Ltd +0d0d MKNet Corp. +0d0e Hybrid Networks, Inc. +0d0f Feng Shin Cable Co., Ltd +0d10 Elastic Networks +0d11 Maspro Denkoh Corp. +0d12 Hansol Electronics, Inc. +0d13 BMF Corp. +0d14 Array Comm, Inc. +0d15 OnStream b.v. +0d16 Hi-Touch Imaging Technologies Co., Ltd +0d17 NALTEC, Inc. +0d18 coaXmedia +0d19 Hank Connection Industrial Co., Ltd +0d32 Leo Hui Electric Wire & Cable Co., Ltd +0d33 AirSpeak, Inc. +0d34 Rearden Steel Technologies +0d35 Dah Kun Co., Ltd +0d3c Sri Cable Technology, Ltd +0d3d Tangtop Technology Co., Ltd +0d3e Fitcom, inc. +0d3f MTS Systems Corp. +0d40 Ascor, Inc. +0d41 Ta Yun Terminals Industrial Co., Ltd +0d42 Full Der Co., Ltd +0d46 Kobil Systems GmbH + 3003 mIDentity Light / KAAN SIM III + 4000 mIDentity (mass storage) + 4001 mIDentity Basic/Classic (composite device) + 4081 mIDentity Basic/Classic (installationless) +0d49 Maxtor +0d4a NF Corp. +0d4b Grape Systems, Inc. +0d4c Tedas AG +0d4d Coherent, Inc. +0d4e Agere Systems Netherland BV +0d4f EADS Airbus France +0d50 Cleware GmbH + 0011 USB-Temp2 Thermometer +0d51 Volex (Asia) Pte., Ltd +0d53 HMI Co., Ltd +0d54 Holon Corp. +0d55 ASKA Technologies, Inc. +0d56 AVLAB Technology, Inc. +0d57 Solomon Microtech, Ltd +0d5c Belkin + a002 F5D6050 802.11b Adapter +0d5e Myacom, Ltd +0d5f CSI, Inc. +0d60 IVL Technologies, Ltd +0d61 Meilu Electronics (Shenzhen) Co., Ltd +0d62 Darfon Electronics Corp. + a100 Benq Mouse +0d63 Fritz Gegauf AG +0d64 DXG Technology Corp. + 0107 Horus MT-409 Camera + 0303 DXG-305V Camera +0d65 KMJP Co., Ltd +0d66 TMT +0d67 Advanet, Inc. +0d68 Super Link Electronics Co., Ltd +0d69 NSI +0d6a Megapower International Corp. +0d6b And-Or Logic +0d70 Try Computer Co., Ltd +0d71 Hirakawa Hewtech Corp. +0d72 Winmate Communication, Inc. +0d73 Hit's Communications, Inc. +0d76 MFP Korea, Inc. +0d77 Power Sentry/Newpoint +0d78 Japan Distributor Corp. +0d7a MARX Datentechnik GmbH +0d7b Wellco Technology Co., Ltd +0d7c Taiwan Line Tek Electronic Co., Ltd +0d7d Phison Electronics Corp. + 0100 PS1001/1011/1006/1026 Flash Disk + 0110 Gigabyte FlexDrive + 0240 I/O-Magic/Transcend 6-in-1 Card Reader + 110E NEC uPD720121/130 USB-ATA/ATAPI Bridge + 1240 Apacer 6-in-1 Card Reader 2.0 + 1300 Flash Disk + 1320 PS2031 Flash Disk + 1420 PS2044 Pen Drive + 1470 Vosonic X's-Drive II+ VP2160 +0d7e American Computer & Digital Components +0d7f Essential Reality LLC +0d80 H.R. Silvine Electronics, Inc. +0d81 TechnoVision +0d83 Think Outside, Inc. +0d89 Oz Software +0d8a King Jim Co., Ltd +0d8b Ascom Telecommunications, Ltd +0d8c C-Media Electronics, Inc. + 000c Audio Adapter +0d8d Promotion & Display Technology, Ltd +0d8e Global Sun Technology, Inc. + 7100 802.11b Adapter + 7a01 PRISM25 802.11b Adapter +0d8f Pitney Bowes +0d90 Sure-Fire Electrical Corp. +0d96 Skanhex Technology, Inc. + 3300 SX330z Camera + 4100 SX410z Camera + 4102 MD 9700 Camera + 5200 SX-520z Camera +0d97 Santa Barbara Instrument Group + 0001 SBIG Astronomy Camera (without firmware) + 0101 SBIG Astronomy Camera (with firmware) +0d98 Mars Semiconductor Corp. +0d99 Trazer Technologies, Inc. +0d9a RTX Telecom AS +0d9b Tat Shing Electrical Co. +0d9c Chee Chen Hi-Technology Co., Ltd +0d9d Sanwa Supply, Inc. +0d9e Avaya +0d9f Powercom Co., Ltd +0da0 Danger Research +0da1 Suzhou Peter's Precise Industrial Co., Ltd +0da2 Land Instruments International, Ltd +0da3 Nippon Electro-Sensory Devices Corp. +0da4 Polar Electro OY +0da7 IOGear, Inc. +0da8 softDSP Co., Ltd + 0001 SDS 200A Oscilloscope +0dab Cubig Group + 0100 DVR/CVR-M140 MP3 Player +0dad Westover Scientific +0db0 Micro Star International + 1967 Bluetooth Dongle + 4011 Medion Flash XL V2.0 Card Reader + 697a Bluetooth Dongle + 6982 Medion Flash XL V2.7A Card Reader +0db1 Wen Te Electronics Co., Ltd +0db2 Shian Hwi Plug Parts, Plastic Factory +0db3 Tekram Technology Co., Ltd +0db4 Chung Fu Chen Yeh Enterprise Corp. +0dbe Jiuh Shiuh Precision Industry Co., Ltd +0dbf Quik Tech Solutions +0dc0 Great Notions +0dc1 Tamagawa Seiki Co., Ltd +0dc3 Athena Smartcard Solutions, Inc. +0dc4 Macpower Peripherals, Ltd +0dc5 SDK Co., Ltd +0dc6 Precision Squared Technology Corp. +0dc7 First Cable Line, Inc. +0dcd NetworkFab Corp. + 0001 Remote Interface Adapter + 0002 High Bandwidth Codec +0dd0 Access Solutions + 1002 Triple Talk Speech Synthesizer +0dd1 Contek Electronics Co., Ltd +0dd2 Power Quotient International Co., Ltd +0dd3 MediaQ +0dd4 Custom Engineering SPA +0dd5 California Micro Devices +0dd7 Kocom Co., Ltd +0dd8 Netac Technology Co., Ltd + e007 OnlyDisk U222 Pendrive +0dd9 HighSpeed Surfing +0dda Integrated Circuit Solution, Inc. +0ddb Tamarack, Inc. +0ddd Datelink Technology Co., Ltd +0dde Ubicom, Inc. +0de0 BD Consumer Healthcare +0ded Novasonics +0dee Lifetime Memory Products +0def Full Rise Electronic Co., Ltd +0df6 Sitecom Europe B.V. + 9071 zd1211 802.11g Adapter +0df7 Mobile Action Technology, Inc. + 0620 MA-620 Infrared Adapter + 0700 MA-700 Bluetooth Adapter +0dfa Toyo Communication Equipment Co., Ltd +0dfc GeneralTouch Technology Co., Ltd + 0001 Touchscreen +0e03 Nippon Systemware Co., Ltd +0e08 Winbest Technology Co., Ltd +0e0c Gesytec + 0101 LonUSB LonTalk Network Adapter +0e16 JMTek, LLC +0e17 Walex Electronic, Ltd +0e1b Crewave +0e21 Cowon Systems, Inc. + 0300 iAudio CW200 +0e23 Liou Yuane Enterprise Co., Ltd +0e25 VinChip Systems, Inc. +0e26 J-Phone East Co., Ltd +0e30 HeartMath LLC +0e34 Micro Computer Control Corp. +0e35 3Pea Technologies, Inc. +0e36 TiePie engineering +0e38 Stratitec, Inc. +0e39 Smart Modular Technologies, Inc. +0e3a Neostar Technology Co., Ltd + 1100 CW-1100 Wireless Network Adapter +0e3b Mansella, Ltd +0e41 Line6, Inc. + 4250 BassPODxt + 4252 BassPODxt Pro + 4642 BassPODxt Live + 4650 PODxt Live + 4750 GuitarPort + 5044 PODxt + 5050 PODxt Pro + 534D SeaMonkey +0e48 Julia Corp., Ltd + 0100 CardPro SmartCard Reader +0e4a Shenzhen Bao Hing Electric Wire & Cable Mfr. Co. +0e4c Radica Games, Ltd +0e55 Speed Dragon Multimedia, Ltd +0e5a Active Co., Ltd +0e5b Union Power Information Industrial Co., Ltd +0e5c Bitland Information Technology Co., Ltd +0e5d Neltron Industrial Co., Ltd +0e66 Hawking + 400c UF100 Ethernet [pegasus2] +0e67 Fossil, Inc. + 0002 Wrist PDA +0e6a Megawin Technology Co., Ltd +0e70 Tokyo Electronic Industry Co., Ltd +0e72 Hsi-Chin Electronics Co., Ltd +0e75 TVS Electronics, Ltd +0e7b On-Tech Industry Co., Ltd +0e7e Gmate, Inc. + 0001 Yopy 3000 PDA +0e82 Ching Tai Electric Wire & Cable Co., Ltd +0e8c Well Force Electronic Co., Ltd +0e90 WiebeTech, LLC +0e91 VTech Engineering Canada, Ltd +0e92 C's Glory Enterprise Co., Ltd +0e93 eM Technics Co., Ltd +0e95 Future Technology Co., Ltd +0e96 Aplux Communications, Ltd +0e97 Fingerworks, Inc. +0e98 Advanced Analogic Technologies, Inc. +0e99 Parallel Dice Co., Ltd +0e9a TA HSING Industries, Ltd +0e9b ADTEC Corp. +0e9c Streamzap, Inc. + 0000 Streamzap Remote Control +0e9f Tamura Corp. +0ea0 Ours Technology, Inc. + 2126 7-in-1 Card Reader + 2168 Transcend JetFlash 2.0 / Astone USB Drive + 6803 OTI-6803 Flash Disk + 6808 OTI-6808 Flash Disk + 6828 OTI-6828 Flash Disk +0ea6 Nihon Computer Co., Ltd +0ea7 MSL Enterprises Corp. +0ea8 CenDyne, Inc. +0ead Humax Co., Ltd +0eb1 WIS Technologies, Inc. +0eb2 Y-S Electronic Co., Ltd +0eb3 Saint Technology Corp. +0eb7 Endor AG +0ebe VWeb Corp. +0ebf Omega Technology of Taiwan, Inc. +0ec0 LHI Technology (China) Co., Ltd +0ec1 Abit Computer Corp. +0ec2 Sweetray Industrial, Ltd +0ec3 Axell Co., Ltd +0ec4 Ballracing Developments, Ltd +0ec5 GT Information System Co., Ltd +0ec6 InnoVISION Multimedia, Ltd +0ec7 Theta Link Corp. + 1008 So., Show 301 Digital Camera +0ecd Lite-On IT Corp. +0ece TaiSol Electronics Co., Ltd +0ecf Phogenix Imaging, LLC +0ed1 WinMaxGroup + 6660 USB Flash Disk 64M-C + 6680 USB Flash Disk 64M-B +0ed2 Kyoto Micro Computer Co., Ltd +0ed3 Wing-Tech Enterprise Co., Ltd +0eda Noriake Itron Corp. +0edf e-MDT Co., Ltd +0ee0 Shima Seiki Mfg., Ltd +0ee1 Sarotech Co., Ltd +0ee2 AMI Semiconductor, Inc. +0ee3 ComTrue Technology Corp. + 1000 Image Tank 1.5 +0ee4 Sunrich Technology, Ltd +0eee Digital Stream Technology, Inc. +0eef D-WAV Scientific Co., Ltd + 0001 eGalax TouchScreen +0ef0 Hitachi Cable, Ltd +0ef1 Aichi Micro Intelligent Corp. +0ef2 I/O Magic Corp. +0ef3 Lynn Products, Inc. +0ef4 DSI Datotech +0ef5 PointChips + 2202 Flash Disk +0ef6 Yield Microelectronics Corp. +0ef7 SM Tech Co., Ltd (Tulip) +0efe Wem Technology, Inc. +0efd Oasis Semiconductor +0f06 Visual Frontier Enterprise Co., Ltd +0f08 CSL Wire & Plug (Shen Zhen) Co. +0f0c CAS Corp. +0f0d Hori Co., Ltd +0f0e Energy Full Corp. +0f12 Mars Engineering Corp. +0f13 Acetek Technology Co., Ltd +0f19 Oracom Co., Ltd +0f1b Onset Computer Corp. +0f1c Funai Electric Co., Ltd +0f1d Iwill Corp. +0f21 IOI Technology Corp. +0f22 Senior Industries, Inc. +0f23 Leader Tech Manufacturer Co., Ltd +0f24 Flex-P Industries, Snd., Bhd. +0f2d ViPower, Inc. +0f2e Geniality Maple Technology Co., Ltd +0f2f Priva Design Services +0f30 Jess Technology Co., Ltd +0f31 Chrysalis Development +0f32 YFC-BonEagle Electric Co., Ltd +0f37 Kokuyo Co., Ltd +0f38 Nien-Yi Industrial Corp. +0f3d Airprime, Incorporated + 0112 CDMA 1xEVDO PC Card, PC 5220 +0f41 RDC Semiconductor Co., Ltd +0f42 Nital Consulting Services, Inc. +0f4b St. John Technology Co., Ltd +0f4c WorldWide Cable Opto Corp. +0f4d Microtune, Inc. + 1000 Bluetooth Dongle +0f4e Freedom Scientific +0f52 Wing Key Electrical Co., Ltd +0f53 Dongguan White Horse Cable Factory, Ltd +0f54 Kawai Musical Instruments Mfg. Co., Ltd +0f55 AmbiCom, Inc. +0f5c Prairiecomm, Inc. +0f5d NewAge International, LLC +0f5f Key Technology Corp. +0f60 NTK, Ltd +0f61 Varian, Inc. +0f62 Acrox Technologies Co., Ltd +0f68 Kobe Steel, Ltd +0f69 Dionex Corp. +0f6a Vibren Technologies, Inc. +0f73 DFI +0f7c DQ Technology, Inc. +0f7d NetBotz, Inc. +0f7e Fluke Corp. +0f88 VTech Holdings, Ltd +0f8b Yazaki Corp. +0f8c Young Generation International Corp. +0f8d Uniwill Computer Corp. +0f8e Kingnet Technology Co., Ltd +0f8f Soma Networks +0f97 CviLux Corp. +0f98 CyberBank Corp. +0f9c Hyun Won, Inc. + 0301 M-Any Premium DAH-610 MP3/WMA Player + 0332 mobiBLU DAH-1200 MP3/Ogg Player +0f9e Lucent Technologies +0fa3 Starconn Electronic Co., Ltd +0fa4 ATL Technology +0fa5 Sotec Co., Ltd +0fa7 Epox Computer Co., Ltd +0fa8 Logic Controls, Inc. +0faf Winpoint Electronic Corp. +0fb0 Haurtian Wire & Cable Co., Ltd +0fb1 Inclose Design, Inc. +0fb2 Juan-Chern Industrial Co., Ltd +0fb8 Wistron Corp. +0fb9 AACom Corp. +0fba San Shing Electronics Co., Ltd +0fbb Bitwise Systems, Inc. +0fc1 Mitac Internatinal Corp. +0fc2 Plug and Jack Industrial, Inc. +0fc5 Delcom Engineering + 1222 I/O Development Board +0fc6 Dataplus Supplies, Inc. +0fca Research In Motion, Ltd. + 0001 Blackberry Handheld +0fce Sony Ericsson Mobile Communications AB + d017 K608i Phone +0fcf Dynastream Innovations, Inc. +0fd0 Tulip Computers B.V. +0fd4 Tenovis GmbH & Co., KG +0fd5 Direct Access Technology, Inc. +0fdc Micro Plus +0fe4 IN-Tech Electronics, Ltd +0fe5 Greenconn (U.S.A.), Inc. +0fe9 DVICO + db00 FusionHDTV DVB-T (MT352+LgZ201) (uninitialized) + db01 FusionHDTV DVB-T (MT352+LgZ201) (initialized) + db10 FusionHDTV DVB-T (MT352+Thomson7579) (uninitialized) + db11 FusionHDTV DVB-T (MT352+Thomson7579) (initialized) +0fea United Computer Accessories +0feb CRS Electronic Co., Ltd +0fec UMC Electronics Co., Ltd +0fed Access Co., Ltd +0fee Xsido Corp. +0fef MJ Research, Inc. +0ff6 Core Valley Co., Ltd +0ff7 CHI SHING Computer Accessories Co., Ltd +0fff Aopen, Inc. +1000 Speed Tech Corp. +1001 Ritronics Components (S) Pte., Ltd +1003 Sigma Corp. +1004 LG Electronics, Inc. + 1fae U8120 3G Cellphone + 6000 VX4400/VX6000 Cellphone + 6800 CDMA Modem +1005 Apacer Technology, Inc. + b113 Handy Steno 2.0 (256MB) +1006 iRiver, Ltd. + 3002 iHP-100/120/140 MP3 Player +1009 Emuzed, Inc. +100a AV Chaseway, Ltd +100b Chou Chin Industrial Co., Ltd +100d Netopia, Inc. + 3342 Cayman 3352 DSL Modem + cb01 Cayman 3341 Ethernet DSL Router +1010 Fukuda Denshi Co., Ltd +1011 Mobile Media Tech. +1012 SDKM Fibres, Wires & Cables Berhad +1013 TST-Touchless Sensor Technology AG +1014 Densitron Technologies PLC +1015 Softronics Pty., Ltd +1016 Xiamen Hung's Enterprise Co., Ltd +1017 Speedy Industrial Supplies, Pte., Ltd +1020 Labtec + 000a Wireless Optical Mouse +1022 Shinko Shoji Co., Ltd +1025 Hyper-Paltek + 005e USB DVB-T device + 005f USB DVB-T device +1026 Newly Corp. +1027 Time Domain +1028 Inovys Corp. +1029 Atlantic Coast Telesys +102a Ramos Technology Co., Ltd +102b Infotronic America, Inc. +102c Etoms Electronics Corp. +102d Winic Corp. +1031 Comax Technology, Inc. +1032 C-One Technology Corp. +1033 Nucam Corp. +1038 Ideazon, Inc. + 0100 Zboard +1043 iCreate Technologies Corp. + 8006 Flash Disk 32 MB +1044 Chu Yuen Enterprise Co., Ltd +1046 Winbond Electronics Corp. [hex] + 9967 W9967CF/W9968CF WebCam IC +104c AMCO TEC International, Inc. +1053 Immanuel Electronics Co., Ltd +1054 BMS International Beheer N.V. +1055 Complex Micro Interconnection Co., Ltd +1056 Hsin Chen Ent Co., Ltd +1057 ON Semiconductor +1058 Western Digital Technologies, Inc. +1059 Giesecke & Devrient GmbH +105c Hong Ji Electric Wire & Cable (Dongguan) Co., Ltd +105d Delkin Devices, Inc. +105e Valence Semiconductor Design, Ltd +105f Chin Shong Enterprise Co., Ltd +1060 Easthome Industrial Co., Ltd +1063 Motorola Electronics Taiwan, Ltd [hex] + 1555 MC141555 Hub +1065 CCYU Technology + 2136 EasyDisk ED1064 +106a Loyal Legend, Ltd +106c Curitel Communications, Inc. + 2101 AudioVox 8900 Cell Phone +106d San Chieh Manufacturing, Ltd +106e ConectL +106f Money Controls +1076 GCT Semiconductor, Inc. +107d Arlec Australia, Ltd +107e Midoriya Electric Co., Ltd +107f KidzMouse, Inc. +1082 Shin-Etsukaken Co., Ltd +1083 Canon Electronics, Inc. +1084 Pantech Co., Ltd +108a Chloride Power Protection +108b Grand-tek Technology Co., Ltd +108c Robert Bosch GmbH +1099 Surface Optics Corp. +109a DATASOFT Systems GmbH +109f eSOL Co., Ltd +10a0 Hirotech, Inc. +10a3 Mitsubishi Materials Corp. +10a9 SK Teletech Co., Ltd +10aa Cables To Go +10ab USI Co., Ltd + 10c5 Sony-Ericsson / Samsung DataCable +10ac Honeywell, Inc. +10ae Princeton Technology Corp. +10b5 Comodo (PLX?) + 9060 Test Board +10b8 DiBcom + 0bb8 DiBcom USB DVB-T reference design (MOD300) (cold) + 0bb9 DiBcom USB DVB-T reference design (MOD300) (warm) + 0bc6 DiBcom USB2.0 DVB-T reference design (MOD3000P) (cold) + 0bc7 DiBcom USB2.0 DVB-T reference design (MOD3000P) (warm) +10bb TM Technology, Inc. +10bc Dinging Technology Co., Ltd +10bd TMT Technology, Inc. +10bf SmartHome + 0001 SmartHome PowerLinc +10c4 Cygnal Integrated Products, Inc. +10c5 Sanei Electric, Inc. +10c6 Intec, Inc. +10cb Eratech +10cc GBM Connector Co., Ltd +10cd Kycon, Inc. +10cf Velleman Components, Inc. + 5500 8055 Experiment Interface Board (address=0) + 5501 8055 Experiment Interface Board (address=1) + 5502 8055 Experiment Interface Board (address=2) + 5503 8055 Experiment Interface Board (address=3) +10d1 Hottinger Baldwin Measurement + 0101 USB-Module for Spider8, CP32 + 0202 CP22 - Communication Processor + 0301 CP42 - Communication Processor +10d4 Man Boon Manufactory, Ltd +10d5 Uni Class Technology Co., Ltd +10d6 Actions Semiconductor Co., Ltd + 1000 MP3 Player + 1100 MPMan MP-Ki 128 MP3 Player/Recorder +10de Authenex, Inc. +10df In-Win Development, Inc. +10e0 Post-Op Video, Inc. +10e1 CablePlus, Ltd +10e2 Nada Electronics, Ltd +10ec Vast Technologies, Inc. +10fb Pictos Technologies, Inc. +10fd Anubis Electronics, Ltd + 804d Typhoon Webshot II Webcam [zc0301] +1a0a ... + badd USB OTG Compliance test device +1100 VirTouch, Ltd + 0001 VTPlayer VTP-1 Braille Mouse +1101 EasyPass Industrial Co., Ltd + 0001 FSK Electronics Super GSM Reader +1108 Brightcom Technologies, Ltd +1110 Analog Devices Canada, Ltd (Allied Telesyn) + 900f AT-AR215 DSL Modem +1112 YM ELECTRIC CO., Ltd +1113 Medion AG +111e VSO Electric Co., Ltd +112e Master Hill Electric Wire and Cable Co., Ltd +112f Cellon International, Inc. +1130 Tenx Technology, Inc. +1131 Integrated System Solution Corp. + 1001 KY-BT100 Bluetooth Adapter +1132 Toshiba Corp., Digital Media Equipment [hex] + 4331 PDR-M4/M5/M70 Digital Camera + 4332 PDR-M60 Digital Camera +113c Arin Tech Co., Ltd +113d Mapower Electronics Co., Ltd +1141 V One Multimedia, Pte., Ltd +1142 CyberScan Technologies, Inc. +1147 Ever Great Electric Wire and Cable Co., Ltd +114c Tinius Olsen Testing Machine Co., Inc. +114d Alpha Imaging Technology Corp. +1162 Secugen Corp. +1163 DeLorme Publishing, Inc. +1164 YUAN High-Tech Development Co., Ltd +1165 Telson Electronics Co., Ltd +1166 Bantam Interactive Technologies +1167 Salient Systems Corp. +1168 BizConn International Corp. +116e Gigastorage Corp. +116f Silicon 10 Technology Corp. +1175 Shengyih Steel Mold Co., Ltd +117d Santa Electronic, Inc. +117e JNC, Inc. +1182 Venture Corp., Ltd +1183 Compaq Computer Corp. [hex] (Digital Dream ??) + 19c7 ISDN TA + 4008 56k FaxModem + 504a PJB-100 Personal Jukebox +1184 Kyocera Elco Corp. +118f You Yang Technology Co., Ltd +1190 Tripace +1191 Loyalty Founder Enterprise Co., Ltd +1196 Yankee Robotics, LLC + 0010 Trifid Camera without code + 0011 Trifid Camera +1197 Technoimagia Co., Ltd +1198 StarShine Technology Corp. +1199 Sierra Wireless, Inc. + 0112 CDMA 1xEVDO PC Card, AirCard 580 +119a ZHAN QI Technology Co., Ltd +119b ruwido austria GmbH + 0400 Infrared Keyboard V2.01 +11a0 Chipcon AS + eb11 CC2400EB 2.0 ZigBee Sniffer +11a3 Technovas Co., Ltd +11aa GlobalMedia Group, LLC +11ab Exito Electronics Co., Ltd +11db Topfield Co., Ltd. + 1000 PVR + 1100 PVR +11f5 Siemens AG (?) + 0003 Mobile phone USB cable +11f7 Alcatel (?) + 02df TD10 Mobile phone USB cable +1209 InterBiometrics + 1001 USB Hub + 1002 USB Relais + 1003 IBSecureCam-P + 1004 IBSecureCam-O + 1005 IBSecureCam-N +120e Hudson Soft Co., Ltd +121e Jungsoft Co., Ltd + 3403 Muzio JM250 Audio Player +1241 Belkin + 1111 Mouse + 1177 F8E842-DL Mouse +124a AirVast + 4017 PC-Chips 802.11b Adapter +124b Nyko (Honey Bee) + 4d01 Airflo EX Joystick +1267 Logic3 / SpectraVideo plc + 0201 A4Tech SWOP-3 Mouse + a001 JP260 PC Game Pad +126e Strobe Data, Inc. +126f TwinMOS + 1325 Mobile Disk + 2168 Mobile Disk III +1275 Xaxero Marine Software Engineering, Ltd. + 0002 WeatherFax 2000 Demodulator + 0080 SkyEye Weather Satellite Receiver +1292 Innomedia + 0258 Creative Labs VoIP Blaster +1293 Belkin Components [hex] + 0002 F5U002 Parallel Port [uss720] + 2101 104-key keyboard +12fd AIN Comm. Technology Co., Ltd + 1001 AWU2000b 802.11b Stick +1310 Roper + 0001 Class 1 Bluetooth Dongle +1312 ICS Electronics +131d Natural Point + 0155 TrackIR 3 Pro Head Tracker +132b Konica Minolta + 0000 Dimage A2 Camera + 0003 Dimage Xg Camera + 0006 Dimage Z2 Camera + 0008 Dimage X21 Camera + 000b Dimage Z10 Camera + 000d Dimage X50 Camera [storage?] + 000f Dimage X50 Camera [p2p?] + 0010 Dimage G600 Camera + 0012 Dimage Scan Elite5400 2 + 0013 Dimage X31 Camera + 0015 Dimage G530 Camera + 0017 Dimage Z3 Camera + 0019 Dimage A200 Camera + 0021 Dimage Z5 Camera +1342 Mobility + 0200 EasiDock 200 Hub + 0201 EasiDock 200 Keyboard and Mouse Port + 0202 EasiDock 200 Serial Port + 0203 EasiDock 200 Printer Port +134e Digby's Bitpile, Inc. DBA D Bit +1370 Swissbit + 6828 Victorinox Flash Drive +1398 Q-tec + 2103 USB 2.0 Storage Device +13b0 Alesis + 000a Photon X25 MIDI Controller +13b1 Linksys + 000b WUSB11 v4.0 802.11b Adapter + 0011 WUSB54GP v4.0 802.11g Adapter + 0018 USB200M 10/100 Ethernet Adapter +13d2 Shark Multimedia + 0400 Pocket Ethernet [klsi] +13d3 IMC Networks + 3201 VisionDTV USB-Ter/HAMA USB DVB-T device cold + 3202 VisionDTV USB-Ter/HAMA USB DVB-T device warm +1453 Radio Shack + 4026 26-183 Serial Cable +1462 Micro Star International + 5512 MegaStick-1 Flash Stick +147a Formosa Industrial Computing, Inc. +1484 Elsa AG [hex] + 1746 Ecomo 19H99 Monitor + 7616 Elsa Hub +148f Ralink Technology, Corp. + 2570 802.11g WiFi +14aa AVerMedia (again) or C&E + 0001 Avermedia AverTV DVBT USB1.1 (cold) + 0002 Avermedia AverTV DVBT USB1.1 (warm) + 0201 AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (cold) + 0221 AVermedia DVBT Tuner Dongle + 0301 AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (warm) +14c2 Gemlight Computer, Ltd +1518 Cheshire Engineering Corp. + 0001 HDReye High Dynamic Range Camera + 0002 HDReye (before firmware loads) +1520 Bitwire Corp. +152e LG (HLDS) + e001 GSA-5120D DVD-RW +1546 U-Blox AG +1554 Prolink Microsystems Corp. +1568 Sunf Pu Technology Co., Ltd +15c2 SoundGraph Inc. + ffdc iMON PAD Remote Controller +15c6 Laboratoires MXM +15e8 SohoWare + 9100 NUB100 Ethernet [pegasus] +15e9 Pacific Digital Corp. +15f4 HanfTek + 0001 HanfTek UMT-010 USB2.0 DVB-T (cold) + 0025 HanfTek UMT-010 USB2.0 DVB-T (warm) +1604 Tascam + 8000 US-428 Audio/Midi Controller (without fw) + 8001 US-428 Audio/Midi Controller + 8004 US-224 Audio/Midi Controller (without fw) + 8005 US-224 Audio/Midi Controller + 8006 US-122 Audio/Midi Interface (without fw) + 8007 US-122 Audio/Midi Interface +1606 Umax [hex] + 0010 Astra 1220U + 0030 Astra 2000U + 0060 Astra 3400U + 0130 Astra 2100U + 0160 Astra 5400U + 0230 Astra 2200/2200SU + 2020 AstraCam 1000 +1608 Inside Out Networks [hex] + 0001 EdgePort/4 Serial Port + 1403 MultiTech Systems MT4X56 Modem +1645 Entrega [hex] + 0001 1S Serial Port + 0002 2S Serial Port + 0003 1S25 Serial Port + 0004 4S Serial Port + 0005 E45 Ethernet [klsi] + 0006 Parallel Port + 0007 U1-SC25 SCSI + 0093 1S9 Serial Port + 8000 EZ-USB + 8002 2x Serial Port + 8093 PortGear Serial Port +1657 Struck Innovative Systeme GmbH + 3150 SIS3150 USB2.0 to VME interface +1668 Actiontec Electronics, Inc. [hex] + 0333 Modem + 0408 Prism2.5 802.11b Adapter + 0421 Prism2.5 802.11b Adapter + 0500 BTM200B BlueTooth Adapter +1690 Askey Computer Corp. [hex] + 0101 Creative Modem Blaster DE5670 + 0103 Askey 1456 VQE-R3 Modem [conexant] + 0109 Askey MagicXpress V.90 Pocket Modem [conexant] +1696 Hitachi Video and Information System, Inc. +1697 VTec Test, Inc. +1706 BlueView Technologies, Inc. +1733 Cellink Technology Co., Ltd + 0101 RF Wireless Optical Mouse OP-701 +17b3 Grey Innovation + 0004 Linux-USB Midi Gadget +17eb Cornice, Inc. +1822 Twinhan + 3201 VisionDTV USB-Ter/HAMA USB DVB-T device cold + 3202 VisionDTV USB-Ter/HAMA USB DVB-T device warm +185b Compro + d000 Compro Videomate DVB-U2000 - DVB-T USB cold + d001 Compro Videomate DVB-U2000 - DVB-T USB warm +1894 Topseed + 5632 Atek Tote Remote + 5641 TSAM-004 Presentation Remote +1977 T-Logic + 0111 TL203 MP3 Player and Voice Recorder +1995 Trillium Technology Pty. Ltd. + 3202 REC-ADPT-USB (recorder) + 3203 REC-A-ADPT-USB (recorder) +1ebb NuCORE Technology, Inc. +2001 D-Link Corp. [hex] + 3200 DWL-120 802.11b (Atmel RFMD503A) [usbvnetr] + 3700 DWL-122 802.11b + 3701 DWL-G120 Spinnaker 802.11b + 3703 DWL-122 802.11b + 3704 DWL-G122 802.11g rev. A2 + 3c00 DWL-G122 802.11g rev. B1 [ralink] + 4000 DSB-650C Ethernet [klsi] + 4001 DSB-650TX Ethernet [pegasus] + 4002 DSB-650TX Ethernet [pegasus] + 4003 DSB-650TX-PNA Ethernet [pegasus] + abc1 DSB-650 Ethernet [pegasus] + f013 DLink 7 port USB2.0 Hub + f10d Accent Communications Modem +2040 Hauppauge + 9300 Hauppauge WinTV NOVA-T USB2 (cold) + 9301 Hauppauge WinTV NOVA-T USB2 (warm) +2101 ActionStar + 0201 SIIG 4-to-2 Printer Switch +2162 Creative (?) + 500c DE5771 Modem Blaster +2222 MacAlly + 0004 iWebKey Keyboard +22b8 Motorola PCS + 0005 V.60c/V.60i GSM Phone + 1005 T280e GSM/GPRS Phone + 2821 T720 GSM Phone + 2822 V.120e GSM Phone + 3002 A835 GSM Phone + 3802 C330/A780 GSM Phone + 4002 A920/A925 UMTS Phone + 4810 E398 Storage + 4902 E398 GSM Phone + 600c A768i GSM Phone + 604c A780 GSM Phone (storage) + 6631 CDC Modem + 6604 Washington CDMA Phone +22b9 eTurboTouch Technology, Inc. +22ba Technology Innovation Holdings, Ltd +2304 Pinnacle Systems, Inc. [hex] + 0109 Pinnacle Studio PCTV USB (SECAM) + 0110 Pinnacle Studio PCTV USB (PAL) + 0111 Miro PCTV USB + 0112 Pinnacle Studio PCTV USB (NTSC) with FM radio + 0208 Pinnacle Studio PCTV USB2 + 0210 Pinnacle Studio PCTV USB (PAL) with FM radio + 0212 Pinnacle Studio PCTV USB (NTSC) + 0214 Pinnacle Studio PCTV USB (PAL) with FM radio + 0300 Pinnacle Studio Linx Video input cable (NTSC) + 0301 Pinnacle Studio Linx Video input cable (PAL) + 0419 Pinnacle PCTV Bungee USB (PAL) with FM radio +2318 Shining Technologies, Inc. [hex] + 0011 CitiDISK Jr. IDE Enclosure +2375 Digit@lway, Inc. + 0001 Digital Audio Player +2406 SANHO Digital Electronics Co., Ltd. + 6688 PD7X Portable Storage +2632 TwinMOS + 3209 7-in-1 Card Reader +2650 Electronics For Imaging, Inc. [hex] +2770 NHJ, Ltd + 9120 Che-ez! Snap / iClick Tiny VGA Digital Camera +2899 Toptronic Industrial Co., Ltd +2fb2 Fujitsu, Ltd +3125 Eagletron + 0001 TrackerPod Camera Stand +3176 Whanam Electronics Co., Ltd +3340 Yakumo + 0e3a Pocket PC 300 GPS SL +3504 Micro Star + f110 Security Key +3538 Power Quotient International Co., Ltd + 0001 Travel Flash + 0042 Cool Drive U339 Flash Disk +3579 DIVA + 6901 Media Reader +3636 InVibro +3838 WEM + 0001 5-in-1 Card Reader +3923 National Instruments Corp. + 703c USB-485 RS485 Cable +4102 iRiver, Ltd. + 1001 iFP-100 series mp3 player + 1003 iFP-300 series mp3 player + 1005 iFP-500 series mp3 player + 1007 iFP-700 series mp3/ogg vorbis player + 1008 iFP-800 series mp3/ogg vorbis player + 100A iFP-1000 series mp3/ogg vorbis player + 1101 iFP-100 series mp3 player (ums firmware) + 1103 iFP-300 series mp3 player (ums firmware) + 1105 iFP-500 series mp3 player (ums firmware) +413c Dell Computer Corp. + 1002 Keyboard Hub + 2002 SK-8125 Keyboard + 2100 SK-3106 Keyboard + 2101 SmartCard Reader Keyboard + 2500 DRAC4 Remote Access Card + 3010 Optical Wheel Mouse + 4001 Axim X5 + 4002 Axim X3 + 4003 Axim X30 + 8100 TrueMobile 1180 802.11b Adapter + 8103 Wireless 350 Bluetooth + a001 Hub + a700 Hub (in 1905FP LCD Monitor) +4242 USB Design by Example + 4201 Buttons and Lights HID device + 4220 Echo 1 Camera +4146 USBest Technology + 9281 Iomega Micro Mini 128MB Flash Drive + ba01 Intuix Flash Drive +4572 Shuttle, Inc. + 4572 Shuttle PN31 Remote +4586 Panram + 1026 Crystal Bar Flash Drive +4670 EMS Production + 9394 Game Cube USB Memory Adaptor 64M +5032 Grandtec + 0bb8 Grandtec USB1.1 DVB-T (cold) + 0bb9 Grandtec USB1.1 DVB-T (warm) + 0fa0 Grandtec USB1.1 DVB-T (cold) + 0fa1 Grandtec USB1.1 DVB-T (warm) +5041 Linksys (?) + 2234 WUSB54G 802.11g Adapter +544d Transmeta Corp. +5543 UC-Logic Technology Corp. + 0002 SuperPen WP3325U Tablet + 0004 Genius MousePen 5x4 Tablet +55aa OnSpec Electronic, Inc. + 1234 ATAPI Bridge + a103 Sandisk SDDR-55 SmartMedia Card Reader + b012 Mitsumi FA402M 8-in-2 Card Reader +636c CoreLogic, Inc. +6666 Prototype product Vendor ID + 0667 Smart Joy PSX, PS-PC Smart JoyPad +6993 Freshtel + b001 FT-102 VoIP USB Phone +6a75 Shanghai Jujo Electronics Co., Ltd +8086 Intel Corp. + 0110 Easy PC Camera + 0431 Intel Pro Video PC Camera + 0510 Digital Movie Creator + 0630 Pocket PC Camera + 07d3 BLOB boot loader firmware + 1111 PRO/Wireless 2011B 802.11b Adapter + 9890 82930 Test Board + c013 Wireless HID Station +8341 EGO Systems, Inc. + 2000 Flashdisk +9710 MosChip Semiconductor + 7705 Printer cable + 7715 Printer cable +c251 Keil Software, Inc. + 2710 ULink +eb1a eMPIA Technology, Inc. + 17de KWorld V-Stream XPERT DTV - DVB-T USB cold + 17df KWorld V-Stream XPERT DTV - DVB-T USB warm + 2710 SilverCrest WebCam + 2800 Terratec Cinergy 200 + 2801 GrabBeeX+ Video Encoder + +# List of known device classes, subclasses and protocols + +# Syntax: +# C class class_name +# subclass subclass_name <-- single tab +# protocol protocol_name <-- two tabs + +C 00 (Defined at Interface level) +C 01 Audio + 01 Control Device + 02 Streaming + 03 MIDI Streaming +C 02 Communications + 01 Direct Line + 02 Abstract (modem) + 00 None + 01 AT-commands (v.25ter) + 02 AT-commands (PCCA101) + 03 AT-commands (PCCA101 + wakeup) + 04 AT-commands (GSM) + 05 AT-commands (3G) + 06 AT-commands (CDMA) + fe Defined by command set descriptor + ff Vendor Specific (MSFT RNDIS?) + 03 Telephone + 04 Multi-Channel + 05 CAPI Control + 06 Ethernet Networking + 07 ATM Networking + 08 Wireless Handset Control + 09 Device Management + 0a Mobile Direct Line + 0b OBEX + 0c Ethernet Emulation + 07 Ethernet Emulation (EEM) +C 03 Human Interface Devices + 00 No Subclass + 00 None + 01 Keyboard + 02 Mouse + 01 Boot Interface Subclass + 00 None + 01 Keyboard + 02 Mouse +C 06 Imaging + 01 Still Image Capture + 01 Picture Transfer Protocol (PIMA 15470) +C 07 Printer + 01 Printer + 00 Reserved/Undefined + 01 Unidirectional + 02 Bidirectional + 03 IEEE 1284.4 compatible bidirectional + ff Vendor Specific +C 08 Mass Storage + 01 RBC (typically Flash) + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk (Zip) + 02 SFF-8020i, MMC-2 (ATAPI) + 03 QIC-157 + 04 Floppy (UFI) + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk (Zip) + 05 SFF-8070i + 06 SCSI + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk (Zip) +C 09 Hub + 00 Unused + 00 Full speed (or root) hub + 01 Single TT + 02 TT per port +C 0a CDC Data + 00 Unused + 30 I.430 ISDN BRI + 31 HDLC + 32 Transparent + 50 Q.921M + 51 Q.921 + 52 Q.921TM + 90 V.42bis + 91 Q.932 EuroISDN + 92 V.120 V.24 rate ISDN + 93 CAPI 2.0 + fd Host Based Driver + fe CDC PUF + ff Vendor specific +C 0b Chip/SmartCard +C 0d Content Security +C 0e Video + 00 Undefined + 01 Video Control + 02 Video Streaming + 03 Video Interface Collection +C dc Diagnostic + 01 Reprogrammable Diagnostics + 01 USB2 Compliance +C e0 Wireless + 01 Radio Frequency + 01 Bluetooth + 02 Ultra WideBand Radio Control + 03 RNDIS + 02 Wireless USB Wire Adapter + 01 Host Wire Adapter Control/Data Streaming + 02 Device Wire Adapter Control/Data Streaming + 03 Device Wire Adapter Isochronous Streaming +C ef Miscellaneous Device + 01 ? + 01 Microsoft ActiveSync + 02 Palm Sync + 02 Common Class + 01 Interface Association + 02 Wire Adapter Multifunction Peripheral + 03 ? + 01 Cable Based Association +C fe Application Specific Interface + 01 Device Firmware Update + 02 IRDA Bridge + 03 Test and Measurement + 01 TMC + 02 USB488 +C ff Vendor Specific Class + ff Vendor Specific Subclass + ff Vendor Specific Protocol + +# List of Audio Class Terminal Types + +# Syntax: +# AT terminal_type terminal_type_name + +AT 0100 USB Undefined +AT 0101 USB Streaming +AT 01ff USB Vendor Specific +AT 0200 Input Undefined +AT 0201 Microphone +AT 0202 Desktop Microphone +AT 0203 Personal Microphone +AT 0204 Omni-directional Microphone +AT 0205 Microphone Array +AT 0206 Processing Microphone Array +AT 0300 Output Undefined +AT 0301 Speaker +AT 0302 Headphones +AT 0303 Head Mounted Display Audio +AT 0304 Desktop Speaker +AT 0305 Room Speaker +AT 0306 Communication Speaker +AT 0307 Low Frequency Effects Speaker +AT 0400 Bidirectional Undefined +AT 0401 Handset +AT 0402 Headset +AT 0403 Speakerphone, no echo reduction +AT 0404 Echo-suppressing speakerphone +AT 0405 Echo-canceling speakerphone +AT 0500 Telephony Undefined +AT 0501 Phone line +AT 0502 Telephone +AT 0503 Down Line Phone +AT 0600 External Undefined +AT 0601 Analog Connector +AT 0602 Digital Audio Interface +AT 0603 Line Connector +AT 0604 Legacy Audio Connector +AT 0605 SPDIF interface +AT 0606 1394 DA stream +AT 0607 1394 DV stream soundtrack +AT 0700 Embedded Undefined +AT 0701 Level Calibration Noise Source +AT 0702 Equalization Noise +AT 0703 CD Player +AT 0704 DAT +AT 0705 DCC +AT 0706 MiniDisc +AT 0707 Analog Tape +AT 0708 Phonograph +AT 0709 VCR Audio +AT 070a Video Disc Audio +AT 070b DVD Audio +AT 070c TV Tuner Audio +AT 070d Satellite Receiver Audio +AT 070e Cable Tuner Audio +AT 070f DSS Audio +AT 0710 Radio Receiver +AT 0711 Radio Transmitter +AT 0712 Multitrack Recorder +AT 0713 Synthesizer + +# List of HID Descriptor Types + +# Syntax: +# HID descriptor_type descriptor_type_name + +HID 21 HID +HID 22 Report +HID 23 Physical + +# List of HID Descriptor Item Types +# Note: 2 bits LSB encode data length following + +# Syntax: +# R item_type item_type_name + +# Main Items +R 80 Input +R 90 Output +R b0 Feature +R a0 Collection +R c0 End Collection + +# Global Items +R 04 Usage Page +R 14 Logical Minimum +R 24 Logical Maximum +R 34 Physical Minimum +R 44 Physical Maximum +R 54 Unit Exponent +R 64 Unit +R 74 Report Size +R 84 Report ID +R 94 Report Count +R a4 Push +R b4 Pop + +# Local Items +R 08 Usage +R 18 Usage Minimum +R 28 Usage Maximum +R 38 Designator Index +R 48 Designator Minimum +R 58 Designator Maximum +R 78 String Index +R 88 String Minimum +R 98 String Maximum +R a8 Delimiter + +# List of Physical Descriptor Bias Types + +# Syntax: +# BIAS item_type item_type_name + +BIAS 0 Not Applicable +BIAS 1 Right Hand +BIAS 2 Left Hand +BIAS 3 Both Hands +BIAS 4 Either Hand + +# List of Physical Descriptor Item Types + +# Syntax: +# PHY item_type item_type_name + +PHY 00 None +PHY 01 Hand +PHY 02 Eyeball +PHY 03 Eyebrow +PHY 04 Eyelid +PHY 05 Ear +PHY 06 Nose +PHY 07 Mouth +PHY 08 Upper Lip +PHY 09 Lower Lip +PHY 0a Jaw +PHY 0b Neck +PHY 0c Upper Arm +PHY 0d Elbow +PHY 0e Forearm +PHY 0f Wrist +PHY 10 Palm +PHY 11 Thumb +PHY 12 Index Finger +PHY 13 Middle Finger +PHY 14 Ring Finger +PHY 15 Little Finger +PHY 16 Head +PHY 17 Shoulder +PHY 18 Hip +PHY 19 Waist +PHY 1a Thigh +PHY 1b Knee +PHY 1c calf +PHY 1d Ankle +PHY 1e Foot +PHY 1f Heel +PHY 20 Ball of Foot +PHY 21 Big Toe +PHY 22 Second Toe +PHY 23 Third Toe +PHY 24 Fourth Toe +PHY 25 Fifth Toe +PHY 26 Brow +PHY 27 Cheek + +# List of HID Usages + +# Syntax: +# HUT hi _usage_page hid_usage_page_name +# hid_usage hid_usage_name + +HUT 00 Undefined +HUT 01 Generic Desktop Controls + 000 Undefined + 001 Pointer + 002 Mouse + 004 Joystick + 005 Gamepad + 006 Keyboard + 007 Keypad + 008 Multi-Axis Controller + 030 Direction-X + 031 Direction-Y + 032 Direction-Z + 033 Rotate-X + 034 Rotate-Y + 035 Rotate-Z + 036 Slider + 037 Dial + 038 Wheel + 039 Hat Switch + 03a Counted Buffer + 03b Byte Count + 03c Motion Wakeup + 03d Start + 03e Select + 040 Vector-X + 041 Vector-Y + 042 Vector-Z + 043 Vector-X relative Body + 044 Vector-Y relative Body + 045 Vector-Z relative Body + 046 Vector + 080 System Control + 081 System Power Down + 082 System Sleep + 083 System Wake Up + 084 System Context Menu + 085 System Main Menu + 086 System App Menu + 087 System Menu Help + 088 System Menu Exit + 089 System Menu Select + 08a System Menu Right + 08b System Menu Left + 08c System Menu Up + 08d System Menu Down + 090 Direction Pad Up + 091 Direction Pad Down + 092 Direction Pad Right + 093 Direction Pad Left +HUT 02 Simulation Controls + 000 Undefined + 001 Flight Simulation Device + 002 Automobile Simulation Device + 003 Tank Simulation Device + 004 Spaceship Simulation Device + 005 Submarine Simulation Device + 006 Sailing Simulation Device + 007 Motorcycle Simulation Device + 008 Sports Simulation Device + 009 Airplane Simualtion Device + 00a Helicopter Simulation Device + 00b Magic Carpet Simulation Device + 00c Bicycle Simulation Device + 020 Flight Control Stick + 021 Flight Stick + 022 Cyclic Control + 023 Cyclic Trim + 024 Flight Yoke + 025 Track Control + 0b0 Aileron + 0b1 Aileron Trim + 0b2 Anti-Torque Control + 0b3 Autopilot Enable + 0b4 Chaff Release + 0b5 Collective Control + 0b6 Dive Break + 0b7 Electronic Countermeasures + 0b8 Elevator + 0b9 Elevator Trim + 0ba Rudder + 0bb Throttle + 0bc Flight COmmunications + 0bd Flare Release + 0be Landing Gear + 0bf Toe Break + 0c0 Trigger + 0c1 Weapon Arm + 0c2 Weapons Select + 0c3 Wing Flaps + 0c4 Accelerator + 0c5 Brake + 0c6 Clutch + 0c7 Shifter + 0c8 Steering + 0c9 Turret Direction + 0ca Barrel Elevation + 0cb Drive Plane + 0cc Ballast + 0cd Bicylce Crank + 0ce Handle Bars + 0cf Front Brake + 0d0 Rear Brake +HUT 03 VR Controls + 000 Unidentified + 001 Belt + 002 Body Suit + 003 Flexor + 004 Glove + 005 Head Tracker + 006 Head Mounted Display + 007 Hand Tracker + 008 Oculometer + 009 Vest + 00a Animatronic Device + 020 Stereo Enable + 021 Display Enable +HUT 04 Sport Controls + 000 Unidentified + 001 Baseball Bat + 002 Golf Club + 003 Rowing Machine + 004 Treadmill + 030 Oar + 031 Slope + 032 Rate + 033 Stick Speed + 034 Stick Face Angle + 035 Stick Heel/Toe + 036 Stick Follow Through + 047 Stick Temp + 038 Stick Type + 039 Stick Height + 050 Putter + 051 1 Iron + 052 2 Iron + 053 3 Iron + 054 4 Iron + 055 5 Iron + 056 6 Iron + 057 7 Iron + 058 8 Iron + 059 9 Iron + 05a 10 Iron + 05b 11 Iron + 05c Sand Wedge + 05d Loft Wedge + 05e Power Wedge + 05f 1 Wood + 060 3 Wood + 061 5 Wood + 062 7 Wood + 063 9 Wood +HUT 05 Game Controls + 000 Undefined + 001 3D Game Controller + 002 Pinball Device + 003 Gun Device + 020 Point Of View + 021 Turn Right/Left + 022 Pitch Right/Left + 023 Roll Forward/Backward + 024 Move Right/Left + 025 Move Forward/Backward + 026 Move Up/Down + 027 Lean Right/Left + 028 Lean Forward/Backward + 029 Height of POV + 02a Flipper + 02b Secondary Flipper + 02c Bump + 02d New Game + 02e Shoot Ball + 02f Player + 030 Gun Bolt + 031 Gun Clip + 032 Gun Selector + 033 Gun Single Shot + 034 Gun Burst + 035 Gun Automatic + 036 Gun Safety + 037 Gamepad Fire/Jump + 038 Gamepad Fun + 039 Gamepad Trigger +HUT 07 Keyboard + 000 No Event + 001 Keyboard ErrorRollOver + 002 Keyboard POSTfail + 003 Keyboard Error Undefined + 004 A + 005 B + 006 C + 007 D + 008 E + 009 F + 00a G + 00b H + 00c I + 00d J + 00e K + 00f L + 010 M + 011 N + 012 O + 013 P + 014 Q + 015 R + 016 S + 017 T + 018 U + 019 V + 01a W + 01b X + 01c Y + 01d Z + 01e 1 and ! (One and Exclamation) + 01f 2 and @ (2 and at) + 020 3 and # (3 and Hash) + 021 4 and $ (4 and Dollar Sign) + 022 5 and % (5 and Percent Sign) + 023 6 and ^ (6 and circumflex) + 024 7 and & (Seven and Ampersand) + 025 8 and * (Eight and asterisk) + 026 9 and ( (Nine and Parenthesis Left) + 027 0 and ) (Zero and Parenthesis Right) + 028 Return (Enter) + 029 Escape + 02a Delete (Backspace) + 02b Tab + 02c Space Bar + 02d - and _ (Minus and underscore) + 02e = and + (Equal and Plus) + 02f [ and { (Bracket and Braces Left) + 030 ] and } (Bracket and Braces Right) + 031 \ and | (Backslash and Bar) + 032 # and ~ (Hash and Tilde, Non-US Keyboard near right shift) + 033 ; and : (Semicolon and Colon) + 034 ´ and " (Accent Acute and Double Quotes) + 035 ` and ~ (Accent Grace and Tilde) + 036 , and < (Comma and Less) + 037 . and > (Period and Greater) + 038 / and ? (Slash and Question Mark) + 039 Caps Lock + 03a F1 + 03b F2 + 03c F3 + 03d F4 + 03e F5 + 03f F6 + 040 F7 + 041 F8 + 042 F9 + 043 F10 + 044 F11 + 045 F12 + 046 Print Screen + 047 Scroll Lock + 048 Pause + 049 Insert + 04a Home + 04b Page Up + 04c Delete Forward (without Changing Position) + 04d End + 04e Page Down + 04f Right Arrow + 050 Left Arrow + 051 Down Arrow + 052 Up Arrow + 053 Num Lock and Clear + 054 Keypad / (Division Sign) + 055 Keypad * (Multiplication Sign) + 056 Keypad - (Subtraction Sign) + 057 Keypad + (Addition Sign) + 058 Keypad Enter + 059 Keypad 1 and END + 05a Keypad 2 and Down Arrow + 05b Keypad 3 and Page Down + 05c Keypad 4 and Left Arrow + 05d Keypad 5 (Tactilei Raised) + 05f Keypad 6 and Right Arrow + 060 Keypad 7 and Home + 061 Keypad 8 and Up Arrow + 062 Keypad 8 and Page Up + 063 Keypad . (decimal delimiter) and Delete + 064 \ and | (Backslash and Bar, UK and Non-US Keyboard near left shift) + 065 Keyboard Application (Windows Key for Win95 or Compose) + 066 Power (not a key) + 067 Keypad = (Equal Sign) + 068 F13 + 069 F14 + 06a F15 + 06b F16 + 06c F17 + 06d F18 + 06e F19 + 06f F20 + 070 F21 + 071 F22 + 072 F23 + 073 F24 + 074 Execute + 075 Help + 076 Menu + 077 Select + 078 Stop + 079 Again + 07a Undo + 07b Cut + 07c Copy + 07d Paste + 07e Find + 07f Mute + 080 Volume Up + 081 Volume Down + 082 Locking Caps Lock + 083 Locking Num Lock + 084 Locking Scroll Lock + 085 Keypad Comma + 086 Keypad Equal Sign (AS/400) + 087 International 1 (PC98) + 088 International 2 (PC98) + 089 International 3 (PC98) + 08a International 4 (PC98) + 08b International 5 (PC98) + 08c International 6 (PC98) + 08d International 7 (Toggle Single/Double Byte Mode) + 08e International 8 + 08f International 9 + 090 LANG 1 (Hangul/English Toggle, Korea) + 091 LANG 2 (Hanja Conversion, Korea) + 092 LANG 3 (Katakana, Japan) + 093 LANG 4 (Hiragana, Japan) + 094 LANG 5 (Zenkaku/Hankaku, Japan) + 095 LANG 6 + 096 LANG 7 + 097 LANG 8 + 098 LANG 9 + 099 Alternate Erase + 09a SysReq/Attention + 09b Cancel + 09c Clear + 09d Prior + 09e Return + 09f Separator + 0a0 Out + 0a1 Open + 0a2 Clear/Again + 0a3 CrSel/Props + 0a4 ExSel + 0e0 Control Left + 0e1 Shift Left + 0e2 Alt Left + 0e3 GUI Left + 0e4 Control Right + 0e5 Shift Right + 0e6 Alt Rigth + 0e7 GUI Right +HUT 08 LEDs + 000 Undefined + 001 NumLock + 002 CapsLock + 003 Scroll Lock + 004 Compose + 005 Kana + 006 Power + 007 Shift + 008 Do not disturb + 009 Mute + 00a Tone Enabke + 00b High Cut Filter + 00c Low Cut Filter + 00d Equalizer Enable + 00e Sound Field ON + 00f Surround On + 010 Repeat + 011 Stereo + 012 Sampling Rate Detect + 013 Spinning + 014 CAV + 015 CLV + 016 Recording Format Detect + 017 Off-Hook + 018 Ring + 019 Message Waiting + 01a Data Mode + 01b Battery Operation + 01c Battery OK + 01d Battery Low + 01e Speaker + 01f Head Set + 020 Hold + 021 Microphone + 022 Coverage + 023 Night Mode + 024 Send Calls + 025 Call Pickup + 026 Conference + 027 Stand-by + 028 Camera On + 029 Camera Off + 02a On-Line + 02b Off-Line + 02c Busy + 02d Ready + 02e Paper-Out + 02f Paper-Jam + 030 Remote + 031 Forward + 032 Reverse + 033 Stop + 034 Rewind + 035 Fast Forward + 036 Play + 037 Pause + 038 Record + 039 Error + 03a Usage Selected Indicator + 03b Usage In Use Indicator + 03c Usage Multi Indicator + 03d Indicator On + 03e Indicator Flash + 03f Indicator Slow Blink + 040 Indicator Fast Blink + 041 Indicator Off + 042 Flash On Time + 043 Slow Blink On Time + 044 Slow Blink Off Time + 045 Fast Blink On Time + 046 Fast Blink Off Time + 047 Usage Color Indicator + 048 Indicator Red + 049 Indicator Green + 04a Indicator Amber + 04b Generic Indicator + 04c System Suspend + 04d External Power Connected +HUT 09 Buttons + 000 No Button Pressed + 001 Button 1 (Primary) + 002 Button 2 (Secondary) + 003 Button 3 (Tertiary) + 004 Button 4 + 005 Button 5 +HUT 0a Ordinal + 001 Instance 1 + 002 Instance 2 + 003 Instance 3 +HUT 0b Telephony + 000 Unassigned + 001 Phone + 002 Answering Machine + 003 Message Controls + 004 Handset + 005 Headset + 006 Telephony Key Pad + 007 Programmable Button + 020 Hook Switch + 021 Flash + 022 Feature + 023 Hold + 024 Redial + 025 Transfer + 026 Drop + 027 Park + 028 Forward Calls + 029 Alternate Function + 02a Line + 02b Speaker Phone + 02c Conference + 02d Ring Enable + 02e Ring Select + 02f Phone Mute + 030 Caller ID + 050 Speed Dial + 051 Store Number + 052 Recall Number + 053 Phone Directory + 070 Voice Mail + 071 Screen Calls + 072 Do Not Disturb + 073 Message + 074 Answer On/Offf + 090 Inside Dial Tone + 091 Outside Dial Tone + 092 Inside Ring Tone + 093 Outside Ring Tone + 094 Priority Ring Tone + 095 Inside Ringback + 096 Priority Ringback + 097 Line Busy Tone + 098 Recorder Tone + 099 Call Waiting Tone + 09a Confirmation Tone 1 + 09b Confirmation Tone 2 + 09c Tones Off + 09d Outside Ringback + 0b0 Key 1 + 0b1 Key 2 + 0b3 Key 3 + 0b4 Key 4 + 0b5 Key 5 + 0b6 Key 6 + 0b7 Key 7 + 0b8 Key 8 + 0b9 Key 9 + 0ba Key Star + 0bb Key Pound + 0bc Key A + 0bd Key B + 0be Key C + 0bf Key D +HUT 0c Consumer + 000 Unassigned + 001 Consumer Control + 002 Numeric Ky Pad + 003 Programmable Buttons + 020 +10 + 021 +100 + 022 AM/PM + 030 Power + 031 Reset + 032 Sleep + 033 Sleep After + 034 Sleep Mode + 035 Illumination + 036 Funtion Buttons + 040 Menu + 041 Menu Pick + 042 Menu Up + 043 Menu Down + 044 Menu Left + 045 Menu Right + 046 Menu Escape + 047 Menu Value Increase + 048 Menu Value Decrease + 060 Data on Screen + 061 Closed Caption + 062 Closed Caption Select + 063 VCR/TV + 064 Broadcast Mode + 065 SNapshot + 066 Still + 080 Selection + 081 Assign Selection + 082 Mode Step + 083 Recall Last + 084 Enter Channel + 085 Order Movie + 086 Channel + 087 Media Selection + 088 Media Select Computer + 089 Media Select TV + 08a Media Select WWW + 08b Media Select DVD + 08c Media Select Telephone + 08d Media Select Program Guide + 08e Media Select Video Phone + 08f Media Select Games + 090 Media Select Messages + 091 Media Select CD + 092 Media Select VCR + 093 Media Select Tuner + 094 Quit + 095 Help + 096 Media Select Tape + 097 Media Select Cable + 098 Media Select Satellite + 099 Media Select Security + 09a Media Select Home + 09b Media Select Call + 09c Channel Increment + 09d Channel Decrement + 09e Media Select SAP + 0a0 VCR Plus + 0a1 Once + 0a2 Daily + 0a3 Weekly + 0a4 Monthly + 0b0 Play + 0b1 Pause + 0b2 Record + 0b3 Fast Forward + 0b4 Rewind + 0b5 Scan Next Track + 0b6 Scan Previous Track + 0b7 Stop + 0b8 Eject + 0b9 Random Play + 0ba Select Disc + 0bb Enter Disc + 0bc Repeat + 0bd Tracking + 0be Track Normal + 0bf Slow Tracking + 0c0 Frame Forward + 0c1 Frame Back + 0c2 Mark + 0c3 Clear Mark + 0c4 Repeat from Mark + 0c5 Return to Mark + 0c6 Search Mark Forward + 0c7 Search Mark Backward + 0c8 Counter Reset + 0c9 Show Counter + 0ca Tracking Increment + 0cb Tracking Decrement + 0cc Stop/Eject + 0cd Play/Pause + 0ce Play/Skip + 0e0 Volume + 0e1 Balance + 0e2 Mute + 0e3 Bass + 0e4 Treble + 0e5 Bass Boost + 0e6 Surround Mode + 0e7 Loudness + 0e8 MPX + 0e9 Volume Increment + 0ea Volume Decrement + 0f0 Speed Select + 0f1 Playback Speed + 0f2 Standard Play + 0f3 Long Play + 0f4 Extended Play + 0f5 Slow + 100 Fan Enable + 101 Fan Speed + 102 Light Enable + 103 Light Illumination Level + 104 Climate Control Enable + 105 Room Temperature + 106 Security Enable + 107 Fire Alarm + 108 Police Alarm + 150 Balance Right + 151 Balance Left + 152 Bass Increment + 153 Bass Decrement + 154 Treble Increment + 155 Treble Decrement + 160 Speaker System + 161 Channel Left + 162 Channel Right + 163 Channel Center + 164 Channel Front + 165 Channel Center Front + 166 Channel Side + 167 Channel Surround + 168 Channel Low Frequency Enhancement + 169 Channel Top + 16a Channel Unknown + 170 Sub-Channel + 171 Sub-Channel Increment + 172 Sub-Channel Decrement + 173 Alternative Audio Increment + 174 Alternative Audio Decrement + 180 Application Launch Buttons + 181 AL Launch Button Configuration Tool + 182 AL Launch Button Configuration + 183 AL Consumer Control Configuration + 184 AL Word Processor + 185 AL Text Editor + 186 AL Spreadsheet + 187 AL Graphics Editor + 188 AL Presentation App + 189 AL Database App + 18a AL Email Reader + 18b AL Newsreader + 18c AL Voicemail + 18d AL Contacts/Address Book + 18e AL Calendar/Schedule + 18f AL Task/Project Manager + 190 AL Log/Jounal/Timecard + 191 AL Checkbook/Finance + 192 AL Calculator + 193 AL A/V Capture/Playback + 194 AL Local Machine Browser + 195 AL LAN/Wan Browser + 196 AL Internet Browser + 197 AL Remote Networking/ISP Connect + 198 AL Network Conference + 199 AL Network Chat + 19a AL Telephony/Dialer + 19b AL Logon + 19c AL Logoff + 19d AL Logon/Logoff + 19e AL Terminal Local/Screensaver + 19f AL Control Panel + 1a0 AL Command Line Processor/Run + 1a1 AL Process/Task Manager + 1a2 AL Select Task/Application + 1a3 AL Next Task/Application + 1a4 AL Previous Task/Application + 1a5 AL Preemptive Halt Task/Application + 200 Generic GUI Application Controls + 201 AC New + 202 AC Open + 203 AC CLose + 204 AC Exit + 205 AC Maximize + 206 AC Minimize + 207 AC Save + 208 AC Print + 209 AC Properties + 21a AC Undo + 21b AC Copy + 21c AC Cut + 21d AC Paste + 21e AC Select All + 21f AC Find + 220 AC Find and Replace + 221 AC Search + 222 AC Go To + 223 AC Home + 224 AC Back + 225 AC Forward + 226 AC Stop + 227 AC Refresh + 228 AC Previous Link + 229 AC Next Link + 22b AC History + 22c AC Subscriptions + 22d AC Zoom In + 22e AC Zoom Out + 22f AC Zoom + 230 AC Full Screen View + 231 AC Normal View + 232 AC View Toggle + 233 AC Scroll Up + 234 AC Scroll Down + 235 AC Scroll + 236 AC Pan Left + 237 AC Pan Right + 238 AC Pan + 239 AC New Window + 23a AC Tile Horizontally + 23b AC Tile Vertically + 23c AC Format +HUT 0d Digitizer + 000 Undefined + 001 Digitizer + 002 Pen + 003 Light Pen + 004 Touch Screen + 005 Touch Pad + 006 White Board + 007 Coordinate Measuring Machine + 008 3D Digitizer + 009 Stereo Plotter + 00a Articulated Arm + 00b Armature + 00c Multiple Point Digitizer + 00d Free Space Wand + 020 Stylus + 021 Puck + 022 Finger + 030 Tip Pressure + 031 Barrel Pressure + 032 In Range + 033 Touch + 034 Untouch + 035 Tap + 036 Quality + 037 Data Valid + 038 Transducer Index + 039 Tablet Function Keys + 03a Program Change Keys + 03b Battery Strength + 03c Invert + 03d X Tilt + 03e Y Tilt + 03f Azimuth + 040 Altitude + 041 Twist + 042 Tip Switch + 043 Secondary Tip Switch + 044 Barrel Switch + 045 Eraser + 046 Tablet Pick +HUT 0f PID Page + 000 Undefined + 001 Physical Interface Device + 020 Normal + 021 Set Effect Report + 022 Effect Block Index + 023 Parameter Block Offset + 024 ROM Flag + 025 Effect Type + 026 ET Constant Force + 027 ET Ramp + 028 ET Custom Force Data + 030 ET Square + 031 ET Sine + 032 ET Triangle + 033 ET Sawtooth Up + 034 ET Sawtooth Down + 040 ET Spring + 041 ET Damper + 042 ET Inertia + 043 ET Friction + 050 Duration + 051 Sample Period + 052 Gain + 053 Trigger Button + 054 Trigger Repeat Interval + 055 Axes Enable + 056 Direction Enable + 057 Direction + 058 Type Specific Block Offset + 059 Block Type + 05A Set Envelope Report + 05B Attack Level + 05C Attack Time + 05D Fade Level + 05E Fade Time + 05F Set Condition Report + 060 CP Offset + 061 Positive Coefficient + 062 Negative Coefficient + 063 Positive Saturation + 064 Negative Saturation + 065 Dead Band + 066 Download Force Sample + 067 Isoch Custom Force Enable + 068 Custom Force Data Report + 069 Custom Force Data + 06A Custom Force Vendor Defined Data + 06B Set Custom Force Report + 06C Custom Force Data Offset + 06D Sample Count + 06E Set Periodic Report + 06F Offset + 070 Magnitude + 071 Phase + 072 Period + 073 Set Constant Force Report + 074 Set Ramp Force Report + 075 Ramp Start + 076 Ramp End + 077 Effect Operation Report + 078 Effect Operation + 079 Op Effect Start + 07A Op Effect Start Solo + 07B Op Effect Stop + 07C Loop Count + 07D Device Gain Report + 07E Device Gain + 07F PID Pool Report + 080 RAM Pool Size + 081 ROM Pool Size + 082 ROM Effect Block Count + 083 Simultaneous Effects Max + 084 Pool Alignment + 085 PID Pool Move Report + 086 Move Source + 087 Move Destination + 088 Move Length + 089 PID Block Load Report + 08B Block Load Status + 08C Block Load Success + 08D Block Load Full + 08E Block Load Error + 08F Block Handle + 090 PID Block Free Report + 091 Type Specific Block Handle + 092 PID State Report + 094 Effect Playing + 095 PID Device Control Report + 096 PID Device Control + 097 DC Enable Actuators + 098 DC Disable Actuators + 099 DC Stop All Effects + 09A DC Device Reset + 09B DC Device Pause + 09C DC Device Continue + 09F Device Paused + 0A0 Actuators Enabled + 0A4 Safety Switch + 0A5 Actuator Override Switch + 0A6 Actuator Power + 0A7 Start Delay + 0A8 Parameter Block Size + 0A9 Device Managed Pool + 0AA Shared Parameter Blocks + 0AB Create New Effect Report + 0AC RAM Pool Available +HUT 10 Unicode +HUT 14 Alphanumeric Display + 000 Undefined + 001 Alphanumeric Display + 020 Display Attributes Report + 021 ASCII Character Set + 022 Data Read Back + 023 Font Read Back + 024 Display Control Report + 025 Clear Display + 026 Display Enable + 027 Screen Saver Delay + 028 Screen Saver Enable + 029 Vertical Scroll + 02a Horizontal Scroll + 02b Character Report + 02c Display Data + 02d Display Status + 02e Stat Not Ready + 02f Stat Ready + 030 Err Not a loadable Character + 031 Err Font Data Cannot Be Read + 032 Cursur Position Report + 033 Row + 034 Column + 035 Rows + 036 Columns + 037 Cursor Pixel Positioning + 038 Cursor Mode + 039 Cursor Enable + 03a Cursor Blink + 03b Font Report + 03c Font Data + 03d Character Width + 03e Character Height + 03f Character Spacing Horizontal + 040 Character Spacing Vertical + 041 Unicode Character Set +HUT 80 USB Monitor + 001 Monitor Control + 002 EDID Information + 003 VDIF Information + 004 VESA Version +HUT 81 USB Monitor Enumerated Values +HUT 82 Monitor VESA Virtual Controls + 001 Degauss + 010 Brightness + 012 Contrast + 016 Red Video Gain + 018 Green Video Gain + 01a Blue Video Gain + 01c Focus + 020 Horizontal Position + 022 Horizontal Size + 024 Horizontal Pincushion + 026 Horizontal Pincushion Balance + 028 Horizontal Misconvergence + 02a Horizontal Linearity + 02c Horizontal Linearity Balance + 030 Vertical Position + 032 Vertical Size + 034 Vertical Pincushion + 036 Vertical Pincushion Balance + 038 Vertical Misconvergence + 03a Vertical Linearity + 03c Vertical Linearity Balance + 040 Parallelogram Balance (Key Distortion) + 042 Trapezoidal Distortion (Key) + 044 Tilt (Rotation) + 046 Top Corner Distortion Control + 048 Top Corner Distortion Balance + 04a Bottom Corner Distortion Control + 04c Bottom Corner Distortion Balance + 056 Horizontal Moire + 058 Vertical Moire + 05e Input Level Select + 060 Input Source Select + 06c Red Video Black Level + 06e Green Video Black Level + 070 Blue Video Black Level + 0a2 Auto Size Center + 0a4 Polarity Horizontal Sychronization + 0a6 Polarity Vertical Synchronization + 0aa Screen Orientation + 0ac Horizontal Frequency in Hz + 0ae Vertical Frequency in 0.1 Hz + 0b0 Settings + 0ca On Screen Display (OSD) + 0d4 Stereo Mode +HUT 84 Power Device Page + 000 Undefined + 001 iName + 002 Present Status + 003 Changed Status + 004 UPS + 005 Power Supply + 010 Battery System + 011 Battery System ID + 012 Battery + 013 Battery ID + 014 Charger + 015 Charger ID + 016 Power Converter + 017 Power Converter ID + 018 Outlet System + 019 Outlet System ID + 01a Input + 01b Input ID + 01c Output + 01d Output ID + 01e Flow + 01f Flow ID + 020 Outlet + 021 Outlet ID + 022 Gang + 023 Gang ID + 024 Power Summary + 025 Power Summary ID + 030 Voltage + 031 Current + 032 Frequency + 033 Apparent Power + 034 Active Power + 035 Percent Load + 036 Temperature + 037 Humidity + 038 Bad Count + 040 Config Voltage + 041 Config Current + 042 Config Frequency + 043 Config Apparent Power + 044 Config Active Power + 045 Config Percent Load + 046 Config Temperature + 047 Config Humidity + 050 Switch On Control + 051 Switch Off Control + 052 Toggle Control + 053 Low Voltage Transfer + 054 High Voltage Transfer + 055 Delay Before Reboot + 056 Delay Before Startup + 057 Delay Before Shutdown + 058 Test + 059 Module Reset + 05a Audible Alarm Control + 060 Present + 061 Good + 062 Internal Failure + 063 Voltage out of range + 064 Frequency out of range + 065 Overload + 066 Over Charged + 067 Over Temperature + 068 Shutdown Requested + 069 Shutdown Imminent + 06a Reserved + 06b Switch On/Off + 06c Switchable + 06d Used + 06e Boost + 06f Buck + 070 Initialized + 071 Tested + 072 Awaiting Power + 073 Communication Lost + 0fd iManufacturer + 0fe iProduct + 0ff iSerialNumber +HUT 85 Battery System Page + 000 Undefined + 001 SMB Battery Mode + 002 SMB Battery Status + 003 SMB Alarm Warning + 004 SMB Charger Mode + 005 SMB Charger Status + 006 SMB Charger Spec Info + 007 SMB Selector State + 008 SMB Selector Presets + 009 SMB Selector Info + 010 Optional Mfg. Function 1 + 011 Optional Mfg. Function 2 + 012 Optional Mfg. Function 3 + 013 Optional Mfg. Function 4 + 014 Optional Mfg. Function 5 + 015 Connection to SMBus + 016 Output Connection + 017 Charger Connection + 018 Battery Insertion + 019 Use Next + 01a OK to use + 01b Battery Supported + 01c SelectorRevision + 01d Charging Indicator + 028 Manufacturer Access + 029 Remaining Capacity Limit + 02a Remaining Time Limit + 02b At Rate + 02c Capacity Mode + 02d Broadcast To Charger + 02e Primary Battery + 02f Charge Controller + 040 Terminate Charge + 041 Terminate Discharge + 042 Below Remaining Capacity Limit + 043 Remaining Time Limit Expired + 044 Charging + 045 Discharging + 046 Fully Charged + 047 Fully Discharged + 048 Conditioning Flag + 049 At Rate OK + 04a SMB Error Code + 04b Need Replacement + 060 At Rate Time To Full + 061 At Rate Time To Empty + 062 Average Current + 063 Max Error + 064 Relative State Of Charge + 065 Absolute State Of Charge + 066 Remaining Capacity + 067 Full Charge Capacity + 068 Run Time To Empty + 069 Average Time To Empty + 06a Average Time To Full + 06b Cycle Count + 080 Batt. Pack Model Level + 081 Internal Charge Controller + 082 Primary Battery Support + 083 Design Capacity + 084 Specification Info + 085 Manufacturer Date + 086 Serial Number + 087 iManufacturerName + 088 iDeviceName + 089 iDeviceChemistry + 08a Manufacturer Data + 08b Rechargeable + 08c Warning Capacity Limit + 08d Capacity Granularity 1 + 08e Capacity Granularity 2 + 08f iOEMInformation + 0c0 Inhibit Charge + 0c1 Enable Polling + 0c2 Reset To Zero + 0d0 AC Present + 0d1 Battery Present + 0d2 Power Fail + 0d3 Alarm Inhibited + 0d4 Thermistor Under Range + 0d5 Thermistor Hot + 0d6 Thermistor Cold + 0d7 Thermistor Over Range + 0d8 Voltage Out Of Range + 0d9 Current Out Of Range + 0da Current Not Regulated + 0db Voltage Not Regulated + 0dc Master Mode + 0f0 Charger Selector Support + 0f1 Charger Spec + 0f2 Level 2 + 0f3 Level 3 +HUT 86 Power Pages +HUT 87 Power Pages +HUT 8c Bar Code Scanner Page (POS) +HUT 8d Scale Page (POS) +HUT 90 Camera Control Page +HUT 91 Arcade Control Page +HUT f0 Cash Device + 0f1 Cash Drawer + 0f2 Cash Drawer Number + 0f3 Cash Drawer Set + 0f4 Cash Drawer Status +HUT ff Vendor Specific + +# List of Languages + +# Syntax: +# L language_id language_name +# dialect_id dialect_name + +L 0001 Arabic + 01 Saudi Arabia + 02 Iraq + 03 Egypt + 04 Libya + 05 Algeria + 06 Morocco + 07 Tunesia + 08 Oman + 09 Yemen + 0a Syria + 0b Jordan + 0c Lebanon + 0d Kuwait + 0e U.A.E + 0f Bahrain + 10 Qatar +L 0002 Bulgarian +L 0003 Catalan +L 0004 Chinese + 01 Traditional + 02 Simplified + 03 Hongkong SAR, PRC + 04 Singapore + 05 Macau SAR +L 0005 Czech +L 0006 Danish +L 0007 German + 01 German + 02 Swiss + 03 Austrian + 04 Luxembourg + 05 Liechtenstein +L 0008 Greek +L 0009 English + 01 US + 02 UK + 03 Australian + 04 Canadian + 05 New Zealand + 06 Ireland + 07 South Africa + 08 Jamaica + 09 Carribean + 0a Belize + 0b Trinidad + 0c Zimbabwe + 0d Philippines +L 000a Spanish + 01 Castilian + 02 Mexican + 03 Modern + 04 Guatemala + 05 Costa Rica + 06 Panama + 07 Dominican Republic + 08 Venzuela + 09 Colombia + 0a Peru + 0b Argentina + 0c Ecuador + 0d Chile + 0e Uruguay + 0f Paraguay + 10 Bolivia + 11 El Salvador + 12 Honduras + 13 Nicaragua + 14 Puerto Rico +L 000b Finnish +L 000c French + 01 French + 02 Belgian + 03 Canadian + 04 Swiss + 05 Luxembourg + 06 Monaco +L 000d Hebrew +L 000e Hungarian +L 000f Idelandic +L 0010 Italian + 01 Italian + 02 Swiss +L 0011 Japanese +L 0012 Korean + 01 Korean +L 0013 Dutch + 01 Dutch + 02 Belgian +L 0014 Norwegian + 01 Bokmal + 02 Nynorsk +L 0015 Polish +L 0016 Portuguese + 01 Portuguese + 02 Brazilian +L 0017 forgotten +L 0018 Romanian +L 0019 Russian +L 001a Serbian + 01 Croatian + 02 Latin + 03 Cyrillic +L 001b Slovak +L 001c Albanian +L 001d Swedish + 01 Swedish + 02 Finland +L 001e Thai +L 001f Turkish +L 0020 Urdu + 01 Pakistan + 02 India +L 0021 Indonesian +L 0022 Ukrainian +L 0023 Belarusian +L 0024 Slovenian +L 0025 Estonian +L 0026 Latvian +L 0027 Lithuanian + 01 Lithuanian +L 0028 forgotten +L 0029 Farsi +L 002a Vietnamese +L 002b Armenian +L 002c Azeri + 01 Cyrillic + 02 Latin +L 002d Basque +L 002e forgotten +L 002f Macedonian +L 0036 Afrikaans +L 0037 Georgian +L 0038 Faeroese +L 0039 Hindi +L 003e Malay + 01 Malaysia + 02 Brunei Darassalam +L 003f Kazak +L 0041 Awahili +L 0043 Uzbek + 01 Latin + 02 Cyrillic +L 0044 Tatar +L 0045 Bengali +L 0046 Punjabi +L 0047 Gujarati +L 0048 Oriya +L 0049 Tamil +L 004a Telugu +L 004b Kannada +L 004c Malayalam +L 004d Assamese +L 004e Marathi +L 004f Sanskrit +L 0057 Konkani +L 0058 Manipuri +L 0059 Sindhi +L 0060 Kashmiri + 02 India +L 0061 Nepali + 02 India + +# HID Descriptor bCountryCode +# HID Specification 1.11 (2001-06-27) page 23 +# +# Syntax: +# HCC country_code keymap_type + +HCC 00 Not supported +HCC 01 Arabic +HCC 02 Belgian +HCC 03 Canadian-Bilingual +HCC 04 Canadian-French +HCC 05 Czech Republic +HCC 06 Danish +HCC 07 Finnish +HCC 08 French +HCC 09 German +HCC 10 Greek +HCC 11 Hebrew +HCC 12 Hungary +HCC 13 International (ISO) +HCC 14 Italian +HCC 15 Japan (Katakana) +HCC 16 Korean +HCC 17 Latin American +HCC 18 Netherlands/Dutch +HCC 19 Norwegian +HCC 20 Persian (Farsi) +HCC 21 Poland +HCC 22 Portuguese +HCC 23 Russia +HCC 24 Slovakia +HCC 25 Spanish +HCC 26 Swedish +HCC 27 Swiss/French +HCC 28 Swiss/German +HCC 29 Switzerland +HCC 30 Taiwan +HCC 31 Turkish-Q +HCC 32 UK +HCC 33 US +HCC 34 Yugoslavia +HCC 35 Turkish-F + +# List of Video Class Terminal Types + +# Syntax: +# VT terminal_type terminal_type_name + +VT 0100 USB Vendor Specific +VT 0101 USB Streaming +VT 0200 Input Vendor Specific +VT 0201 Camera Sensor +VT 0202 Sequential Media +VT 0300 Output Vendor Specific +VT 0301 Generic Display +VT 0302 Sequential Media +VT 0400 External Vendor Specific +VT 0401 Composite Video +VT 0402 S-Video +VT 0403 Component Video +