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