From owner-p4-projects@FreeBSD.ORG Wed Jul 15 13:14:55 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3FBD51065674; Wed, 15 Jul 2009 13:14:55 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DB30F1065670 for ; Wed, 15 Jul 2009 13:14:54 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id C03D98FC29 for ; Wed, 15 Jul 2009 13:14:54 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n6FDEsWP083226 for ; Wed, 15 Jul 2009 13:14:54 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n6FDEse0083224 for perforce@freebsd.org; Wed, 15 Jul 2009 13:14:54 GMT (envelope-from hselasky@FreeBSD.org) Date: Wed, 15 Jul 2009 13:14:54 GMT Message-Id: <200907151314.n6FDEse0083224@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 166129 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Jul 2009 13:14:56 -0000 http://perforce.freebsd.org/chv.cgi?CH=166129 Change 166129 by hselasky@hselasky_laptop001 on 2009/07/15 13:14:05 LibUSB v1.0 - fix transfer completion. LibUSB compiles again. Affected files ... .. //depot/projects/usb/src/lib/libusb/libusb10.c#9 edit .. //depot/projects/usb/src/lib/libusb/libusb10.h#7 edit .. //depot/projects/usb/src/lib/libusb/libusb10_io.c#6 edit Differences ... ==== //depot/projects/usb/src/lib/libusb/libusb10.c#9 (text+ko) ==== @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include "libusb20.h" @@ -44,14 +46,15 @@ /* Prototypes */ -static struct libusb20_transfer *libusb10_get_transfer(struct libusb20_device *pdev, uint8_t endpoint, uint8_t index); -static int libusb10_get_maxframe(struct libusb20_device *pdev, libusb_transfer *xfer); -static int libusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer); +static struct libusb20_transfer *libusb10_get_transfer(struct libusb20_device *, uint8_t, uint8_t); +static int libusb10_get_maxframe(struct libusb20_device *, libusb_transfer *); +static int libusb10_get_buffsize(struct libusb20_device *, libusb_transfer *); static int libusb10_convert_error(uint8_t status); -static void libusb10_isoc_proxy(struct libusb20_transfer *pxfer); -static void libusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer); -static void libusb10_ctrl_proxy(struct libusb20_transfer *pxfer); -static void libusb10_submit_transfer_sub(struct libusb20_device *pdev, uint8_t endpoint); +static void libusb10_complete_transfer(struct libusb20_transfer *, struct libusb_super_transfer *, int); +static void libusb10_isoc_proxy(struct libusb20_transfer *); +static void libusb10_bulk_intr_proxy(struct libusb20_transfer *); +static void libusb10_ctrl_proxy(struct libusb20_transfer *); +static void libusb10_submit_transfer_sub(struct libusb20_device *, uint8_t); /* Library initialisation / deinitialisation */ @@ -83,10 +86,13 @@ ctx->debug_fixed = 1; } TAILQ_INIT(&ctx->pollfds); + TAILQ_INIT(&ctx->tr_done); pthread_mutex_init(&ctx->ctx_lock, NULL); pthread_cond_init(&ctx->ctx_cond, NULL); + ctx->ctx_handler = NO_THREAD; + ret = pipe(ctx->ctrl_pipe); if (ret < 0) { pthread_mutex_destroy(&ctx->ctx_lock); @@ -94,6 +100,12 @@ free(ctx); return (LIBUSB_ERROR_OTHER); } + /* set non-blocking mode on the control pipe to avoid deadlock */ + ret = 1; + ioctl(ctx->ctrl_pipe[0], FIONBIO, &ret); + ret = 1; + ioctl(ctx->ctrl_pipe[1], FIONBIO, &ret); + libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN); pthread_mutex_lock(&default_context_lock); @@ -190,7 +202,6 @@ /* init transfer queues */ TAILQ_INIT(&dev->tr_head); - TAILQ_INIT(&dev->tr_done); /* set context we belong to */ dev->ctx = ctx; @@ -477,10 +488,10 @@ set_config: + libusb10_cancel_all_transfer(dev); + libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); - usb_cancel_all_dev(dev); - err = libusb20_dev_set_config_index(pdev, i); libusb10_add_pollfd(dev->ctx, &dev->dev_poll, pdev, libusb20_dev_get_fd(pdev), POLLIN | @@ -557,10 +568,10 @@ if (err) return (err); + libusb10_cancel_all_transfer(dev); + libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); - usb_cancel_all_dev(dev); - err = libusb20_dev_set_alt_index(pdev, interface_number, alternate_setting); @@ -627,10 +638,10 @@ if (dev == NULL) return (LIBUSB20_ERROR_INVALID_PARAM); + libusb10_cancel_all_transfer(dev); + libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); - usb_cancel_all_dev(dev); - err = libusb20_dev_reset(pdev); libusb10_add_pollfd(dev->ctx, &dev->dev_poll, @@ -801,7 +812,31 @@ } } +/* This function must be called locked */ + static void +libusb10_complete_transfer(struct libusb20_transfer *pxfer, + struct libusb_super_transfer *sxfer, int status) +{ + struct libusb_transfer *uxfer; + struct libusb_device *dev; + + uxfer = (struct libusb_transfer *)( + ((uint8_t *)sxfer) + sizeof(*sxfer)); + + if (pxfer != NULL) + libusb20_tr_set_priv_sc1(pxfer, NULL); + + uxfer->status = status; + + dev = libusb_get_device(uxfer->dev_handle); + + TAILQ_INSERT_TAIL(&dev->ctx->tr_done, sxfer, entry); +} + +/* This function must be called locked */ + +static void libusb10_isoc_proxy(struct libusb20_transfer *pxfer) { struct libusb_super_transfer *sxfer; @@ -843,7 +878,7 @@ uxfer->iso_packet_desc[i].actual_length = libusb20_tr_get_length(pxfer, i); } - libusb_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); + libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); break; case LIBUSB20_TRANSFER_START: @@ -868,11 +903,13 @@ break; default: - libusb_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); + libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); break; } } +/* This function must be called locked */ + static void libusb10_bulk_intr_proxy(struct libusb20_transfer *pxfer) { @@ -904,15 +941,15 @@ /* check for short packet */ if (sxfer->last_len != actlen) { if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { - libusb_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); + libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); } else { - libusb_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); + libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); } break; } /* check for end of data */ if (sxfer->rem_len == 0) { - libusb_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); + libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); break; } /* FALLTHROUGH */ @@ -938,11 +975,13 @@ break; default: - libusb_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); + libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); break; } } +/* This function must be called locked */ + static void libusb10_ctrl_proxy(struct libusb20_transfer *pxfer) { @@ -977,15 +1016,15 @@ /* check for short packet */ if (sxfer->last_len != actlen) { if (flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { - libusb_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); + libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_ERROR); } else { - libusb_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); + libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); } break; } /* check for end of data */ if (sxfer->rem_len == 0) { - libusb_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); + libusb10_complete_transfer(pxfer, sxfer, LIBUSB_TRANSFER_COMPLETED); break; } /* FALLTHROUGH */ @@ -1025,7 +1064,7 @@ break; default: - libusb_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); + libusb10_complete_transfer(pxfer, sxfer, libusb10_convert_error(status)); break; } } @@ -1044,6 +1083,7 @@ int buffsize; int maxframe; int temp; + uint8_t dummy; dev = libusb_get_device(pdev); @@ -1115,17 +1155,15 @@ break; case LIBUSB_TRANSFER_TYPE_CONTROL: libusb20_tr_set_callback(pxfer0, libusb10_ctrl_proxy); - if (sxfer->rem_len < 8) { - libusb_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); - return; - } + if (sxfer->rem_len < 8) + goto failure; + /* remove SETUP packet from data */ sxfer->rem_len -= 8; sxfer->curr_data += 8; break; default: - libusb_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); - return; + goto failure; } buffsize = libusb10_get_buffsize(pdev, uxfer); @@ -1134,50 +1172,17 @@ /* make sure the transfer is opened */ err = libusb20_tr_open(pxfer0, buffsize, maxframe, endpoint); if (err && (err != LIBUSB20_ERROR_BUSY)) { - libusb_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); - return; + goto failure; } libusb20_tr_start(pxfer0); -} + return; -/* The following function must be called locked */ +failure: + libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); -UNEXPORTED void -libusb10_complete_transfer_sub(struct libusb20_device *pdev) -{ - struct libusb_device *dev; - struct libusb_super_transfer *sxfer; - struct libusb_transfer *uxfer; - - dev = libusb_get_device(pdev); - - while ((sxfer = TAILQ_FIRST(&dev->tr_done))) { - TAILQ_REMOVE(&dev->tr_done, sxfer, entry); - sxfer->entry.tqe_prev = NULL; - - dev->tr_done_ref++; - - CTX_UNLOCK(dev->ctx); - - uxfer = (struct libusb_transfer *)( - ((uint8_t *)sxfer) + sizeof(*sxfer)); - - if (uxfer->callback != NULL) - (uxfer->callback) (uxfer); - - if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) - free(uxfer->buffer); - - if (uxfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER) - libusb_free_transfer(uxfer); - - CTX_LOCK(dev->ctx); - - pthread_cond_broadcast(&dev->ctx->ctx_cond); - - dev->tr_done_ref--; - dev->tr_done_gen++; - } + /* make sure our event loop spins the done handler */ + dummy = 0; + write(dev->ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); } /* The following function must be called unlocked */ @@ -1237,6 +1242,8 @@ return (err); } +/* Asynchronous transfer cancel */ + int libusb_cancel_transfer(struct libusb_transfer *uxfer) { @@ -1245,7 +1252,6 @@ struct libusb_super_transfer *sxfer; struct libusb_device *dev; unsigned int endpoint; - int err; if (uxfer == NULL) return (LIBUSB_ERROR_INVALID_PARAM); @@ -1274,43 +1280,34 @@ /* we are lucky - transfer is on a queue */ TAILQ_REMOVE(&dev->tr_head, sxfer, entry); sxfer->entry.tqe_prev = NULL; - err = 0; + libusb10_complete_transfer(NULL, sxfer, LIBUSB_TRANSFER_CANCELLED); } else if (pxfer0 == NULL || pxfer1 == NULL) { - err = LIBUSB_ERROR_OTHER; + /* not started */ } else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) { - libusb20_tr_set_priv_sc1(pxfer0, NULL); + libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_CANCELLED); libusb20_tr_stop(pxfer0); /* make sure the queue doesn't stall */ libusb10_submit_transfer_sub( uxfer->dev_handle, endpoint); - err = 0; } else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) { - libusb20_tr_set_priv_sc1(pxfer1, NULL); + libusb10_complete_transfer(pxfer1, sxfer, LIBUSB_TRANSFER_CANCELLED); libusb20_tr_stop(pxfer1); /* make sure the queue doesn't stall */ libusb10_submit_transfer_sub( uxfer->dev_handle, endpoint); - err = 0; } else { - /* - * Check if any callback is pending and wait for it to - * complete: - */ - if (dev->tr_done_ref != 0) { - int my_gen = dev->tr_done_gen; - - while (dev->tr_done_gen == my_gen) { - pthread_cond_wait(&dev->ctx->ctx_cond, - &dev->ctx->ctx_lock); - } - } /* not started */ - err = 0; } CTX_UNLOCK(dev->ctx); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave %d", err); + DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); + + return (0); +} - return (err); +UNEXPORTED void +libusb10_cancel_all_transfer(libusb_device *dev) +{ + /* TODO */ } ==== //depot/projects/usb/src/lib/libusb/libusb10.h#7 (text+ko) ==== @@ -60,7 +60,7 @@ }; struct libusb_super_transfer { - TAILQ_ENTRY(libusb_super_transfer)entry; + TAILQ_ENTRY(libusb_super_transfer) entry; uint8_t *curr_data; uint32_t rem_len; uint32_t last_len; @@ -71,6 +71,8 @@ int debug; int debug_fixed; int ctrl_pipe[2]; + int tr_done_ref; + int tr_done_gen; pthread_mutex_t ctx_lock; pthread_cond_t ctx_cond; @@ -78,6 +80,7 @@ #define NO_THREAD ((pthread_t)-1) TAILQ_HEAD(, libusb_super_pollfd) pollfds; + TAILQ_HEAD(, libusb_super_transfer) tr_done; struct libusb_super_pollfd ctx_poll; @@ -88,8 +91,6 @@ struct libusb_device { int refcnt; - int tr_done_ref; - int tr_done_gen; uint32_t claimed_interfaces; @@ -97,8 +98,7 @@ struct libusb_context *ctx; - TAILQ_HEAD(, libusb_super_transfer)tr_head; - TAILQ_HEAD(, libusb_super_transfer)tr_done; + TAILQ_HEAD(, libusb_super_transfer) tr_head; struct libusb20_device *os_priv; }; @@ -107,6 +107,6 @@ void libusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, struct libusb20_device *pdev, int fd, short events); void libusb10_remove_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd); -void libusb10_complete_transfer_sub(libusb_device_handle *devh); +void libusb10_cancel_all_transfer(libusb_device *dev); #endif /* __LIBUSB10_H__ */ ==== //depot/projects/usb/src/lib/libusb/libusb10_io.c#6 (text+ko) ==== @@ -86,9 +86,12 @@ static int libusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv) { + struct libusb_device *dev; struct libusb20_device **ppdev; struct libusb_super_pollfd *pfd; struct pollfd *fds; + struct libusb_super_transfer *sxfer; + struct libusb_transfer *uxfer; nfds_t nfds; int timeout; int i; @@ -135,21 +138,32 @@ if (err < 1) { for (i = 0; i != nfds; i++) { - if (ppdev[i] != NULL) - libusb_unref_device_locked(libusb_get_device(ppdev[i])); + if (ppdev[i] != NULL) { + CTX_UNLOCK(ctx); + libusb_unref_device(libusb_get_device(ppdev[i])); + CTX_LOCK(ctx); + } } - return (err); + goto do_done; } for (i = 0; i != nfds; i++) { if (fds[i].revents == 0) continue; if (ppdev[i] != NULL) { + dev = libusb_get_device(ppdev[i]); + err = libusb20_dev_process(ppdev[i]); if (err) { - XXX_device_is_gone(); + /* cancel all transfers - device is gone */ + libusb10_cancel_all_transfer(dev); + /* + * make sure we don't go into an infinite + * loop + */ + libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); } CTX_UNLOCK(ctx); - libusb_unref_device(libusb_get_device(ppdev[i])); + libusb_unref_device(dev); CTX_LOCK(ctx); } else { @@ -161,7 +175,43 @@ } } } - return (0); + + err = 0; + +do_done: + + /* Do all done callbacks */ + + while ((sxfer = TAILQ_FIRST(&ctx->tr_done))) { + TAILQ_REMOVE(&ctx->tr_done, sxfer, entry); + sxfer->entry.tqe_prev = NULL; + + ctx->tr_done_ref++; + + CTX_UNLOCK(ctx); + + uxfer = (struct libusb_transfer *)( + ((uint8_t *)sxfer) + sizeof(*sxfer)); + + if (uxfer->callback != NULL) + (uxfer->callback) (uxfer); + + if (uxfer->flags & LIBUSB_TRANSFER_FREE_BUFFER) + free(uxfer->buffer); + + if (uxfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER) + libusb_free_transfer(uxfer); + + CTX_LOCK(ctx); + + ctx->tr_done_ref--; + ctx->tr_done_gen++; + } + + /* Wakeup other waiters */ + pthread_cond_broadcast(&ctx->ctx_cond); + + return (err); } /* Polling and timing */ @@ -453,20 +503,10 @@ libusb_free_transfer(xfer); return (ret); } - XXX_locking(); - while (complet == 0) { if ((ret = libusb_handle_events(ctx)) < 0) { libusb_cancel_transfer(xfer); - libusb_free_transfer(xfer); - - XXX(); - - while (complet == 0) { - if (libusb_handle_events(ctx) < 0) - break; - } - return (ret); + usleep(1000); /* nice it */ } }