PERFORCE change 163010 for review
Sylvestre Gallon
syl at FreeBSD.org
Fri May 29 12:12:33 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=163010
Change 163010 by syl at 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
More information about the p4-projects
mailing list