PERFORCE change 161928 for review
Sylvestre Gallon
syl at FreeBSD.org
Mon May 11 08:45:25 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=161928
Change 161928 by syl at syl_atuin on 2009/05/11 08:44:31
- Add a missing field in struct libusb_context.
- Implement list foreach
- Add default_context handling in libusb_init.
- Init I/O mutex in libusb_init.
- Add pollfds handling in libusb_init.
- Implent libusb_get_pollfds.
Affected files ...
.. //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb.h#8 edit
.. //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb10.c#9 edit
Differences ...
==== //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb.h#8 (text+ko) ====
@@ -196,6 +196,9 @@
struct list_head flying_transfers;
pthread_mutex_t flying_transfers_lock;
+ struct list_head pollfds;
+ pthread_mutex_t pollfds_lock;
+
unsigned int pollfd_modify;
pthread_mutex_t pollfd_modify_lock;
==== //depot/projects/soc2009/syl_usb/src/lib/libusb/libusb10.c#9 (text+ko) ====
@@ -25,7 +25,9 @@
#include <sys/queue.h>
#include <stdlib.h>
+#include <unistd.h>
#include <stdio.h>
+#include <poll.h>
#include <pthread.h>
#include "libusb20.h"
@@ -34,6 +36,13 @@
#include "libusb.h"
/*
+ * XXX TODO
+ * - default context handling.
+ * - implement debug messages.
+ * - implement last io funcs.
+ */
+
+/*
* The two following macros were taken from the original LibUSB v1.0
* for sake of compatibility:
*/
@@ -54,6 +63,18 @@
(entry)->next->prev = (entry)->prev; \
(entry)->prev->next = (entry)->next;
+#define LIST_ENT(ptr, type, member) \
+ ((type *)((char *)(ptr) - (unsigned long) (&((type*)0L)->member)))
+#define LIST_FOREACH_ENTRY(pos, head, member) \
+ for (pos = LIST_ENT((head)->next, typeof(*pos), member) ; \
+ &pos->member != head ; \
+ pos = LIST_ENT(pos->member.next, typeof(*pos), member))
+#define LIST_FOREACH_ENTRY_SAFE(pos, n, head, member) \
+ for (pos = LIST_ENT((head)->next, typeof(*pos), member), \
+ n = LIST_ENT(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = LIST_ENT(n->member.next, typeof(*n), member))
+
/* fetxh libusb20_transfer from libusb20_device */
#define GET_XFER(xfer, endpoint, pdev)\
xfer = libusb20_tr_get_pointer(pdev, \
@@ -61,8 +82,16 @@
if (xfer == NULL) \
return (LIBUSB_ERROR_OTHER);
+struct libusb_context *usbi_default_context = NULL;
+static pthread_mutex_t default_context_lock = PTHREAD_MUTEX_INITIALIZER;
+
/* Library initialisation / deinitialisation */
+struct usb_pollfd {
+ struct libusb_pollfd pollfd;
+ struct list_head list;
+};
+
void
libusb_set_debug(libusb_context * ctx, int level)
{
@@ -70,10 +99,64 @@
ctx->debug = level;
}
+static int
+usb_add_pollfd(libusb_context *ctx, int fd, short events)
+{
+ struct usb_pollfd *pollfd;
+
+ if (ctx == NULL)
+ return (LIBUSB_ERROR_INVALID_PARAM);
+
+ pollfd = malloc(sizeof(*pollfd));
+ if (pollfd == NULL)
+ return (LIBUSB_ERROR_NO_MEM);
+
+ pollfd->pollfd.fd = fd;
+ pollfd->pollfd.events = events;
+
+ pthread_mutex_lock(&ctx->pollfds_lock);
+ LIST_ADD_TAIL(&pollfd->list, &ctx->pollfds);
+ pthread_mutex_unlock(&ctx->pollfds_lock);
+
+ if (ctx->fd_added_cb)
+ ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
+ return (0);
+}
+
+static void
+usb_remove_pollfd(libusb_context *ctx, int fd)
+{
+ struct usb_pollfd *pollfd;
+ int found;
+
+ found = 0;
+ pthread_mutex_lock(&ctx->pollfds_lock);
+
+ LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list) {
+ if (pollfd->pollfd.fd == fd) {
+ found = 1;
+ break ;
+ }
+ }
+
+ if (found == 0) {
+ pthread_mutex_unlock(&ctx->pollfds_lock);
+ return ;
+ }
+
+ LIST_DEL(&pollfd->list);
+ pthread_mutex_unlock(&ctx->pollfds_lock);
+ free(pollfd);
+
+ if (ctx->fd_removed_cb)
+ ctx->fd_removed_cb(fd, ctx->fd_cb_user_data);
+}
+
int
libusb_init(libusb_context ** contex)
{
struct libusb_context *ctx;
+ int ret;
ctx = malloc(sizeof(*ctx));
if (!ctx)
@@ -86,6 +169,39 @@
USB_LIST_INIT(&ctx->usb_devs);
USB_LIST_INIT(&ctx->open_devs);
+ pthread_mutex_init(&ctx->flying_transfers_lock, NULL);
+ pthread_mutex_init(&ctx->pollfds_lock, NULL);
+ pthread_mutex_init(&ctx->pollfd_modify_lock, NULL);
+ pthread_mutex_init(&ctx->events_lock, NULL);
+ pthread_mutex_init(&ctx->event_waiters_lock, NULL);
+ pthread_cond_init(&ctx->event_waiters_cond, NULL);
+
+ USB_LIST_INIT(&ctx->flying_transfers);
+ USB_LIST_INIT(&ctx->pollfds);
+
+ ret = pipe(ctx->ctrl_pipe);
+ if (ret < 0) {
+ free(ctx);
+ usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
+ close(ctx->ctrl_pipe[0]);
+ close(ctx->ctrl_pipe[1]);
+ return (LIBUSB_ERROR_OTHER);
+ }
+
+ ret = usb_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN);
+ if (ret < 0) {
+ free(ctx);
+ usb_remove_pollfd(ctx, ctx->ctrl_pipe[0]);
+ close(ctx->ctrl_pipe[0]);
+ close(ctx->ctrl_pipe[1]);
+ return ret;
+ }
+
+ pthread_mutex_lock(&default_context_lock);
+ if (!usbi_default_context) {
+ usbi_default_context = ctx;
+ }
+
if (contex)
*contex = ctx;
@@ -747,7 +863,27 @@
struct libusb_pollfd **
libusb_get_pollfds(libusb_context * ctx)
{
- return (NULL);
+ struct usb_pollfd *pollfd;
+ libusb_pollfd **ret;
+ int i;
+
+ i = 0;
+ pthread_mutex_lock(&ctx->pollfds_lock);
+ LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list)
+ i++;
+
+ ret = calloc(i + 1 , sizeof(struct libusb_pollfd *));
+ if (ret == NULL) {
+ pthread_mutex_unlock(&ctx->pollfds_lock);
+ return (NULL);
+ }
+
+ i = 0;
+ LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list)
+ ret[i++] = (struct libusb_pollfd *) pollfd;
+ ret[i] = NULL;
+
+ return (ret);
}
/* Synchronous device I/O */
More information about the p4-projects
mailing list