Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 May 2009 12:12:30 GMT
From:      Sylvestre Gallon <syl@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 163010 for review
Message-ID:  <200905291212.n4TCCU7u026327@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=163010

Change 163010 by syl@syl_rincewind on 2009/05/29 12:11:59

	Fix perror string in test3.
	Implement test5 that dump string descroptors.
	Implement get_next_timeout, handle_timeouts, handle_events helpers.
	Add usb_devs list management in libusb_get_device_list.
	Update libusb_close and libusb_open for handling io and poll.
	Implement libusb_handle_events_locked.
	Implement libusb_handle_events_timeout.

Affected files ...

.. //depot/projects/soc2009/syl_usb/libusb-tests/descriptors/test2/test2.c#4 edit
.. //depot/projects/soc2009/syl_usb/libusb-tests/descriptors/test3/test3.c#3 edit
.. //depot/projects/soc2009/syl_usb/libusb-tests/descriptors/test5/test5.c#2 edit
.. //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb10.c#16 edit

Differences ...

==== //depot/projects/soc2009/syl_usb/libusb-tests/descriptors/test2/test2.c#4 (text+ko) ====


==== //depot/projects/soc2009/syl_usb/libusb-tests/descriptors/test3/test3.c#3 (text+ko) ====

@@ -23,7 +23,7 @@
 
 	ddesc = malloc(sizeof(libusb_device_descriptor));
 	if (ddesc == NULL) {
-		perror("test1");
+		perror("test3");
 		return (EXIT_FAILURE);
 	}
 

==== //depot/projects/soc2009/syl_usb/libusb-tests/descriptors/test5/test5.c#2 (text+ko) ====

@@ -3,8 +3,53 @@
 #include <stdio.h>
 #include <libusb.h>
 	
+libusb_context *ctx;
+
 int
 main(int ac, const char *av[])
 {
+	libusb_device_handle *devh;
+	libusb_device **devs_list;	
+	char buff[512];
+	int ret;
+	int ret2;
+	int i;
+
+	printf("This program will print out all the device"
+	    " strings descriptors for all the present devices.\n");
+
+	if (libusb_init(&ctx) != 0) {
+		fprintf(stderr, "libusb_init failed\n");
+		return (EXIT_FAILURE);
+	}
+
+	if ((ret = libusb_get_device_list(ctx, &devs_list)) < 0) {
+		fprintf(stderr,"libusb_get_device_list failed with 0x%x error code\n",
+		    ret);
+		return (EXIT_FAILURE);
+	}
+	
+	if (ret == 0) {
+		fprintf(stderr, "No device match or lack of permissions.\n");
+		return (EXIT_SUCCESS);
+	}
+	printf("\nThere are %i devices\n\n", ret);
+	for (i = 0 ; i < ret ; i++) {
+		printf("device number = %i\n", i);
+
+		ret2 = libusb_open(devs_list[i], &devh); 
+		if (ret2 != 0) {
+			fprintf(stderr, "libusb open error.\n");
+			return (EXIT_SUCCESS);
+		}
+
+		ret2 = libusb_get_string_descriptor_ascii(devh, 0, buff, 512); 
+		if (ret2 > 0) {
+			fprintf(stderr, "libusb open error.\n");
+			return (EXIT_SUCCESS);
+		} else {
+			printf("string desc size : %i\n", ret2);
+		}
+	}
 	return (EXIT_SUCCESS);
 }

==== //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb10.c#16 (text+ko) ====

@@ -86,6 +86,9 @@
 		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);
 struct libusb_context *usbi_default_context = NULL;
 static pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER;
 
@@ -95,6 +98,7 @@
 	if (ctx == NULL) ctx = usbi_default_context;
 
 #define MAX(a,b) (((a)>(b))?(a):(b))
+#define USB_TIMED_OUT (1<<0)
 
 /*  Library initialisation / deinitialisation */
 
@@ -297,6 +301,10 @@
 		/* link together the two structures */
 		dev->os_priv = pdev;
 
+		pthread_mutex_lock(&ctx->usb_devs_lock);
+		LIST_ADD(&dev->list, &ctx->usb_devs);
+		pthread_mutex_unlock(&ctx->usb_devs_lock);
+
 		(*list)[i] = libusb_ref_device(dev);
 		i++;
 	}
@@ -400,6 +408,10 @@
 	pthread_mutex_unlock(&dev->lock);
 
 	if (dev->refcnt == 0) {
+		pthread_mutex_lock(&dev->ctx->usb_devs_lock);
+		LIST_DEL(&dev->list);
+		pthread_mutex_unlock(&dev->ctx->usb_devs_lock);
+
 		libusb20_dev_free(dev->os_priv);
 		free(dev);
 	}
