All four implementations of hubs (and root hubs) were very similar.
Replace them with a single implementation that uses callbacks for the
three custom parts (detect, reset, disconnect) of each type of hub.
---
src/usb-ehci.c | 100 ++++++++++++++++++++++++++---------------------------
src/usb-hub.c | 106 ++++++++++++++++++++++++++-----------------------------
src/usb-hub.h | 10 -----
src/usb-ohci.c | 82 ++++++++++++++++++-------------------------
src/usb-uhci.c | 75 ++++++++++++++++++---------------------
src/usb.c | 64 ++++++++++++++++++++++++++++++++-
src/usb.h | 25 ++++++++++++--
7 files changed, 253 insertions(+), 209 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c
index 8e3219f..1f683c8 100644
--- a/src/usb-ehci.c
+++ b/src/usb-ehci.c
@@ -13,7 +13,6 @@
#include "pci_regs.h" // PCI_BASE_ADDRESS_0
#include "usb.h" // struct usb_s
#include "farptr.h" // GET_FLATPTR
-#include "usb-hub.h" // struct usbhub_s
#include "usb-uhci.h" // init_uhci
#include "usb-ohci.h" // init_ohci
@@ -40,13 +39,17 @@ struct usb_ehci_s {
#define EHCI_TIME_POSTPOWER 20
#define EHCI_TIME_POSTRESET 2
-// Start processing of companion controllers for full/low speed devices
+// Check if need companion controllers for full/low speed devices
static void
-ehci_startcompanion(struct usb_ehci_s *cntl)
+ehci_note_port(struct usb_ehci_s *cntl)
{
+ if (--cntl->checkports)
+ // Ports still being detected.
+ return;
if (! cntl->legacycount)
// No full/low speed devices found.
return;
+ // Start companion controllers.
int i;
for (i=0; i<ARRAY_SIZE(cntl->companion); i++) {
u16 type = cntl->companion[i].type;
@@ -59,13 +62,11 @@ ehci_startcompanion(struct usb_ehci_s *cntl)
}
}
-static void
-init_ehci_port(void *data)
+// Check if device attached to port
+static int
+ehci_hub_detect(struct usbhub_s *hub, u32 port)
{
- struct usbhub_s *hub = data;
- u32 port = hub->port; // XXX - find better way to pass port
struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
-
u32 *portreg = &cntl->regs->portsc[port];
u32 portsc = readl(portreg);
@@ -92,15 +93,31 @@ init_ehci_port(void *data)
// XXX - if just powered up, need to wait for USB_TIME_ATTDB?
- // Reset port
+ // Begin reset on port
portsc = (portsc & ~PORT_PE) | PORT_RESET;
writel(portreg, portsc);
msleep(USB_TIME_DRSTR);
- mutex_lock(&cntl->usb.resetlock);
+ return 0;
+
+doneearly:
+ ehci_note_port(cntl);
+ return -1;
+}
+
+// Reset device on port
+static int
+ehci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+ struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
+ u32 *portreg = &cntl->regs->portsc[port];
+ u32 portsc = readl(portreg);
+
+ // Finish reset on port
portsc &= ~PORT_RESET;
writel(portreg, portsc);
msleep(EHCI_TIME_POSTRESET);
+ int rv = -1;
portsc = readl(portreg);
if (!(portsc & PORT_CONNECT))
// No longer connected
@@ -112,58 +129,39 @@ init_ehci_port(void *data)
goto resetfail;
}
- if (! --cntl->checkports)
- ehci_startcompanion(cntl);
-
- struct usb_pipe *pipe = usb_set_address(hub, port, USB_HIGHSPEED);
- if (!pipe) {
- writel(portreg, portsc & ~PORT_PE);
- mutex_unlock(&cntl->usb.resetlock);
- goto done;
- }
- mutex_unlock(&cntl->usb.resetlock);
-
- // Configure port
- int count = configure_usb_device(pipe);
- free_pipe(pipe);
- if (! count)
- // Disable port
- writel(portreg, portsc & ~PORT_PE);
- hub->devcount += count;
-done:
- hub->threads--;
- return;
-
+ rv = USB_HIGHSPEED;
resetfail:
- mutex_unlock(&cntl->usb.resetlock);
-doneearly:
- if (! --cntl->checkports)
- ehci_startcompanion(cntl);
- goto done;
+ ehci_note_port(cntl);
+ return rv;
+}
+
+// Disable port
+static void
+ehci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+ struct usb_ehci_s *cntl = container_of(hub->cntl, struct usb_ehci_s, usb);
+ u32 *portreg = &cntl->regs->portsc[port];
+ u32 portsc = readl(portreg);
+ writel(portreg, portsc & ~PORT_PE);
}
+static struct usbhub_op_s ehci_HubOp = {
+ .detect = ehci_hub_detect,
+ .reset = ehci_hub_reset,
+ .disconnect = ehci_hub_disconnect,
+};
+
// Find any devices connected to the root hub.
static int
check_ehci_ports(struct usb_ehci_s *cntl)
{
ASSERT32FLAT();
-
- // Launch a thread for every port.
struct usbhub_s hub;
memset(&hub, 0, sizeof(hub));
hub.cntl = &cntl->usb;
- int ports = cntl->checkports;
- hub.threads = ports;
- int i;
- for (i=0; i<ports; i++) {
- hub.port = i;
- run_thread(init_ehci_port, &hub);
- }
-
- // Wait for threads to complete.
- while (hub.threads)
- yield();
-
+ hub.portcount = cntl->checkports;
+ hub.op = &ehci_HubOp;
+ usb_enumerate(&hub);
return hub.devcount;
}
diff --git a/src/usb-hub.c b/src/usb-hub.c
index 9effbc3..1586bac 100644
--- a/src/usb-hub.c
+++ b/src/usb-hub.c
@@ -28,7 +28,7 @@ set_port_feature(struct usbhub_s *hub, int port, int feature)
req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
req.bRequest = USB_REQ_SET_FEATURE;
req.wValue = feature;
- req.wIndex = port;
+ req.wIndex = port + 1;
req.wLength = 0;
mutex_lock(&hub->lock);
int ret = send_default_control(hub->pipe, &req, NULL);
@@ -43,7 +43,7 @@ clear_port_feature(struct usbhub_s *hub, int port, int feature)
req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
req.bRequest = USB_REQ_CLEAR_FEATURE;
req.wValue = feature;
- req.wIndex = port;
+ req.wIndex = port + 1;
req.wLength = 0;
mutex_lock(&hub->lock);
int ret = send_default_control(hub->pipe, &req, NULL);
@@ -58,7 +58,7 @@ get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER;
req.bRequest = USB_REQ_GET_STATUS;
req.wValue = 0;
- req.wIndex = port;
+ req.wIndex = port + 1;
req.wLength = sizeof(*sts);
mutex_lock(&hub->lock);
int ret = send_default_control(hub->pipe, &req, sts);
@@ -66,12 +66,10 @@ get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
return ret;
}
-static void
-init_hub_port(void *data)
+// Check if device attached to port
+static int
+usb_hub_detect(struct usbhub_s *hub, u32 port)
{
- struct usbhub_s *hub = data;
- u32 port = hub->port; // XXX - find better way to pass port
-
// Turn on power to port.
int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER);
if (ret)
@@ -92,29 +90,48 @@ init_hub_port(void *data)
break;
if (check_time(end))
// No device found.
- goto done;
+ return -1;
msleep(5);
}
// XXX - wait USB_TIME_ATTDB time?
- // Reset port.
- mutex_lock(&hub->cntl->resetlock);
- ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET);
+ return 0;
+
+fail:
+ dprintf(1, "Failure on hub port %d detect\n", port);
+ return -1;
+}
+
+// Disable port
+static void
+usb_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+ int ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
+ if (ret)
+ dprintf(1, "Failure on hub port %d disconnect\n", port);
+}
+
+// Reset device on port
+static int
+usb_hub_reset(struct usbhub_s *hub, u32 port)
+{
+ int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET);
if (ret)
- goto resetfail;
+ goto fail;
// Wait for reset to complete.
- end = calc_future_tsc(USB_TIME_DRST * 2);
+ struct usb_port_status sts;
+ u64 end = calc_future_tsc(USB_TIME_DRST * 2);
for (;;) {
ret = get_port_status(hub, port, &sts);
if (ret)
- goto resetfail;
+ goto fail;
if (!(sts.wPortStatus & USB_PORT_STAT_RESET))
break;
if (check_time(end)) {
warn_timeout();
- goto resetfail;
+ goto fail;
}
msleep(5);
}
@@ -122,37 +139,23 @@ init_hub_port(void *data)
// Reset complete.
if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION))
// Device no longer present
- goto resetfail;
-
- // Set address of port
- struct usb_pipe *pipe = usb_set_address(
- hub, port, ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
- >> USB_PORT_STAT_SPEED_SHIFT));
- if (!pipe)
- goto resetfail;
- mutex_unlock(&hub->cntl->resetlock);
-
- // Configure the device
- int count = configure_usb_device(pipe);
- free_pipe(pipe);
- if (!count) {
- ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
- if (ret)
- goto fail;
- }
- hub->devcount += count;
-done:
- hub->threads--;
- return;
-
-resetfail:
- clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
- mutex_unlock(&hub->cntl->resetlock);
+ return -1;
+
+ return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
+ >> USB_PORT_STAT_SPEED_SHIFT);
+
fail:
- dprintf(1, "Failure on hub port %d setup\n", port);
- goto done;
+ dprintf(1, "Failure on hub port %d reset\n", port);
+ usb_hub_disconnect(hub, port);
+ return -1;
}
+static struct usbhub_op_s HubOp = {
+ .detect = usb_hub_detect,
+ .reset = usb_hub_reset,
+ .disconnect = usb_hub_disconnect,
+};
+
// Configure a usb hub and then find devices connected to it.
int
usb_hub_init(struct usb_pipe *pipe)
@@ -171,18 +174,9 @@ usb_hub_init(struct usb_pipe *pipe)
hub.pipe = pipe;
hub.cntl = pipe->cntl;
hub.powerwait = desc.bPwrOn2PwrGood * 2;
-
- // Launch a thread for every port.
- int i;
- for (i=1; i<=desc.bNbrPorts; i++) {
- hub.port = i;
- hub.threads++;
- run_thread(init_hub_port, &hub);
- }
-
- // Wait for threads to complete.
- while (hub.threads)
- yield();
+ hub.portcount = desc.bNbrPorts;
+ hub.op = &HubOp;
+ usb_enumerate(&hub);
dprintf(1, "Initialized USB HUB (%d ports used)\n", hub.devcount);
if (hub.devcount)
diff --git a/src/usb-hub.h b/src/usb-hub.h
index 0994320..7672028 100644
--- a/src/usb-hub.h
+++ b/src/usb-hub.h
@@ -1,16 +1,6 @@
#ifndef __USB_HUB_H
#define __USB_HUB_H
-struct usbhub_s {
- struct usb_pipe *pipe;
- struct usb_s *cntl;
- struct mutex_s lock;
- u32 powerwait;
- u32 port;
- u32 threads;
- u32 devcount;
-};
-
// usb-hub.c
struct usb_pipe;
int usb_hub_init(struct usb_pipe *pipe);
diff --git a/src/usb-ohci.c b/src/usb-ohci.c
index 71ae561..43fe238 100644
--- a/src/usb-ohci.c
+++ b/src/usb-ohci.c
@@ -11,7 +11,6 @@
#include "pci_regs.h" // PCI_BASE_ADDRESS_0
#include "usb.h" // struct usb_s
#include "farptr.h" // GET_FLATPTR
-#include "usb-hub.h" // struct usbhub_s
#define FIT (1 << 31)
@@ -25,23 +24,36 @@ struct usb_ohci_s {
* Root hub
****************************************************************/
-static void
-init_ohci_port(void *data)
+// Check if device attached to port
+static int
+ohci_hub_detect(struct usbhub_s *hub, u32 port)
{
- struct usbhub_s *hub = data;
- u32 port = hub->port; // XXX - find better way to pass port
struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
-
u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
if (!(sts & RH_PS_CCS))
// No device.
- goto done;
+ return -1;
// XXX - need to wait for USB_TIME_ATTDB if just powered up?
- // Signal reset
- mutex_lock(&cntl->usb.resetlock);
+ return 0;
+}
+
+// Disable port
+static void
+ohci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+ struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
+ writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
+}
+
+// Reset device on port
+static int
+ohci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+ struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS);
+ u32 sts;
u64 end = calc_future_tsc(USB_TIME_DRSTR * 2);
for (;;) {
sts = readl(&cntl->regs->roothub_portstatus[port]);
@@ -51,39 +63,25 @@ init_ohci_port(void *data)
if (check_time(end)) {
// Timeout.
warn_timeout();
- goto resetfail;
+ ohci_hub_disconnect(hub, port);
+ return -1;
}
yield();
}
if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES))
// Device no longer present
- goto resetfail;
-
- // Set address of port
- struct usb_pipe *pipe = usb_set_address(hub, port, !!(sts & RH_PS_LSDA));
- if (!pipe)
- goto resetfail;
- mutex_unlock(&cntl->usb.resetlock);
-
- // Configure the device
- int count = configure_usb_device(pipe);
- free_pipe(pipe);
- if (! count)
- // Shutdown port
- writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
- hub->devcount += count;
-done:
- hub->threads--;
- return;
+ return -1;
-resetfail:
- // Shutdown port
- writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
- mutex_unlock(&cntl->usb.resetlock);
- goto done;
+ return !!(sts & RH_PS_LSDA);
}
+static struct usbhub_op_s ohci_HubOp = {
+ .detect = ohci_hub_detect,
+ .reset = ohci_hub_reset,
+ .disconnect = ohci_hub_disconnect,
+};
+
// Find any devices connected to the root hub.
static int
check_ohci_ports(struct usb_ohci_s *cntl)
@@ -97,22 +95,12 @@ check_ohci_ports(struct usb_ohci_s *cntl)
msleep((rha >> 24) * 2);
// XXX - need to sleep for USB_TIME_SIGATT if just powered up?
- // Lanuch a thread per port.
struct usbhub_s hub;
memset(&hub, 0, sizeof(hub));
hub.cntl = &cntl->usb;
- int ports = rha & RH_A_NDP;
- hub.threads = ports;
- int i;
- for (i=0; i<ports; i++) {
- hub.port = i;
- run_thread(init_ohci_port, &hub);
- }
-
- // Wait for threads to complete.
- while (hub.threads)
- yield();
-
+ hub.portcount = rha & RH_A_NDP;
+ hub.op = &ohci_HubOp;
+ usb_enumerate(&hub);
return hub.devcount;
}
diff --git a/src/usb-uhci.c b/src/usb-uhci.c
index 4e0c276..b05e09a 100644
--- a/src/usb-uhci.c
+++ b/src/usb-uhci.c
@@ -12,7 +12,6 @@
#include "pci_regs.h" // PCI_BASE_ADDRESS_4
#include "usb.h" // struct usb_s
#include "farptr.h" // GET_FLATPTR
-#include "usb-hub.h" // struct usbhub_s
struct usb_uhci_s {
struct usb_s usb;
@@ -26,55 +25,59 @@ struct usb_uhci_s {
* Root hub
****************************************************************/
-static void
-init_uhci_port(void *data)
+// Check if device attached to a given port
+static int
+uhci_hub_detect(struct usbhub_s *hub, u32 port)
{
- struct usbhub_s *hub = data;
- u32 port = hub->port; // XXX - find better way to pass port
struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
u16 status = inw(ioport);
if (!(status & USBPORTSC_CCS))
// No device
- goto done;
+ return -1;
// XXX - if just powered up, need to wait for USB_TIME_ATTDB?
- // Reset port
+ // Begin reset on port
outw(USBPORTSC_PR, ioport);
msleep(USB_TIME_DRSTR);
- mutex_lock(&cntl->usb.resetlock);
+ return 0;
+}
+
+// Reset device on port
+static int
+uhci_hub_reset(struct usbhub_s *hub, u32 port)
+{
+ struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
+ u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
+
+ // Finish reset on port
outw(0, ioport);
udelay(6); // 64 high-speed bit times
- status = inw(ioport);
+ u16 status = inw(ioport);
if (!(status & USBPORTSC_CCS))
// No longer connected
- goto resetfail;
+ return -1;
outw(USBPORTSC_PE, ioport);
- struct usb_pipe *pipe = usb_set_address(
- hub, port, !!(status & USBPORTSC_LSDA));
- if (!pipe)
- goto resetfail;
- mutex_unlock(&cntl->usb.resetlock);
-
- // Configure port
- int count = configure_usb_device(pipe);
- free_pipe(pipe);
- if (! count)
- // Disable port
- outw(0, ioport);
- hub->devcount += count;
-done:
- hub->threads--;
- return;
-
-resetfail:
+ return !!(status & USBPORTSC_LSDA);
+}
+
+// Disable port
+static void
+uhci_hub_disconnect(struct usbhub_s *hub, u32 port)
+{
+ struct usb_uhci_s *cntl = container_of(hub->cntl, struct usb_uhci_s, usb);
+ u16 ioport = cntl->iobase + USBPORTSC1 + port * 2;
outw(0, ioport);
- mutex_unlock(&cntl->usb.resetlock);
- goto done;
}
+static struct usbhub_op_s uhci_HubOp = {
+ .detect = uhci_hub_detect,
+ .reset = uhci_hub_reset,
+ .disconnect = uhci_hub_disconnect,
+};
+
// Find any devices connected to the root hub.
static int
check_uhci_ports(struct usb_uhci_s *cntl)
@@ -83,17 +86,9 @@ check_uhci_ports(struct usb_uhci_s *cntl)
struct usbhub_s hub;
memset(&hub, 0, sizeof(hub));
hub.cntl = &cntl->usb;
- hub.threads = 2;
-
- // Launch a thread for every port.
- run_thread(init_uhci_port, &hub);
- hub.port = 1;
- run_thread(init_uhci_port, &hub);
-
- // Wait for threads to complete.
- while (hub.threads)
- yield();
-
+ hub.portcount = 2;
+ hub.op = &uhci_HubOp;
+ usb_enumerate(&hub);
return hub.devcount;
}
diff --git a/src/usb.c b/src/usb.c
index 8b3c36e..694ea28 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -242,7 +242,7 @@ set_configuration(struct usb_pipe *pipe, u16 val)
// Assign an address to a device in the default state on the given
// controller.
-struct usb_pipe *
+static struct usb_pipe *
usb_set_address(struct usbhub_s *hub, int port, int speed)
{
ASSERT32FLAT();
@@ -299,7 +299,7 @@ usb_set_address(struct usbhub_s *hub, int port, int speed)
// Called for every found device - see if a driver is available for
// this device and do setup if so.
-int
+static int
configure_usb_device(struct usb_pipe *pipe)
{
ASSERT32FLAT();
@@ -356,6 +356,66 @@ fail:
return 0;
}
+static void
+usb_init_hub_port(void *data)
+{
+ struct usbhub_s *hub = data;
+ u32 port = hub->port; // XXX - find better way to pass port
+
+ // Detect if device present (and possibly start reset)
+ int ret = hub->op->detect(hub, port);
+ if (ret)
+ // No device present
+ goto done;
+
+ // Reset port and determine device speed
+ mutex_lock(&hub->cntl->resetlock);
+ ret = hub->op->reset(hub, port);
+ if (ret < 0)
+ // Reset failed
+ goto resetfail;
+
+ // Set address of port
+ struct usb_pipe *pipe = usb_set_address(hub, port, ret);
+ if (!pipe) {
+ hub->op->disconnect(hub, port);
+ goto resetfail;
+ }
+ mutex_unlock(&hub->cntl->resetlock);
+
+ // Configure the device
+ int count = configure_usb_device(pipe);
+ free_pipe(pipe);
+ if (!count)
+ hub->op->disconnect(hub, port);
+ hub->devcount += count;
+done:
+ hub->threads--;
+ return;
+
+resetfail:
+ mutex_unlock(&hub->cntl->resetlock);
+ goto done;
+}
+
+void
+usb_enumerate(struct usbhub_s *hub)
+{
+ u32 portcount = hub->portcount;
+ hub->threads = portcount;
+
+ // Launch a thread for every port.
+ int i;
+ for (i=0; i<portcount; i++) {
+ hub->port = i;
+ run_thread(usb_init_hub_port, hub);
+ }
+
+ // Wait for threads to complete.
+ while (hub->threads)
+ yield();
+}
+
void
usb_setup(void)
{
diff --git a/src/usb.h b/src/usb.h
index b5cbf2e..f28a3a7 100644
--- a/src/usb.h
+++ b/src/usb.h
@@ -4,6 +4,7 @@
#include "util.h" // struct mutex_s
+// Information on a USB end point.
struct usb_pipe {
struct usb_s *cntl;
u8 type;
@@ -24,6 +25,26 @@ struct usb_s {
u8 maxaddr;
};
+// Information for enumerating USB hubs
+struct usbhub_s {
+ struct usbhub_op_s *op;
+ struct usb_pipe *pipe;
+ struct usb_s *cntl;
+ struct mutex_s lock;
+ u32 powerwait;
+ u32 port;
+ u32 threads;
+ u32 portcount;
+ u32 devcount;
+};
+
+// Hub callback (32bit) info
+struct usbhub_op_s {
+ int (*detect)(struct usbhub_s *hub, u32 port);
+ int (*reset)(struct usbhub_s *hub, u32 port);
+ void (*disconnect)(struct usbhub_s *hub, u32 port);
+};
+
#define USB_TYPE_UHCI 1
#define USB_TYPE_OHCI 2
#define USB_TYPE_EHCI 3
@@ -175,9 +196,7 @@ struct usb_endpoint_descriptor {
// usb.c
void usb_setup(void);
-struct usbhub_s;
-struct usb_pipe *usb_set_address(struct usbhub_s *hub, int port, int speed);
-int configure_usb_device(struct usb_pipe *pipe);
+void usb_enumerate(struct usbhub_s *hub);
int send_default_control(struct usb_pipe *pipe, const struct usb_ctrlrequest *req
, void *data);
int usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize);
--
1.6.6.1