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>