@@ -411,6 +423,7 @@
 	libusb_context *ctx = dev->ctx;
 	struct libusb20_device *pdev = dev->os_priv;
 	libusb_device_handle *hdl;
+	unsigned char dummy = 1;
 	int err;
 
 	if (devh == NULL)
@@ -438,9 +451,25 @@
 
 	*devh = hdl;
 
-	/*
-	 * XXX Some poll things to implement.
-	 */
+	pthread_mutex_lock(&ctx->pollfd_modify_lock);
+	ctx->pollfd_modify++;
+	pthread_mutex_unlock(&ctx->pollfd_modify_lock);	
+
+	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
+	if (err <= 0) {
+		pthread_mutex_lock(&ctx->pollfd_modify_lock);
+		ctx->pollfd_modify--;
+		pthread_mutex_unlock(&ctx->pollfd_modify_lock);
+		return 0;
+	}
+
+	libusb_lock_events(ctx);
+	err = read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy));
+	pthread_mutex_lock(&ctx->pollfd_modify_lock);
+	ctx->pollfd_modify--;
+	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
+	libusb_unlock_events;
+
 	return (0);
 }
 
@@ -474,17 +503,46 @@
 {
 	libusb_context *ctx;
 	struct libusb20_device *pdev;
+	unsigned char dummy = 1;
 	int err;
 
 	ctx = devh->dev->ctx;
 	pdev = devh->os_priv;
 
-	pthread_mutex_lock(&(ctx->open_devs_lock));
-	err = libusb20_dev_close(pdev);
-	LIST_DEL(&(devh->list));
-	pthread_mutex_unlock(&(ctx->open_devs_lock));
+	pthread_mutex_lock(&ctx->pollfd_modify_lock);
+	ctx->pollfd_modify++;
+	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
+
+	err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy));
+	
+	if (err <= 0) {
+		pthread_mutex_lock(&ctx->open_devs_lock);
+		LIST_DEL(&devh->list);
+		pthread_mutex_unlock(&ctx->open_devs_lock);
+		libusb_unref_device(devh->dev);
+		libusb20_dev_close(pdev);
+		free(devh);
+
+		pthread_mutex_lock(&ctx->pollfd_modify_lock);
+		ctx->pollfd_modify--;
+		pthread_mutex_unlock(&ctx->pollfd_modify_lock);
+		return ;
+	}
+	libusb_lock_events(ctx);
+
+	err = read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy));
+	pthread_mutex_lock(&ctx->open_devs_lock);
+	LIST_DEL(&devh->list);
+	pthread_mutex_unlock(&ctx->open_devs_lock);
 	libusb_unref_device(devh->dev);
+	libusb20_dev_close(pdev);
 	free(devh);
+
+	pthread_mutex_lock(&ctx->pollfd_modify_lock);
+	ctx->pollfd_modify--;
+	pthread_mutex_unlock(&ctx->pollfd_modify_lock);
+
+	libusb_unlock_events(ctx);
 }
 
 libusb_device *
@@ -956,10 +1014,176 @@
 	return (0);
 }
 
