Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 May 2009 20:29:33 GMT
From:      Sylvestre Gallon <syl@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 161952 for review
Message-ID:  <200905112029.n4BKTXF9029104@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <stdio.h>
 #include <poll.h>
 #include <pthread.h>
+#include <time.h>
+#include <errno.h>
 
 #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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905112029.n4BKTXF9029104>