summaryrefslogtreecommitdiffstats
path: root/lib/libusb/libusb10.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libusb/libusb10.h')
-rw-r--r--lib/libusb/libusb10.h245
1 files changed, 245 insertions, 0 deletions
diff --git a/lib/libusb/libusb10.h b/lib/libusb/libusb10.h
new file mode 100644
index 0000000..60a13da
--- /dev/null
+++ b/lib/libusb/libusb10.h
@@ -0,0 +1,245 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __LIBUSB10_H__
+#define __LIBUSB10_H__
+
+/*
+ * The two following macros were taken from the original LibUSB v1.0
+ * for sake of compatibility:
+ */
+#define USB_LIST_INIT(entry) \
+ (entry)->prev = (entry)->next = entry;
+#define USB_LIST_EMPTY(entry) \
+ ((entry)->next = (entry))
+
+#define LIST_ADD(entry, head) \
+ (entry)->next = (head)->next; \
+ (entry)->prev = (head); \
+ (head)->next->prev = (entry); \
+ (head)->next = (entry);
+#define LIST_ADD_TAIL(entry, head) \
+ (entry)->next = (head); \
+ (entry)->prev = (head)->prev; \
+ (head)->prev->next = (entry); \
+ (head)->prev = (entry);
+#define LIST_DEL(entry) \
+ (entry)->next->prev = (entry)->prev; \
+ (entry)->prev->next = (entry)->next;
+
+#define LIST_ENT(ptr, type, member) \
+ ((type *)((char *)(ptr) - (unsigned long) (&((type*)0L)->member)))
+#define LIST_FOREACH_ENTRY(pos, head, member) \
+ for (pos = LIST_ENT((head)->next, typeof(*pos), member) ; \
+ &pos->member != head ; \
+ pos = LIST_ENT(pos->member.next, typeof(*pos), member))
+#define LIST_FOREACH_ENTRY_SAFE(pos, n, head, member) \
+ for (pos = LIST_ENT((head)->next, typeof(*pos), member), \
+ n = LIST_ENT(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = LIST_ENT(n->member.next, typeof(*n), member))
+
+/* fetch libusb20_transfer from libusb20_device */
+#define GET_XFER(xfer, endpoint, pdev)\
+ xfer = libusb20_tr_get_pointer(pdev, \
+ (2 *endpoint)|(endpoint/0x80)); \
+ if (xfer == NULL) \
+ return (LIBUSB_ERROR_OTHER);
+
+
+static int get_next_timeout(libusb_context *ctx, struct timeval *tv, struct timeval *out);
+static int handle_timeouts(struct libusb_context *ctx);
+static int handle_events(struct libusb_context *ctx, struct timeval *tv);
+extern struct libusb_context *usbi_default_context;
+extern pthread_mutex_t libusb20_lock;
+
+/* if ctx is NULL use default context*/
+
+#define GET_CONTEXT(ctx) \
+ if (ctx == NULL) ctx = usbi_default_context;
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define USB_TIMED_OUT (1<<0)
+
+static inline void
+dprintf(libusb_context *ctx, int debug, char *str)
+{
+ if (ctx->debug != debug)
+ return ;
+
+ switch (ctx->debug) {
+ case LIBUSB_DEBUG_NO:
+ break ;
+ case LIBUSB_DEBUG_FUNCTION:
+ printf("LIBUSB FUNCTION : %s\n", str);
+ break ;
+ case LIBUSB_DEBUG_TRANSFER:
+ printf("LIBUSB TRANSFER : %s\n", str);
+ break ;
+ default:
+ printf("LIBUSB UNKNOW DEBUG\n");
+ break ;
+ }
+ return ;
+}
+
+struct usb_pollfd {
+ struct libusb_pollfd pollfd;
+ struct list_head list;
+};
+
+struct usb_transfer {
+ int num_iso_packets;
+ struct list_head list;
+ struct timeval timeout;
+ int transferred;
+ uint8_t flags;
+};
+
+static inline int
+usb_add_pollfd(libusb_context *ctx, int fd, short events)
+{
+ struct usb_pollfd *pollfd;
+
+ if (ctx == NULL)
+ return (LIBUSB_ERROR_INVALID_PARAM);
+
+ pollfd = malloc(sizeof(*pollfd));
+ if (pollfd == NULL)
+ return (LIBUSB_ERROR_NO_MEM);
+
+ pollfd->pollfd.fd = fd;
+ pollfd->pollfd.events = events;
+
+ pthread_mutex_lock(&ctx->pollfds_lock);
+ LIST_ADD_TAIL(&pollfd->list, &ctx->pollfds);
+ pthread_mutex_unlock(&ctx->pollfds_lock);
+
+ if (ctx->fd_added_cb)
+ ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
+ return (0);
+}
+
+static inline void
+usb_remove_pollfd(libusb_context *ctx, int fd)
+{
+ struct usb_pollfd *pollfd;
+ int found;
+
+ found = 0;
+ pthread_mutex_lock(&ctx->pollfds_lock);
+
+ LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list) {
+ if (pollfd->pollfd.fd == fd) {
+ found = 1;
+ break ;
+ }
+ }
+
+ if (found == 0) {
+ pthread_mutex_unlock(&ctx->pollfds_lock);
+ return ;
+ }
+
+ LIST_DEL(&pollfd->list);
+ pthread_mutex_unlock(&ctx->pollfds_lock);
+ free(pollfd);
+
+ if (ctx->fd_removed_cb)
+ ctx->fd_removed_cb(fd, ctx->fd_cb_user_data);
+}
+
+static inline void
+usb_handle_transfer_completion(struct usb_transfer *uxfer,
+ enum libusb_transfer_status status)
+{
+ libusb_transfer *xfer;
+ libusb_context *ctx;
+ int len;
+
+ xfer = (struct libusb_transfer *) ((uint8_t *)uxfer +
+ sizeof(struct usb_transfer));
+ ctx = xfer->dev_handle->dev->ctx;
+
+ pthread_mutex_lock(&ctx->flying_transfers_lock);
+ LIST_DEL(&uxfer->list);
+ pthread_mutex_unlock(&ctx->flying_transfers_lock);
+
+ if (status == LIBUSB_TRANSFER_COMPLETED && xfer->flags &
+ LIBUSB_TRANSFER_SHORT_NOT_OK) {
+ len = xfer->length;
+ if (xfer->type == LIBUSB_TRANSFER_TYPE_CONTROL)
+ len -= sizeof(libusb_control_setup);
+ if (len != uxfer->transferred) {
+ status = LIBUSB_TRANSFER_ERROR;
+ }
+ }
+
+ xfer->status = status;
+ xfer->actual_length = uxfer->transferred;
+
+ if (xfer->callback)
+ xfer->callback(xfer);
+ if (xfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER)
+ libusb_free_transfer(xfer);
+
+ pthread_mutex_lock(&ctx->event_waiters_lock);
+ pthread_cond_broadcast(&ctx->event_waiters_cond);
+ pthread_mutex_unlock(&ctx->event_waiters_lock);
+}
+
+static inline void
+usb_handle_disconnect(struct libusb_device_handle *devh)
+{
+ struct libusb_context *ctx;
+ struct libusb_transfer *xfer;
+ struct usb_transfer *cur;
+ struct usb_transfer *to_cancel;
+
+ ctx = devh->dev->ctx;
+
+ while (1) {
+ pthread_mutex_lock(&ctx->flying_transfers_lock);
+ to_cancel = NULL;
+ LIST_FOREACH_ENTRY(cur, &ctx->flying_transfers, list) {
+ xfer = (struct libusb_transfer *) ((uint8_t *)cur +
+ sizeof(struct usb_transfer));
+ if (xfer->dev_handle == devh) {
+ to_cancel = cur;
+ break ;
+ }
+ }
+ pthread_mutex_unlock(&ctx->flying_transfers_lock);
+
+ if (to_cancel == NULL)
+ break ;
+
+ usb_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
+ }
+ return ;
+}
+
+#endif /*__LIBUSB10_H__*/
OpenPOWER on IntegriCloud