+static int 
+get_next_timeout(libusb_context *ctx, struct timeval *tv, struct timeval *out)
+{
+	struct timeval timeout;
+	int ret;
+
+	ret = libusb_get_next_timeout(ctx, &timeout);
+	
+	if (ret) {
+		if (timerisset(&timeout) == 0)
+			return 1;
+		if (timercmp(&timeout, tv, <) != 0)
+			*out = timeout;
+		else
+			*out = *tv;
+	} else {
+		*out = *tv;
+	}
+
+	return (0);
+}	
+
+static int 
+handle_timeouts(struct libusb_context *ctx)
+{
+	struct timespec sys_ts;
+	struct timeval sys_tv;
+	struct timeval *cur_tv;
+	struct usb_transfer *xfer;
+	struct libusb_transfer *uxfer;
+	int ret;
+
+	GET_CONTEXT(ctx);
+	ret = 0;
+
+	pthread_mutex_lock(&ctx->flying_transfers_lock);
+	if (USB_LIST_EMPTY(&ctx->flying_transfers));
+		goto out;
+
+	ret = clock_gettime(CLOCK_MONOTONIC, &sys_ts);
+	TIMESPEC_TO_TIMEVAL(&sys_tv, &sys_ts);
+
+	LIST_FOREACH_ENTRY(xfer, &ctx->flying_transfers, list) {
+		cur_tv = &xfer->timeout;
+
+		if (timerisset(cur_tv) == 0)
+			goto out;
+	
+		if (xfer->flags & USB_TIMED_OUT)
+			continue;
+	
+		if ((cur_tv->tv_sec > sys_tv.tv_sec) || (cur_tv->tv_sec == sys_tv.tv_sec &&
+		    cur_tv->tv_usec > sys_tv.tv_usec))
+			goto out;
+
+		xfer->flags |= USB_TIMED_OUT;
+		uxfer = (libusb_transfer *) (((uint8_t *)xfer) +
+		    sizeof(struct usb_transfer));
+		ret = libusb_cancel_transfer(uxfer);
+	}
+out:
+	pthread_mutex_unlock(&ctx->flying_transfers_lock);
+	return (ret);
+}
+
+static int
+handle_events(struct libusb_context *ctx, struct timeval *tv)
+{
+	struct usb_pollfd *ipollfd;
+	struct libusb_pollfd *tmppollfd;
+	struct pollfd *fds;
+	int tmpfd;
+	int ret;
+	int timeout;
+	nfds_t nfds;
+	int i;
+       
+	nfds = 0;
+	i = -1;
+
+	pthread_mutex_lock(&ctx->pollfds_lock);
+	LIST_FOREACH_ENTRY(ipollfd, &ctx->pollfds, list)
+		nfds++;
+
+	fds = malloc(sizeof(*fds) * nfds);
+	if (fds == NULL)
+		return (LIBUSB_ERROR_NO_MEM);
+
+	LIST_FOREACH_ENTRY(ipollfd, &ctx->pollfds, list) {
+		tmppollfd = &ipollfd->pollfd;
+		tmpfd = tmppollfd->fd;
+		i++;
+		fds[i].fd = tmpfd;
+		fds[i].events = tmppollfd->events;
+		fds[i].revents = 0;
+	}
+
+	pthread_mutex_unlock(&ctx->pollfds_lock);
+
+	timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
+	if (tv->tv_usec % 1000)
+		timeout++;
+
+	ret = poll(fds, nfds, timeout);
+	if (ret == 0) {
+		free(fds);
+		return(handle_timeouts(ctx));
+	} else if (ret == -1 && errno == EINTR) {
+		free(fds);
+		return LIBUSB_ERROR_INTERRUPTED;
+	} else if (ret < 0) {
+		free(fds);
+		return (LIBUSB_ERROR_IO);
+	}	
+
+	if (fds[0].revents) {
+		if (ret == 1){
+			ret = 0;
+			goto handled;
+		} else {
+			fds[0].revents = 0;
+			ret--;
+		}
+	}
+
+	ret = /*unknown*/0;
+handled:
+	free(fds);
+	return ret;
+}
+
 int
 libusb_handle_events_timeout(libusb_context * ctx, struct timeval *tv)
 {
+	struct timeval timeout;
+	struct timeval poll_timeout;
+	int ret;
+	
 	GET_CONTEXT(ctx);
+	ret = libusb_get_next_timeout(ctx, &timeout);
+	if (ret != 0) {
+		if (timerisset(&timeout) == 0)
+			return (handle_timeouts(ctx));
+		if (timercmp(&timeout, tv, <))
+			poll_timeout = timeout;
+		else
+			poll_timeout = *tv;
+	} else {
+		poll_timeout = *tv;
+	}
+retry:
+	if (libusb_try_lock_events(ctx) == 0) {
+		ret = handle_events(ctx, &poll_timeout);
+		libusb_unlock_events(ctx);
+		return ret;
+	}
+
+	libusb_lock_event_waiters(ctx);
+	if (libusb_event_handler_active(ctx) == 0) {
+		libusb_unlock_event_waiters(ctx);
+		goto retry;
+	}
+	
+	ret = libusb_wait_for_event(ctx, &poll_timeout);
+	libusb_unlock_event_waiters(ctx);
+
+	if (ret < 0)
+		return ret;
+	else if (ret == 1)
+		return (handle_timeouts(ctx));
 	return (0);
 }
 
@@ -976,8 +1200,23 @@
 int
 libusb_handle_events_locked(libusb_context * ctx, struct timeval *tv)
 {
+	int ret;
+	struct timeval timeout;
+	struct timeval poll_tv;
+
 	GET_CONTEXT(ctx);
-	return (0);
+	ret = libusb_get_next_timeout(ctx, &timeout);
+	if (ret) {
+		if (timerisset(&timeout) == 0)
+			return handle_timeouts(ctx);
+		if (timercmp(&timeout, tv, <) != 0)
+			poll_tv = timeout;
+		else
+			poll_tv = *tv;
+	} else {
+		poll_tv = *tv;
+	}
+	return (handle_events(ctx, &poll_tv));
 }
 
 int



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