#include "transport.h"
#define TRACE_TAG TRACE_USB
+#define DEBUG_URB 0
+#define LOG_DEBUG_URB(args...) do { if (DEBUG_URB) LOG_DEBUG(args); } while (0)
+
#define URB_TRANSFER_TIMEOUT 0
#define USB_DEV_BASE_PATH "/dev/bus/usb"
#if SDB_USB_INOTIFY
LIST_NODE* usb_list = NULL;
+#define SDB_URB_TYPE_READ 0
+#define SDB_URB_TYPE_WRITE 1
struct usb_handle {
LIST_NODE* node;
int node_fd;
unsigned char end_point[2]; // 0:in, 1:out
int interface;
+
+ struct usbdevfs_urb urb_in;
+ struct usbdevfs_urb urb_out;
};
static int get_usb_device_serial_number(int usb_fd, __u8 serial_index, char* serial)
#define URB_USERCONTEXT_COOKIE ((void *)0x1)
static int usb_urb_transfer(usb_handle *h, int ep, char *bytes, int size,
- int timeout) {
- struct usbdevfs_urb urb;
+ int timeout, int rwtype) {
int bytesdone = 0, requested;
struct timeval tv, tv_ref, tv_now;
+ struct usbdevfs_urb *p_urb;
struct usbdevfs_urb *context;
int ret, waiting;
}
do {
+ LOG_DEBUG_URB("URB[%d]: do-while: entered\n", rwtype);
fd_set writefds;
requested = size - bytesdone;
LOG_DEBUG("requested bytes over than %d\n", MAX_READ_WRITE);
}
- urb.type = USBDEVFS_URB_TYPE_BULK;
- urb.endpoint = ep;
- urb.flags = 0;
- urb.buffer = bytes + bytesdone;
- urb.buffer_length = requested;
- urb.signr = 0;
- urb.actual_length = 0;
- urb.number_of_packets = 0; /* don't do isochronous yet */
- urb.usercontext = NULL;
-
- ret = ioctl(h->node_fd, USBDEVFS_SUBMITURB, &urb);
+ if ( rwtype == SDB_URB_TYPE_READ ) {
+ memset(&(h->urb_in), 0, sizeof(h->urb_in));
+ p_urb = &(h->urb_in);
+ LOG_DEBUG_URB("URB[%d]: READ urb type: p_urb=%p\n", rwtype, p_urb);
+ } else if ( rwtype == SDB_URB_TYPE_WRITE ) {
+ memset(&(h->urb_out), 0, sizeof(h->urb_out));
+ p_urb = &(h->urb_out);
+ LOG_DEBUG_URB("URB[%d]: WRITE urb type: p_urb=%p\n", rwtype, p_urb);
+ } else {
+ LOG_ERROR("Unknown URB type : %d\n", rwtype);
+ return -1;
+ }
+
+ p_urb->type = USBDEVFS_URB_TYPE_BULK;
+ p_urb->endpoint = ep;
+ p_urb->flags = 0;
+ p_urb->buffer = bytes + bytesdone;
+ p_urb->buffer_length = requested;
+ p_urb->signr = 0;
+ p_urb->actual_length = 0;
+ p_urb->number_of_packets = 0; /* don't do isochronous yet */
+ p_urb->usercontext = NULL;
+
+ ret = ioctl(h->node_fd, USBDEVFS_SUBMITURB, p_urb);
if (ret < 0) {
LOG_DEBUG("failed to submit urb: %s\n", strerror(errno));
return -1;
}
+ LOG_DEBUG_URB("URB[%d]: urb submit: p_urb=%p requested=%d, size=%d, bytesdone=%d\n", rwtype, p_urb, requested, size, bytesdone);
FD_ZERO(&writefds);
FD_SET(h->node_fd, &writefds);
for (;;) {
ret = ioctl(h->node_fd, USBDEVFS_REAPURBNDELAY, &context);
int saved_errno = errno;
- if (!urb.usercontext && (ret == -1) && waiting) {
+ LOG_DEBUG_URB("URB[%d]: urb reapndelay: ret=%d, saved_errno=%d, context=%p, waiting=%d, urb.usercontext=%p\n", rwtype, ret, saved_errno, context, waiting, p_urb->usercontext);
+ if (!p_urb->usercontext && (ret == -1) && waiting) {
// continue but,
if (saved_errno == ENODEV) {
LOG_DEBUG("device may be unplugged: %s\n", strerror(saved_errno));
}
}
- if (context && context != &urb) {
+ LOG_DEBUG_URB("URB[%d]: leave reap loop: context=%p, p_urb=%p\n", rwtype, context, p_urb);
+ if (context && context != p_urb) {
context->usercontext = URB_USERCONTEXT_COOKIE;
/* We need to restart since we got a successful URB, but not ours */
+ LOG_DEBUG_URB("URB[%d]: usercontext cookie: not ours\n", rwtype);
goto restart;
}
* something happened during the reaping and we should return that
* error now
*/
- if (ret < 0 && !urb.usercontext && errno != EAGAIN)
+ if (ret < 0 && !p_urb->usercontext && errno != EAGAIN)
LOG_DEBUG("error reaping URB: %s\n", strerror(errno));
- bytesdone += urb.actual_length;
- } while ((ret == 0 || urb.usercontext) && bytesdone < size
- && urb.actual_length == requested);
+ bytesdone += p_urb->actual_length;
+
+ LOG_DEBUG_URB("URB[%d]: do-while: check condition: ret=%d, urb.usercontext=%p, bytesdone=%d, size=%d, urb.actual_length=%d, requested=%d\n", rwtype, ret, p_urb->usercontext, bytesdone, size, p_urb->actual_length, requested);
+ } while ((ret == 0 || p_urb->usercontext) && bytesdone < size
+ && p_urb->actual_length == requested);
+ LOG_DEBUG_URB("URB[%d]: do-while: leaved\n", rwtype);
/* If the URB didn't complete in success or error, then let's unlink it */
- if (ret < 0 && !urb.usercontext) {
+ if (ret < 0 && !p_urb->usercontext) {
+ LOG_DEBUG_URB("URB[%d]: urb error case: entered\n", rwtype);
int rc;
if (!waiting)
rc = -ETIMEDOUT;
else
- rc = urb.status;
+ rc = p_urb->status;
- ret = ioctl(h->node_fd, USBDEVFS_DISCARDURB, &urb);
+ ret = ioctl(h->node_fd, USBDEVFS_DISCARDURB, p_urb);
if (ret < 0 && errno != EINVAL)
LOG_DEBUG("error discarding URB: %s\n", strerror(errno));
+ LOG_DEBUG_URB("URB[%d]: urb discard: ret=%d, errno=%d\n", rwtype, ret, errno);
+
/*
* When the URB is unlinked, it gets moved to the completed list and
* then we need to reap it or else the next time we call this function,
if (ret < 0 && errno != EINVAL)
LOG_DEBUG("error reaping URB: %s\n", strerror(errno));
+ LOG_DEBUG_URB("URB[%d]: urb reap: ret=%d, errno=%d\n", rwtype, ret, errno);
+
return rc;
}
+ LOG_DEBUG_URB("URB[%d]: urb transfer done: bytesdone=%d\n", rwtype, bytesdone);
return bytesdone;
}
while (len > 0) {
int xfer = (len > MAX_READ_WRITE) ? MAX_READ_WRITE : len;
- n = usb_urb_transfer(h, h->end_point[1], data, xfer, URB_TRANSFER_TIMEOUT);
+ n = usb_urb_transfer(h, h->end_point[1], data, xfer, URB_TRANSFER_TIMEOUT, SDB_URB_TYPE_WRITE);
if (n != xfer) {
LOG_DEBUG("fail to usb write: n = %d, errno = %d (%s)\n", n, errno, strerror(errno));
return -1;
while (len > 0) {
int xfer = (len > MAX_READ_WRITE) ? MAX_READ_WRITE : len;
- n = usb_urb_transfer(h, h->end_point[0], data, xfer, URB_TRANSFER_TIMEOUT);
+ n = usb_urb_transfer(h, h->end_point[0], data, xfer, URB_TRANSFER_TIMEOUT, SDB_URB_TYPE_READ);
if (n != xfer) {
if ((errno == ETIMEDOUT)) {
LOG_DEBUG("usb bulk read timeout\n");