From owner-p4-projects@FreeBSD.ORG Mon May 11 20:29:35 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7236F106566C; Mon, 11 May 2009 20:29:34 +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 2F64E1065673 for ; Mon, 11 May 2009 20:29:34 +0000 (UTC) (envelope-from syl@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 1DE4D8FC15 for ; Mon, 11 May 2009 20:29:34 +0000 (UTC) (envelope-from syl@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 n4BKTYXU029106 for ; Mon, 11 May 2009 20:29:34 GMT (envelope-from syl@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n4BKTXF9029104 for perforce@freebsd.org; Mon, 11 May 2009 20:29:33 GMT (envelope-from syl@FreeBSD.org) Date: Mon, 11 May 2009 20:29:33 GMT Message-Id: <200905112029.n4BKTXF9029104@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to syl@FreeBSD.org using -f From: Sylvestre Gallon To: Perforce Change Reviews Cc: Subject: PERFORCE change 161952 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: Mon, 11 May 2009 20:29:35 -0000 http://perforce.freebsd.org/chv.cgi?CH=161952 Change 161952 by syl@syl_atuin on 2009/05/11 20:29:11 - Add USB_LIST_EMPTY macro. - Add stuct usb_transfer for implementation of flying_transfers. - Update libusb_exit to deinitialise pollfd and default_context - Update libusb_alloc_transfer to use usb_transfer. - Update libusb_submit_transfer to use flying_transfers. - Implement libusb_wait_for_events. - Implement libusb_get_next_timeout. Affected files ... .. //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb10.c#10 edit Differences ... ==== //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb10.c#10 (text+ko) ==== @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "libusb20.h" #include "libusb20_desc.h" @@ -48,6 +50,8 @@ */ #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; \ @@ -92,6 +96,14 @@ struct list_head list; }; +struct usb_transfer { + int num_iso_packets; + struct list_head list; + struct timeval timeout; + int transferred; + uint8_t flags; +}; + void libusb_set_debug(libusb_context * ctx, int level) { @@ -211,8 +223,17 @@ void libusb_exit(libusb_context * ctx) { + usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]); + close(ctx->ctrl_pipe[0]); + close(ctx->ctrl_pipe[1]); + + pthread_mutex_lock(&default_context_lock); + if (ctx == usbi_default_context) { + usbi_default_context = NULL; + } + pthread_mutex_unlock(&default_context_lock); + free(ctx); - return; } /* Device handling and initialisation. */ @@ -635,8 +656,9 @@ struct libusb_transfer *xfer; int len; - len = sizeof(libusb_transfer) + - (iso_packets * sizeof(libusb_iso_packet_descriptor)); + len = sizeof(struct libusb_transfer) + + sizeof(struct usb_transfer) + + (iso_packets * sizeof(libusb_iso_packet_descriptor)); xfer = malloc(len); if (xfer == NULL) @@ -644,6 +666,8 @@ memset(xfer, 0, len); + xfer = (struct libusb_transfer *) ((void *)xfer + + sizeof(struct usb_transfer)); return (xfer); } @@ -672,20 +696,76 @@ libusb_submit_transfer(struct libusb_transfer *xfer) { struct libusb20_transfer *usb20_xfer; + struct usb_transfer *usb_backend; + struct usb_transfer *usb_node; struct libusb20_device *pdev; + struct libusb_context *ctx; + struct timespec cur_ts; + struct timeval *cur_tv; int ret; + if (xfer == NULL) + return (LIBUSB_ERROR_NO_MEM); + + ctx = xfer->dev_handle->dev->ctx; pdev = xfer->dev_handle->os_priv; + + usb_backend = (struct usb_transfer *) ((void *)xfer - + sizeof(struct usb_transfer)); + usb_backend->transferred = 0; + usb_backend->flags = 0; + + /*calculate_timeout*/ + if (xfer->timeout == 0) + return (LIBUSB_ERROR_OTHER); + + ret = clock_gettime(CLOCK_MONOTONIC, &cur_ts); + cur_ts.tv_sec += xfer->timeout / 1000; + cur_ts.tv_nsec += (xfer->timeout % 1000) * 1000000; + if (cur_ts.tv_nsec > 1000000000) { + cur_ts.tv_nsec -= 1000000000; + cur_ts.tv_sec++; + } + TIMESPEC_TO_TIMEVAL(&usb_backend->timeout, &cur_ts); + + /*Add to flying list*/ + pthread_mutex_lock(&ctx->flying_transfers_lock); + if (USB_LIST_EMPTY(&ctx->flying_transfers)) { + LIST_ADD(&usb_backend->list, &ctx->flying_transfers); + goto out; + } + if (timerisset(&usb_backend->timeout)) { + LIST_ADD_TAIL(&usb_backend->list, &ctx->flying_transfers); + goto out; + } + LIST_FOREACH_ENTRY(usb_node, &ctx->flying_transfers, list) { + cur_tv = &usb_node->timeout; + if (timerisset(cur_tv) == 0 || + (cur_tv->tv_sec > usb_backend->timeout.tv_sec) || + (cur_tv->tv_sec == usb_backend->timeout.tv_sec && + cur_tv->tv_usec > usb_backend->timeout.tv_usec)) { + LIST_ADD_TAIL(&usb_backend->list, &usb_node->list); + goto out; + } + } + LIST_ADD_TAIL(&usb_backend->list, &ctx->flying_transfers); + +out: + pthread_mutex_unlock(&ctx->flying_transfers_lock); + + /*libusb20 dependent code*/ GET_XFER(usb20_xfer, xfer->endpoint, pdev); xfer->os_priv = usb20_xfer; ret = libusb20_tr_open(usb20_xfer, xfer->length, xfer->num_iso_packets, xfer->endpoint); - if (ret == LIBUSB20_ERROR_BUSY) - return (LIBUSB_ERROR_BUSY); - if (ret != 0) + if (ret != 0) { + pthread_mutex_lock(&ctx->flying_transfers_lock); + LIST_DEL(&usb_backend->list); + pthread_mutex_unlock(&ctx->flying_transfers_lock); return (LIBUSB_ERROR_OTHER); + } libusb20_tr_set_timeout(usb20_xfer, xfer->timeout); libusb20_tr_set_buffer(usb20_xfer, xfer->buffer, xfer->num_iso_packets); @@ -819,6 +899,31 @@ int libusb_wait_for_event(libusb_context * ctx, struct timeval *tv) { + int ret; + struct timespec ts; + + if (tv == NULL) { + pthread_cond_wait(&ctx->event_waiters_cond, + &ctx->event_waiters_lock); + return (0); + } + + ret = clock_gettime(CLOCK_REALTIME, &ts); + if (ret < 0) + return (LIBUSB_ERROR_OTHER); + + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec * 1000; + if (ts.tv_nsec > 1000000000) { + ts.tv_nsec -= 1000000000; + ts.tv_sec++; + } + + ret = pthread_cond_timedwait(&ctx->event_waiters_cond, + &ctx->event_waiters_lock, &ts); + + if (ret == ETIMEDOUT) + return (1); return (0); } @@ -847,7 +952,45 @@ int libusb_get_next_timeout(libusb_context * ctx, struct timeval *tv) { - return (0); + struct usb_transfer *xfer; + struct timeval *next_tv; + struct timeval cur_tv; + struct timespec cur_ts; + int found; + int ret; + + found = 0; + pthread_mutex_lock(&ctx->flying_transfers_lock); + if (USB_LIST_EMPTY(&ctx->flying_transfers)) + return (0); + + LIST_FOREACH_ENTRY(xfer, &ctx->flying_transfers, list) { + if (!(xfer->flags & LIBUSB_TRANSFER_TIMED_OUT)) { + found = 1; + break ; + } + } + pthread_mutex_unlock(&ctx->flying_transfers_lock); + + if (found == 0) { + return 0; + } + + next_tv = &xfer->timeout; + if (timerisset(next_tv) == 0) + return (0); + + ret = clock_gettime(CLOCK_MONOTONIC, &cur_ts); + if (ret < 0) + return (LIBUSB_ERROR_OTHER); + TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts); + + if (timercmp(&cur_tv, next_tv, >=)) + timerclear(tv); + else + timersub(next_tv, &cur_tv, tv); + + return (1); } void