diff options
author | Daniel Drake <dsd@gentoo.org> | 2008-03-09 01:01:57 +0000 |
---|---|---|
committer | Daniel Drake <dsd@gentoo.org> | 2008-03-09 01:06:08 +0000 |
commit | 1ac0a7d88f282b6f293c456fac8edb143cbaca3d (patch) | |
tree | e75ff5bcaf431f71fa6189c5c0ddaa185470ea39 | |
parent | 66348c90ea4570bf999ac301089e006d0cce1926 (diff) | |
download | libusb-1ac0a7d88f282b6f293c456fac8edb143cbaca3d.tar.gz |
Move synchronous I/O implementation to its own file
-rw-r--r-- | libusb/Makefile.am | 2 | ||||
-rw-r--r-- | libusb/io.c | 150 | ||||
-rw-r--r-- | libusb/sync.c | 169 |
3 files changed, 171 insertions, 150 deletions
diff --git a/libusb/Makefile.am b/libusb/Makefile.am index ff69290..462bd2f 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -1,7 +1,7 @@ lib_LTLIBRARIES = libusb-1.0.la libusb_1_0_la_CFLAGS = -fvisibility=hidden $(AM_CFLAGS) -libusb_1_0_la_SOURCES = libusbi.h usbfs.h core.c descriptor.c io.c +libusb_1_0_la_SOURCES = libusbi.h usbfs.h core.c descriptor.c io.c sync.c libusb_1_0_la_LIBADD = -lrt hdrdir = $(includedir)/libusb-1.0 diff --git a/libusb/io.c b/libusb/io.c index accecab..522a010 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -19,12 +19,11 @@ */ #include <config.h> - #include <errno.h> #include <signal.h> #include <stdint.h> -#include <string.h> #include <stdlib.h> +#include <string.h> #include <sys/select.h> #include <sys/time.h> #include <time.h> @@ -532,153 +531,6 @@ API_EXPORTED int libusb_get_next_timeout(struct timeval *tv) return 1; } -static void ctrl_transfer_cb(struct libusb_transfer *transfer) -{ - int *completed = transfer->user_data; - *completed = 1; - usbi_dbg("actual_length=%d", transfer->actual_length); - /* caller interprets result and frees transfer */ -} - -API_EXPORTED int libusb_control_transfer(libusb_dev_handle *dev_handle, - uint8_t bRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout) -{ - struct libusb_transfer *transfer = libusb_alloc_transfer(); - unsigned char *buffer; - int length = wLength + LIBUSB_CONTROL_SETUP_SIZE; - int completed = 0; - int r; - - if (!transfer) - return -ENOMEM; - - buffer = malloc(length); - if (!buffer) { - libusb_free_transfer(transfer); - return -ENOMEM; - } - - libusb_fill_control_setup(buffer, bRequestType, bRequest, wValue, wIndex, - wLength); - if ((bRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) - memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); - - libusb_fill_control_transfer(transfer, dev_handle, buffer, length, - ctrl_transfer_cb, &completed, timeout); - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - return r; - } - - while (!completed) { - r = libusb_poll(); - if (r < 0) { - libusb_cancel_transfer_sync(dev_handle, transfer); - libusb_free_transfer(transfer); - return r; - } - } - - if ((bRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) - memcpy(data, libusb_control_transfer_get_data(transfer), - transfer->actual_length); - - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - r = transfer->actual_length; - break; - case LIBUSB_TRANSFER_TIMED_OUT: - r = -ETIMEDOUT; - break; - default: - usbi_warn("unrecognised status code %d", transfer->status); - r = -1; - } - - libusb_free_transfer(transfer); - return r; -} - -struct sync_bulk_handle { - enum libusb_transfer_status status; - int actual_length; -}; - -static void bulk_transfer_cb(struct libusb_transfer *transfer) -{ - int *completed = transfer->user_data; - *completed = 1; - usbi_dbg("actual_length=%d", transfer->actual_length); - /* caller interprets results and frees transfer */ -} - -static int do_sync_bulk_transfer(struct libusb_dev_handle *dev_handle, - unsigned char endpoint, unsigned char *buffer, int length, - int *transferred, unsigned int timeout, unsigned char endpoint_type) -{ - struct libusb_transfer *transfer = libusb_alloc_transfer(); - int completed = 0; - int r; - - if (!transfer) - return -ENOMEM; - - libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, - bulk_transfer_cb, &completed, timeout); - transfer->endpoint_type = endpoint_type; - - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - return r; - } - - while (!completed) { - r = libusb_poll(); - if (r < 0) { - libusb_cancel_transfer_sync(dev_handle, transfer); - libusb_free_transfer(transfer); - return r; - } - } - - *transferred = transfer->actual_length; - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - r = 0; - break; - case LIBUSB_TRANSFER_TIMED_OUT: - r = -ETIMEDOUT; - break; - default: - usbi_warn("unrecognised status code %d", transfer->status); - r = -1; - } - - libusb_free_transfer(transfer); - return r; -} - -/* FIXME: should transferred be the return value? */ -API_EXPORTED int libusb_bulk_transfer(struct libusb_dev_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, int *transferred, - unsigned int timeout) -{ - return do_sync_bulk_transfer(dev_handle, endpoint, data, length, - transferred, timeout, LIBUSB_ENDPOINT_TYPE_BULK); -} - -/* FIXME: do we need an interval param here? usbfs doesn't expose it? */ -API_EXPORTED int libusb_interrupt_transfer(struct libusb_dev_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, int *transferred, - unsigned int timeout) -{ - return do_sync_bulk_transfer(dev_handle, endpoint, data, length, - transferred, timeout, LIBUSB_ENDPOINT_TYPE_INTERRUPT); -} - API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer) { struct usbi_transfer *itransfer; diff --git a/libusb/sync.c b/libusb/sync.c new file mode 100644 index 0000000..2bcfc5b --- /dev/null +++ b/libusb/sync.c @@ -0,0 +1,169 @@ +/* + * Synchronous I/O functions for libusb + * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "libusbi.h" + +static void ctrl_transfer_cb(struct libusb_transfer *transfer) +{ + int *completed = transfer->user_data; + *completed = 1; + usbi_dbg("actual_length=%d", transfer->actual_length); + /* caller interprets result and frees transfer */ +} + +API_EXPORTED int libusb_control_transfer(libusb_dev_handle *dev_handle, + uint8_t bRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout) +{ + struct libusb_transfer *transfer = libusb_alloc_transfer(); + unsigned char *buffer; + int length = wLength + LIBUSB_CONTROL_SETUP_SIZE; + int completed = 0; + int r; + + if (!transfer) + return -ENOMEM; + + buffer = malloc(length); + if (!buffer) { + libusb_free_transfer(transfer); + return -ENOMEM; + } + + libusb_fill_control_setup(buffer, bRequestType, bRequest, wValue, wIndex, + wLength); + if ((bRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) + memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); + + libusb_fill_control_transfer(transfer, dev_handle, buffer, length, + ctrl_transfer_cb, &completed, timeout); + r = libusb_submit_transfer(transfer); + if (r < 0) { + libusb_free_transfer(transfer); + return r; + } + + while (!completed) { + r = libusb_poll(); + if (r < 0) { + libusb_cancel_transfer_sync(dev_handle, transfer); + libusb_free_transfer(transfer); + return r; + } + } + + if ((bRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) + memcpy(data, libusb_control_transfer_get_data(transfer), + transfer->actual_length); + + switch (transfer->status) { + case LIBUSB_TRANSFER_COMPLETED: + r = transfer->actual_length; + break; + case LIBUSB_TRANSFER_TIMED_OUT: + r = -ETIMEDOUT; + break; + default: + usbi_warn("unrecognised status code %d", transfer->status); + r = -1; + } + + libusb_free_transfer(transfer); + return r; +} + +static void bulk_transfer_cb(struct libusb_transfer *transfer) +{ + int *completed = transfer->user_data; + *completed = 1; + usbi_dbg("actual_length=%d", transfer->actual_length); + /* caller interprets results and frees transfer */ +} + +static int do_sync_bulk_transfer(struct libusb_dev_handle *dev_handle, + unsigned char endpoint, unsigned char *buffer, int length, + int *transferred, unsigned int timeout, unsigned char endpoint_type) +{ + struct libusb_transfer *transfer = libusb_alloc_transfer(); + int completed = 0; + int r; + + if (!transfer) + return -ENOMEM; + + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, + bulk_transfer_cb, &completed, timeout); + transfer->endpoint_type = endpoint_type; + + r = libusb_submit_transfer(transfer); + if (r < 0) { + libusb_free_transfer(transfer); + return r; + } + + while (!completed) { + r = libusb_poll(); + if (r < 0) { + libusb_cancel_transfer_sync(dev_handle, transfer); + libusb_free_transfer(transfer); + return r; + } + } + + *transferred = transfer->actual_length; + switch (transfer->status) { + case LIBUSB_TRANSFER_COMPLETED: + r = 0; + break; + case LIBUSB_TRANSFER_TIMED_OUT: + r = -ETIMEDOUT; + break; + default: + usbi_warn("unrecognised status code %d", transfer->status); + r = -1; + } + + libusb_free_transfer(transfer); + return r; +} + +/* FIXME: should transferred be the return value? */ +API_EXPORTED int libusb_bulk_transfer(struct libusb_dev_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, int *transferred, + unsigned int timeout) +{ + return do_sync_bulk_transfer(dev_handle, endpoint, data, length, + transferred, timeout, LIBUSB_ENDPOINT_TYPE_BULK); +} + +/* FIXME: do we need an interval param here? usbfs doesn't expose it? */ +API_EXPORTED int libusb_interrupt_transfer(struct libusb_dev_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, int *transferred, + unsigned int timeout) +{ + return do_sync_bulk_transfer(dev_handle, endpoint, data, length, + transferred, timeout, LIBUSB_ENDPOINT_TYPE_INTERRUPT); +} + |