diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h index 4a8a4fcd8..3deb1824c 100644 --- a/include/usbhost/usbhost.h +++ b/include/usbhost/usbhost.h @@ -39,6 +39,17 @@ struct usb_descriptor_iter { unsigned char* curr_desc; }; +struct usb_request +{ + struct usb_device *dev; + void* buffer; + int buffer_length; + int actual_length; + int max_packet_size; + void *private_data; /* struct usbdevfs_urb* */ + void *client_data; /* free for use by client */ +}; + /* Callback for notification when new USB devices are attached. * Return true to exit from usb_host_run. */ @@ -170,38 +181,23 @@ int usb_device_claim_interface(struct usb_device *device, unsigned int interface /* Releases the specified interface of a USB device */ int usb_device_release_interface(struct usb_device *device, unsigned int interface); +/* Creates a new usb_request. */ +struct usb_request *usb_request_new(struct usb_device *dev, + const struct usb_endpoint_descriptor *ep_desc); -/* Creates a new usb_endpoint for the specified endpoint of a USB device. - * This can be used to read or write data across the endpoint. - */ -struct usb_endpoint *usb_endpoint_open(struct usb_device *dev, - const struct usb_endpoint_descriptor *desc); +/* Releases all resources associated with the request */ +void usb_request_free(struct usb_request *req); -/* Releases all resources associated with the endpoint */ -void usb_endpoint_close(struct usb_endpoint *ep); +/* Submits a read or write request on the specified device */ +int usb_request_queue(struct usb_request *req); -/* Begins a read or write operation on the specified endpoint */ -int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len); - - /* Waits for the results of a previous usb_endpoint_queue operation on the - * specified endpoint. Returns number of bytes transferred, or a negative - * value for error. + /* Waits for the results of a previous usb_request_queue operation. + * Returns a usb_request, or NULL for error. */ -int usb_endpoint_wait(struct usb_device *device, int *out_ep_num); +struct usb_request *usb_request_wait(struct usb_device *dev); -/* Cancels a pending usb_endpoint_queue() operation on an endpoint. */ -int usb_endpoint_cancel(struct usb_endpoint *ep); - -/* Returns the usb_device for the given endpoint */ -struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep); - -/* Returns the endpoint address for the given endpoint */ -int usb_endpoint_number(struct usb_endpoint *ep); - -/* Returns the maximum packet size for the given endpoint. - * For bulk endpoints this should be 512 for highspeed or 64 for fullspeed. - */ -int usb_endpoint_max_packet(struct usb_endpoint *ep); +/* Cancels a pending usb_request_queue() operation. */ +int usb_request_cancel(struct usb_request *req); #ifdef __cplusplus } diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk index c9a1c8a30..52b4eadc9 100644 --- a/libusbhost/Android.mk +++ b/libusbhost/Android.mk @@ -40,4 +40,7 @@ LOCAL_SRC_FILES := usbhost.c LOCAL_CFLAGS := -g -DUSE_LIBLOG +# needed for logcat +LOCAL_SHARED_LIBRARIES := libcutils + include $(BUILD_SHARED_LIBRARY) diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c index dbc7962cb..d6736d358 100644 --- a/libusbhost/usbhost.c +++ b/libusbhost/usbhost.c @@ -45,12 +45,6 @@ #include #include -#include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) -#include -#else -#include -#endif #include #include "usbhost/usbhost.h" @@ -72,13 +66,6 @@ struct usb_device { int writeable; }; -struct usb_endpoint -{ - struct usb_device *dev; - struct usb_endpoint_descriptor desc; - struct usbdevfs_urb urb; -}; - static inline int badname(const char *name) { while(*name) { @@ -465,83 +452,89 @@ int usb_device_release_interface(struct usb_device *device, unsigned int interfa return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface); } -struct usb_endpoint *usb_endpoint_open(struct usb_device *dev, - const struct usb_endpoint_descriptor *desc) +struct usb_request *usb_request_new(struct usb_device *dev, + const struct usb_endpoint_descriptor *ep_desc) { - struct usb_endpoint *ep = calloc(1, sizeof(struct usb_endpoint)); - memcpy(&ep->desc, desc, sizeof(ep->desc)); - ep->dev = dev; - return ep; + struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb)); + if (!urb) + return NULL; + + if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) + urb->type = USBDEVFS_URB_TYPE_BULK; + else if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) + urb->type = USBDEVFS_URB_TYPE_INTERRUPT; + else { + D("Unsupported endpoint type %d", ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + free(urb); + return NULL; + } + urb->endpoint = ep_desc->bEndpointAddress; + + struct usb_request *req = calloc(1, sizeof(struct usb_request)); + if (!req) { + free(urb); + return NULL; + } + + req->dev = dev; + req->max_packet_size = __le16_to_cpu(ep_desc->wMaxPacketSize); + req->private_data = urb; + urb->usercontext = req; + + return req; } -void usb_endpoint_close(struct usb_endpoint *ep) +void usb_request_free(struct usb_request *req) { - // cancel IO here? - free(ep); + free(req->private_data); + free(req); } -int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len) +int usb_request_queue(struct usb_request *req) { - struct usbdevfs_urb *urb = &ep->urb; + struct usbdevfs_urb *urb = (struct usbdevfs_urb*)req->private_data; int res; - D("usb_endpoint_queue\n"); - memset(urb, 0, sizeof(*urb)); - urb->type = USBDEVFS_URB_TYPE_BULK; - urb->endpoint = ep->desc.bEndpointAddress; urb->status = -1; - urb->buffer = data; - urb->buffer_length = len; + urb->buffer = req->buffer; + urb->buffer_length = req->buffer_length; do { - res = ioctl(ep->dev->fd, USBDEVFS_SUBMITURB, urb); + res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb); } while((res < 0) && (errno == EINTR)); return res; } -int usb_endpoint_wait(struct usb_device *dev, int *out_ep_num) +struct usb_request *usb_request_wait(struct usb_device *dev) { - struct usbdevfs_urb *out = NULL; + struct usbdevfs_urb *urb = NULL; + struct usb_request *req = NULL; int res; while (1) { - res = ioctl(dev->fd, USBDEVFS_REAPURB, &out); + int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb); D("USBDEVFS_REAPURB returned %d\n", res); if (res < 0) { if(errno == EINTR) { continue; } D("[ reap urb - error ]\n"); - *out_ep_num = -1; + return NULL; } else { D("[ urb @%p status = %d, actual = %d ]\n", - out, out->status, out->actual_length); - res = out->actual_length; - *out_ep_num = out->endpoint; + urb, urb->status, urb->actual_length); + req = (struct usb_request*)urb->usercontext; + req->actual_length = urb->actual_length; } break; } - return res; + return req; } -int usb_endpoint_cancel(struct usb_endpoint *ep) +int usb_request_cancel(struct usb_request *req) { - return ioctl(ep->dev->fd, USBDEVFS_DISCARDURB, &ep->urb); -} - -struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep) -{ - return ep->dev; -} - -int usb_endpoint_number(struct usb_endpoint *ep) -{ - return ep->desc.bEndpointAddress; -} - -int usb_endpoint_max_packet(struct usb_endpoint *ep) -{ - return __le16_to_cpu(ep->desc.wMaxPacketSize); + struct usbdevfs_urb *urb = ((struct usbdevfs_urb*)req->private_data); + return ioctl(req->dev->fd, USBDEVFS_DISCARDURB, &urb); }