aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-07-03 11:11:11 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2006-07-03 11:11:11 -0700
commitbbc466d1931e2ca1f095824f455833944d9a35ae (patch)
tree193544144770e17a7cb5a0f9b45a8ed6402180e9 /usb
parentedebd83392a7b67e4b4aa1a3d387f0593d07f053 (diff)
downloadpatches-bbc466d1931e2ca1f095824f455833944d9a35ae.tar.gz
move usbip patches and remove MSI ones.
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-usbip-build-fix.patch59
-rw-r--r--usb/usb-usbip-more-dead-code-fix.patch40
-rw-r--r--usb/usb-usbip-warning-fixes.patch48
-rw-r--r--usb/usbip.patch4611
4 files changed, 0 insertions, 4758 deletions
diff --git a/usb/usb-usbip-build-fix.patch b/usb/usb-usbip-build-fix.patch
deleted file mode 100644
index 4ff26199efae7..0000000000000
--- a/usb/usb-usbip-build-fix.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From akpm@osdl.org Thu Jan 5 22:54:11 2006
-Message-Id: <200601060650.k066omZZ008821@shell0.pdx.osdl.net>
-From: Andrew Morton <akpm@osdl.org>
-Subject: USB: usbip build fix
-To: greg@kroah.com
-Cc: akpm@osdl.org, taka-hir@is.naist.jp
-Date: Thu, 05 Jan 2006 22:50:36 -0800
-
-
-From: Andrew Morton <akpm@osdl.org>
-
-Fix this:
-
-drivers/usb/ip/usbip_common.c: In function `socket_to_addrstr':
-drivers/usb/ip/usbip_common.c:582: dereferencing pointer to incomplete type
-drivers/usb/ip/usbip_common.c:582: dereferencing pointer to incomplete type
-drivers/usb/ip/usbip_common.c:582: dereferencing pointer to incomplete type
-drivers/usb/ip/usbip_common.c:582: dereferencing pointer to incomplete type
-
-And this:
-
-drivers/usb/ip/usbip_common.h: At top level:
-drivers/usb/ip/usbip_common.c:441: warning: `usbip_dump_urb' defined but not used
-
-Cc: Takahiro Hirofuchi <taka-hir@is.naist.jp>
-Signed-off-by: Andrew Morton <akpm@osdl.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
----
- drivers/usb/ip/usbip_common.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- gregkh-2.6.orig/drivers/usb/ip/usbip_common.c
-+++ gregkh-2.6/drivers/usb/ip/usbip_common.c
-@@ -23,6 +23,7 @@
- #include <linux/kernel.h>
- #include <linux/file.h>
- #include <linux/tcp.h>
-+#include <linux/in.h>
- #include "usbip_common.h"
-
- static void usbip_dump_buffer(char *, int size);
-@@ -254,7 +255,7 @@ static void usbip_dump_pipe(unsigned int
-
- }
-
--
-+#if 0
- static void usbip_dump_usb_device(struct usb_device *dev)
- {
- if (dev == NULL) {
-@@ -466,7 +467,7 @@ static void usbip_dump_urb (struct urb *
- printk(" context :%p\n", purb->context);
- printk(" complete :%p\n", purb->complete);
- }
--
-+#endif
-
- void setquickack(struct socket *socket)
- {
diff --git a/usb/usb-usbip-more-dead-code-fix.patch b/usb/usb-usbip-more-dead-code-fix.patch
deleted file mode 100644
index f1ff1eb5705b3..0000000000000
--- a/usb/usb-usbip-more-dead-code-fix.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From akpm@osdl.org Thu Jan 5 22:54:28 2006
-Message-Id: <200601060650.k066ooIj008824@shell0.pdx.osdl.net>
-From: Andrew Morton <akpm@osdl.org>
-Subject: USB: usbip more dead code fix
-To: greg@kroah.com
-Cc: akpm@osdl.org, taka-hir@is.naist.jp
-From: akpm@osdl.org
-Date: Thu, 05 Jan 2006 22:50:37 -0800
-
-
-From: Andrew Morton <akpm@osdl.org>
-
-drivers/usb/ip/vhci_hcd.c:639: warning: `vhci_device_unlink_all_urb' defined but not used
-
-Cc: Takahiro Hirofuchi <taka-hir@is.naist.jp>
-Signed-off-by: Andrew Morton <akpm@osdl.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
----
- drivers/usb/ip/vhci_hcd.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- gregkh-2.6.orig/drivers/usb/ip/vhci_hcd.c
-+++ gregkh-2.6/drivers/usb/ip/vhci_hcd.c
-@@ -634,7 +634,7 @@ static int vhci_urb_dequeue(struct usb_h
- return 0;
- }
-
--
-+#if 0
- static void vhci_device_unlink_all_urb(struct vhci_device *vdev)
- {
- struct vhci_priv *priv, *tmp;
-@@ -674,6 +674,7 @@ static void vhci_device_unlink_all_urb(s
-
- spin_unlock(&vdev->priv_lock);
- }
-+#endif
-
- /*
- * The important thing is that only one context begins cleanup.
diff --git a/usb/usb-usbip-warning-fixes.patch b/usb/usb-usbip-warning-fixes.patch
deleted file mode 100644
index e6cf05290d8ca..0000000000000
--- a/usb/usb-usbip-warning-fixes.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From akpm@osdl.org Thu Jan 19 23:59:29 2006
-Message-Id: <200601200759.k0K7xPcm020721@shell0.pdx.osdl.net>
-Subject: [patch 1/2] usb: usbip warning fixes
-To: greg@kroah.com
-Cc: akpm@osdl.org
-From: akpm@osdl.org
-Date: Thu, 19 Jan 2006 23:59:11 -0800
-
-
-From: Andrew Morton <akpm@osdl.org>
-
-drivers/usb/ip/stub_tx.c: In function `stub_send_txdata':
-drivers/usb/ip/stub_tx.c:158: warning: int format, different type arg (arg 7)
-drivers/usb/ip/vhci_tx.c: In function `vhci_send_txdata':
-drivers/usb/ip/vhci_tx.c:137: warning: int format, different type arg (arg 7)
-
-
-Signed-off-by: Andrew Morton <akpm@osdl.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
----
- drivers/usb/ip/stub_tx.c | 3 ++-
- drivers/usb/ip/vhci_tx.c | 3 ++-
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
---- gregkh-2.6.orig/drivers/usb/ip/stub_tx.c
-+++ gregkh-2.6/drivers/usb/ip/stub_tx.c
-@@ -155,7 +155,8 @@ static int stub_send_txdata(struct stub_
- int ret;
- ret = usbip_sendmsg(sdev->ud.tcp_socket, &msg, txsize);
- if (ret != txsize) {
-- VHCI_ERROR("vhci_sendmsg failed!, retval %d for %d\n", ret, txsize);
-+ VHCI_ERROR("vhci_sendmsg failed!, retval %d for %zd\n",
-+ ret, txsize);
- usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
- return -1;
- }
---- gregkh-2.6.orig/drivers/usb/ip/vhci_tx.c
-+++ gregkh-2.6/drivers/usb/ip/vhci_tx.c
-@@ -134,7 +134,8 @@ static int vhci_send_txdata(struct vhci_
- int ret;
- ret = usbip_sendmsg(vdev->ud.tcp_socket, &msg, txsize);
- if (ret != txsize) {
-- VHCI_ERROR("vhci_sendmsg failed!, retval %d for %d\n", ret, txsize);
-+ VHCI_ERROR("vhci_sendmsg failed!, retval %d for %zd\n",
-+ ret, txsize);
- usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
- return -1;
- }
diff --git a/usb/usbip.patch b/usb/usbip.patch
deleted file mode 100644
index 78da15bd294dc..0000000000000
--- a/usb/usbip.patch
+++ /dev/null
@@ -1,4611 +0,0 @@
-Subject: USB: add USB IP host and client driver
-From: Takahiro Hirofuchi <taka-hir@is.naist.jp>
-
-Implementes a USB over IP host driver and client device. Still a bit
-rough around the edges, but a great first implementation.
-
-See http://usbip.naist.jp/ for more information about this project, and
-a link to the userspace tools needed to get this to work.
-
----
- drivers/usb/Kconfig | 2
- drivers/usb/Makefile | 2
- drivers/usb/ip/Kconfig | 32 +
- drivers/usb/ip/Makefile | 13
- drivers/usb/ip/stub.h | 93 +++
- drivers/usb/ip/stub_dev.c | 419 +++++++++++++++++
- drivers/usb/ip/stub_main.c | 319 +++++++++++++
- drivers/usb/ip/stub_rx.c | 320 +++++++++++++
- drivers/usb/ip/stub_tx.c | 205 ++++++++
- drivers/usb/ip/usbip_common.c | 860 +++++++++++++++++++++++++++++++++++
- drivers/usb/ip/usbip_common.h | 392 ++++++++++++++++
- drivers/usb/ip/usbip_event.c | 147 ++++++
- drivers/usb/ip/vhci.h | 110 ++++
- drivers/usb/ip/vhci_hcd.c | 1026 ++++++++++++++++++++++++++++++++++++++++++
- drivers/usb/ip/vhci_rx.c | 149 ++++++
- drivers/usb/ip/vhci_sysfs.c | 265 ++++++++++
- drivers/usb/ip/vhci_tx.c | 165 ++++++
- 17 files changed, 4519 insertions(+)
-
---- gregkh-2.6.orig/drivers/usb/Kconfig
-+++ gregkh-2.6/drivers/usb/Kconfig
-@@ -81,6 +81,8 @@ source "drivers/usb/core/Kconfig"
-
- source "drivers/usb/host/Kconfig"
-
-+source "drivers/usb/ip/Kconfig"
-+
- source "drivers/usb/class/Kconfig"
-
- source "drivers/usb/storage/Kconfig"
---- gregkh-2.6.orig/drivers/usb/Makefile
-+++ gregkh-2.6/drivers/usb/Makefile
-@@ -17,6 +17,8 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
- obj-$(CONFIG_ETRAX_USB_HOST) += host/
- obj-$(CONFIG_USB_OHCI_AT91) += host/
-
-+obj-$(CONFIG_USB_IP) += ip/
-+
- obj-$(CONFIG_USB_ACM) += class/
- obj-$(CONFIG_USB_PRINTER) += class/
-
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/Kconfig
-@@ -0,0 +1,32 @@
-+#config USB_IP
-+# bool "USB IP support (EXPERIMENTAL)"
-+# depends on USB && EXPERIMENTAL
-+# default N
-+# ---help---
-+# This enables pushing USB packets over IP to allow remote
-+# machines access to USB devices directly. For more details,
-+# and links to the userspace utility programs to let this work
-+# properly, see http://usbip.naist.jp/
-+#
-+# If unsure, say N.
-+
-+config USB_IP_VHCI
-+ tristate "USB IP Host controller driver"
-+ depends on USB_IP
-+ ---help---
-+ This enables the USB IP host controller driver which will
-+ run on the client machine.
-+
-+ To compile this driver as a module, choose M here: the
-+ module will be called vhci-hcd.
-+
-+config USB_IP_STUB
-+ tristate "USB IP stub driver"
-+ depends on USB_IP
-+ ---help---
-+ This enables the USB IP device driver which will run on the
-+ host machine.
-+
-+ To compile this driver as a module, choose M here: the
-+ module will be called stub.
-+
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/Makefile
-@@ -0,0 +1,13 @@
-+# Makefile for the USB/IP driver
-+
-+obj-$(CONFIG_USB_IP_VHCI) += vhci-hcd.o
-+vhci-hcd-objs := usbip_common.o usbip_event.o vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o
-+
-+obj-$(CONFIG_USB_IP_STUB) += stub.o
-+stub-objs := usbip_common.o usbip_event.o stub_dev.o stub_main.o stub_rx.o stub_tx.o
-+
-+
-+ifeq ($(CONFIG_USB_DEBUG),y)
-+ EXTRA_CFLAGS += -DDEBUG
-+endif
-+
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/stub.h
-@@ -0,0 +1,93 @@
-+/*
-+ * $Id: stub.h 265 2005-09-01 09:24:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 <linux/list.h>
-+#include <linux/spinlock.h>
-+#include <linux/slab.h>
-+
-+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 StubPrivCache 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;
-+
-+};
-+
-+struct stub_priv {
-+ unsigned long seqnum;
-+ struct list_head list;
-+ struct stub_device *sdev;
-+ struct urb *urb;
-+
-+ /*
-+ * This flag is true between usb_submit_urb() and urb->complete()
-+ * to show a urb needs usb_unlink_urb().
-+ */
-+ atomic_t in_submit;
-+};
-+
-+extern kmem_cache_t *StubPrivCache;
-+
-+#if 0
-+enum stub_priv_list_operation {
-+ CLEAR_BY_SEQNUM,
-+ CLEAR_BY_SDEV,
-+ DUMP_ALL
-+} ;
-+
-+int stub_priv_list_data(struct stub_device *, enum stub_priv_list_operation operation, void *arg);
-+#endif
-+void stub_device_cleanup_urbs(struct stub_device *sdev);
-+
-+/*
-+ * 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_shutdown_connection(struct usbip_device *sdev);
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/stub_dev.c
-@@ -0,0 +1,419 @@
-+/*
-+ * $Id: stub_dev.c 265 2005-09-01 09:24:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 <linux/kernel.h>
-+#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);
-+
-+
-+/* Now all devices except USB Hub are claimed. */
-+static struct usb_device_id stub_table [] = {
-+#if 0
-+ { 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
-+ { .driver_info = 1 },
-+ { } /* Terminating entry */
-+};
-+
-+#include <linux/module.h>
-+MODULE_DEVICE_TABLE (usb, stub_table);
-+
-+/* usb specific object needed to register this driver with the usb subsystem */
-+struct usb_driver stub_driver = {
-+ .name = "usbip_stub",
-+ .probe = stub_probe,
-+ .disconnect = stub_disconnect,
-+ /* If id_table is null and any other driver claimed,
-+ * probe() is always called . */
-+ .id_table = stub_table,
-+};
-+
-+
-+
-+
-+
-+/* ------------------------------------------------------------ */
-+/* ------------------------------------------------------------ */
-+/* ------------------------------------------------------------ */
-+
-+
-+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) {
-+ VHCI_ERROR("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);
-+
-+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) {
-+ VHCI_ERROR("sdev is null\n");
-+ return -ENODEV;
-+ }
-+
-+ sscanf(buf, "%u", &sockfd);
-+
-+ if (sockfd != 0) {
-+ VHCI_INFO("stub up\n");
-+
-+ spin_lock(&sdev->ud.lock);
-+
-+ if (sdev->ud.status != SDEV_ST_AVAILABLE) {
-+ VHCI_ERROR("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 {
-+ VHCI_INFO("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 ssize_t show_sockfd(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct stub_device *sdev = dev_get_drvdata(dev);
-+
-+ if (!sdev) {
-+ VHCI_ERROR("sdev is null\n");
-+ return -ENODEV;
-+ }
-+
-+ return snprintf(buf, PAGE_SIZE, "%d\n", 0);
-+}
-+static DEVICE_ATTR(usbip_sockfd, S_IWUGO | S_IRUGO, show_sockfd, 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);
-+}
-+
-+
-+
-+/* ------------------------------------------------------------ */
-+/* ------------------------------------------------------------ */
-+/* ------------------------------------------------------------ */
-+
-+static void stub_shutdown_connection(struct usbip_device *ud)
-+{
-+ struct stub_device *sdev = container_of(ud, struct stub_device, ud);
-+
-+ /* 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 != NULL) {
-+ sock_release(ud->tcp_socket);
-+ ud->tcp_socket = NULL;
-+ }
-+
-+ /* 3. free used data */
-+ //stub_priv_list_data(sdev, CLEAR_BY_SDEV, NULL);
-+ stub_device_cleanup_urbs(sdev);
-+}
-+
-+
-+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) {
-+ VHCI_ERROR("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) {
-+ VHCI_ERROR("device reset\n");
-+ ud->status = SDEV_ST_ERROR;
-+
-+ } else {
-+ VHCI_INFO("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 *) kmalloc(sizeof(struct stub_device), GFP_KERNEL);
-+ if(!sdev) {
-+ VHCI_ERROR("no memory for stub_device\n");
-+ return NULL;
-+ }
-+
-+ memset(sdev, 0, sizeof(struct stub_device));
-+
-+ 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);
-+ sdev->priv_lock = SPIN_LOCK_UNLOCKED;
-+
-+ 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);
-+
-+ VHCI_DEBUG("register new interface\n");
-+ return sdev;
-+}
-+
-+static int stub_device_free(struct stub_device *sdev)
-+{
-+ if( !sdev ) return -EINVAL;
-+
-+ kfree(sdev);
-+ VHCI_DEBUG("kfree udev ok\n");
-+
-+ return 0;
-+}
-+
-+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;
-+
-+ VHCI_DEBUG("Enter\n");
-+
-+ /* We do not claim HUB device */
-+ if(udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
-+ VHCI_DEBUG("HUB device, we do no claim\n");
-+ return -ENOMEM;
-+ }
-+
-+#include <linux/string.h>
-+ if(strcmp(udev->bus->bus_name, "VHCI") == 0) {
-+ VHCI_DEBUG("dev's bus is VHCI, so do not go anymore!\n");
-+ return -ENOMEM;
-+ }
-+
-+
-+ if((sdev = stub_device_alloc(interface)) != NULL) {
-+ struct usb_device *udev = interface_to_usbdev(interface);
-+
-+ VHCI_INFO("USB/IP Stub: new inteface register, bus %u dev %u ifn %u\n",
-+ udev->bus->busnum, udev->devnum, interface->cur_altsetting->desc.bInterfaceNumber);
-+ } else {
-+ VHCI_ERROR("error \n"); return -ENOMEM;
-+ }
-+
-+
-+ /* init MUTEX LOCKED here? */
-+
-+
-+ {
-+ int i;
-+ for(i=0; i< interface->num_altsetting; i++) {
-+ VHCI_INFO("alt %u ", interface->altsetting[i].desc.bAlternateSetting);
-+ printk("NrEp %u ", interface->altsetting[i].desc.bNumEndpoints);
-+ printk("Cls %x ", interface->altsetting[i].desc.bInterfaceClass);
-+ printk("SCls %x ", interface->altsetting[i].desc.bInterfaceSubClass);
-+ printk("Pro %x ", interface->altsetting[i].desc.bInterfaceProtocol);
-+ printk("\n");
-+ }
-+ }
-+
-+
-+#if 0
-+ /* set dummy configuration value for being called stub_disconnect */
-+ /* Most devices have just one configration. */
-+ if(usb_set_configuration (udev, 0) < 0) {
-+ VHCI_ERROR("set_configuration failed\n");
-+ return -ENODEV;
-+ }
-+#endif
-+
-+ /* 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);
-+ //struct usb_device *udev = interface_to_usbdev(interface);
-+
-+ VHCI_DEBUG("Enter\n");
-+
-+ /* get stub_device */
-+ if(!sdev) BUG();
-+
-+ usb_set_intfdata(interface, NULL);
-+
-+
-+ /*
-+ * NOTE:
-+ * In future, rx/tx threads are invoked for each usb_device.
-+ * And, the Stub driver probes each usb_interface.
-+ *
-+ * But, a usb device driver is responsible for *a* usb_interace.
-+ * It's not a good solution.
-+ */
-+ 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);
-+
-+
-+ VHCI_DEBUG("bye\n");
-+}
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/stub_main.c
-@@ -0,0 +1,319 @@
-+/*
-+ * $Id: stub_main.c 265 2005-09-01 09:24:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 <linux/kernel.h>
-+#include "usbip_common.h"
-+#include "stub.h"
-+
-+/* Version Information */
-+#define DRIVER_VERSION "$Id: stub_main.c 265 2005-09-01 09:24:10Z taka-hir $"
-+#define DRIVER_AUTHOR "Takahiro Hirofuchi <taka-hir@is.naist.jp>"
-+#define DRIVER_DESC "Stub Driver for USB/IP"
-+
-+
-+
-+/* stub_priv is allocated from StubPrivCache */
-+kmem_cache_t *StubPrivCache = NULL;
-+
-+
-+static int __init usb_stub_init(void)
-+{
-+ int ret;
-+
-+ StubPrivCache = kmem_cache_create("stub_priv", sizeof(struct stub_priv),
-+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-+ if( !StubPrivCache ) {
-+ VHCI_ERROR("create stub_priv_cache\n");
-+ return -ENOMEM;
-+ }
-+
-+ ret = usb_register(&stub_driver);
-+ if(ret) {
-+ VHCI_ERROR("usb_register failed %d\n", ret);
-+ return ret;
-+ }
-+
-+
-+ info(DRIVER_DESC "" DRIVER_VERSION);
-+ return ret;
-+}
-+
-+
-+#if 0
-+static void free_priv_data(struct stub_priv *priv)
-+{
-+ int ret;
-+ struct urb *urb = priv->urb;
-+ VHCI_DEBUG("priv %p urb %p seq %lu\n", priv, urb, priv->seqnum);
-+
-+ /* A urb in HCD is unlinked asynchronously. */
-+ if(atomic_read(&priv->in_submit)) {
-+ /* this needs to be synchronous.
-+ * because it may free urb and etc before stub_complete is called.
-+ * stub_complete may touch a nulled urb.
-+ */
-+ ret = usb_unlink_urb(urb);
-+ if(ret != -EINPROGRESS) {
-+ uerr("usb_unlink_urb error, ret %d\n", ret);
-+ }
-+ }
-+
-+ /* free priv, buffers and the urb */
-+ list_del(&priv->list);
-+ kmem_cache_free(StubPrivCache, priv);
-+ if(urb->transfer_buffer != NULL)
-+ kfree(urb->transfer_buffer);
-+ if(urb->setup_packet != NULL)
-+ kfree(urb->setup_packet);
-+ usb_free_urb(urb);
-+}
-+
-+
-+static void free_list_data(struct list_head *listhead)
-+{
-+ struct stub_priv *priv, *tmp;
-+
-+ list_for_each_entry_safe(priv, tmp, listhead, list) {
-+ free_priv_data(priv);
-+ }
-+}
-+
-+static void free_list_data_by_seqnum(struct list_head *listhead, __u32 seqnum)
-+{
-+ struct stub_priv *priv, *tmp;
-+
-+ list_for_each_entry_safe(priv, tmp, listhead, list) {
-+ if(priv->seqnum == seqnum)
-+ free_priv_data(priv);
-+ }
-+}
-+
-+
-+static int dump_priv_data(struct list_head *listhead, char *out)
-+{
-+ struct list_head *ptr;
-+ struct stub_priv *priv;
-+ char *s = out;
-+
-+
-+ for(ptr = listhead->next; ptr != listhead; ptr = ptr->next) {
-+ priv = list_entry(ptr, struct stub_priv, list);
-+
-+ out += sprintf(out, "Sub ");
-+ out += sprintf(out, "%10lu ", priv->seqnum);
-+
-+ switch (usb_pipetype(priv->urb->pipe)) {
-+ case PIPE_CONTROL:
-+ out += sprintf(out, "%s ", "CTL");
-+ break;
-+ case PIPE_BULK:
-+ out += sprintf(out, "%s ", "BLK");
-+ break;
-+ case PIPE_INTERRUPT:
-+ out += sprintf(out, "%s ", "INT");
-+ break;
-+ case PIPE_ISOCHRONOUS:
-+ out += sprintf(out, "%s ", "ISO");
-+ break;
-+ }
-+
-+ if( usb_pipein(priv->urb->pipe) ) {
-+ out += sprintf(out, "%s ", "IN ");
-+ } else {
-+ out += sprintf(out, "%s ", "OUT");
-+ }
-+
-+ out += sprintf(out, "\n");
-+ }
-+
-+ return out - s;
-+}
-+#endif
-+
-+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(StubPrivCache, priv);
-+ if(urb->transfer_buffer != NULL)
-+ kfree(urb->transfer_buffer);
-+ if(urb->setup_packet != NULL)
-+ kfree(urb->setup_packet);
-+ usb_free_urb(urb);
-+
-+ }
-+}
-+
-+#if 0
-+static void free_priv_data(struct stub_priv *priv)
-+{
-+ int ret;
-+ struct urb *urb = priv->urb;
-+ VHCI_DEBUG("priv %p urb %p seq %lu\n", priv, urb, priv->seqnum);
-+
-+ /* A urb in HCD is unlinked asynchronously. */
-+ if(atomic_read(&priv->in_submit)) {
-+ /* this needs to be synchronous.
-+ * because it may free urb and etc before stub_complete is called.
-+ * stub_complete may touch a nulled urb.
-+ */
-+ ret = usb_unlink_urb(urb);
-+ if(ret != -EINPROGRESS) {
-+ uerr("usb_unlink_urb error, ret %d\n", ret);
-+ }
-+ }
-+
-+ /* free priv, buffers and the urb */
-+ list_del(&priv->list);
-+ kmem_cache_free(StubPrivCache, priv);
-+ if(urb->transfer_buffer != NULL)
-+ kfree(urb->transfer_buffer);
-+ if(urb->setup_packet != NULL)
-+ kfree(urb->setup_packet);
-+ usb_free_urb(urb);
-+}
-+
-+int stub_priv_list_data(struct stub_device *sdev, enum stub_priv_list_operation operation, void *arg)
-+{
-+ unsigned long flags;
-+ int ret = 0;
-+ __u32 seqnum;
-+ char *out, *s;
-+
-+ spin_lock_irqsave(&sdev->priv_lock, flags);
-+
-+ switch(operation) {
-+ case CLEAR_BY_SDEV:
-+ free_list_data(&sdev->priv_init);
-+ free_list_data(&sdev->priv_tx);
-+ free_list_data(&sdev->priv_free);
-+ break;
-+
-+ case CLEAR_BY_SEQNUM:
-+ seqnum = *((__u32 *) arg);
-+ free_list_data_by_seqnum(&sdev->priv_init, seqnum);
-+ free_list_data_by_seqnum(&sdev->priv_tx, seqnum);
-+ free_list_data_by_seqnum(&sdev->priv_free, seqnum);
-+ break;
-+
-+ case DUMP_ALL:
-+ out = (char *) arg;
-+ s = out;
-+ out += sprintf(out, "priv_init\n");
-+ out += dump_priv_data(&sdev->priv_init, out);
-+ out += sprintf(out+ret, "priv_tx\n");
-+ out += dump_priv_data(&sdev->priv_init, out);
-+ out += sprintf(out+ret, "priv_free\n");
-+ out += dump_priv_data(&sdev->priv_init, out);
-+ ret = out -s;
-+ break;
-+
-+ default:
-+ /* NOTREACHED */
-+ VHCI_ERROR("BUG\n");
-+ }
-+
-+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
-+
-+ return ret;
-+}
-+#endif
-+
-+
-+static void __exit usb_stub_exit(void)
-+{
-+ int ret;
-+
-+ VHCI_DEBUG("enter\n");
-+
-+
-+ /* deregister() calls stub_disconnect() for all devices. Device
-+ * specific data is cleared in stub_disconnect(). */
-+ usb_deregister(&stub_driver);
-+
-+
-+ ret = kmem_cache_destroy(StubPrivCache);
-+ if (ret != 0) {
-+ VHCI_ERROR("memory leak of stub_priv, %d\n", ret);
-+ }
-+
-+
-+ VHCI_DEBUG("bye\n");
-+}
-+
-+
-+
-+
-+module_init (usb_stub_init);
-+module_exit (usb_stub_exit);
-+
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/stub_rx.c
-@@ -0,0 +1,320 @@
-+/*
-+ * $Id: stub_rx.c 276 2005-11-22 08:06:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 check_clear_halt(struct urb *urb)
-+{
-+ struct usb_ctrlrequest *req;
-+
-+ if (usb_pipetype(urb->pipe) != PIPE_CONTROL) {
-+ dbg_stub_rx("not clear halt command\n");
-+ return;
-+ }
-+
-+ if (!urb->setup_packet) {
-+ dbg_stub_rx("no need for check clear halt\n");
-+ return;
-+ }
-+
-+ req = (struct usb_ctrlrequest *)urb->setup_packet;
-+
-+ if (req->bRequest == USB_REQ_CLEAR_FEATURE &&
-+ req->bRequestType == USB_RECIP_ENDPOINT &&
-+ req->wValue == USB_ENDPOINT_HALT) {
-+ /* CLEAR HALT command */
-+ /* the next line is wrong.
-+ * because we must clear halt of stalled endpoint. */
-+ //int endp = usb_pipeendpoint(urb->pipe);
-+
-+ /* wIndex is 2bytes and it has target endpoint number. */
-+ int endp = (req->wIndex & 0x000f );
-+ int in = (req->wIndex & 0x0080 ); /* include USB_DIR_IN bit */
-+ //int target_pipe = usb_rcvctrlpipe(urb->dev, endp);
-+ int target_pipe ;
-+ int ret;
-+
-+ if (in) {
-+ dbg_stub_rx("in\n");
-+ target_pipe = usb_rcvctrlpipe(urb->dev, endp);
-+ } else {
-+ dbg_stub_rx("out\n");
-+ target_pipe = usb_sndctrlpipe(urb->dev, endp);
-+ }
-+
-+ dbg_stub_rx("CLEAR HALT command, devnum %d endp %d\n", urb->dev->devnum, endp);
-+ ret = usb_clear_halt(urb->dev, target_pipe);
-+ if (ret == 0)
-+ VHCI_INFO("clear halt ep %d ok\n",endp);
-+ else
-+ VHCI_INFO("clear halt ep %d failed, ret %d\n", endp, ret);
-+ } else if (req->bRequest == USB_REQ_SET_INTERFACE &&
-+ req->bRequestType == USB_RECIP_INTERFACE) {
-+ /* SET INTERFACE command */
-+ __u16 alternate = req->wValue;
-+ __u16 interface = req->wIndex;
-+
-+ dbg_stub_rx("SET INTERFACE command, interface %u alternate %u\n", interface, alternate);
-+
-+ usb_set_interface(urb->dev, interface, alternate);
-+ } else {
-+ dbg_stub_rx("not a clear halt command\n");
-+ }
-+}
-+
-+static int stub_recv_unlink(struct stub_device *sdev, struct usbip_header *pdu)
-+{
-+ __u32 seqnum = pdu->u.unlink.seqnum;
-+ struct list_head *listhead = &sdev->priv_init;
-+ struct list_head *ptr;
-+ struct stub_priv *priv;
-+ struct urb *urb = NULL;
-+ int ret;
-+
-+ uinfo("recv_unlink: %d\n", seqnum);
-+
-+ spin_lock(&sdev->priv_lock);
-+
-+ for(ptr = listhead->next; ptr != listhead; ptr = ptr->next) {
-+ priv = list_entry(ptr, struct stub_priv, list);
-+ if (priv->seqnum == seqnum) {
-+ spin_unlock(&sdev->priv_lock);
-+ urb = priv->urb;
-+ break;
-+ }
-+ }
-+
-+ if (!urb){
-+ uinfo("An unlinking urb is already completed.\n");
-+ uinfo("Or, to begin with, stub did not recieve the urb\n");
-+ spin_unlock(&sdev->priv_lock);
-+ return 0;
-+ }
-+
-+ ret = usb_unlink_urb(urb);
-+ if (ret != -EINPROGRESS)
-+ uerr("faild to unlink a urb %p, ret %d\n", urb, ret);
-+
-+ spin_unlock(&sdev->priv_lock);
-+
-+ 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 void stub_recv_submit(struct stub_device *sdev, struct usbip_header *pdu)
-+{
-+ int ret;
-+ struct stub_priv *priv = NULL;
-+ struct usbip_device *ud = &sdev->ud;
-+
-+
-+ /*
-+ * After a stub_priv is linked to a list_head,
-+ * the error handler can free allocated data.
-+ */
-+ {
-+ unsigned long flag;
-+
-+ spin_lock_irqsave(&sdev->priv_lock, flag);
-+
-+ priv = kmem_cache_alloc(StubPrivCache, GFP_ATOMIC);
-+ if (!priv) {
-+ VHCI_ERROR("malloc stub_priv\n");
-+ spin_unlock_irqrestore(&sdev->priv_lock, flag);
-+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-+ return;
-+ }
-+ memset(priv, 0, sizeof(struct stub_priv));
-+
-+ priv->seqnum = pdu->base.seqnum;
-+ priv->sdev = sdev;
-+
-+
-+ list_add_tail(&priv->list, &sdev->priv_init);
-+ spin_unlock_irqrestore(&sdev->priv_lock, flag);
-+ }
-+
-+ /*
-+ * setup a urb
-+ */
-+ if (usb_pipeisoc(pdu->base.pipe))
-+ priv->urb = usb_alloc_urb(pdu->u.submit.number_of_packets, GFP_KERNEL);
-+ else
-+ priv->urb = usb_alloc_urb(0, GFP_KERNEL);
-+
-+ if (!priv->urb) {
-+ VHCI_ERROR("malloc urb\n");
-+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-+ return;
-+ }
-+
-+ /* set priv->urb->transfer_buffer */
-+ if (pdu->u.submit.transfer_buffer_length > 0) {
-+ priv->urb->transfer_buffer = kmalloc(pdu->u.submit.transfer_buffer_length, GFP_KERNEL);
-+ if (!priv->urb->transfer_buffer) {
-+ VHCI_ERROR("malloc x_buff\n");
-+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-+ return;
-+ }
-+ memset(priv->urb->transfer_buffer, 0, pdu->u.submit.transfer_buffer_length);
-+ }
-+
-+ /* set priv->urb->setup_packet */
-+ {
-+ priv->urb->setup_packet = kmalloc(8, GFP_KERNEL);
-+ if (!priv->urb->setup_packet) {
-+ VHCI_ERROR("allocate setup_packet\n");
-+ usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-+ return;
-+ }
-+ memset(priv->urb->setup_packet, 0, 8);
-+ memcpy(priv->urb->setup_packet, &pdu->u.submit.setup, 8);
-+ }
-+
-+ 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, VHC_C_SUBMIT, 0);
-+
-+
-+ if (usbip_recv_xbuff(ud, priv->urb) < 0)
-+ return;
-+
-+ if (usbip_recv_iso(ud, priv->urb) < 0)
-+ return;
-+
-+ check_clear_halt(priv->urb);
-+
-+ /*
-+ * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb().
-+ * By unlinking the urb asynchronously, stub_rx can continuously
-+ * process comming urbs. Even if the urb is unlinked, its completion
-+ * handler will be called and stub_tx will send a return pdu.
-+ */
-+
-+ atomic_set(&priv->in_submit, 1);
-+
-+ ret = usb_submit_urb(priv->urb, GFP_KERNEL);
-+
-+ if (ret == 0) {
-+ dbg_stub_rx("submit urb ok, seqnum %u\n", pdu->base.seqnum);
-+ } else {
-+ VHCI_ERROR("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)) {
-+ VHCI_ERROR("recv a header, %d\n", ret);
-+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-+ return;
-+ }
-+
-+ if (dbg_flag_stub_rx)
-+ usbip_dump_header(&pdu);
-+
-+ if (!valid_request(sdev, &pdu)) {
-+ VHCI_ERROR("recv invalid request\n");
-+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-+ return;
-+ }
-+
-+ switch (pdu.base.command) {
-+ case VHC_C_UNLINK:
-+ stub_recv_unlink(sdev, &pdu);
-+ break;
-+
-+ case VHC_C_SUBMIT:
-+ stub_recv_submit(sdev, &pdu);
-+ break;
-+
-+ default:
-+ /* NOTREACHED */
-+ VHCI_ERROR("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);
-+ }
-+}
-+
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/stub_tx.c
-@@ -0,0 +1,205 @@
-+/*
-+ * $Id: stub_tx.c 265 2005-09-01 09:24:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 DECLARE_WAIT_QUEUE_HEAD(waitq);
-+
-+/**
-+ * 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 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;
-+
-+ dbg_stub_tx("complete! status %d\n", urb->status);
-+
-+
-+ switch (urb->status) {
-+ case 0:
-+ /* OK */
-+ break;
-+ case -ENOENT:
-+ uinfo("stopped by a call to usb_kill_urb()\n");
-+ uinfo("because of cleaning up a virtual connection\n");
-+ return;
-+ case -ECONNRESET:
-+ uinfo("unlinked by a call to usb_unlink_urb()\n");
-+ break;
-+ case -EPIPE:
-+ uinfo("endpoint is stalled\n");
-+ break;
-+ default:
-+ VHCI_ERROR("NOT YET: completion with non-zero status %d\n", urb->status);
-+ }
-+
-+ /* link a urb to the queue of tx. */
-+ {
-+ unsigned long flags;
-+
-+ atomic_set(&priv->in_submit, 0);
-+
-+ spin_lock_irqsave(&sdev->priv_lock, flags);
-+ list_move_tail(&priv->list, &sdev->priv_tx);
-+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
-+ }
-+
-+ /* wake up tx_thread */
-+ wake_up(&waitq);
-+}
-+
-+static void setup_pdu(struct usbip_header *rpdu, struct urb *urb)
-+{
-+ struct stub_priv *priv = (struct stub_priv *) urb->context;
-+
-+ rpdu->base.command = VHC_C_RETURN;
-+ rpdu->base.pipe = urb->pipe;
-+ rpdu->base.seqnum = priv->seqnum;
-+
-+ usbip_pack_pdu(rpdu, urb, VHC_C_RETURN, 1);
-+}
-+
-+#define MAX_SUBMIT_QUEUE_DEPTH 100
-+static struct usbip_header ReturnPDU[MAX_SUBMIT_QUEUE_DEPTH];
-+
-+/* create msghdr to tx from the StubPrivListPendingTX queue */
-+static int stub_send_txdata(struct stub_device *sdev)
-+{
-+ unsigned long flags;
-+ struct stub_priv *priv, *tmp;
-+ size_t txsize = 0;
-+ int count = 0;
-+
-+ struct msghdr msg;
-+ struct iovec iov[MAX_SUBMIT_QUEUE_DEPTH];
-+
-+ memset(iov, 0, sizeof(iov));
-+ memset(&msg, 0, sizeof(msg));
-+ msg.msg_iov = iov;
-+ msg.msg_iovlen = 0;
-+
-+ memset(&ReturnPDU, 0, sizeof(struct usbip_header) * MAX_SUBMIT_QUEUE_DEPTH);
-+
-+ spin_lock_irqsave(&sdev->priv_lock, flags);
-+
-+ list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) {
-+ struct urb *urb = priv->urb;
-+
-+ dbg_stub_tx("setup txdata for urb %p\n", urb);
-+
-+ /* 1. setup usbip_header */
-+ setup_pdu(&ReturnPDU[count], urb);
-+
-+ iov[msg.msg_iovlen].iov_base = (void *) &ReturnPDU[count];
-+ iov[msg.msg_iovlen].iov_len = sizeof(struct usbip_header);
-+ msg.msg_iovlen++;
-+ txsize += sizeof(struct usbip_header);
-+
-+ /* 2. setup transfer buffer */
-+ if (usb_pipein(urb->pipe) && urb->transfer_buffer != NULL && urb->actual_length > 0) {
-+ iov[msg.msg_iovlen].iov_base = urb->transfer_buffer;
-+ iov[msg.msg_iovlen].iov_len = urb->actual_length;
-+ msg.msg_iovlen++;
-+ txsize += urb->actual_length;
-+ }
-+
-+ /* 3. setup iso_packet_descriptor */
-+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-+ iov[msg.msg_iovlen].iov_base = &urb->iso_frame_desc[0];
-+ iov[msg.msg_iovlen].iov_len = urb->number_of_packets * sizeof(struct usb_iso_packet_descriptor);
-+ msg.msg_iovlen++;
-+ txsize += urb->number_of_packets * sizeof(struct usb_iso_packet_descriptor);
-+ }
-+
-+ list_move_tail(&priv->list, &sdev->priv_free);
-+
-+
-+ count++;
-+ if (count == MAX_SUBMIT_QUEUE_DEPTH) {
-+ uinfo("max urbs are processed, %d\n", MAX_SUBMIT_QUEUE_DEPTH);
-+ break;
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
-+
-+ if (txsize > 0) {
-+ int ret;
-+ ret = usbip_sendmsg(sdev->ud.tcp_socket, &msg, txsize);
-+ if (ret != txsize) {
-+ VHCI_ERROR("vhci_sendmsg failed!, retval %d for %d\n", ret, txsize);
-+ usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
-+ return -1;
-+ }
-+
-+ dbg_stub_tx("send txdata \n");
-+ }
-+
-+
-+ spin_lock_irqsave(&sdev->priv_lock, flags);
-+
-+ list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
-+ struct urb *urb = priv->urb;
-+
-+ dbg_stub_tx("setup txdata for urb %p\n", urb);
-+
-+ kfree(urb->transfer_buffer);
-+ list_del(&priv->list);
-+ kmem_cache_free(StubPrivCache, priv);
-+
-+ usb_free_urb(urb);
-+ }
-+
-+ spin_unlock_irqrestore(&sdev->priv_lock, flags);
-+
-+ return txsize;
-+}
-+
-+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;
-+
-+ if (stub_send_txdata(sdev) < 0)
-+ break;
-+
-+ wait_event_interruptible(waitq, !list_empty(&sdev->priv_tx));
-+ }
-+}
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/usbip_common.c
-@@ -0,0 +1,860 @@
-+/*
-+ * $Id: usbip_common.c 265 2005-09-01 09:24:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 <linux/kernel.h>
-+#include <linux/file.h>
-+#include <linux/tcp.h>
-+#include "usbip_common.h"
-+
-+static void usbip_dump_buffer(char *, int size);
-+
-+/*
-+ * Send or receive packet.
-+ * 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) {
-+ VHCI_ERROR("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) {
-+ VHCI_DEBUG("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 usbip_sendmsg(struct socket *socket, struct msghdr *msg, int len)
-+{
-+ int rc = 0;
-+ mm_segment_t oldfs;
-+
-+ dbg_xmit("enter\n");
-+
-+ if (dbg_flag_xmit) {
-+ int i;
-+ for(i = 0; i < msg->msg_iovlen; i++) {
-+ usbip_dump_buffer(msg->msg_iov[i].iov_base,
-+ msg->msg_iov[i].iov_len);
-+ }
-+ }
-+
-+ if (socket) {
-+ oldfs = get_fs();
-+ set_fs(get_ds());
-+
-+ /* Try to avoid resource acquisition deadlocks by using GFP_ATOMIC. */
-+ socket->sk->sk_allocation = GFP_ATOMIC;
-+ //socket->sk->sk_allocation = GFP_NOIO;
-+
-+ /* FIXME: ought to loop handling short writes, unless a signal occurs */
-+ rc = sock_sendmsg(socket, msg, len);
-+
-+ set_fs(oldfs);
-+ }
-+
-+ return rc;
-+}
-+
-+
-+#if 0
-+static int usbip_recvmsg( struct socket *socket, struct msghdr *msg, int len )
-+{
-+ int rc = 0;
-+ mm_segment_t oldfs;
-+
-+ VHCI_DEBUG("Enter\n");
-+
-+ if (socket) {
-+ oldfs = get_fs();
-+ set_fs( get_ds() );
-+
-+ /* Try to avoid resource acquisition deadlocks by using GFP_ATOMIC. */
-+ socket->sk->allocation = GFP_ATOMIC;
-+
-+ /* FIXME: ought to loop handling short writes, unless a signal occurs */
-+ rc = sock_recvmsg(socket, msg, len);
-+
-+ set_fs( oldfs );
-+ }
-+
-+#ifdef CONFIG_USB_DEBUG
-+ {
-+ int i;
-+ for(i = 0; i < msg->msg_iovlen; i++) {
-+ usbip_dump_buffer(msg->msg_iov[i].iov_base,
-+ msg->msg_iov[i].iov_len);
-+ }
-+ }
-+#endif
-+
-+ return rc;
-+}
-+#endif
-+
-+
-+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");
-+/*
-+ printk("DT%d ", data ? 1 : 0);
-+ printk("%s ", speed ? "LOW" : "FULL");
-+*/
-+ 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)
-+{
-+ if (dev == NULL) {
-+ 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(" refcnt %d", dev->refcnt.counter);
-+ printk("\n");
-+
-+ printk(" ");
-+ {
-+ int i;
-+ for(i = 0; i < 16; i++) {
-+ printk(" %2u", i);
-+ }
-+ }
-+ printk("\n");
-+
-+ printk(" toggle0(IN) :");
-+ {
-+ int i;
-+ for(i = 0; i< 16; i++){
-+ printk(" %2u", ( dev->toggle[0] & (1 << i) ) ? 1 : 0);
-+ }
-+ }
-+ printk("\n");
-+
-+ printk(" toggle1(OUT):");
-+ {
-+ int i;
-+ for(i = 0; i< 16; i++){
-+ printk(" %2u", ( dev->toggle[1] & (1 << i) ) ? 1 : 0);
-+ }
-+ }
-+ printk("\n");
-+
-+
-+ {
-+ int i;
-+ printk(" epmaxp_in :");
-+ for(i = 0; i < 16; i++) {
-+ printk(" %2u", dev->ep_in[i]->desc.wMaxPacketSize);
-+ }
-+ printk("\n");
-+
-+ printk(" epmaxp_out :");
-+ for(i = 0; i < 16; 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 == NULL) {
-+ 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");
-+}
-+
-+static void usbip_dump_urb (struct urb *purb)
-+{
-+ if (!purb) {
-+ printk(" dump urb: null pointer!!\n");
-+ return;
-+ }
-+
-+ printk(" urb :%p\n", purb);
-+ //printk(" next :%p\n", purb->next);
-+ 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 != NULL && 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 setquickack(struct socket *socket)
-+{
-+ mm_segment_t oldfs;
-+ int ret = 1;
-+
-+ oldfs = get_fs();
-+ set_fs(get_ds());
-+ ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK, (char *) &ret, sizeof(ret));
-+ set_fs(oldfs);
-+}
-+
-+void setnodelay(struct socket *socket)
-+{
-+ mm_segment_t oldfs;
-+ int ret = 1;
-+
-+ oldfs = get_fs();
-+ set_fs(get_ds());
-+ ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY, (char *) &ret, sizeof(ret));
-+ set_fs(oldfs);
-+}
-+
-+void setkeepalive(struct socket *socket)
-+{
-+ mm_segment_t oldfs;
-+ int ret = 1;
-+
-+ oldfs = get_fs();
-+ set_fs(get_ds());
-+ ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &ret, sizeof(ret));
-+ set_fs(oldfs);
-+}
-+
-+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) {
-+ VHCI_ERROR("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;
-+}
-+
-+int set_sockaddr(struct socket *socket, struct sockaddr_storage *ss)
-+{
-+ int addrlen;
-+ int ret;
-+
-+ ret = socket->ops->getname(socket, (struct sockaddr *) ss, &addrlen, 1);
-+ if (ret) {
-+ VHCI_ERROR("getname failed, socket %p\n", socket);
-+ return ret;
-+ }
-+ return ret;
-+}
-+
-+#if 0
-+int sprintf_sockaddr(char *buf, struct sockaddr_storage *ss)
-+{
-+ int ret;
-+
-+ if (ss->ss_family == AF_INET) {
-+ struct sockaddr_in *v4addr = (struct sockaddr_in *) ss;
-+ ret = sprintf(buf, "%u.%u.%u.%u(%u)", NIPQUAD(v4addr->sin_addr),
-+ v4addr->sin_port);
-+
-+ } else if (ss->ss_family == AF_INET6) {
-+ struct sockaddr_in6 *v6addr = (struct sockaddr_in6 *) ss;
-+ ret = sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x(%d)",
-+ NIP6(v6addr->sin6_addr), v6addr->sin6_port);
-+
-+ } else {
-+ VHCI_ERROR("unknown sa_family %d", ss->ss_family);
-+ ret = -1;
-+ }
-+
-+ return ret;
-+}
-+#endif
-+
-+ssize_t socket_to_addrstr(struct socket *socket, char *buf)
-+{
-+ struct sockaddr uaddr;
-+ int uaddrlen;
-+ int ret;
-+
-+ ret = socket->ops->getname(socket, &uaddr, &uaddrlen, 1);
-+ if (ret) {
-+ VHCI_ERROR("getname failed, socket %p\n", socket);
-+ return ret;
-+ }
-+
-+ if (uaddr.sa_family == AF_INET) {
-+ struct sockaddr_in *v4addr = (struct sockaddr_in *) &uaddr;
-+ ret = sprintf(buf, "%u.%u.%u.%u", NIPQUAD(v4addr->sin_addr.s_addr));
-+ } else if (uaddr.sa_family == AF_INET6) {
-+ struct sockaddr_in6 *v6addr = (struct sockaddr_in6 *) &uaddr;
-+ ret = sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
-+ NIP6(v6addr->sin6_addr));
-+ } else {
-+ VHCI_ERROR("unknown sa_family %d\n", uaddr.sa_family);
-+ ret = -1;
-+ }
-+
-+ return ret;
-+}
-+
-+void usbip_dump_header(struct usbip_header *pdu)
-+{
-+ VHCI_DEBUG("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);
-+
-+#ifdef CONFIG_USB_DEBUG
-+ usbip_dump_pipe(pdu->base.pipe);
-+#endif
-+
-+ switch(pdu->base.command) {
-+ case VHC_C_SUBMIT:
-+ VHCI_DEBUG("SUBMIT: x_flags %u x_len %u bw %u sf %u #p %u iv %u\n",
-+ pdu->u.submit.transfer_flags,
-+ pdu->u.submit.transfer_buffer_length,
-+ pdu->u.submit.bandwidth,
-+ pdu->u.submit.start_frame,
-+ pdu->u.submit.number_of_packets,
-+ pdu->u.submit.interval);
-+ break;
-+ case VHC_C_UNLINK:
-+ VHCI_DEBUG("UNLINK: seq %u\n", pdu->u.unlink.seqnum);
-+ break;
-+ case VHC_C_RETURN:
-+ VHCI_DEBUG("RETURN: st %d x_flags %u al %u bw %u sf %d ec %d\n",
-+ pdu->u.ret.status,
-+ pdu->u.ret.transfer_flags,
-+ pdu->u.ret.actual_length,
-+ pdu->u.ret.bandwidth,
-+ pdu->u.ret.start_frame,
-+ pdu->u.ret.error_count);
-+ break;
-+ default:
-+ /* NOT REACHED */
-+ VHCI_DEBUG("UNKNOWN\n");
-+ }
-+}
-+
-+int usbip_thread(void *param)
-+{
-+ struct usbip_task *ut = (struct usbip_task *) param;
-+
-+ VHCI_DEBUG("Enter\n");
-+
-+ 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;
-+
-+ VHCI_DEBUG("bye\n");
-+
-+ 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);
-+ VHCI_DEBUG("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);
-+ VHCI_DEBUG("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;
-+}
-+
-+static void usbip_pack_submit_pdu(struct usbip_header *pdu, struct urb *urb, int pack)
-+{
-+ if (pack) {
-+ /* vhci_tx.c */
-+ pdu->u.submit.transfer_flags = urb->transfer_flags & ~URB_NO_TRANSFER_DMA_MAP & ~URB_NO_SETUP_DMA_MAP;
-+ pdu->u.submit.transfer_buffer_length = urb->transfer_buffer_length;
-+ pdu->u.submit.bandwidth = urb->bandwidth;
-+ pdu->u.submit.start_frame = urb->start_frame;
-+ pdu->u.submit.number_of_packets = urb->number_of_packets;
-+ pdu->u.submit.interval = urb->interval;
-+ } else {
-+ /* stub_rx.c */
-+ urb->transfer_flags = pdu->u.submit.transfer_flags;
-+ urb->transfer_buffer_length = pdu->u.submit.transfer_buffer_length;
-+ urb->bandwidth = pdu->u.submit.bandwidth;
-+ urb->start_frame = pdu->u.submit.start_frame;
-+ urb->number_of_packets = pdu->u.submit.number_of_packets;
-+ urb->interval = pdu->u.submit.interval;
-+ }
-+}
-+
-+static void usbip_pack_return_pdu(struct usbip_header *pdu, struct urb *urb, int pack)
-+{
-+ if (pack) {
-+ /* stub_tx.c */
-+ pdu->u.ret.transfer_flags = urb->transfer_flags;
-+ pdu->u.ret.status = urb->status;
-+ pdu->u.ret.actual_length = urb->actual_length;
-+ pdu->u.ret.bandwidth = urb->bandwidth;
-+ pdu->u.ret.start_frame = urb->start_frame;
-+
-+ pdu->u.ret.number_of_packets = urb->number_of_packets;
-+ } else {
-+ /* vhci_rx.c */
-+ urb->transfer_flags = pdu->u.ret.transfer_flags;
-+ urb->status = pdu->u.ret.status;
-+ urb->actual_length = pdu->u.ret.actual_length;
-+ urb->bandwidth = pdu->u.ret.bandwidth;
-+ urb->start_frame = pdu->u.ret.start_frame;
-+
-+ urb->error_count = pdu->u.ret.error_count;
-+ }
-+}
-+
-+void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd, int pack)
-+{
-+ switch(cmd) {
-+ case VHC_C_SUBMIT:
-+ usbip_pack_submit_pdu(pdu, urb, pack);
-+ break;
-+ case VHC_C_RETURN:
-+ usbip_pack_return_pdu(pdu, urb, pack);
-+ break;
-+ default:
-+ /* NOTREACHED */
-+ BUG();
-+ }
-+}
-+
-+/* some members of urb must be substituted before. */
-+int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
-+{
-+ int ret;
-+ char *iso_frame_desc = (char *) &urb->iso_frame_desc[0];
-+ int np = urb->number_of_packets;
-+ int size = np * sizeof(struct usb_iso_packet_descriptor);
-+
-+ if (!usb_pipeisoc(urb->pipe))
-+ return 0;
-+
-+ ret = usbip_xmit(0, ud->tcp_socket, iso_frame_desc, size, 0);
-+ if (ret != size ) {
-+ VHCI_ERROR("recv iso_frame_descriptor, %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;
-+}
-+
-+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;
-+}
-+
-+/* 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) {
-+ VHCI_ERROR("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;
-+}
-+
-+#ifdef CONFIG_USB_DEBUG
-+unsigned long usbip_debug_flag = 0xffff;
-+#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);
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/usbip_common.h
-@@ -0,0 +1,392 @@
-+/*
-+ * $Id: usbip_common.h 265 2005-09-01 09:24:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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
-+
-+#if 0
-+#include <linux/file.h>
-+#include <linux/in.h>
-+#include <linux/in6.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/sched.h>
-+#include <linux/signal.h>
-+#include <linux/smp_lock.h>
-+#include <linux/socket.h>
-+#include <linux/usb.h>
-+#include <net/sock.h>
-+#include <asm-i386/hardirq.h>
-+#include <asm/byteorder.h>
-+#include <asm/semaphore.h>
-+#include <asm/uaccess.h>
-+
-+#endif
-+
-+#include <linux/usb.h>
-+#include <net/sock.h>
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/*
-+ * define macros to print messages
-+ */
-+
-+/**
-+ * VHCI_DEBUG - 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)
-+
-+#define VHCI_DEBUG(fmt, args...) udbg(fmt , ##args)
-+
-+#else /* CONFIG_USB_DEBUG */
-+
-+#define udbg(fmt, args...) do{ }while(0)
-+#define VHCI_DEBUG(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)
-+
-+
-+/**
-+ * VHCI_ERROR - 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)
-+
-+#define VHCI_ERROR(fmt, args...) uerr(fmt , ##args)
-+
-+#if 0
-+#define VHCI_ERROR(fmt, args...) \
-+ do{ \
-+ if(!in_interrupt()) { \
-+ printk(KERN_ERR "%-10s:", current->comm); \
-+ } else { \
-+ printk(KERN_ERR "interrupt :"); \
-+ } \
-+ printk("usbip: ***ERROR*** (%s, %d, %s)", __FILE__, __LINE__, __FUNCTION__); \
-+ printk("usbip: " fmt , ## args); \
-+ }while(0)
-+#endif
-+
-+/**
-+ * VHCI_INFO - print information messages
-+ * @fmt:
-+ * @args:
-+ */
-+
-+#define uinfo(fmt, args...) \
-+ do { \
-+ printk(KERN_INFO "usbip: " fmt , ## args); \
-+ } while(0)
-+
-+#define VHCI_INFO(fmt, args...) \
-+ do { \
-+ printk(KERN_INFO "usbip: " fmt , ## args); \
-+ } while(0)
-+
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/*
-+ * USB/IP packet headers.
-+ * At now, we define 3 packet types:
-+ *
-+ * - SUBMIT transfers a USB request. This is corresponding to usb_submit_urb().
-+ *
-+ * - RETURN transfers a result of a USB request.
-+ *
-+ * - UNLINK transfers an unlink request of a pending USB request.
-+ * This is corresponding to usb_unlink_urb() but not yet implemented.
-+ *
-+ * TODO:
-+ *
-+ * - big endian or little endian, aligenment.
-+ * - inter-operability between other OSs
-+ * - UNLINK and other operations
-+ */
-+
-+/*
-+ * A basic header followed by other additional headers.
-+ */
-+struct usbip_header_basic {
-+#define VHC_C_SUBMIT 0x0001
-+#define VHC_C_RETURN 0x0002
-+#define VHC_C_UNLINK 0x0004
-+ __u32 command;
-+
-+ __u32 busnum;
-+ __u32 devnum;
-+ __u32 seqnum; /* seaquencial number which identifies URBs */
-+ __u32 pipe;
-+};
-+
-+/*
-+ * An additional header for a SUBMIT packet.
-+ */
-+struct usbip_header_submit {
-+ __u32 transfer_flags;
-+ __u32 transfer_buffer_length;
-+ __u32 bandwidth;
-+ __u32 start_frame;
-+ __u32 number_of_packets;
-+ __u32 interval;
-+ unsigned char setup[8]; /* CTRL only */
-+};
-+
-+/*
-+ * An additional header for a RETURN packet.
-+ */
-+struct usbip_header_return {
-+ __u32 status;
-+ __u32 transfer_flags;
-+ __u32 actual_length; /* returned data length */
-+ __u32 bandwidth;
-+ __u32 start_frame; /* ISO and INT */
-+ __u32 number_of_packets; /* ISO only */
-+ __u32 error_count; /* ISO only */
-+};
-+
-+/*
-+ * An additional header for a UNLINK packet.
-+ */
-+struct usbip_header_unlink {
-+ __u32 seqnum; /* URB's seqnum which will be unlinked */
-+};
-+
-+
-+/*
-+ * All usbip packets use a common header to keep code simple.
-+ */
-+struct usbip_header {
-+ struct usbip_header_basic base;
-+
-+ union {
-+ struct usbip_header_submit submit;
-+ struct usbip_header_return ret;
-+ struct usbip_header_unlink unlink;
-+ } u;
-+};
-+
-+
-+
-+
-+/*-------------------------------------------------------------------------*/
-+
-+
-+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;
-+}
-+
-+void setnodelay(struct socket *);
-+void setquickack(struct socket *);
-+void 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);
-+#define ss_v6_addr(x) (((struct sockaddr_in6 *) &(x))->sin6_addr)
-+#define ss_v6_port(x) (((struct sockaddr_in6 *) &(x))->sin6_port)
-+#define ss_v4_addr(x) (((struct sockaddr_in *) &(x))->sin_addr)
-+#define ss_v4_port(x) (((struct sockaddr_in *) &(x))->sin_port)
-+//int sprintf_sockaddr(char *buf, struct sockaddr_storage *ss);
-+
-+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,
-+};
-+
-+/* a common structure for stub_device and vhci_device */
-+struct usbip_device{
-+ enum usbip_side side;
-+
-+ enum {
-+ /* 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
-+ } status;
-+
-+ /* lock for status */
-+ spinlock_t lock;
-+
-+ struct socket *tcp_socket;
-+ struct sockaddr_storage tcp_ss;
-+
-+ 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);
-+/* 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);
-+
-+
-+/* 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
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/usbip_event.c
-@@ -0,0 +1,147 @@
-+/*
-+ * $Id: usbip_event.c 261 2005-08-30 10:49:17Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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;
-+
-+// if(eh->thread != NULL) {
-+// send_sig(SIGKILL, eh->thread, 1);
-+ wait_for_completion(&eh->thread_done);
-+ dbg_eh("usbip_eh has finished\n");
-+// }
-+
-+ dbg_eh("bye\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);
-+}
-+
-+
-+
-+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 */
-+ VHCI_ERROR("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");
-+ }
-+}
-+
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/vhci.h
-@@ -0,0 +1,110 @@
-+/*
-+ * $Id: vhci.h 249 2005-08-10 12:15:26Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 <linux/platform_device.h>
-+
-+#define VHCI_DEVICE_INFO_SIZE 80
-+
-+struct vhci_device {
-+ struct usb_device *udev;
-+
-+ __u32 busnum; /* remote bus num */
-+ __u32 devnum; /* remote dev num */
-+ __u32 infnum;
-+
-+ enum usb_device_speed speed;
-+
-+ char info[VHCI_DEVICE_INFO_SIZE];
-+
-+ __u32 rhport; /* root hub port number */
-+
-+ struct usbip_device ud;
-+
-+ /* vhci_priv is linked to any one of these lists. */
-+ spinlock_t priv_lock;
-+ struct list_head priv_tx;
-+ struct list_head priv_rx;
-+
-+ wait_queue_head_t waitq;
-+};
-+
-+
-+/* urb->hcpriv, use container_of() */
-+struct vhci_priv {
-+ unsigned long seqnum;
-+ struct list_head list;
-+
-+ struct vhci_device *vdev;
-+ struct urb *urb;
-+};
-+
-+
-+/*
-+ * 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 2
-+
-+/* for usb_bus.hcpriv */
-+struct vhci_hcd {
-+ struct usb_hcd hcd; /* must come first! */
-+ spinlock_t lock;
-+
-+ struct platform_device pdev;
-+
-+ u32 port_status[VHCI_NPORTS];
-+ int started;
-+ struct completion released;
-+ 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;
-+};
-+
-+
-+
-+/* vhci_hcd.c */
-+void rh_port_connect(int rhport, enum usb_device_speed speed);
-+void rh_port_disconnect(int rhport);
-+extern struct vhci_hcd *the_controller;
-+#define hardware (&the_controller->pdev.dev)
-+
-+struct vhci_device *port_to_vdev(__u32 port);
-+
-+void vhci_rx_loop(struct usbip_task *ut);
-+void vhci_tx_loop(struct usbip_task *ut);
-+
-+
-+/* vhci_sysfs.c */
-+extern struct attribute_group dev_attr_group;
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/vhci_hcd.c
-@@ -0,0 +1,1026 @@
-+/*
-+ * $Id: vhci_hcd.c 267 2005-09-02 17:21:42Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 "../core/hcd.h"
-+#include "vhci.h"
-+
-+#define DRIVER_VERSION " $Id: vhci_hcd.c 267 2005-09-02 17:21:42Z taka-hir $ "
-+#define DRIVER_AUTHOR "HIROFUCHI Takahiro <taka-hir@is.naist.jp>"
-+#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);
-+
-+
-+
-+
-+/* See usb gadget dummy hcd */
-+
-+
-+
-+
-+static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd)
-+{
-+ return (struct vhci_hcd *) (hcd->hcd_priv);
-+}
-+
-+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;
-+
-+
-+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);
-+}
-+
-+
-+
-+
-+
-+
-+/* 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 = __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;
-+
-+ /*
-+ * 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)
-+ VHCI_ERROR("invalid port number %d\n", wIndex);
-+ rhport = ((__u8 ) (wIndex & 0x00ff)) -1;
-+
-+ //dum = container_of (hcd, struct vhci_hcd, hcd);
-+ dum = hcd_to_vhci(hcd);
-+ spin_lock_irqsave (&dum->lock, flags);
-+ 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;
-+ 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) {
-+ VHCI_ERROR("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)) {
-+ VHCI_ERROR("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");
-+ VHCI_ERROR("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:
-+ VHCI_ERROR("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;
-+ }
-+
-+ spin_unlock_irqrestore (&dum->lock, flags);
-+
-+ dbg_vhci_rh("bye\n");
-+ return retval;
-+}
-+
-+
-+
-+
-+#define PORT_C_MASK \
-+ ((1 << USB_PORT_FEAT_C_CONNECTION) \
-+ | (1 << USB_PORT_FEAT_C_ENABLE) \
-+ | (1 << USB_PORT_FEAT_C_SUSPEND) \
-+ | (1 << USB_PORT_FEAT_C_OVER_CURRENT) \
-+ | (1 << USB_PORT_FEAT_C_RESET))
-+
-+/*
-+ * @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 changed, return 0.
-+ * If the number of ports is less than or equal to 6, return 1.
-+ */
-+static int vhci_hub_status (struct usb_hcd *hcd, char *buf)
-+{
-+ struct vhci_hcd *dum;
-+ unsigned long flags;
-+ int retval;
-+
-+ /* the enough buffer is allocated according to USB_MAXCHILDREN */
-+ unsigned long *event_bits = (unsigned long *) buf;
-+ int rhport;
-+ int changed = 0;
-+
-+
-+ *event_bits = 0;
-+ //dbg_vhci_rh("enter\n");
-+
-+ //dum = container_of (hcd, struct vhci_hcd, hcd);
-+ dum = hcd_to_vhci(hcd);
-+
-+ spin_lock_irqsave (&dum->lock, flags);
-+
-+ for(rhport = 0; rhport < VHCI_NPORTS; rhport++) {
-+
-+ if (!(dum->port_status[rhport] & PORT_C_MASK)) {
-+ /* The status of a port has not been changed, */
-+ //retval = 0;
-+ } else {
-+ /* The status of a port has been changed, */
-+ dbg_vhci_rh("port %d is changed\n", rhport);
-+
-+ *event_bits |= 1 << ( rhport + 1);
-+ //*buf = (1 << 1);
-+ dev_dbg (hardware, "port %d status 0x%08x has changes\n", rhport, dum->port_status[rhport]);
-+ //retval = 1;
-+ //
-+ changed = 1;
-+ }
-+#if 0
-+ if (!(dum->port_status[rhport] & PORT_C_MASK))
-+ /* The status of a port has not been changed, */
-+ retval = 0;
-+ else {
-+ /* The status of a port has been changed, */
-+ *buf = (1 << 1);
-+ dev_dbg (hardware, "port status 0x%08x has changes\n", dum->port_status[rhport]);
-+ retval = 1;
-+ }
-+#endif
-+ }
-+
-+ if (changed)
-+ retval = 1 + (VHCI_NPORTS / 8);
-+ else
-+ retval = 0;
-+
-+ spin_unlock_irqrestore (&dum->lock, flags);
-+
-+ //dbg_vhci_rh("event_bits %lx\n", *event_bits);
-+
-+ //dbg_vhci_rh("bye\n");
-+ return retval;
-+
-+}
-+
-+#if 0
-+int devnum_to_port(int devnum)
-+{
-+ int i;
-+ for(i=0; i< VHCI_NPORTS; i++ ) {
-+ if (the_controller->vdev[i].dev != NULL)
-+ if (the_controller->vdev[i].dev->devnum == devnum)
-+ return i;
-+ }
-+
-+ return -1;
-+}
-+
-+static void maybe_set_status (struct urb *urb, int status)
-+{
-+ spin_lock (&urb->lock);
-+ if (urb->status == -EINPROGRESS)
-+ urb->status = status;
-+ spin_unlock (&urb->lock);
-+}
-+#endif
-+
-+
-+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_read(&the_controller->seqnum);
-+ atomic_inc(&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);
-+ 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 ) {
-+ VHCI_ERROR("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 */
-+ VHCI_ERROR("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:
-+ //urb->hcpriv = NULL;
-+
-+ spin_unlock_irqrestore(&the_controller->lock, flags);
-+ usb_hcd_giveback_urb(&the_controller->hcd, 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.
-+ */
-+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) {
-+ 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);
-+ }
-+
-+ if (!vdev->ud.tcp_socket) {
-+ spin_unlock_irqrestore(&the_controller->lock, flags);
-+
-+ uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n", urb);
-+ usb_hcd_giveback_urb(&the_controller->hcd, urb, NULL);
-+ } else {
-+ spin_unlock_irqrestore(&the_controller->lock, flags);
-+ }
-+
-+ dbg_vhci_hc("leave\n");
-+ return 0;
-+}
-+
-+
-+static void vhci_device_unlink_all_urb(struct vhci_device *vdev)
-+{
-+ struct vhci_priv *priv, *tmp;
-+ struct urb *urb;
-+
-+ spin_lock(&vdev->priv_lock);
-+
-+ list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
-+ urb = priv->urb;
-+ list_del(&priv->list);
-+ kfree(priv);
-+
-+ urb->hcpriv = NULL;
-+
-+ /* FIXME:
-+ * Should i give back a urb to usbcore ?
-+ */
-+ spin_unlock(&vdev->priv_lock);
-+ usb_hcd_giveback_urb(&the_controller->hcd, urb, NULL);
-+ spin_lock(&vdev->priv_lock);
-+ }
-+
-+ list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) {
-+ urb = priv->urb;
-+ list_del(&priv->list);
-+ kfree(priv);
-+
-+ urb->hcpriv = NULL;
-+
-+ /* FIXME:
-+ * Should i give back a urb to usbcore ?
-+ */
-+ spin_unlock(&vdev->priv_lock);
-+ usb_hcd_giveback_urb(&the_controller->hcd, urb, NULL);
-+ spin_lock(&vdev->priv_lock);
-+ }
-+
-+ 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);
-+
-+
-+ 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");
-+
-+ /*
-+ * 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);
-+
-+ /* Comment out. See the upper NOTE */
-+#if 0
-+ /* the priv lists are freed */
-+ vhci_device_unlink_all_urb(vdev);
-+ uinfo("unlink all urbs\n");
-+#endif
-+
-+ 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;
-+
-+ //usbip_stop_threads(ud);
-+
-+ 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);
-+ vdev->priv_lock = SPIN_LOCK_UNLOCKED;
-+
-+ init_waitqueue_head(&vdev->waitq);
-+
-+ 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);
-+
-+ dbg_vhci_hc("enter vhci_start\n");
-+
-+ hcd->state = HC_STATE_RUNNING;
-+
-+ return 0;
-+}
-+
-+static void vhci_stop(struct usb_hcd *hcd)
-+{
-+ struct vhci_hcd *vhci = hcd_to_vhci(hcd);
-+
-+ dbg_vhci_hc("stop VHCI controller\n");
-+
-+ {
-+ __u32 rhport = 0;
-+ struct vhci_device *vdev;
-+
-+ for( rhport = 0 ; rhport < VHCI_NPORTS; rhport++) {
-+ 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;
-+}
-+
-+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,
-+ //.hub_suspend = vhci_hub_suspend,
-+ //.hub_resume = vhci_hub_resume,
-+};
-+
-+static int vhci_hcd_probe(struct device *dev)
-+{
-+ struct usb_hcd *hcd;
-+ struct platform_device *pdev;
-+ struct vhci_hcd *vhci;
-+ int ret;
-+
-+ uinfo("proving...\n");
-+
-+
-+ pdev = container_of(dev, struct platform_device, dev);
-+ dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
-+
-+
-+ /*
-+ * Allocate and initialize hcd.
-+ * Our private data is also allocated automatically.
-+ */
-+ hcd = usb_create_hcd(&vhci_hc_driver, dev, dev->bus_id);
-+ if (!hcd)
-+ return -ENOMEM;
-+
-+
-+ the_controller = vhci = hcd_to_vhci(hcd);
-+ {
-+ int port;
-+ for(port=0; port < VHCI_NPORTS; port++) {
-+ struct vhci_device *vdev = &vhci->vdev[port];
-+ vhci_device_init( vdev );
-+ vdev->rhport = port;
-+ }
-+ }
-+ atomic_set(&vhci->seqnum, 1);
-+ spin_lock_init(&vhci->lock);
-+
-+
-+
-+ hcd->product_desc = "USB/IP VHCI driver";
-+
-+
-+ /*
-+ * 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) {
-+ usb_put_hcd(hcd);
-+ return ret;
-+ }
-+
-+ sysfs_create_group(&hcd->self.controller->kobj, &dev_attr_group);
-+
-+ dbg_vhci_hc("bye\n");
-+ return 0;
-+}
-+
-+
-+static int vhci_hcd_remove(struct device *dev)
-+{
-+ struct usb_hcd *hcd;
-+
-+ hcd = dev_get_drvdata(dev);
-+
-+ /*
-+ * 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;
-+
-+ sysfs_remove_group(&hcd->self.controller->kobj, &dev_attr_group);
-+
-+ return 0;
-+}
-+
-+static int vhci_hcd_suspend(struct device *dev, pm_message_t state)
-+{
-+ struct usb_hcd *hcd;
-+
-+ dev_dbg(dev, "%s=n", __FUNCTION__);
-+ hcd = dev_get_drvdata(dev);
-+
-+#ifndef CONFIG_USB_SUSPEND
-+ uerr("Not yet supported!\n");
-+#endif
-+
-+ hcd->state = HC_STATE_SUSPENDED;
-+ return 0;
-+}
-+
-+static int vhci_hcd_resume(struct device *dev)
-+{
-+ struct usb_hcd *hcd;
-+
-+ dev_dbg(dev, "%s=n", __FUNCTION__);
-+ hcd = dev_get_drvdata(dev);
-+ hcd->state = HC_STATE_RUNNING;
-+
-+#ifndef CONFIG_USB_SUSPEND
-+ uerr("Not yet supported!\n");
-+#endif
-+
-+ usb_hcd_poll_rh_status(hcd);
-+ return 0;
-+}
-+
-+static struct device_driver vhci_driver = {
-+ .name = (char *) driver_name,
-+ .bus = &platform_bus_type,
-+ .probe = vhci_hcd_probe,
-+ .remove = vhci_hcd_remove,
-+ .suspend = vhci_hcd_suspend,
-+ .resume = vhci_hcd_resume,
-+};
-+
-+/*----------------------------------------------------------------------*/
-+
-+/* The VHCI 'device' is 'virtual';
-+ * it has no hardware and automatic detection.
-+ * We need to add this virtual device as a platform device arbitrarily:
-+ * 1. platform_device_register()
-+ * 2. vhci_driver.probe()
-+ */
-+static void the_pdev_release(struct device *dev)
-+{
-+ return;
-+}
-+
-+static struct platform_device the_pdev = {
-+ .name = "hc",
-+ .dev.driver = &vhci_driver,
-+ .dev.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 = driver_register(&vhci_driver);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = platform_device_register(&the_pdev);
-+ if (ret < 0) {
-+ driver_unregister(&vhci_driver);
-+ return ret;
-+ }
-+
-+ ret = vhci_driver.probe(&the_pdev.dev);
-+ if (ret < 0) {
-+ platform_device_unregister(&the_pdev);
-+ driver_unregister(&vhci_driver);
-+ }
-+
-+ dbg_vhci_hc("bye\n");
-+ return ret;
-+}
-+module_init(vhci_init);
-+
-+
-+static void __exit vhci_cleanup(void)
-+{
-+ dbg_vhci_hc("enter\n");
-+
-+ /* device_unregister will call vhci_driver.remove() */
-+ platform_device_unregister(&the_pdev);
-+ driver_unregister(&vhci_driver);
-+
-+ dbg_vhci_hc("bye\n");
-+}
-+module_exit(vhci_cleanup);
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/vhci_rx.c
-@@ -0,0 +1,149 @@
-+/*
-+ * $Id: vhci_rx.c 265 2005-09-01 09:24:10Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 "../core/hcd.h"
-+#include "vhci.h"
-+
-+/* get URB from transmitted 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_return(struct vhci_device *vdev, struct usbip_header *pdu)
-+{
-+ struct usbip_device *ud = &vdev->ud;
-+ struct urb *urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
-+
-+ if (!urb) {
-+ VHCI_ERROR("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
-+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-+ return;
-+ }
-+
-+
-+ /* unpack the pdu to a urb */
-+ usbip_pack_pdu(pdu, urb, VHC_C_RETURN, 0);
-+
-+ /* recv transfer buffer */
-+ if (usbip_recv_xbuff(ud, urb) < 0)
-+ return;
-+
-+ /* recv iso_packet_descriptor */
-+ if (usbip_recv_iso(ud, urb) < 0)
-+ return;
-+
-+ dbg_vhci_rx("now giveback urb %p\n", urb);
-+
-+ usb_hcd_giveback_urb(&the_controller->hcd, urb, NULL);
-+
-+ dbg_vhci_rx("Leave\n");
-+
-+ 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)) {
-+ VHCI_ERROR("recv a header, %d\n", ret);
-+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-+ return;
-+ }
-+
-+ if (dbg_flag_vhci_rx)
-+ usbip_dump_header(&pdu);
-+
-+ switch(pdu.base.command) {
-+ case VHC_C_RETURN:
-+ vhci_recv_return(vdev, &pdu);
-+ break;
-+ default:
-+ /* NOTREACHED */
-+ VHCI_ERROR("unknown pdu\n");
-+ 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);
-+ }
-+}
-+
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/vhci_sysfs.c
-@@ -0,0 +1,265 @@
-+/*
-+ * $Id: vhci_sysfs.c 260 2005-08-30 10:35:16Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 <linux/in.h>
-+#include <linux/in6.h>
-+#include "usbip_common.h"
-+#include "../core/hcd.h"
-+#include "vhci.h"
-+
-+
-+struct vhci_device *port_to_vdev(__u32 port)
-+{
-+ return &the_controller->vdev[port];
-+}
-+
-+
-+static int vhci_proc_vcdown(__u32 rhport)
-+{
-+ struct vhci_device *vdev = port_to_vdev(rhport);
-+
-+ dbg_vhci_sysfs("enter\n");
-+
-+ spin_lock(&vdev->priv_lock);
-+
-+ if (vdev->ud.status == VDEV_ST_NULL) {
-+ VHCI_ERROR("not connected %d\n", vdev->ud.status);
-+ spin_unlock(&vdev->priv_lock);
-+ return -EINVAL;
-+ }
-+
-+ spin_unlock(&vdev->priv_lock);
-+
-+ usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
-+
-+ return 0;
-+}
-+
-+static int vhci_proc_status(char *out)
-+{
-+ char *s = out;
-+ int i = 0;
-+
-+ /*
-+ * prt sta bus dev ipaddr port busid
-+ * 000 004 000 000 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx xxxxxx xxxxxxxxx...
-+ * 001 004 000 000 xxx.xxx.xxx.xxx xxxxxx xxxxxxxxx...
-+ */
-+
-+ out += sprintf(out, "prt sta spd bus dev ipaddr port busid\n");
-+
-+ if (!the_controller) {
-+ VHCI_ERROR("the_controller is NULL\n");
-+ return 0;
-+ }
-+
-+
-+ 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);
-+
-+ if (vdev->ud.tcp_ss.ss_family == AF_INET) {
-+ out += sprintf(out, "%03u.%03u.%03u.%03u ",
-+ NIPQUAD(ss_v4_addr(vdev->ud.tcp_ss)));
-+ out += sprintf(out, "%06d ", ss_v4_port(vdev->ud.tcp_ss));
-+
-+ } else if (vdev->ud.tcp_ss.ss_family == AF_INET6) {
-+ out += sprintf(out, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
-+ NIP6(ss_v6_addr(vdev->ud.tcp_ss)));
-+ out += sprintf(out, "%06d ", ss_v6_port(vdev->ud.tcp_ss));
-+
-+ } else {
-+ VHCI_ERROR("unknown ss_family %d\n", vdev->ud.tcp_ss.ss_family);
-+ }
-+
-+ out += sprintf(out, "%s", vdev->info);
-+
-+ } else {
-+ out += sprintf(out, "000 000 000 0000:0000:0000:0000:0000:0000:0000:0000 000000 xxx");
-+ }
-+
-+
-+ out += sprintf(out, "\n");
-+
-+ spin_unlock(&vdev->ud.lock);
-+ }
-+
-+
-+ return out - s ;
-+}
-+
-+
-+
-+
-+
-+
-+static int valid_args(__u32 rhport, __u32 busnum, __u32 devnum, enum usb_device_speed speed)
-+{
-+
-+ /* check rhport */
-+ if ((rhport < 0) || (rhport >= VHCI_NPORTS)) {
-+ VHCI_ERROR("invalid port %u\n", rhport);
-+ return -EINVAL;
-+ }
-+
-+ /* check busnum & devnum */
-+ if ((busnum<=0) || (busnum>=128) || (devnum<=0) || (devnum>=128)) {
-+ VHCI_ERROR("invalid busnum or portnum\n");
-+ return -EINVAL;
-+ }
-+
-+ /* check speed */
-+ switch(speed) {
-+ case USB_SPEED_LOW:
-+ case USB_SPEED_FULL:
-+ case USB_SPEED_HIGH:
-+ break;
-+
-+ default:
-+ VHCI_ERROR("invalid speed\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+
-+/* -------------------------------------------- */
-+
-+static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ return vhci_proc_status(buf);
-+}
-+static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
-+
-+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 < 0) || (rhport >= VHCI_NPORTS)) {
-+ VHCI_ERROR("invalid port %u\n", rhport);
-+ return -EINVAL;
-+ }
-+
-+ err = vhci_proc_vcdown(rhport);
-+ if (err < 0) {
-+ return -EINVAL;
-+ }
-+
-+ dbg_vhci_sysfs("Leave\n");
-+ return count;
-+}
-+static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach);
-+
-+static ssize_t store_attach(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-+{
-+ struct socket *socket;
-+ char info[VHCI_DEVICE_INFO_SIZE];
-+ __u32 rhport=0, sockfd=0, busnum=0, devnum=0, speed=0;
-+ struct vhci_device *vdev;
-+
-+ memset(info, 0, VHCI_DEVICE_INFO_SIZE);
-+ sscanf(buf, "%u %u %u %u %u %s", &rhport, &sockfd, &busnum, &devnum, &speed, info);
-+
-+ dbg_vhci_sysfs("rhport(%u) sockfd(%u) busnum(%u) devnum(%u) speed(%u)\n",
-+ rhport, sockfd, busnum, devnum, speed);
-+
-+ if (valid_args(rhport, busnum, devnum, speed) < 0) {
-+ return -EINVAL;
-+ }
-+
-+ /* check sockfd */
-+ socket = sockfd_to_socket(sockfd);
-+ if (!socket) {
-+ return -EINVAL;
-+ }
-+
-+ setnodelay(socket);
-+
-+ vdev = port_to_vdev(rhport);
-+
-+ /* begin a lock */
-+ spin_lock(&vdev->ud.lock);
-+
-+ if (vdev->ud.status != VDEV_ST_NULL) {
-+ spin_unlock(&vdev->ud.lock);
-+ VHCI_ERROR("port %d already used\n", rhport);
-+ return -EINVAL;
-+ }
-+
-+ VHCI_INFO("rhport(%u) sockfd(%u) busnum(%u) devnum(%u) speed(%u)\n",
-+ rhport, sockfd, busnum, devnum, speed);
-+ VHCI_INFO(" info: %s\n", info);
-+
-+ vdev->busnum = busnum;
-+ vdev->devnum = devnum;
-+ vdev->speed = speed;
-+ vdev->ud.tcp_socket = socket;
-+ set_sockaddr(socket, &vdev->ud.tcp_ss);
-+ vdev->ud.status = VDEV_ST_NOTASSIGNED;
-+ memcpy(vdev->info, info, VHCI_DEVICE_INFO_SIZE);
-+
-+ spin_unlock(&vdev->ud.lock);
-+ /* end the lock */
-+
-+ if (vdev->ud.tcp_ss.ss_family == AF_INET)
-+ VHCI_INFO("connected to %u.%u.%u.%u(%d)\n",
-+ NIPQUAD(ss_v4_addr(vdev->ud.tcp_ss)), ss_v4_port(vdev->ud.tcp_ss));
-+ else if (vdev->ud.tcp_ss.ss_family == AF_INET6)
-+ VHCI_INFO("connected to %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x(%d)",
-+ NIP6(ss_v6_addr(vdev->ud.tcp_ss)), ss_v6_port(vdev->ud.tcp_ss));
-+ else
-+ VHCI_ERROR("unknown ss_family %d\n", vdev->ud.tcp_ss.ss_family);
-+
-+
-+
-+ 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 = {
-+ //.name = "usbip",
-+ .attrs = dev_attrs,
-+};
-+
---- /dev/null
-+++ gregkh-2.6/drivers/usb/ip/vhci_tx.c
-@@ -0,0 +1,165 @@
-+/*
-+ * $Id: vhci_tx.c 260 2005-08-30 10:35:16Z taka-hir $
-+ *
-+ * Copyright (C) 2003-2005 Takahiro Hirofuchi <taka-hir@is.naist.jp>
-+ *
-+ *
-+ * 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 "../core/hcd.h"
-+#include "vhci.h"
-+
-+
-+/* @p: pipe whose dev number modified
-+ * @pdev: new devive number */
-+static unsigned long vhci_change_pipe_devnum(__u32 p, __u8 pdev)
-+{
-+ __u32 oldp;
-+ oldp = p;
-+
-+ if (pdev > 0x7f)
-+ VHCI_ERROR("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_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 = VHC_C_SUBMIT;
-+ pdup->base.busnum = vdev->busnum;
-+ pdup->base.devnum = vdev->devnum;
-+ pdup->base.seqnum = priv->seqnum;
-+ pdup->base.pipe = vhci_change_pipe_devnum(urb->pipe, vdev->devnum);
-+ usbip_pack_pdu(pdup, urb, VHC_C_SUBMIT, 1);
-+
-+ if (urb->setup_packet != NULL)
-+ memcpy(pdup->u.submit.setup, urb->setup_packet, 8);
-+}
-+
-+#define MAX_SUBMIT_QUEUE_DEPTH 100
-+static struct usbip_header SubmitPDU[MAX_SUBMIT_QUEUE_DEPTH];
-+
-+static int vhci_send_txdata(struct vhci_device *vdev)
-+{
-+ unsigned long flags;
-+ struct vhci_priv *priv, *tmp;
-+ size_t txsize = 0;
-+ int count = 0; /* the number of queued pdu */
-+
-+ struct msghdr msg;
-+ struct iovec iov[MAX_SUBMIT_QUEUE_DEPTH];
-+
-+ memset(iov, 0, sizeof(iov));
-+ memset(&msg, 0, sizeof(msg));
-+ msg.msg_iov = iov;
-+ msg.msg_iovlen = 0;
-+
-+ memset(&SubmitPDU, 0, sizeof(struct usbip_header)*MAX_SUBMIT_QUEUE_DEPTH);
-+
-+ spin_lock_irqsave(&vdev->priv_lock, flags);
-+
-+ /* setup txdata to msghdr from queued urbs */
-+ list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
-+ struct urb *urb = priv->urb;
-+
-+ dbg_vhci_tx("setup txdata %d for urb %p\n", count, urb);
-+
-+ /* 1. setup usbip_header */
-+ setup_pdu(&SubmitPDU[count], urb);
-+
-+ iov[msg.msg_iovlen].iov_base = (void *)&SubmitPDU[count];
-+ iov[msg.msg_iovlen].iov_len = sizeof(struct usbip_header);
-+ msg.msg_iovlen ++;
-+ txsize += sizeof(struct usbip_header);
-+
-+ /* 2. setup transfer buffer */
-+ if (!usb_pipein(urb->pipe) &&
-+ urb->transfer_buffer != NULL &&
-+ urb->transfer_buffer_length > 0) {
-+ iov[msg.msg_iovlen].iov_base = urb->transfer_buffer;
-+ iov[msg.msg_iovlen].iov_len = urb->transfer_buffer_length;
-+ msg.msg_iovlen++;
-+ txsize += urb->transfer_buffer_length;
-+ }
-+
-+ /* 3. setup iso_packet_descriptor */
-+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-+ iov[msg.msg_iovlen].iov_base = &urb->iso_frame_desc[0];
-+ iov[msg.msg_iovlen].iov_len = urb->number_of_packets * sizeof(struct usb_iso_packet_descriptor);
-+ msg.msg_iovlen++;
-+ txsize += urb->number_of_packets * sizeof(struct usb_iso_packet_descriptor);
-+ }
-+
-+ list_move_tail(&priv->list, &vdev->priv_rx);
-+
-+ count++;
-+ if (count == MAX_SUBMIT_QUEUE_DEPTH) {
-+ dbg_vhci_tx("max urbs are processed, %d\n", MAX_SUBMIT_QUEUE_DEPTH);
-+ break;
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&vdev->priv_lock,flags);
-+
-+ if (txsize > 0) {
-+ int ret;
-+ ret = usbip_sendmsg(vdev->ud.tcp_socket, &msg, txsize);
-+ if (ret != txsize) {
-+ VHCI_ERROR("vhci_sendmsg failed!, retval %d for %d\n", ret, txsize);
-+ usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
-+ return -1;
-+ }
-+
-+ dbg_vhci_tx("send txdata \n");
-+ }
-+
-+ return txsize;
-+}
-+
-+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)) {
-+ VHCI_INFO("vhci_tx signal catched\n");
-+ break;
-+ }
-+
-+ if (vhci_send_txdata(vdev) < 0)
-+ break;
-+
-+ wait_event_interruptible(vdev->waitq, !list_empty(&vdev->priv_tx));
-+ dbg_vhci_tx("pending urbs ?, now wake up\n");
-+ }
-+}