diff options
author | Chris Dickens <christopher.a.dickens@gmail.com> | 2020-09-15 14:15:00 -0700 |
---|---|---|
committer | Chris Dickens <christopher.a.dickens@gmail.com> | 2020-11-10 14:13:12 -0800 |
commit | f69548c3b3340f3e4d9d6f6192451e533ccb2b70 (patch) | |
tree | c500604d062f8d667f1fa66bc3446878e651e94e | |
parent | 851ff404003a26c1e3428b9a1332227173cc124b (diff) | |
download | libusb-f69548c3b3340f3e4d9d6f6192451e533ccb2b70.tar.gz |
examples: Enable all examples to build on all platforms
Prior to this change, the dpfp and sam3u_benchmark examples were only
built on POSIX platforms due to a dependency on sigaction(). Furthermore
the dpfp_threaded example only worked with POSIX threads.
Lift this limitation by breaking the dependence on sigaction(). Also
provide a minimal threading abstraction so that dpfp_threaded can be
built on Windows as well.
Also merge the sources for dpfp and dpfp_threaded. The only difference
between the two is how libusb's event handling functions are called and
this can be easily handled within a single source file.
Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | examples/Makefile.am | 14 | ||||
-rw-r--r-- | examples/dpfp.c | 312 | ||||
-rw-r--r-- | examples/dpfp_threaded.c | 557 | ||||
-rw-r--r-- | examples/sam3u_benchmark.c | 63 | ||||
-rw-r--r--[-rwxr-xr-x] | examples/testlibusb.c | 0 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
7 files changed, 299 insertions, 654 deletions
diff --git a/configure.ac b/configure.ac index 041eab8..4025649 100644 --- a/configure.ac +++ b/configure.ac @@ -325,10 +325,6 @@ AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build], [build example applications [default=no]])], [build_examples=$enableval], [build_examples=no]) -if test "x$build_examples" != xno; then - dnl sigaction needed for some example programs - AC_CHECK_FUNC([sigaction], [have_sigaction=yes], [have_sigaction=]) -fi dnl Tests build AC_ARG_ENABLE([tests-build], @@ -339,7 +335,6 @@ AC_ARG_ENABLE([tests-build], AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != xno]) AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != xno]) AM_CONDITIONAL([CREATE_IMPORT_LIB], [test "x$create_import_lib" = xyes]) -AM_CONDITIONAL([HAVE_SIGACTION], [test "x$have_sigaction" = xyes]) AM_CONDITIONAL([OS_DARWIN], [test "x$backend" = xdarwin]) AM_CONDITIONAL([OS_HAIKU], [test "x$backend" = xhaiku]) AM_CONDITIONAL([OS_LINUX], [test "x$backend" = xlinux]) diff --git a/examples/Makefile.am b/examples/Makefile.am index db757b0..540b027 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -2,17 +2,11 @@ AM_CPPFLAGS = -I$(top_srcdir)/libusb LDADD = ../libusb/libusb-1.0.la LIBS = -noinst_PROGRAMS = fxload hotplugtest listdevs testlibusb xusb +noinst_PROGRAMS = dpfp dpfp_threaded fxload hotplugtest listdevs sam3u_benchmark testlibusb xusb -fxload_SOURCES = ezusb.c ezusb.h fxload.c - -if HAVE_SIGACTION -noinst_PROGRAMS += dpfp -if PLATFORM_POSIX -noinst_PROGRAMS += dpfp_threaded +dpfp_threaded_CPPFLAGS = $(AM_CPPFLAGS) -DDPFP_THREADED dpfp_threaded_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) dpfp_threaded_LDADD = $(LDADD) $(THREAD_LIBS) -endif +dpfp_threaded_SOURCES = dpfp.c -noinst_PROGRAMS += sam3u_benchmark -endif +fxload_SOURCES = ezusb.c ezusb.h fxload.c diff --git a/examples/dpfp.c b/examples/dpfp.c index 77f9476..cbbfc8d 100644 --- a/examples/dpfp.c +++ b/examples/dpfp.c @@ -1,6 +1,8 @@ /* * libusb example program to manipulate U.are.U 4000B fingerprint scanner. * Copyright © 2007 Daniel Drake <dsd@gentoo.org> + * Copyright © 2016 Nathan Hjelm <hjelmn@mac.com> + * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com> * * Basic image capture program only, does not consider the powerup quirks or * the fact that image encryption may be enabled. Not expected to work @@ -21,14 +23,108 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <config.h> + #include <errno.h> #include <signal.h> -#include <string.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "libusb.h" +#if defined(DPFP_THREADED) +#if defined(PLATFORM_POSIX) +#include <pthread.h> +#include <semaphore.h> + +#define THREAD_RETURN_VALUE NULL +typedef sem_t semaphore_t; +typedef pthread_t thread_t; + +static inline int semaphore_init(semaphore_t *semaphore) +{ + return sem_init(semaphore, 0, 0); +} + +static inline void semaphore_give(semaphore_t *semaphore) +{ + (void)sem_post(semaphore); +} + +static inline void semaphore_take(semaphore_t *semaphore) +{ + (void)sem_wait(semaphore); +} + +static inline void semaphore_destroy(semaphore_t *semaphore) +{ + (void)sem_destroy(semaphore); +} + +static inline int thread_create(thread_t *thread, + void *(*thread_entry)(void *arg), void *arg) +{ + return pthread_create(thread, NULL, thread_entry, arg) == 0 ? 0 : -1; +} + +static inline void thread_join(thread_t thread) +{ + (void)pthread_join(thread, NULL); +} +#elif defined(PLATFORM_WINDOWS) +#define THREAD_RETURN_VALUE 0 +typedef HANDLE semaphore_t; +typedef HANDLE thread_t; + +#if defined(__CYGWIN__) +typedef DWORD thread_return_t; +#else +#include <process.h> +typedef unsigned thread_return_t; +#endif + +static inline int semaphore_init(semaphore_t *semaphore) +{ + *semaphore = CreateSemaphore(NULL, 0, 1, NULL); + return *semaphore != NULL ? 0 : -1; +} + +static inline void semaphore_give(semaphore_t *semaphore) +{ + (void)ReleaseSemaphore(*semaphore, 1, NULL); +} + +static inline void semaphore_take(semaphore_t *semaphore) +{ + (void)WaitForSingleObject(*semaphore, INFINITE); +} + +static inline void semaphore_destroy(semaphore_t *semaphore) +{ + (void)CloseHandle(*semaphore); + *semaphore = NULL; +} + +static inline int thread_create(thread_t *thread, + thread_return_t (__stdcall *thread_entry)(void *arg), void *arg) +{ +#if defined(__CYGWIN__) + *thread = CreateThread(NULL, 0, thread_entry, arg, 0, NULL); +#else + *thread = (HANDLE)_beginthreadex(NULL, 0, thread_entry, arg, 0, NULL); +#endif + return *thread != NULL ? 0 : -1; +} + +static inline void thread_join(thread_t thread) +{ + (void)WaitForSingleObject(thread, INFINITE); + (void)CloseHandle(thread); +} +#endif +#endif + #define EP_INTR (1 | LIBUSB_ENDPOINT_IN) #define EP_DATA (2 | LIBUSB_ENDPOINT_IN) #define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN) @@ -57,25 +153,65 @@ enum { }; static int state = 0; -static struct libusb_device_handle *devh = NULL; +static libusb_device_handle *devh = NULL; static unsigned char imgbuf[0x1b340]; static unsigned char irqbuf[INTR_LENGTH]; static struct libusb_transfer *img_transfer = NULL; static struct libusb_transfer *irq_transfer = NULL; static int img_idx = 0; -static int do_exit = 0; +static volatile sig_atomic_t do_exit = 0; + +#if defined(DPFP_THREADED) +static semaphore_t exit_semaphore; +static thread_t poll_thread; +#endif + +static void request_exit(sig_atomic_t code) +{ + do_exit = code; +#if defined(DPFP_THREADED) + semaphore_give(&exit_semaphore); +#endif +} + +#if defined(DPFP_THREADED) +#if defined(PLATFORM_POSIX) +static void *poll_thread_main(void *arg) +#elif defined(PLATFORM_WINDOWS) +static thread_return_t __stdcall poll_thread_main(void *arg) +#endif +{ + (void)arg; + + printf("poll thread running\n"); + + while (!do_exit) { + struct timeval tv = { 1, 0 }; + int r; + + r = libusb_handle_events_timeout(NULL, &tv); + if (r < 0) { + request_exit(2); + break; + } + } + + printf("poll thread shutting down\n"); + return THREAD_RETURN_VALUE; +} +#endif static int find_dpfp_device(void) { devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a); - return devh ? 0 : -EIO; + return devh ? 0 : -ENODEV; } static int print_f0_data(void) { unsigned char data[0x10]; + size_t i; int r; - unsigned int i; r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data, sizeof(data), 0); @@ -83,14 +219,14 @@ static int print_f0_data(void) fprintf(stderr, "F0 error %d\n", r); return r; } - if ((unsigned int) r < sizeof(data)) { + if (r < (int)sizeof(data)) { fprintf(stderr, "short read (%d)\n", r); return -1; } printf("F0 data:"); for (i = 0; i < sizeof(data); i++) - printf("%02x ", data[i]); + printf(" %02x", data[i]); printf("\n"); return 0; } @@ -104,7 +240,7 @@ static int get_hwstat(unsigned char *status) fprintf(stderr, "read hwstat error %d\n", r); return r; } - if ((unsigned int) r < 1) { + if (r < 1) { fprintf(stderr, "short read (%d)\n", r); return -1; } @@ -123,8 +259,8 @@ static int set_hwstat(unsigned char data) fprintf(stderr, "set hwstat error %d\n", r); return r; } - if ((unsigned int) r < 1) { - fprintf(stderr, "short write (%d)", r); + if (r < 1) { + fprintf(stderr, "short write (%d)\n", r); return -1; } @@ -134,15 +270,15 @@ static int set_hwstat(unsigned char data) static int set_mode(unsigned char data) { int r; - printf("set mode %02x\n", data); + printf("set mode %02x\n", data); r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0); if (r < 0) { fprintf(stderr, "set mode error %d\n", r); return r; } - if ((unsigned int) r < 1) { - fprintf(stderr, "short write (%d)", r); + if (r < 1) { + fprintf(stderr, "short write (%d)\n", r); return -1; } @@ -153,18 +289,18 @@ static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { fprintf(stderr, "mode change transfer not completed!\n"); - do_exit = 2; + request_exit(2); } printf("async cb_mode_changed length=%d actual_length=%d\n", transfer->length, transfer->actual_length); if (next_state() < 0) - do_exit = 2; + request_exit(2); } static int set_mode_async(unsigned char data) { - unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); + unsigned char *buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); struct libusb_transfer *transfer; if (!buf) @@ -203,7 +339,7 @@ static int do_sync_intr(unsigned char *data) return -1; } - printf("recv interrupt %04x\n", *((uint16_t *) data)); + printf("recv interrupt %04x\n", *((uint16_t *)data)); return 0; } @@ -223,17 +359,17 @@ static int sync_intr(unsigned char type) static int save_to_file(unsigned char *data) { - FILE *fd; + FILE *f; char filename[64]; snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++); - fd = fopen(filename, "w"); - if (!fd) + f = fopen(filename, "w"); + if (!f) return -1; - fputs("P5 384 289 255 ", fd); - (void) fwrite(data + 64, 1, 384*289, fd); - fclose(fd); + fputs("P5 384 289 255 ", f); + (void)fwrite(data + 64, 1, 384*289, f); + fclose(f); printf("saved image to %s\n", filename); return 0; } @@ -241,6 +377,7 @@ static int save_to_file(unsigned char *data) static int next_state(void) { int r = 0; + printf("old state: %d\n", state); switch (state) { case STATE_AWAIT_IRQ_FINGER_REMOVED: @@ -282,57 +419,60 @@ static void LIBUSB_CALL cb_irq(struct libusb_transfer *transfer) if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { fprintf(stderr, "irq transfer status %d?\n", transfer->status); - do_exit = 2; - libusb_free_transfer(transfer); - irq_transfer = NULL; - return; + goto err_free_transfer; } printf("IRQ callback %02x\n", irqtype); switch (state) { case STATE_AWAIT_IRQ_FINGER_DETECTED: if (irqtype == 0x01) { - if (next_state() < 0) { - do_exit = 2; - return; - } + if (next_state() < 0) + goto err_free_transfer; } else { printf("finger-on-sensor detected in wrong state!\n"); } break; case STATE_AWAIT_IRQ_FINGER_REMOVED: if (irqtype == 0x02) { - if (next_state() < 0) { - do_exit = 2; - return; - } + if (next_state() < 0) + goto err_free_transfer; } else { printf("finger-on-sensor detected in wrong state!\n"); } break; } if (libusb_submit_transfer(irq_transfer) < 0) - do_exit = 2; + goto err_free_transfer; + + return; + +err_free_transfer: + libusb_free_transfer(transfer); + irq_transfer = NULL; + request_exit(2); } static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { fprintf(stderr, "img transfer status %d?\n", transfer->status); - do_exit = 2; - libusb_free_transfer(transfer); - img_transfer = NULL; - return; + goto err_free_transfer; } printf("Image callback\n"); save_to_file(imgbuf); - if (next_state() < 0) { - do_exit = 2; - return; - } + if (next_state() < 0) + goto err_free_transfer; + if (libusb_submit_transfer(img_transfer) < 0) - do_exit = 2; + goto err_free_transfer; + + return; + +err_free_transfer: + libusb_free_transfer(transfer); + img_transfer = NULL; + request_exit(2); } static int init_capture(void) @@ -413,17 +553,33 @@ static void sighandler(int signum) { (void)signum; - do_exit = 1; + request_exit(1); } -int main(void) +static void setup_signals(void) { +#if defined(PLATFORM_POSIX) struct sigaction sigact; + + sigact.sa_handler = sighandler; + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + (void)sigaction(SIGINT, &sigact, NULL); + (void)sigaction(SIGTERM, &sigact, NULL); + (void)sigaction(SIGQUIT, &sigact, NULL); +#else + (void)signal(SIGINT, sighandler); + (void)signal(SIGTERM, sighandler); +#endif +} + +int main(void) +{ int r; r = libusb_init(NULL); if (r < 0) { - fprintf(stderr, "failed to initialise libusb\n"); + fprintf(stderr, "failed to initialise libusb %d - %s\n", r, libusb_strerror(r)); exit(1); } @@ -435,7 +591,7 @@ int main(void) r = libusb_claim_interface(devh, 0); if (r < 0) { - fprintf(stderr, "usb_claim_interface error %d\n", r); + fprintf(stderr, "claim interface error %d - %s\n", r, libusb_strerror(r)); goto out; } printf("claimed interface\n"); @@ -450,44 +606,66 @@ int main(void) /* async from here onwards */ + setup_signals(); + r = alloc_transfers(); if (r < 0) goto out_deinit; +#if defined(DPFP_THREADED) + r = semaphore_init(&exit_semaphore); + if (r < 0) { + fprintf(stderr, "failed to initialise semaphore\n"); + goto out_deinit; + } + + r = thread_create(&poll_thread, poll_thread_main, NULL); + if (r) { + semaphore_destroy(&exit_semaphore); + goto out_deinit; + } + r = init_capture(); if (r < 0) - goto out_deinit; + request_exit(2); - sigact.sa_handler = sighandler; - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction(SIGINT, &sigact, NULL); - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGQUIT, &sigact, NULL); + while (!do_exit) + semaphore_take(&exit_semaphore); +#else + r = init_capture(); + if (r < 0) + goto out_deinit; while (!do_exit) { r = libusb_handle_events(NULL); if (r < 0) - goto out_deinit; + request_exit(2); } +#endif printf("shutting down...\n"); - if (irq_transfer) { - r = libusb_cancel_transfer(irq_transfer); - if (r < 0) - goto out_deinit; - } +#if defined(DPFP_THREADED) + thread_join(poll_thread); + semaphore_destroy(&exit_semaphore); +#endif if (img_transfer) { r = libusb_cancel_transfer(img_transfer); if (r < 0) - goto out_deinit; + fprintf(stderr, "failed to cancel transfer %d - %s\n", r, libusb_strerror(r)); } - while (irq_transfer || img_transfer) + if (irq_transfer) { + r = libusb_cancel_transfer(irq_transfer); + if (r < 0) + fprintf(stderr, "failed to cancel transfer %d - %s\n", r, libusb_strerror(r)); + } + + while (img_transfer || irq_transfer) { if (libusb_handle_events(NULL) < 0) break; + } if (do_exit == 1) r = 0; @@ -495,8 +673,10 @@ int main(void) r = 1; out_deinit: - libusb_free_transfer(img_transfer); - libusb_free_transfer(irq_transfer); + if (img_transfer) + libusb_free_transfer(img_transfer); + if (irq_transfer) + libusb_free_transfer(irq_transfer); set_mode(0); set_hwstat(0x80); out_release: diff --git a/examples/dpfp_threaded.c b/examples/dpfp_threaded.c deleted file mode 100644 index ee6aad0..0000000 --- a/examples/dpfp_threaded.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * libusb example program to manipulate U.are.U 4000B fingerprint scanner. - * Copyright © 2007 Daniel Drake <dsd@gentoo.org> - * Copyright © 2016 Nathan Hjelm <hjelmn@mac.com> - * - * Basic image capture program only, does not consider the powerup quirks or - * the fact that image encryption may be enabled. Not expected to work - * flawlessly all of the time. - * - * 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 <errno.h> -#include <pthread.h> -#include <semaphore.h> -#include <signal.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> - -#include "libusb.h" - -#define EP_INTR (1 | LIBUSB_ENDPOINT_IN) -#define EP_DATA (2 | LIBUSB_ENDPOINT_IN) -#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN) -#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT) -#define USB_RQ 0x04 -#define INTR_LENGTH 64 -#define SEM_NAME "/org.libusb.example.dpfp_threaded" - -enum { - MODE_INIT = 0x00, - MODE_AWAIT_FINGER_ON = 0x10, - MODE_AWAIT_FINGER_OFF = 0x12, - MODE_CAPTURE = 0x20, - MODE_SHUT_UP = 0x30, - MODE_READY = 0x80, -}; - -static int next_state(void); - -enum { - STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1, - STATE_AWAIT_IRQ_FINGER_DETECTED, - STATE_AWAIT_MODE_CHANGE_CAPTURE, - STATE_AWAIT_IMAGE, - STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF, - STATE_AWAIT_IRQ_FINGER_REMOVED, -}; - -static int state = 0; -static struct libusb_device_handle *devh = NULL; -static unsigned char imgbuf[0x1b340]; -static unsigned char irqbuf[INTR_LENGTH]; -static struct libusb_transfer *img_transfer = NULL; -static struct libusb_transfer *irq_transfer = NULL; -static int img_idx = 0; -static volatile sig_atomic_t do_exit = 0; - -static pthread_t poll_thread; -static sem_t *exit_sem; - -static void request_exit(sig_atomic_t code) -{ - do_exit = code; - sem_post(exit_sem); -} - -static void *poll_thread_main(void *arg) -{ - int r = 0; - printf("poll thread running\n"); - - (void)arg; - - while (!do_exit) { - struct timeval tv = { 1, 0 }; - r = libusb_handle_events_timeout(NULL, &tv); - if (r < 0) { - request_exit(2); - break; - } - } - - printf("poll thread shutting down\n"); - return NULL; -} - -static int find_dpfp_device(void) -{ - devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a); - return devh ? 0 : -EIO; -} - -static int print_f0_data(void) -{ - unsigned char data[0x10]; - int r; - unsigned int i; - - r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data, - sizeof(data), 0); - if (r < 0) { - fprintf(stderr, "F0 error %d\n", r); - return r; - } - if ((unsigned int) r < sizeof(data)) { - fprintf(stderr, "short read (%d)\n", r); - return -1; - } - - printf("F0 data:"); - for (i = 0; i < sizeof(data); i++) - printf("%02x ", data[i]); - printf("\n"); - return 0; -} - -static int get_hwstat(unsigned char *status) -{ - int r; - - r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0); - if (r < 0) { - fprintf(stderr, "read hwstat error %d\n", r); - return r; - } - if ((unsigned int) r < 1) { - fprintf(stderr, "short read (%d)\n", r); - return -1; - } - - printf("hwstat reads %02x\n", *status); - return 0; -} - -static int set_hwstat(unsigned char data) -{ - int r; - - printf("set hwstat to %02x\n", data); - r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0); - if (r < 0) { - fprintf(stderr, "set hwstat error %d\n", r); - return r; - } - if ((unsigned int) r < 1) { - fprintf(stderr, "short write (%d)", r); - return -1; - } - - return 0; -} - -static int set_mode(unsigned char data) -{ - int r; - printf("set mode %02x\n", data); - - r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0); - if (r < 0) { - fprintf(stderr, "set mode error %d\n", r); - return r; - } - if ((unsigned int) r < 1) { - fprintf(stderr, "short write (%d)", r); - return -1; - } - - return 0; -} - -static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer) -{ - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fprintf(stderr, "mode change transfer not completed!\n"); - request_exit(2); - } - - printf("async cb_mode_changed length=%d actual_length=%d\n", - transfer->length, transfer->actual_length); - if (next_state() < 0) - request_exit(2); -} - -static int set_mode_async(unsigned char data) -{ - unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); - struct libusb_transfer *transfer; - - if (!buf) - return -ENOMEM; - - transfer = libusb_alloc_transfer(0); - if (!transfer) { - free(buf); - return -ENOMEM; - } - - printf("async set mode %02x\n", data); - libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1); - buf[LIBUSB_CONTROL_SETUP_SIZE] = data; - libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL, - 1000); - - transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK - | LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER; - return libusb_submit_transfer(transfer); -} - -static int do_sync_intr(unsigned char *data) -{ - int r; - int transferred; - - r = libusb_interrupt_transfer(devh, EP_INTR, data, INTR_LENGTH, - &transferred, 1000); - if (r < 0) { - fprintf(stderr, "intr error %d\n", r); - return r; - } - if (transferred < INTR_LENGTH) { - fprintf(stderr, "short read (%d)\n", r); - return -1; - } - - printf("recv interrupt %04x\n", *((uint16_t *) data)); - return 0; -} - -static int sync_intr(unsigned char type) -{ - int r; - unsigned char data[INTR_LENGTH]; - - while (1) { - r = do_sync_intr(data); - if (r < 0) - return r; - if (data[0] == type) - return 0; - } -} - -static int save_to_file(unsigned char *data) -{ - FILE *fd; - char filename[64]; - - snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++); - fd = fopen(filename, "w"); - if (!fd) - return -1; - - fputs("P5 384 289 255 ", fd); - (void) fwrite(data + 64, 1, 384*289, fd); - fclose(fd); - printf("saved image to %s\n", filename); - return 0; -} - -static int next_state(void) -{ - int r = 0; - printf("old state: %d\n", state); - switch (state) { - case STATE_AWAIT_IRQ_FINGER_REMOVED: - state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON; - r = set_mode_async(MODE_AWAIT_FINGER_ON); - break; - case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON: - state = STATE_AWAIT_IRQ_FINGER_DETECTED; - break; - case STATE_AWAIT_IRQ_FINGER_DETECTED: - state = STATE_AWAIT_MODE_CHANGE_CAPTURE; - r = set_mode_async(MODE_CAPTURE); - break; - case STATE_AWAIT_MODE_CHANGE_CAPTURE: - state = STATE_AWAIT_IMAGE; - break; - case STATE_AWAIT_IMAGE: - state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF; - r = set_mode_async(MODE_AWAIT_FINGER_OFF); - break; - case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF: - state = STATE_AWAIT_IRQ_FINGER_REMOVED; - break; - default: - printf("unrecognised state %d\n", state); - } - if (r < 0) { - fprintf(stderr, "error detected changing state\n"); - return r; - } - - printf("new state: %d\n", state); - return 0; -} - -static void LIBUSB_CALL cb_irq(struct libusb_transfer *transfer) -{ - unsigned char irqtype = transfer->buffer[0]; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fprintf(stderr, "irq transfer status %d?\n", transfer->status); - irq_transfer = NULL; - request_exit(2); - return; - } - - printf("IRQ callback %02x\n", irqtype); - switch (state) { - case STATE_AWAIT_IRQ_FINGER_DETECTED: - if (irqtype == 0x01) { - if (next_state() < 0) { - request_exit(2); - return; - } - } else { - printf("finger-on-sensor detected in wrong state!\n"); - } - break; - case STATE_AWAIT_IRQ_FINGER_REMOVED: - if (irqtype == 0x02) { - if (next_state() < 0) { - request_exit(2); - return; - } - } else { - printf("finger-on-sensor detected in wrong state!\n"); - } - break; - } - if (libusb_submit_transfer(irq_transfer) < 0) - request_exit(2); -} - -static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer) -{ - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fprintf(stderr, "img transfer status %d?\n", transfer->status); - img_transfer = NULL; - request_exit(2); - return; - } - - printf("Image callback\n"); - save_to_file(imgbuf); - if (next_state() < 0) { - request_exit(2); - return; - } - if (libusb_submit_transfer(img_transfer) < 0) - request_exit(2); -} - -static int init_capture(void) -{ - int r; - - r = libusb_submit_transfer(irq_transfer); - if (r < 0) - return r; - - r = libusb_submit_transfer(img_transfer); - if (r < 0) { - libusb_cancel_transfer(irq_transfer); - while (irq_transfer) - if (libusb_handle_events(NULL) < 0) - break; - return r; - } - - /* start state machine */ - state = STATE_AWAIT_IRQ_FINGER_REMOVED; - return next_state(); -} - -static int do_init(void) -{ - unsigned char status; - int r; - - r = get_hwstat(&status); - if (r < 0) - return r; - - if (!(status & 0x80)) { - r = set_hwstat(status | 0x80); - if (r < 0) - return r; - r = get_hwstat(&status); - if (r < 0) - return r; - } - - status &= ~0x80; - r = set_hwstat(status); - if (r < 0) - return r; - - r = get_hwstat(&status); - if (r < 0) - return r; - - r = sync_intr(0x56); - if (r < 0) - return r; - - return 0; -} - -static int alloc_transfers(void) -{ - img_transfer = libusb_alloc_transfer(0); - if (!img_transfer) - return -ENOMEM; - - irq_transfer = libusb_alloc_transfer(0); - if (!irq_transfer) - return -ENOMEM; - - libusb_fill_bulk_transfer(img_transfer, devh, EP_DATA, imgbuf, - sizeof(imgbuf), cb_img, NULL, 0); - libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR, irqbuf, - sizeof(irqbuf), cb_irq, NULL, 0); - - return 0; -} - -static void sighandler(int signum) -{ - (void)signum; - - request_exit(1); -} - -int main(void) -{ - struct sigaction sigact; - int r = 1; - - exit_sem = sem_open (SEM_NAME, O_CREAT, 0); - if (!exit_sem) { - fprintf(stderr, "failed to initialise semaphore error %d", errno); - exit(1); - } - - /* only using this semaphore in this process so go ahead and unlink it now */ - sem_unlink (SEM_NAME); - - r = libusb_init(NULL); - if (r < 0) { - fprintf(stderr, "failed to initialise libusb\n"); - exit(1); - } - - r = find_dpfp_device(); - if (r < 0) { - fprintf(stderr, "Could not find/open device\n"); - goto out; - } - - r = libusb_claim_interface(devh, 0); - if (r < 0) { - fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r)); - goto out; - } - printf("claimed interface\n"); - - r = print_f0_data(); - if (r < 0) - goto out_release; - - r = do_init(); - if (r < 0) - goto out_deinit; - - /* async from here onwards */ - - sigact.sa_handler = sighandler; - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction(SIGINT, &sigact, NULL); - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGQUIT, &sigact, NULL); - - r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL); - if (r) - goto out_deinit; - - r = alloc_transfers(); - if (r < 0) { - request_exit(1); - pthread_join(poll_thread, NULL); - goto out_deinit; - } - - r = init_capture(); - if (r < 0) { - request_exit(1); - pthread_join(poll_thread, NULL); - goto out_deinit; - } - - while (!do_exit) - sem_wait(exit_sem); - - printf("shutting down...\n"); - pthread_join(poll_thread, NULL); - - r = libusb_cancel_transfer(irq_transfer); - if (r < 0) { - request_exit(1); - goto out_deinit; - } - - r = libusb_cancel_transfer(img_transfer); - if (r < 0) { - request_exit(1); - goto out_deinit; - } - - while (img_transfer || irq_transfer) - if (libusb_handle_events(NULL) < 0) - break; - - if (do_exit == 1) - r = 0; - else - r = 1; - -out_deinit: - libusb_free_transfer(img_transfer); - libusb_free_transfer(irq_transfer); - set_mode(0); - set_hwstat(0x80); -out_release: - libusb_release_interface(devh, 0); -out: - libusb_close(devh); - libusb_exit(NULL); - return r >= 0 ? r : -r; -} diff --git a/examples/sam3u_benchmark.c b/examples/sam3u_benchmark.c index 68c157d..5cc4065 100644 --- a/examples/sam3u_benchmark.c +++ b/examples/sam3u_benchmark.c @@ -22,24 +22,54 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> +#include <config.h> + #include <errno.h> #include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#include <time.h> #include "libusb.h" - #define EP_DATA_IN 0x82 #define EP_ISO_IN 0x86 -static int do_exit = 0; +static volatile sig_atomic_t do_exit = 0; static struct libusb_device_handle *devh = NULL; static unsigned long num_bytes = 0, num_xfer = 0; static struct timeval tv_start; +static void get_timestamp(struct timeval *tv) +{ +#if defined(PLATFORM_WINDOWS) + static LARGE_INTEGER frequency; + LARGE_INTEGER counter; + + if (!frequency.QuadPart) + QueryPerformanceFrequency(&frequency); + + QueryPerformanceCounter(&counter); + counter.QuadPart *= 1000000; + counter.QuadPart /= frequency.QuadPart; + + tv->tv_sec = (long)(counter.QuadPart / 1000000ULL); + tv->tv_usec = (long)(counter.QuadPart % 1000000ULL); +#elif defined(HAVE_CLOCK_GETTIME) + struct timespec ts; + + (void)clock_gettime(CLOCK_MONOTONIC, &ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000L; +#else + gettimeofday(tv, NULL); +#endif +} + static void LIBUSB_CALL cb_xfr(struct libusb_transfer *xfr) { int i; @@ -103,7 +133,7 @@ static int benchmark_in(uint8_t ep) libusb_fill_bulk_transfer(xfr, devh, ep, buf, sizeof(buf), cb_xfr, NULL, 0); - gettimeofday(&tv_start, NULL); + get_timestamp(&tv_start); /* NOTE: To reach maximum possible performance the program must * submit *multiple* transfers here, not just one. @@ -127,7 +157,7 @@ static void measure(void) struct timeval tv_stop; unsigned long diff_msec; - gettimeofday(&tv_stop, NULL); + get_timestamp(&tv_stop); diff_msec = (tv_stop.tv_sec - tv_start.tv_sec) * 1000L; diff_msec += (tv_stop.tv_usec - tv_start.tv_usec) / 1000L; @@ -138,23 +168,26 @@ static void measure(void) static void sig_hdlr(int signum) { - switch (signum) { - case SIGINT: - measure(); - do_exit = 1; - break; - } + (void)signum; + + measure(); + do_exit = 1; } int main(void) { int rc; + +#if defined(PLATFORM_POSIX) struct sigaction sigact; sigact.sa_handler = sig_hdlr; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; - sigaction(SIGINT, &sigact, NULL); + (void)sigaction(SIGINT, &sigact, NULL); +#else + (void)signal(SIGINT, sig_hdlr); +#endif rc = libusb_init(NULL); if (rc < 0) { @@ -184,7 +217,7 @@ int main(void) /* Measurement has already been done by the signal handler. */ - libusb_release_interface(devh, 0); + libusb_release_interface(devh, 2); out: if (devh) libusb_close(devh); diff --git a/examples/testlibusb.c b/examples/testlibusb.c index ba00f90..ba00f90 100755..100644 --- a/examples/testlibusb.c +++ b/examples/testlibusb.c diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 371785c..047bfa8 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11574 +#define LIBUSB_NANO 11575 |