X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=libusb%2Fio.c;h=e6d413243d635b2edd0a031442da0d42974bb71a;hb=3fadb8b4facf5106f1127e389e1855013c1701ca;hp=984fe31498cb916186ec38dfb974840b552159f4;hpb=83a029062c1d2bfb584d7a6ee94915583d37464c;p=platform%2Fupstream%2Flibusb.git diff --git a/libusb/io.c b/libusb/io.c index 984fe31..e6d4132 100644 --- a/libusb/io.c +++ b/libusb/io.c @@ -1,7 +1,7 @@ /* - * I/O functions for libusb - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (c) 2001 Johannes Erdfelt + * I/O functions for libusbx + * Copyright © 2007-2009 Daniel Drake + * Copyright © 2001 Johannes Erdfelt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,15 +20,19 @@ #include #include -#include -#include #include #include #include #include -#include #include -#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef USBI_TIMERFD_AVAILABLE +#include +#endif #include "libusbi.h" @@ -37,10 +41,10 @@ * * \section intro Introduction * - * If you're using libusb in your application, you're probably wanting to + * If you're using libusbx in your application, you're probably wanting to * perform I/O with devices - you want to perform USB data transfers. * - * libusb offers two separate interfaces for device I/O. This page aims to + * libusbx offers two separate interfaces for device I/O. This page aims to * introduce the two in order to help you decide which one is more suitable * for your application. You can also choose to use both interfaces in your * application by considering each transfer on a case-by-case basis. @@ -70,7 +74,7 @@ * Data will arrive when the button is pressed by the user, which is * potentially hours later. * - * libusb offers both a synchronous and an asynchronous interface to performing + * libusbx offers both a synchronous and an asynchronous interface to performing * USB transfers. The main difference is that the synchronous interface * combines both steps indicated above into a single function call, whereas * the asynchronous interface separates them. @@ -88,8 +92,8 @@ * in the following style: \code unsigned char data[4]; -int actual_length, -int r = libusb_bulk_transfer(handle, EP_IN, data, sizeof(data), &actual_length, 0); +int actual_length; +int r = libusb_bulk_transfer(handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0); if (r == 0 && actual_length == sizeof(data)) { // results of the transaction can now be found in the data buffer // parse them here and report button press @@ -117,7 +121,7 @@ if (r == 0 && actual_length == sizeof(data)) { * * For details on how to use the synchronous API, see the * \ref syncio "synchronous I/O API documentation" pages. - * + * * \section async The asynchronous interface * * Asynchronous I/O is the most significant new feature in libusb-1.0. @@ -125,9 +129,9 @@ if (r == 0 && actual_length == sizeof(data)) { * above. * * Instead of providing which functions that block until the I/O has complete, - * libusb's asynchronous interface presents non-blocking functions which + * libusbx's asynchronous interface presents non-blocking functions which * begin a transfer and then return immediately. Your application passes a - * callback function pointer to this non-blocking function, which libusb will + * callback function pointer to this non-blocking function, which libusbx will * call with the results of the transaction when it has completed. * * Transfers which have been submitted through the non-blocking functions @@ -138,12 +142,12 @@ if (r == 0 && actual_length == sizeof(data)) { * to use threads. * * This added flexibility does come with some complications though: - * - In the interest of being a lightweight library, libusb does not create + * - In the interest of being a lightweight library, libusbx does not create * threads and can only operate when your application is calling into it. Your - * application must call into libusb from it's main loop when events are ready - * to be handled, or you must use some other scheme to allow libusb to + * application must call into libusbx from it's main loop when events are ready + * to be handled, or you must use some other scheme to allow libusbx to * undertake whatever work needs to be done. - * - libusb also needs to be called into at certain fixed points in time in + * - libusbx also needs to be called into at certain fixed points in time in * order to accurately handle transfer timeouts. * - Memory handling becomes more complex. You cannot use stack memory unless * the function with that stack is guaranteed not to return until the transfer @@ -153,7 +157,7 @@ if (r == 0 && actual_length == sizeof(data)) { * results are handled. This becomes particularly obvious when you want to * submit a second transfer based on the results of an earlier transfer. * - * Internally, libusb's synchronous interface is expressed in terms of function + * Internally, libusbx's synchronous interface is expressed in terms of function * calls to the asynchronous interface. * * For details on how to use the asynchronous API, see the @@ -170,25 +174,25 @@ if (r == 0 && actual_length == sizeof(data)) { * constraints on packet size defined by endpoint descriptors. The host must * not send data payloads larger than the endpoint's maximum packet size. * - * libusb and the underlying OS abstract out the packet concept, allowing you + * libusbx and the underlying OS abstract out the packet concept, allowing you * to request transfers of any size. Internally, the request will be divided * up into correctly-sized packets. You do not have to be concerned with * packet sizes, but there is one exception when considering overflows. * * \section overflow Bulk/interrupt transfer overflows * - * When requesting data on a bulk endpoint, libusb requires you to supply a - * buffer and the maximum number of bytes of data that libusb can put in that + * When requesting data on a bulk endpoint, libusbx requires you to supply a + * buffer and the maximum number of bytes of data that libusbx can put in that * buffer. However, the size of the buffer is not communicated to the device - * the device is just asked to send any amount of data. * * There is no problem if the device sends an amount of data that is less than - * or equal to the buffer size. libusb reports this condition to you through + * or equal to the buffer size. libusbx reports this condition to you through * the \ref libusb_transfer::actual_length "libusb_transfer.actual_length" * field. * * Problems may occur if the device attempts to send more data than can fit in - * the buffer. libusb reports LIBUSB_TRANSFER_OVERFLOW for this condition but + * the buffer. libusbx reports LIBUSB_TRANSFER_OVERFLOW for this condition but * other behaviour is largely undefined: actual_length may or may not be * accurate, the chunk of data that can fit in the buffer (before overflow) * may or may not have been transferred. @@ -206,7 +210,7 @@ if (r == 0 && actual_length == sizeof(data)) { /** * @defgroup asyncio Asynchronous device I/O * - * This page details libusb's asynchronous (non-blocking) API for USB device + * This page details libusbx's asynchronous (non-blocking) API for USB device * I/O. This interface is very powerful but is also quite complex - you will * need to read this page carefully to understand the necessary considerations * and issues surrounding use of this interface. Simplistic applications @@ -221,7 +225,7 @@ if (r == 0 && actual_length == sizeof(data)) { * * \section asyncabstraction Transfer abstraction * - * For the asynchronous I/O, libusb implements the concept of a generic + * For the asynchronous I/O, libusbx implements the concept of a generic * transfer entity for all types of I/O (control, bulk, interrupt, * isochronous). The generic transfer object must be treated slightly * differently depending on which type of I/O you are performing with it. @@ -231,11 +235,14 @@ if (r == 0 && actual_length == sizeof(data)) { * \section asynctrf Asynchronous transfers * * We can view asynchronous I/O as a 5 step process: - * -# Allocation - * -# Filling - * -# Submission - * -# Completion handling - * -# Deallocation + * -# Allocation: allocate a libusb_transfer + * -# Filling: populate the libusb_transfer instance with information + * about the transfer you wish to perform + * -# Submission: ask libusbx to submit the transfer + * -# Completion handling: examine transfer results in the + * libusb_transfer structure + * -# Deallocation: clean up resources + * * * \subsection asyncalloc Allocation * @@ -276,6 +283,12 @@ if (r == 0 && actual_length == sizeof(data)) { * be invoked. It is up to the callback function to determine which of the * above actually happened and to act accordingly. * + * The user-specified callback is passed a pointer to the libusb_transfer + * structure which was used to setup and submit the transfer. At completion + * time, libusbx has populated this structure with results of the transfer: + * success or failure reason, number of bytes of data transferred, etc. See + * the libusb_transfer structure documentation for more information. + * * \subsection Deallocation * * When a transfer has completed (i.e. the callback function has been invoked), @@ -310,6 +323,10 @@ if (r == 0 && actual_length == sizeof(data)) { * Freeing the transfer after it has been cancelled but before cancellation * has completed will result in undefined behaviour. * + * When a transfer is cancelled, some of the data may have been transferred. + * libusbx will communicate this to you in the transfer callback. Do not assume + * that no data was transferred. + * * \section bulk_overflows Overflows on device-to-host bulk/interrupt endpoints * * If your device does not have predictable transfer sizes (or it misbehaves), @@ -378,7 +395,7 @@ if (r == 0 && actual_length == sizeof(data)) { * request was not supported. * * \section asyncintr Considerations for interrupt transfers - * + * * All interrupt transfers are performed using the polling interval presented * by the bInterval value of the endpoint descriptor. * @@ -401,11 +418,16 @@ if (r == 0 && actual_length == sizeof(data)) { * Next, populate the length field for the first num_iso_packets entries in * the \ref libusb_transfer::iso_packet_desc "iso_packet_desc" array. Section * 5.6.3 of the USB2 specifications describe how the maximum isochronous - * packet length is determined by wMaxPacketSize field in the endpoint - * descriptor. Two functions can help you here: - * - * - libusb_get_max_packet_size() is an easy way to determine the max - * packet size for an endpoint. + * packet length is determined by the wMaxPacketSize field in the endpoint + * descriptor. + * Two functions can help you here: + * + * - libusb_get_max_iso_packet_size() is an easy way to determine the max + * packet size for an isochronous endpoint. Note that the maximum packet + * size is actually the maximum number of bytes that can be transmitted in + * a single microframe, therefore this function multiplies the maximum number + * of bytes per transaction by the number of transaction opportunities per + * microframe. * - libusb_set_iso_packet_lengths() assigns the same length to all packets * within a transfer, which is usually what you want. * @@ -444,7 +466,7 @@ if (r == 0 && actual_length == sizeof(data)) { * * In most circumstances, it is not safe to use stack memory for transfer * buffers. This is because the function that fired off the asynchronous - * transfer may return before libusb has finished using the buffer, and when + * transfer may return before libusbx has finished using the buffer, and when * the function returns it's stack gets destroyed. This is true for both * host-to-device and device-to-host transfers. * @@ -464,53 +486,53 @@ if (r == 0 && actual_length == sizeof(data)) { * \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR "LIBUSB_TRANSFER_ERROR" * (they would normally be regarded as COMPLETED) * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER - * "LIBUSB_TRANSFER_FREE_BUFFER" allows you to ask libusb to free the transfer + * "LIBUSB_TRANSFER_FREE_BUFFER" allows you to ask libusbx to free the transfer * buffer when freeing the transfer. * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_TRANSFER - * "LIBUSB_TRANSFER_FREE_TRANSFER" causes libusb to automatically free the + * "LIBUSB_TRANSFER_FREE_TRANSFER" causes libusbx to automatically free the * transfer after the transfer callback returns. * * \section asyncevent Event handling * - * In accordance of the aim of being a lightweight library, libusb does not - * create threads internally. This means that libusb code does not execute - * at any time other than when your application is calling a libusb function. - * However, an asynchronous model requires that libusb perform work at various + * In accordance of the aim of being a lightweight library, libusbx does not + * create threads internally. This means that libusbx code does not execute + * at any time other than when your application is calling a libusbx function. + * However, an asynchronous model requires that libusbx perform work at various * points in time - namely processing the results of previously-submitted * transfers and invoking the user-supplied callback function. * * This gives rise to the libusb_handle_events() function which your - * application must call into when libusb has work do to. This gives libusb + * application must call into when libusbx has work do to. This gives libusbx * the opportunity to reap pending transfers, invoke callbacks, etc. * * The first issue to discuss here is how your application can figure out - * when libusb has work to do. In fact, there are two naive options which + * when libusbx has work to do. In fact, there are two naive options which * do not actually require your application to know this: * -# Periodically call libusb_handle_events() in non-blocking mode at fixed * short intervals from your main loop * -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated * thread. * - * The first option is plainly not very nice, and will cause unnecessary + * The first option is plainly not very nice, and will cause unnecessary * CPU wakeups leading to increased power usage and decreased battery life. * The second option is not very nice either, but may be the nicest option * available to you if the "proper" approach can not be applied to your * application (read on...). - * - * The recommended option is to integrate libusb with your application main - * event loop. libusb exposes a set of file descriptors which allow you to do + * + * The recommended option is to integrate libusbx with your application main + * event loop. libusbx exposes a set of file descriptors which allow you to do * this. Your main loop is probably already calling poll() or select() or a * variant on a set of file descriptors for other event sources (e.g. keyboard * button presses, mouse movements, network sockets, etc). You then add - * libusb's file descriptors to your poll()/select() calls, and when activity + * libusbx's file descriptors to your poll()/select() calls, and when activity * is detected on such descriptors you know it is time to call * libusb_handle_events(). * - * There is one final event handling complication. libusb supports + * There is one final event handling complication. libusbx supports * asynchronous transfers which time out after a specified time period, and - * this requires that libusb is called into at or after the timeout so that - * the timeout can be handled. So, in addition to considering libusb's file - * descriptors in your main event loop, you must also consider that libusb + * this requires that libusbx is called into at or after the timeout so that + * the timeout can be handled. So, in addition to considering libusbx's file + * descriptors in your main event loop, you must also consider that libusbx * sometimes needs to be called into at fixed points in time even when there * is no file descriptor activity. * @@ -521,7 +543,7 @@ if (r == 0 && actual_length == sizeof(data)) { /** * @defgroup poll Polling and timing * - * This page documents libusb's functions for polling events and timing. + * This page documents libusbx's functions for polling events and timing. * These functions are only necessary for users of the * \ref asyncio "asynchronous API". If you are only using the simpler * \ref syncio "synchronous API" then you do not need to ever call these @@ -529,10 +551,10 @@ if (r == 0 && actual_length == sizeof(data)) { * * The justification for the functionality described here has already been * discussed in the \ref asyncevent "event handling" section of the - * asynchronous API documentation. In summary, libusb does not create internal + * asynchronous API documentation. In summary, libusbx does not create internal * threads for event processing and hence relies on your application calling - * into libusb at certain points in time so that pending events can be handled. - * In order to know precisely when libusb needs to be called into, libusb + * into libusbx at certain points in time so that pending events can be handled. + * In order to know precisely when libusbx needs to be called into, libusbx * offers you a set of pollable file descriptors and information about when * the next timeout expires. * @@ -541,10 +563,10 @@ if (r == 0 && actual_length == sizeof(data)) { * * \section pollsimple The simple option * - * If your application revolves solely around libusb and does not need to + * If your application revolves solely around libusbx and does not need to * handle other event sources, you can have a program structure as follows: \code -// initialize libusb +// initialize libusbx // find and open device // maybe fire off some initial async I/O @@ -560,46 +582,108 @@ while (user_has_not_requested_exit) * * \section pollmain The more advanced option * + * \note This functionality is currently only available on Unix-like platforms. + * On Windows, libusb_get_pollfds() simply returns NULL. Exposing event sources + * on Windows will require some further thought and design. + * * In more advanced applications, you will already have a main loop which * is monitoring other event sources: network sockets, X11 events, mouse - * movements, etc. Through exposing a set of file descriptors, libusb is + * movements, etc. Through exposing a set of file descriptors, libusbx is * designed to cleanly integrate into such main loops. * * In addition to polling file descriptors for the other event sources, you - * take a set of file descriptors from libusb and monitor those too. When you - * detect activity on libusb's file descriptors, you call + * take a set of file descriptors from libusbx and monitor those too. When you + * detect activity on libusbx's file descriptors, you call * libusb_handle_events_timeout() in non-blocking mode. * - * You must also consider the fact that libusb sometimes has to handle events - * at certain known times which do not generate activity on file descriptors. - * Your main loop must also consider these times, modify it's poll()/select() - * timeout accordingly, and track time so that libusb_handle_events_timeout() - * is called in non-blocking mode when timeouts expire. + * What's more, libusbx may also need to handle events at specific moments in + * time. No file descriptor activity is generated at these times, so your + * own application needs to be continually aware of when the next one of these + * moments occurs (through calling libusb_get_next_timeout()), and then it + * needs to call libusb_handle_events_timeout() in non-blocking mode when + * these moments occur. This means that you need to adjust your + * poll()/select() timeout accordingly. + * + * libusbx provides you with a set of file descriptors to poll and expects you + * to poll all of them, treating them as a single entity. The meaning of each + * file descriptor in the set is an internal implementation detail, + * platform-dependent and may vary from release to release. Don't try and + * interpret the meaning of the file descriptors, just do as libusbx indicates, + * polling all of them at once. * * In pseudo-code, you want something that looks like: \code -// initialise libusb +// initialise libusbx libusb_get_pollfds(ctx) while (user has not requested application exit) { libusb_get_next_timeout(ctx); - select(on libusb file descriptors plus any other event sources of interest, - using a timeout no larger than the value libusb just suggested) - if (select() indicated activity on libusb file descriptors) - libusb_handle_events_timeout(ctx, 0); - if (time has elapsed to or beyond the libusb timeout) - libusb_handle_events_timeout(ctx, 0); + poll(on libusbx file descriptors plus any other event sources of interest, + using a timeout no larger than the value libusbx just suggested) + if (poll() indicated activity on libusbx file descriptors) + libusb_handle_events_timeout(ctx, &zero_tv); + if (time has elapsed to or beyond the libusbx timeout) + libusb_handle_events_timeout(ctx, &zero_tv); + // handle events from other sources here +} + +// clean up and exit +\endcode + * + * \subsection polltime Notes on time-based events + * + * The above complication with having to track time and call into libusbx at + * specific moments is a bit of a headache. For maximum compatibility, you do + * need to write your main loop as above, but you may decide that you can + * restrict the supported platforms of your application and get away with + * a more simplistic scheme. + * + * These time-based event complications are \b not required on the following + * platforms: + * - Darwin + * - Linux, provided that the following version requirements are satisfied: + * - Linux v2.6.27 or newer, compiled with timerfd support + * - glibc v2.9 or newer + * - libusbx v1.0.5 or newer + * + * Under these configurations, libusb_get_next_timeout() will \em always return + * 0, so your main loop can be simplified to: +\code +// initialise libusbx + +libusb_get_pollfds(ctx) +while (user has not requested application exit) { + poll(on libusbx file descriptors plus any other event sources of interest, + using any timeout that you like) + if (poll() indicated activity on libusbx file descriptors) + libusb_handle_events_timeout(ctx, &zero_tv); + // handle events from other sources here } // clean up and exit \endcode * - * The set of file descriptors that libusb uses as event sources may change + * Do remember that if you simplify your main loop to the above, you will + * lose compatibility with some platforms (including legacy Linux platforms, + * and any future platforms supported by libusbx which may have time-based + * event requirements). The resultant problems will likely appear as + * strange bugs in your application. + * + * You can use the libusb_pollfds_handle_timeouts() function to do a runtime + * check to see if it is safe to ignore the time-based event complications. + * If your application has taken the shortcut of ignoring libusbx's next timeout + * in your main loop, then you are advised to check the return value of + * libusb_pollfds_handle_timeouts() during application startup, and to abort + * if the platform does suffer from these timing complications. + * + * \subsection fdsetchange Changes in the file descriptor set + * + * The set of file descriptors that libusbx uses as event sources may change * during the life of your application. Rather than having to repeatedly * call libusb_get_pollfds(), you can set up notification functions for when * the file descriptor set changes using libusb_set_pollfd_notifiers(). * - * \section mtissues Multi-threaded considerations + * \subsection mtissues Multi-threaded considerations * * Unfortunately, the situation is complicated further when multiple threads * come into play. If two threads are monitoring the same file descriptors, @@ -615,10 +699,10 @@ while (user has not requested application exit) { /** \page mtasync Multi-threaded applications and asynchronous I/O * - * libusb is a thread-safe library, but extra considerations must be applied - * to applications which interact with libusb from multiple threads. + * libusbx is a thread-safe library, but extra considerations must be applied + * to applications which interact with libusbx from multiple threads. * - * The underlying issue that must be addressed is that all libusb I/O + * The underlying issue that must be addressed is that all libusbx I/O * revolves around monitoring file descriptors through the poll()/select() * system calls. This is directly exposed at the * \ref asyncio "asynchronous interface" but it is important to note that the @@ -626,13 +710,13 @@ while (user has not requested application exit) { * asynchonrous interface, therefore the same considerations apply. * * The issue is that if two or more threads are concurrently calling poll() - * or select() on libusb's file descriptors then only one of those threads + * or select() on libusbx's file descriptors then only one of those threads * will be woken up when an event arrives. The others will be completely * oblivious that anything has happened. * * Consider the following pseudo-code, which submits an asynchronous transfer * then waits for its completion. This style is one way you could implement a - * synchronous interface on top of the asynchronous interface (and libusb + * synchronous interface on top of the asynchronous interface (and libusbx * does something similar, albeit more advanced due to the complications * explained on this page). * @@ -644,7 +728,6 @@ void cb(struct libusb_transfer *transfer) } void myfunc() { - const struct timeval timeout = { 120, 0 }; struct libusb_transfer *transfer; unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE]; int completed = 0; @@ -656,9 +739,9 @@ void myfunc() { libusb_submit_transfer(transfer); while (!completed) { - poll(libusb file descriptors, 120*1000); + poll(libusbx file descriptors, 120*1000); if (poll indicates activity) - libusb_handle_events_timeout(ctx, 0); + libusb_handle_events_timeout(ctx, &zero_tv); } printf("completed!"); // other code here @@ -670,7 +753,7 @@ void myfunc() { * The poll() loop has a long timeout to minimize CPU usage during situations * when nothing is happening (it could reasonably be unlimited). * - * If this is the only thread that is polling libusb's file descriptors, there + * If this is the only thread that is polling libusbx's file descriptors, there * is no problem: there is no danger that another thread will swallow up the * event that we are interested in. On the other hand, if there is another * thread polling the same descriptors, there is a chance that it will receive @@ -679,31 +762,72 @@ void myfunc() { * the loop, up to 120 seconds later. Clearly a two-minute delay is * undesirable, and don't even think about using short timeouts to circumvent * this issue! - * + * * The solution here is to ensure that no two threads are ever polling the * file descriptors at the same time. A naive implementation of this would - * impact the capabilities of the library, so libusb offers the scheme + * impact the capabilities of the library, so libusbx offers the scheme * documented below to ensure no loss of functionality. * * Before we go any further, it is worth mentioning that all libusb-wrapped * event handling procedures fully adhere to the scheme documented below. - * This includes libusb_handle_events() and all the synchronous I/O functions - - * libusb hides this headache from you. You do not need to worry about any - * of these issues if you stick to that level. + * This includes libusb_handle_events() and its variants, and all the + * synchronous I/O functions - libusbx hides this headache from you. + * + * \section Using libusb_handle_events() from multiple threads + * + * Even when only using libusb_handle_events() and synchronous I/O functions, + * you can still have a race condition. You might be tempted to solve the + * above with libusb_handle_events() like so: + * +\code + libusb_submit_transfer(transfer); + + while (!completed) { + libusb_handle_events(ctx); + } + printf("completed!"); +\endcode + * + * This however has a race between the checking of completed and + * libusb_handle_events() acquiring the events lock, so another thread + * could have completed the transfer, resulting in this thread hanging + * until either a timeout or another event occurs. See also commit + * 6696512aade99bb15d6792af90ae329af270eba6 which fixes this in the + * synchronous API implementation of libusb. + * + * Fixing this race requires checking the variable completed only after + * taking the event lock, which defeats the concept of just calling + * libusb_handle_events() without worrying about locking. This is why + * libusb-1.0.9 introduces the new libusb_handle_events_timeout_completed() + * and libusb_handle_events_completed() functions, which handles doing the + * completion check for you after they have acquired the lock: + * +\code + libusb_submit_transfer(transfer); + + while (!completed) { + libusb_handle_events_completed(ctx, &completed); + } + printf("completed!"); +\endcode + * + * This nicely fixes the race in our example. Note that if all you want to + * do is submit a single transfer and wait for its completion, then using + * one of the synchronous I/O functions is much easier. + * + * \section eventlock The events lock * - * The problem is when we consider the fact that libusb exposes file + * The problem is when we consider the fact that libusbx exposes file * descriptors to allow for you to integrate asynchronous USB I/O into * existing main loops, effectively allowing you to do some work behind - * libusb's back. If you do take libusb's file descriptors and pass them to + * libusbx's back. If you do take libusbx's file descriptors and pass them to * poll()/select() yourself, you need to be aware of the associated issues. * - * \section eventlock The events lock - * * The first concept to be introduced is the events lock. The events lock * is used to serialize threads that want to handle events, such that only * one thread is handling events at any one time. * - * You must take the events lock before polling libusb file descriptors, + * You must take the events lock before polling libusbx file descriptors, * using libusb_lock_events(). You must release the lock as soon as you have * aborted your poll()/select() loop, using libusb_unlock_events(). * @@ -714,11 +838,11 @@ void myfunc() { \code libusb_lock_events(ctx); while (!completed) { - poll(libusb file descriptors, 120*1000); + poll(libusbx file descriptors, 120*1000); if (poll indicates activity) - libusb_handle_events_timeout(ctx, 0); + libusb_handle_events_timeout(ctx, &zero_tv); } - libusb_lock_events(ctx); + libusb_unlock_events(ctx); \endcode * ...and the answer is that it is not. This is because the transfer in the * code shown above may take a long time (say 30 seconds) to complete, and @@ -730,7 +854,7 @@ void myfunc() { * status of its transfer until the code above has finished (30 seconds later) * due to contention on the lock. * - * To solve this, libusb offers you a mechanism to determine when another + * To solve this, libusbx offers you a mechanism to determine when another * thread is handling events. It also offers a mechanism to block your thread * until the event handling thread has completed an event (and this mechanism * does not involve polling of file descriptors). @@ -751,9 +875,12 @@ void myfunc() { retry: if (libusb_try_lock_events(ctx) == 0) { // we obtained the event lock: do our own event handling - libusb_lock_events(ctx); while (!completed) { - poll(libusb file descriptors, 120*1000); + if (!libusb_event_handling_ok(ctx)) { + libusb_unlock_events(ctx); + goto retry; + } + poll(libusbx file descriptors, 120*1000); if (poll indicates activity) libusb_handle_events_locked(ctx, 0); } @@ -772,14 +899,21 @@ if (libusb_try_lock_events(ctx) == 0) { libusb_unlock_event_waiters(ctx); goto retry; } - - libusb_wait_for_event(ctx); + + libusb_wait_for_event(ctx, NULL); } libusb_unlock_event_waiters(ctx); } printf("completed!\n"); \endcode * + * A naive look at the above code may suggest that this can only support + * one event waiter (hence a total of 2 competing threads, the other doing + * event handling), because the event waiter seems to have taken the event + * waiters lock while waiting for an event. However, the system does support + * multiple event waiters, because libusb_wait_for_event() actually drops + * the lock while waiting, and reaquires it before continuing. + * * We have now implemented code which can dynamically handle situations where * nobody is handling events (so we should do it ourselves), and it can also * handle situations where another thread is doing event handling (so we can @@ -788,29 +922,106 @@ printf("completed!\n"); * whatever reason it stops doing so before our condition is met, so we take * over the event handling. * - * Three functions were introduced in the above pseudo-code. Their importance + * Four functions were introduced in the above pseudo-code. Their importance * should be apparent from the code shown above. * -# libusb_try_lock_events() is a non-blocking function which attempts * to acquire the events lock but returns a failure code if it is contended. + * -# libusb_event_handling_ok() checks that libusbx is still happy for your + * thread to be performing event handling. Sometimes, libusbx needs to + * interrupt the event handler, and this is how you can check if you have + * been interrupted. If this function returns 0, the correct behaviour is + * for you to give up the event handling lock, and then to repeat the cycle. + * The following libusb_try_lock_events() will fail, so you will become an + * events waiter. For more information on this, read \ref fullstory below. * -# libusb_handle_events_locked() is a variant of * libusb_handle_events_timeout() that you can call while holding the * events lock. libusb_handle_events_timeout() itself implements similar * logic to the above, so be sure not to call it when you are - * "working behind libusb's back", as is the case here. + * "working behind libusbx's back", as is the case here. * -# libusb_event_handler_active() determines if someone is currently * holding the events lock * * You might be wondering why there is no function to wake up all threads - * blocked on libusb_wait_for_event(). This is because libusb can do this + * blocked on libusb_wait_for_event(). This is because libusbx can do this * internally: it will wake up all such threads when someone calls * libusb_unlock_events() or when a transfer completes (at the point after its * callback has returned). * + * \subsection fullstory The full story + * + * The above explanation should be enough to get you going, but if you're + * really thinking through the issues then you may be left with some more + * questions regarding libusbx's internals. If you're curious, read on, and if + * not, skip to the next section to avoid confusing yourself! + * + * The immediate question that may spring to mind is: what if one thread + * modifies the set of file descriptors that need to be polled while another + * thread is doing event handling? + * + * There are 2 situations in which this may happen. + * -# libusb_open() will add another file descriptor to the poll set, + * therefore it is desirable to interrupt the event handler so that it + * restarts, picking up the new descriptor. + * -# libusb_close() will remove a file descriptor from the poll set. There + * are all kinds of race conditions that could arise here, so it is + * important that nobody is doing event handling at this time. + * + * libusbx handles these issues internally, so application developers do not + * have to stop their event handlers while opening/closing devices. Here's how + * it works, focusing on the libusb_close() situation first: + * + * -# During initialization, libusbx opens an internal pipe, and it adds the read + * end of this pipe to the set of file descriptors to be polled. + * -# During libusb_close(), libusbx writes some dummy data on this control pipe. + * This immediately interrupts the event handler. libusbx also records + * internally that it is trying to interrupt event handlers for this + * high-priority event. + * -# At this point, some of the functions described above start behaving + * differently: + * - libusb_event_handling_ok() starts returning 1, indicating that it is NOT + * OK for event handling to continue. + * - libusb_try_lock_events() starts returning 1, indicating that another + * thread holds the event handling lock, even if the lock is uncontended. + * - libusb_event_handler_active() starts returning 1, indicating that + * another thread is doing event handling, even if that is not true. + * -# The above changes in behaviour result in the event handler stopping and + * giving up the events lock very quickly, giving the high-priority + * libusb_close() operation a "free ride" to acquire the events lock. All + * threads that are competing to do event handling become event waiters. + * -# With the events lock held inside libusb_close(), libusbx can safely remove + * a file descriptor from the poll set, in the safety of knowledge that + * nobody is polling those descriptors or trying to access the poll set. + * -# After obtaining the events lock, the close operation completes very + * quickly (usually a matter of milliseconds) and then immediately releases + * the events lock. + * -# At the same time, the behaviour of libusb_event_handling_ok() and friends + * reverts to the original, documented behaviour. + * -# The release of the events lock causes the threads that are waiting for + * events to be woken up and to start competing to become event handlers + * again. One of them will succeed; it will then re-obtain the list of poll + * descriptors, and USB I/O will then continue as normal. + * + * libusb_open() is similar, and is actually a more simplistic case. Upon a + * call to libusb_open(): + * + * -# The device is opened and a file descriptor is added to the poll set. + * -# libusbx sends some dummy data on the control pipe, and records that it + * is trying to modify the poll descriptor set. + * -# The event handler is interrupted, and the same behaviour change as for + * libusb_close() takes effect, causing all event handling threads to become + * event waiters. + * -# The libusb_open() implementation takes its free ride to the events lock. + * -# Happy that it has successfully paused the events handler, libusb_open() + * releases the events lock. + * -# The event waiter threads are all woken up and compete to become event + * handlers again. The one that succeeds will obtain the list of poll + * descriptors again, which will include the addition of the new device. + * * \subsection concl Closing remarks * * The above may seem a little complicated, but hopefully I have made it clear * why such complications are necessary. Also, do not forget that this only - * applies to applications that take libusb's file descriptors and integrate + * applies to applications that take libusbx's file descriptors and integrate * them into their own polling loops. * * You may decide that it is OK for your multi-threaded application to ignore @@ -827,20 +1038,87 @@ printf("completed!\n"); * in them getting along in perfect harmony. * * If you do have a dedicated thread doing event handling, it is perfectly - * legal for it to take the event handling lock and never release it. Any + * legal for it to take the event handling lock for long periods of time. Any * synchronous I/O functions you call from other threads will transparently - * fall back to the "event waiters" mechanism detailed above. + * fall back to the "event waiters" mechanism detailed above. The only + * consideration that your event handling thread must apply is the one related + * to libusb_event_handling_ok(): you must call this before every poll(), and + * give up the events lock if instructed. */ -void usbi_io_init(struct libusb_context *ctx) +int usbi_io_init(struct libusb_context *ctx) { - pthread_mutex_init(&ctx->flying_transfers_lock, NULL); - pthread_mutex_init(&ctx->pollfds_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); + int r; + + usbi_mutex_init(&ctx->flying_transfers_lock, NULL); + usbi_mutex_init(&ctx->pollfds_lock, NULL); + usbi_mutex_init(&ctx->pollfd_modify_lock, NULL); + usbi_mutex_init_recursive(&ctx->events_lock, NULL); + usbi_mutex_init(&ctx->event_waiters_lock, NULL); + usbi_cond_init(&ctx->event_waiters_cond, NULL); list_init(&ctx->flying_transfers); list_init(&ctx->pollfds); + + /* FIXME should use an eventfd on kernels that support it */ + r = usbi_pipe(ctx->ctrl_pipe); + if (r < 0) { + r = LIBUSB_ERROR_OTHER; + goto err; + } + + r = usbi_add_pollfd(ctx, ctx->ctrl_pipe[0], POLLIN); + if (r < 0) + goto err_close_pipe; + +#ifdef USBI_TIMERFD_AVAILABLE + ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(), + TFD_NONBLOCK); + if (ctx->timerfd >= 0) { + usbi_dbg("using timerfd for timeouts"); + r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); + if (r < 0) { + usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]); + close(ctx->timerfd); + goto err_close_pipe; + } + } else { + usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno); + ctx->timerfd = -1; + } +#endif + + return 0; + +err_close_pipe: + usbi_close(ctx->ctrl_pipe[0]); + usbi_close(ctx->ctrl_pipe[1]); +err: + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->pollfds_lock); + usbi_mutex_destroy(&ctx->pollfd_modify_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); + return r; +} + +void usbi_io_exit(struct libusb_context *ctx) +{ + usbi_remove_pollfd(ctx, ctx->ctrl_pipe[0]); + usbi_close(ctx->ctrl_pipe[0]); + usbi_close(ctx->ctrl_pipe[1]); +#ifdef USBI_TIMERFD_AVAILABLE + if (usbi_using_timerfd(ctx)) { + usbi_remove_pollfd(ctx, ctx->timerfd); + close(ctx->timerfd); + } +#endif + usbi_mutex_destroy(&ctx->flying_transfers_lock); + usbi_mutex_destroy(&ctx->pollfds_lock); + usbi_mutex_destroy(&ctx->pollfd_modify_lock); + usbi_mutex_destroy(&ctx->events_lock); + usbi_mutex_destroy(&ctx->event_waiters_lock); + usbi_cond_destroy(&ctx->event_waiters_cond); } static int calculate_timeout(struct usbi_transfer *transfer) @@ -848,12 +1126,12 @@ static int calculate_timeout(struct usbi_transfer *transfer) int r; struct timespec current_time; unsigned int timeout = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; + USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; if (!timeout) return 0; - r = clock_gettime(CLOCK_MONOTONIC, ¤t_time); + r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); if (r < 0) { usbi_err(ITRANSFER_CTX(transfer), "failed to read monotonic clock, errno=%d", errno); @@ -872,13 +1150,18 @@ static int calculate_timeout(struct usbi_transfer *transfer) return 0; } -static void add_to_flying_list(struct usbi_transfer *transfer) +/* add a transfer to the (timeout-sorted) active transfers list. + * returns 1 if the transfer has a timeout and it is the timeout next to + * expire */ +static int add_to_flying_list(struct usbi_transfer *transfer) { struct usbi_transfer *cur; struct timeval *timeout = &transfer->timeout; struct libusb_context *ctx = ITRANSFER_CTX(transfer); - - pthread_mutex_lock(&ctx->flying_transfers_lock); + int r = 0; + int first = 1; + + usbi_mutex_lock(&ctx->flying_transfers_lock); /* if we have no other flying transfers, start the list with this one */ if (list_empty(&ctx->flying_transfers)) { @@ -889,11 +1172,12 @@ static void add_to_flying_list(struct usbi_transfer *transfer) /* if we have infinite timeout, append to end of list */ if (!timerisset(timeout)) { list_add_tail(&transfer->list, &ctx->flying_transfers); + /* first is irrelevant in this case */ goto out; } /* otherwise, find appropriate place in list */ - list_for_each_entry(cur, &ctx->flying_transfers, list) { + list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) { /* find first timeout that occurs after the transfer in question */ struct timeval *cur_tv = &cur->timeout; @@ -903,16 +1187,37 @@ static void add_to_flying_list(struct usbi_transfer *transfer) list_add_tail(&transfer->list, &cur->list); goto out; } + first = 0; } + /* first is 0 at this stage (list not empty) */ /* otherwise we need to be inserted at the end */ list_add_tail(&transfer->list, &ctx->flying_transfers); out: - pthread_mutex_unlock(&ctx->flying_transfers_lock); +#ifdef USBI_TIMERFD_AVAILABLE + if (first && usbi_using_timerfd(ctx) && timerisset(timeout)) { + /* if this transfer has the lowest timeout of all active transfers, + * rearm the timerfd with this transfer's timeout */ + const struct itimerspec it = { {0, 0}, + { transfer->timeout.tv_sec, transfer->timeout.tv_usec * 1000 } }; + usbi_dbg("arm timerfd for timeout in %dms (first in line)", + USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); + r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); + if (r < 0) { + usbi_warn(ctx, "failed to arm first timerfd (error %d)", r); + r = LIBUSB_ERROR_OTHER; + } + } +#else + UNUSED(first); +#endif + + usbi_mutex_unlock(&ctx->flying_transfers_lock); + return r; } /** \ingroup asyncio - * Allocate a libusb transfer with a specified number of isochronous packet + * Allocate a libusbx transfer with a specified number of isochronous packet * descriptors. The returned transfer is pre-initialized for you. When the new * transfer is no longer needed, it should be freed with * libusb_free_transfer(). @@ -934,21 +1239,23 @@ out: * \param iso_packets number of isochronous packet descriptors to allocate * \returns a newly allocated transfer, or NULL on error */ -API_EXPORTED struct libusb_transfer *libusb_alloc_transfer(int iso_packets) +DEFAULT_VISIBILITY +struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( + int iso_packets) { size_t os_alloc_size = usbi_backend->transfer_priv_size + (usbi_backend->add_iso_packet_size * iso_packets); - int alloc_size = sizeof(struct usbi_transfer) + size_t alloc_size = sizeof(struct usbi_transfer) + sizeof(struct libusb_transfer) + (sizeof(struct libusb_iso_packet_descriptor) * iso_packets) + os_alloc_size; - struct usbi_transfer *itransfer = malloc(alloc_size); + struct usbi_transfer *itransfer = calloc(1, alloc_size); if (!itransfer) return NULL; - memset(itransfer, 0, alloc_size); itransfer->num_iso_packets = iso_packets; - return __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + usbi_mutex_init(&itransfer->lock, NULL); + return USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); } /** \ingroup asyncio @@ -963,9 +1270,12 @@ API_EXPORTED struct libusb_transfer *libusb_alloc_transfer(int iso_packets) * It is legal to call this function with a NULL transfer. In this case, * the function will simply return safely. * + * It is not legal to free an active transfer (one which has been submitted + * and has not yet completed). + * * \param transfer the transfer to free */ -API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer) +void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) { struct usbi_transfer *itransfer; if (!transfer) @@ -974,48 +1284,117 @@ API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer) if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer) free(transfer->buffer); - itransfer = __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + usbi_mutex_destroy(&itransfer->lock); free(itransfer); } +#ifdef USBI_TIMERFD_AVAILABLE +static int disarm_timerfd(struct libusb_context *ctx) +{ + const struct itimerspec disarm_timer = { { 0, 0 }, { 0, 0 } }; + int r; + + usbi_dbg(""); + r = timerfd_settime(ctx->timerfd, 0, &disarm_timer, NULL); + if (r < 0) + return LIBUSB_ERROR_OTHER; + else + return 0; +} + +/* iterates through the flying transfers, and rearms the timerfd based on the + * next upcoming timeout. + * must be called with flying_list locked. + * returns 0 if there was no timeout to arm, 1 if the next timeout was armed, + * or a LIBUSB_ERROR code on failure. + */ +static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) +{ + struct usbi_transfer *transfer; + + list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { + struct timeval *cur_tv = &transfer->timeout; + + /* if we've reached transfers of infinite timeout, then we have no + * arming to do */ + if (!timerisset(cur_tv)) + goto disarm; + + /* act on first transfer that is not already cancelled */ + if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) { + int r; + const struct itimerspec it = { {0, 0}, + { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } }; + usbi_dbg("next timeout originally %dms", USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); + r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); + if (r < 0) + return LIBUSB_ERROR_OTHER; + return 1; + } + } + +disarm: + return disarm_timerfd(ctx); +} +#else +static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) +{ + (void)ctx; + return 0; +} +#endif + /** \ingroup asyncio * Submit a transfer. This function will fire off the USB transfer and then * return immediately. * - * It is undefined behaviour to submit a transfer that has already been - * submitted but has not yet completed. - * * \param transfer the transfer to submit * \returns 0 on success * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns LIBUSB_ERROR_BUSY if the transfer has already been submitted. + * \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported + * by the operating system. * \returns another LIBUSB_ERROR code on other failure */ -API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) +int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) { + struct libusb_context *ctx = TRANSFER_CTX(transfer); struct usbi_transfer *itransfer = - __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); int r; + int updated_fds; + usbi_mutex_lock(&itransfer->lock); itransfer->transferred = 0; + itransfer->flags = 0; r = calculate_timeout(itransfer); - if (r < 0) - return LIBUSB_ERROR_OTHER; + if (r < 0) { + r = LIBUSB_ERROR_OTHER; + goto out; + } - add_to_flying_list(itransfer); + r = add_to_flying_list(itransfer); + if (r) + goto out; r = usbi_backend->submit_transfer(itransfer); if (r) { - pthread_mutex_lock(&TRANSFER_CTX(transfer)->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); list_del(&itransfer->list); - pthread_mutex_unlock(&TRANSFER_CTX(transfer)->flying_transfers_lock); + arm_timerfd_for_next_timeout(ctx); + usbi_mutex_unlock(&ctx->flying_transfers_lock); } +out: + updated_fds = (itransfer->flags & USBI_TRANSFER_UPDATED_FDS); + usbi_mutex_unlock(&itransfer->lock); + if (updated_fds) + usbi_fd_notification(ctx); return r; } /** \ingroup asyncio * Asynchronously cancel a previously submitted transfer. - * It is undefined behaviour to call this function on a transfer that is - * already being cancelled or has already completed. * This function returns immediately, but this does not indicate cancellation * is complete. Your callback function will be invoked at some later time * with a transfer status of @@ -1024,19 +1403,33 @@ API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer) * * \param transfer the transfer to cancel * \returns 0 on success + * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is already complete or + * cancelled. * \returns a LIBUSB_ERROR code on failure */ -API_EXPORTED int libusb_cancel_transfer(struct libusb_transfer *transfer) +int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) { struct usbi_transfer *itransfer = - __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); + LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); int r; usbi_dbg(""); + usbi_mutex_lock(&itransfer->lock); r = usbi_backend->cancel_transfer(itransfer); - if (r < 0) - usbi_err(TRANSFER_CTX(transfer), - "cancel transfer failed error %d", r); + if (r < 0) { + if (r != LIBUSB_ERROR_NOT_FOUND) + usbi_err(TRANSFER_CTX(transfer), + "cancel transfer failed error %d", r); + else + usbi_dbg("cancel transfer failed error %d", r); + + if (r == LIBUSB_ERROR_NO_DEVICE) + itransfer->flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; + } + + itransfer->flags |= USBI_TRANSFER_CANCELLING; + + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1044,18 +1437,31 @@ API_EXPORTED int libusb_cancel_transfer(struct libusb_transfer *transfer) * This will invoke the user-supplied callback function, which may end up * freeing the transfer. Therefore you cannot use the transfer structure * after calling this function, and you should free all backend-specific - * data before calling it. */ -void usbi_handle_transfer_completion(struct usbi_transfer *itransfer, + * data before calling it. + * Do not call this function with the usbi_transfer lock held. User-specified + * callback functions may attempt to directly resubmit the transfer, which + * will attempt to take the lock. */ +int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status) { struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = TRANSFER_CTX(transfer); uint8_t flags; + int r = 0; + + /* FIXME: could be more intelligent with the timerfd here. we don't need + * to disarm the timerfd if there was no timer running, and we only need + * to rearm the timerfd if the transfer that expired was the one with + * the shortest timeout. */ - pthread_mutex_lock(&ctx->flying_transfers_lock); + usbi_mutex_lock(&ctx->flying_transfers_lock); list_del(&itransfer->list); - pthread_mutex_unlock(&ctx->flying_transfers_lock); + if (usbi_using_timerfd(ctx)) + r = arm_timerfd_for_next_timeout(ctx); + usbi_mutex_unlock(&ctx->flying_transfers_lock); + if (usbi_using_timerfd(ctx) && (r < 0)) + return r; if (status == LIBUSB_TRANSFER_COMPLETED && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { @@ -1071,41 +1477,44 @@ void usbi_handle_transfer_completion(struct usbi_transfer *itransfer, flags = transfer->flags; transfer->status = status; transfer->actual_length = itransfer->transferred; + usbi_dbg("transfer %p has callback %p", transfer, transfer->callback); if (transfer->callback) transfer->callback(transfer); /* transfer might have been freed by the above call, do not use from * this point. */ if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) libusb_free_transfer(transfer); - pthread_mutex_lock(&ctx->event_waiters_lock); - pthread_cond_broadcast(&ctx->event_waiters_cond); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); + usbi_cond_broadcast(&ctx->event_waiters_cond); + usbi_mutex_unlock(&ctx->event_waiters_lock); + return 0; } /* Similar to usbi_handle_transfer_completion() but exclusively for transfers * that were asynchronously cancelled. The same concerns w.r.t. freeing of * transfers exist here. - */ -void usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) + * Do not call this function with the usbi_transfer lock held. User-specified + * callback functions may attempt to directly resubmit the transfer, which + * will attempt to take the lock. */ +int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) { /* if the URB was cancelled due to timeout, report timeout to the user */ if (transfer->flags & USBI_TRANSFER_TIMED_OUT) { usbi_dbg("detected timeout cancellation"); - usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT); - return; + return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT); } /* otherwise its a normal async cancel */ - usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED); + return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED); } /** \ingroup poll * Attempt to acquire the event handling lock. This lock is used to ensure that - * only one thread is monitoring libusb event sources at any one time. + * only one thread is monitoring libusbx event sources at any one time. * * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly. - * If you stick to libusb's event handling loop functions (e.g. + * which calls poll() or select() on libusbx's file descriptors directly. + * If you stick to libusbx's event handling loop functions (e.g. * libusb_handle_events()) then you do not need to be concerned with this * locking. * @@ -1118,27 +1527,37 @@ void usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) * \returns 1 if the lock was not obtained (i.e. another thread holds the lock) * \see \ref mtasync */ -API_EXPORTED int libusb_try_lock_events(libusb_context *ctx) +int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) { int r; USBI_GET_CONTEXT(ctx); - - r = pthread_mutex_trylock(&ctx->events_lock); + + /* is someone else waiting to modify poll fds? if so, don't let this thread + * start event handling */ + usbi_mutex_lock(&ctx->pollfd_modify_lock); + r = ctx->pollfd_modify; + usbi_mutex_unlock(&ctx->pollfd_modify_lock); + if (r) { + usbi_dbg("someone else is modifying poll fds"); + return 1; + } + + r = usbi_mutex_trylock(&ctx->events_lock); if (r) return 1; - ctx->event_handler_active = 1; + ctx->event_handler_active = 1; return 0; } /** \ingroup poll * Acquire the event handling lock, blocking until successful acquisition if * it is contended. This lock is used to ensure that only one thread is - * monitoring libusb event sources at any one time. + * monitoring libusbx event sources at any one time. * * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly. - * If you stick to libusb's event handling loop functions (e.g. + * which calls poll() or select() on libusbx's file descriptors directly. + * If you stick to libusbx's event handling loop functions (e.g. * libusb_handle_events()) then you do not need to be concerned with this * locking. * @@ -1149,10 +1568,10 @@ API_EXPORTED int libusb_try_lock_events(libusb_context *ctx) * \param ctx the context to operate on, or NULL for the default context * \see \ref mtasync */ -API_EXPORTED void libusb_lock_events(libusb_context *ctx) +void API_EXPORTED libusb_lock_events(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->events_lock); + usbi_mutex_lock(&ctx->events_lock); ctx->event_handler_active = 1; } @@ -1164,17 +1583,60 @@ API_EXPORTED void libusb_lock_events(libusb_context *ctx) * \param ctx the context to operate on, or NULL for the default context * \see \ref mtasync */ -API_EXPORTED void libusb_unlock_events(libusb_context *ctx) +void API_EXPORTED libusb_unlock_events(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); ctx->event_handler_active = 0; - pthread_mutex_unlock(&ctx->events_lock); + usbi_mutex_unlock(&ctx->events_lock); + + /* FIXME: perhaps we should be a bit more efficient by not broadcasting + * the availability of the events lock when we are modifying pollfds + * (check ctx->pollfd_modify)? */ + usbi_mutex_lock(&ctx->event_waiters_lock); + usbi_cond_broadcast(&ctx->event_waiters_cond); + usbi_mutex_unlock(&ctx->event_waiters_lock); +} + +/** \ingroup poll + * Determine if it is still OK for this thread to be doing event handling. + * + * Sometimes, libusbx needs to temporarily pause all event handlers, and this + * is the function you should use before polling file descriptors to see if + * this is the case. + * + * If this function instructs your thread to give up the events lock, you + * should just continue the usual logic that is documented in \ref mtasync. + * On the next iteration, your thread will fail to obtain the events lock, + * and will hence become an event waiter. + * + * This function should be called while the events lock is held: you don't + * need to worry about the results of this function if your thread is not + * the current event handler. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns 1 if event handling can start or continue + * \returns 0 if this thread must give up the events lock + * \see \ref fullstory "Multi-threaded I/O: the full story" + */ +int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx) +{ + int r; + USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->event_waiters_lock); - pthread_cond_broadcast(&ctx->event_waiters_cond); - pthread_mutex_unlock(&ctx->event_waiters_lock); + /* is someone else waiting to modify poll fds? if so, don't let this thread + * continue event handling */ + usbi_mutex_lock(&ctx->pollfd_modify_lock); + r = ctx->pollfd_modify; + usbi_mutex_unlock(&ctx->pollfd_modify_lock); + if (r) { + usbi_dbg("someone else is modifying poll fds"); + return 0; + } + + return 1; } + /** \ingroup poll * Determine if an active thread is handling events (i.e. if anyone is holding * the event handling lock). @@ -1184,9 +1646,21 @@ API_EXPORTED void libusb_unlock_events(libusb_context *ctx) * \returns 0 if there are no threads currently handling events * \see \ref mtasync */ -API_EXPORTED int libusb_event_handler_active(libusb_context *ctx) +int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) { + int r; USBI_GET_CONTEXT(ctx); + + /* is someone else waiting to modify poll fds? if so, don't let this thread + * start event handling -- indicate that event handling is happening */ + usbi_mutex_lock(&ctx->pollfd_modify_lock); + r = ctx->pollfd_modify; + usbi_mutex_unlock(&ctx->pollfd_modify_lock); + if (r) { + usbi_dbg("someone else is modifying poll fds"); + return 1; + } + return ctx->event_handler_active; } @@ -1200,19 +1674,19 @@ API_EXPORTED int libusb_event_handler_active(libusb_context *ctx) * events, then call libusb_wait_for_event(). * * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly, + * which calls poll() or select() on libusbx's file descriptors directly, * and may potentially be handling events from 2 threads simultaenously. - * If you stick to libusb's event handling loop functions (e.g. + * If you stick to libusbx's event handling loop functions (e.g. * libusb_handle_events()) then you do not need to be concerned with this * locking. * * \param ctx the context to operate on, or NULL for the default context * \see \ref mtasync */ -API_EXPORTED void libusb_lock_event_waiters(libusb_context *ctx) +void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->event_waiters_lock); + usbi_mutex_lock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1220,10 +1694,10 @@ API_EXPORTED void libusb_lock_event_waiters(libusb_context *ctx) * \param ctx the context to operate on, or NULL for the default context * \see \ref mtasync */ -API_EXPORTED void libusb_unlock_event_waiters(libusb_context *ctx) +void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) { USBI_GET_CONTEXT(ctx); - pthread_mutex_unlock(&ctx->event_waiters_lock); + usbi_mutex_unlock(&ctx->event_waiters_lock); } /** \ingroup poll @@ -1251,18 +1725,18 @@ API_EXPORTED void libusb_unlock_event_waiters(libusb_context *ctx) * \returns 1 if the timeout expired * \see \ref mtasync */ -API_EXPORTED int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) +int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) { struct timespec timeout; int r; USBI_GET_CONTEXT(ctx); if (tv == NULL) { - pthread_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); + usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); return 0; } - r = clock_gettime(CLOCK_REALTIME, &timeout); + r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout); if (r < 0) { usbi_err(ctx, "failed to read realtime clock, error %d", errno); return LIBUSB_ERROR_OTHER; @@ -1275,7 +1749,7 @@ API_EXPORTED int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) timeout.tv_sec++; } - r = pthread_cond_timedwait(&ctx->event_waiters_cond, + r = usbi_cond_timedwait(&ctx->event_waiters_cond, &ctx->event_waiters_lock, &timeout); return (r == ETIMEDOUT); } @@ -1283,7 +1757,7 @@ API_EXPORTED int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) static void handle_timeout(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = - __USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); int r; itransfer->flags |= USBI_TRANSFER_TIMED_OUT; @@ -1293,52 +1767,78 @@ static void handle_timeout(struct usbi_transfer *itransfer) "async cancel failed %d errno=%d", r, errno); } -static int handle_timeouts(struct libusb_context *ctx) +static int handle_timeouts_locked(struct libusb_context *ctx) { + int r; struct timespec systime_ts; struct timeval systime; struct usbi_transfer *transfer; - int r = 0; - USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->flying_transfers_lock); if (list_empty(&ctx->flying_transfers)) - goto out; + return 0; /* get current time */ - r = clock_gettime(CLOCK_MONOTONIC, &systime_ts); + r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); if (r < 0) - goto out; + return r; TIMESPEC_TO_TIMEVAL(&systime, &systime_ts); /* iterate through flying transfers list, finding all transfers that * have expired timeouts */ - list_for_each_entry(transfer, &ctx->flying_transfers, list) { + list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { struct timeval *cur_tv = &transfer->timeout; /* if we've reached transfers of infinite timeout, we're all done */ if (!timerisset(cur_tv)) - goto out; + return 0; /* ignore timeouts we've already handled */ - if (transfer->flags & USBI_TRANSFER_TIMED_OUT) + if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) continue; /* if transfer has non-expired timeout, nothing more to do */ if ((cur_tv->tv_sec > systime.tv_sec) || (cur_tv->tv_sec == systime.tv_sec && cur_tv->tv_usec > systime.tv_usec)) - goto out; - + return 0; + /* otherwise, we've got an expired timeout to handle */ handle_timeout(transfer); } + return 0; +} + +static int handle_timeouts(struct libusb_context *ctx) +{ + int r; + USBI_GET_CONTEXT(ctx); + usbi_mutex_lock(&ctx->flying_transfers_lock); + r = handle_timeouts_locked(ctx); + usbi_mutex_unlock(&ctx->flying_transfers_lock); + return r; +} + +#ifdef USBI_TIMERFD_AVAILABLE +static int handle_timerfd_trigger(struct libusb_context *ctx) +{ + int r; + + usbi_mutex_lock(&ctx->flying_transfers_lock); + + /* process the timeout that just happened */ + r = handle_timeouts_locked(ctx); + if (r < 0) + goto out; + + /* arm for next timeout*/ + r = arm_timerfd_for_next_timeout(ctx); out: - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); return r; } +#endif /* do the actual event handling. assumes that no other thread is concurrently * doing the same thing. */ @@ -1346,21 +1846,24 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) { int r; struct usbi_pollfd *ipollfd; - nfds_t nfds = 0; - struct pollfd *fds; + POLL_NFDS_TYPE nfds = 0; + struct pollfd *fds = NULL; int i = -1; int timeout_ms; - pthread_mutex_lock(&ctx->pollfds_lock); - list_for_each_entry(ipollfd, &ctx->pollfds, list) + usbi_mutex_lock(&ctx->pollfds_lock); + list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) nfds++; /* TODO: malloc when number of fd's changes, not on every poll */ - fds = malloc(sizeof(*fds) * nfds); - if (!fds) + if (nfds != 0) + fds = malloc(sizeof(*fds) * nfds); + if (!fds) { + usbi_mutex_unlock(&ctx->pollfds_lock); return LIBUSB_ERROR_NO_MEM; + } - list_for_each_entry(ipollfd, &ctx->pollfds, list) { + list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) { struct libusb_pollfd *pollfd = &ipollfd->pollfd; int fd = pollfd->fd; i++; @@ -1368,7 +1871,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) fds[i].events = pollfd->events; fds[i].revents = 0; } - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); timeout_ms = (tv->tv_sec * 1000) + (tv->tv_usec / 1000); @@ -1377,7 +1880,7 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) timeout_ms++; usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); - r = poll(fds, nfds, timeout_ms); + r = usbi_poll(fds, nfds, timeout_ms); usbi_dbg("poll() returned %d", r); if (r == 0) { free(fds); @@ -1391,10 +1894,53 @@ static int handle_events(struct libusb_context *ctx, struct timeval *tv) return LIBUSB_ERROR_IO; } + /* fd[0] is always the ctrl pipe */ + if (fds[0].revents) { + /* another thread wanted to interrupt event handling, and it succeeded! + * handle any other events that cropped up at the same time, and + * simply return */ + usbi_dbg("caught a fish on the control pipe"); + + if (r == 1) { + r = 0; + goto handled; + } else { + /* prevent OS backend from trying to handle events on ctrl pipe */ + fds[0].revents = 0; + r--; + } + } + +#ifdef USBI_TIMERFD_AVAILABLE + /* on timerfd configurations, fds[1] is the timerfd */ + if (usbi_using_timerfd(ctx) && fds[1].revents) { + /* timerfd indicates that a timeout has expired */ + int ret; + usbi_dbg("timerfd triggered"); + + ret = handle_timerfd_trigger(ctx); + if (ret < 0) { + /* return error code */ + r = ret; + goto handled; + } else if (r == 1) { + /* no more active file descriptors, nothing more to do */ + r = 0; + goto handled; + } else { + /* more events pending... + * prevent OS backend from trying to handle events on timerfd */ + fds[1].revents = 0; + r--; + } + } +#endif + r = usbi_backend->handle_events(ctx, fds, nfds, r); if (r) usbi_err(ctx, "backend handle_events failed with error %d", r); +handled: free(fds); return r; } @@ -1429,7 +1975,7 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, /** \ingroup poll * Handle any pending events. * - * libusb determines "pending events" by checking if any timeouts have expired + * libusbx determines "pending events" by checking if any timeouts have expired * and by checking the set of file descriptors for activity. * * If a zero timeval is passed, this function will handle any already-pending @@ -1440,13 +1986,20 @@ static int get_next_timeout(libusb_context *ctx, struct timeval *tv, * timeout. If an event arrives or a signal is raised, this function will * return early. * + * If the parameter completed is not NULL then after obtaining the event + * handling lock this function will return immediately if the integer + * pointed to is not 0. This allows for race free waiting for the completion + * of a specific transfer. + * * \param ctx the context to operate on, or NULL for the default context - * \param tv the maximum time to block waiting for events, or zero for - * non-blocking mode + * \param tv the maximum time to block waiting for events, or an all zero + * timeval struct for non-blocking mode + * \param completed pointer to completion integer to check, or NULL * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \see \ref mtasync */ -API_EXPORTED int libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv) +int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx, + struct timeval *tv, int *completed) { int r; struct timeval poll_timeout; @@ -1460,16 +2013,22 @@ API_EXPORTED int libusb_handle_events_timeout(libusb_context *ctx, retry: if (libusb_try_lock_events(ctx) == 0) { - /* we obtained the event lock: do our own event handling */ - r = handle_events(ctx, &poll_timeout); + if (completed == NULL || !*completed) { + /* we obtained the event lock: do our own event handling */ + usbi_dbg("doing our own event handling"); + r = handle_events(ctx, &poll_timeout); + } libusb_unlock_events(ctx); return r; } - /* another thread is doing event handling. wait for pthread events that + /* another thread is doing event handling. wait for thread events that * notify event completion. */ libusb_lock_event_waiters(ctx); + if (completed && *completed) + goto already_done; + if (!libusb_event_handler_active(ctx)) { /* we hit a race: whoever was event handling earlier finished in the * time it took us to reach this point. try the cycle again. */ @@ -1480,6 +2039,8 @@ retry: usbi_dbg("another thread is doing event handling"); r = libusb_wait_for_event(ctx, &poll_timeout); + +already_done: libusb_unlock_event_waiters(ctx); if (r < 0) @@ -1491,21 +2052,70 @@ retry: } /** \ingroup poll - * Handle any pending events in blocking mode with a sensible timeout. This - * timeout is currently hardcoded at 2 seconds but we may change this if we - * decide other values are more sensible. For finer control over whether this - * function is blocking or non-blocking, or the maximum timeout, use - * libusb_handle_events_timeout() instead. + * Handle any pending events + * + * Like libusb_handle_events_timeout_completed(), but without the completed + * parameter, calling this function is equivalent to calling + * libusb_handle_events_timeout_completed() with a NULL completed parameter. + * + * This function is kept primarily for backwards compatibility. + * All new code should call libusb_handle_events_completed() or + * libusb_handle_events_timeout_completed() to avoid race conditions. + * + * \param ctx the context to operate on, or NULL for the default context + * \param tv the maximum time to block waiting for events, or an all zero + * timeval struct for non-blocking mode + * \returns 0 on success, or a LIBUSB_ERROR code on failure + */ +int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, + struct timeval *tv) +{ + return libusb_handle_events_timeout_completed(ctx, tv, NULL); +} + +/** \ingroup poll + * Handle any pending events in blocking mode. There is currently a timeout + * hardcoded at 60 seconds but we plan to make it unlimited in future. For + * finer control over whether this function is blocking or non-blocking, or + * for control over the timeout, use libusb_handle_events_timeout_completed() + * instead. + * + * This function is kept primarily for backwards compatibility. + * All new code should call libusb_handle_events_completed() or + * libusb_handle_events_timeout_completed() to avoid race conditions. * * \param ctx the context to operate on, or NULL for the default context * \returns 0 on success, or a LIBUSB_ERROR code on failure */ -API_EXPORTED int libusb_handle_events(libusb_context *ctx) +int API_EXPORTED libusb_handle_events(libusb_context *ctx) { struct timeval tv; - tv.tv_sec = 2; + tv.tv_sec = 60; tv.tv_usec = 0; - return libusb_handle_events_timeout(ctx, &tv); + return libusb_handle_events_timeout_completed(ctx, &tv, NULL); +} + +/** \ingroup poll + * Handle any pending events in blocking mode. + * + * Like libusb_handle_events(), with the addition of a completed parameter + * to allow for race free waiting for the completion of a specific transfer. + * + * See libusb_handle_events_timeout_completed() for details on the completed + * parameter. + * + * \param ctx the context to operate on, or NULL for the default context + * \param completed pointer to completion integer to check, or NULL + * \returns 0 on success, or a LIBUSB_ERROR code on failure + * \see \ref mtasync + */ +int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, + int *completed) +{ + struct timeval tv; + tv.tv_sec = 60; + tv.tv_usec = 0; + return libusb_handle_events_timeout_completed(ctx, &tv, completed); } /** \ingroup poll @@ -1514,9 +2124,9 @@ API_EXPORTED int libusb_handle_events(libusb_context *ctx) * held, see libusb_lock_events(). * * This function is designed to be called under the situation where you have - * taken the event lock and are calling poll()/select() directly on libusb's + * taken the event lock and are calling poll()/select() directly on libusbx's * file descriptors (as opposed to using libusb_handle_events() or similar). - * You detect events on libusb's descriptors, so you then call this function + * You detect events on libusbx's descriptors, so you then call this function * with a zero timeout value (while still holding the event lock). * * \param ctx the context to operate on, or NULL for the default context @@ -1525,7 +2135,7 @@ API_EXPORTED int libusb_handle_events(libusb_context *ctx) * \returns 0 on success, or a LIBUSB_ERROR code on failure * \see \ref mtasync */ -API_EXPORTED int libusb_handle_events_locked(libusb_context *ctx, +int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv) { int r; @@ -1542,31 +2152,73 @@ API_EXPORTED int libusb_handle_events_locked(libusb_context *ctx, } /** \ingroup poll - * Determine the next internal timeout that libusb needs to handle. You only + * Determines whether your application must apply special timing considerations + * when monitoring libusbx's file descriptors. + * + * This function is only useful for applications which retrieve and poll + * libusbx's file descriptors in their own main loop (\ref pollmain). + * + * Ordinarily, libusbx's event handler needs to be called into at specific + * moments in time (in addition to times when there is activity on the file + * descriptor set). The usual approach is to use libusb_get_next_timeout() + * to learn about when the next timeout occurs, and to adjust your + * poll()/select() timeout accordingly so that you can make a call into the + * library at that time. + * + * Some platforms supported by libusbx do not come with this baggage - any + * events relevant to timing will be represented by activity on the file + * descriptor set, and libusb_get_next_timeout() will always return 0. + * This function allows you to detect whether you are running on such a + * platform. + * + * Since v1.0.5. + * + * \param ctx the context to operate on, or NULL for the default context + * \returns 0 if you must call into libusbx at times determined by + * libusb_get_next_timeout(), or 1 if all timeout events are handled internally + * or through regular activity on the file descriptors. + * \see \ref pollmain "Polling libusbx file descriptors for event handling" + */ +int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx) +{ +#if defined(USBI_TIMERFD_AVAILABLE) + USBI_GET_CONTEXT(ctx); + return usbi_using_timerfd(ctx); +#else + (void)ctx; + return 0; +#endif +} + +/** \ingroup poll + * Determine the next internal timeout that libusbx needs to handle. You only * need to use this function if you are calling poll() or select() or similar - * on libusb's file descriptors yourself - you do not need to use it if you + * on libusbx's file descriptors yourself - you do not need to use it if you * are calling libusb_handle_events() or a variant directly. - * + * * You should call this function in your main loop in order to determine how - * long to wait for select() or poll() to return results. libusb needs to be + * long to wait for select() or poll() to return results. libusbx needs to be * called into at this timeout, so you should use it as an upper bound on * your select() or poll() call. * * When the timeout has expired, call into libusb_handle_events_timeout() - * (perhaps in non-blocking mode) so that libusb can handle the timeout. + * (perhaps in non-blocking mode) so that libusbx can handle the timeout. * * This function may return 1 (success) and an all-zero timeval. If this is - * the case, it indicates that libusb has a timeout that has already expired + * the case, it indicates that libusbx has a timeout that has already expired * so you should call libusb_handle_events_timeout() or similar immediately. * A return code of 0 indicates that there are no pending timeouts. * + * On some platforms, this function will always returns 0 (no pending + * timeouts). See \ref polltime. + * * \param ctx the context to operate on, or NULL for the default context * \param tv output location for a relative time against the current - * clock in which libusb must be called into in order to process timeout events + * clock in which libusbx must be called into in order to process timeout events * \returns 0 if there are no pending timeouts, 1 if a timeout was returned, * or LIBUSB_ERROR_OTHER on failure */ -API_EXPORTED int libusb_get_next_timeout(libusb_context *ctx, +int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv) { struct usbi_transfer *transfer; @@ -1577,43 +2229,45 @@ API_EXPORTED int libusb_get_next_timeout(libusb_context *ctx, int found = 0; USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->flying_transfers_lock); + if (usbi_using_timerfd(ctx)) + return 0; + + usbi_mutex_lock(&ctx->flying_transfers_lock); if (list_empty(&ctx->flying_transfers)) { - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); usbi_dbg("no URBs, no timeout!"); return 0; } /* find next transfer which hasn't already been processed as timed out */ - list_for_each_entry(transfer, &ctx->flying_transfers, list) { - if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) { - found = 1; - break; - } + list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { + if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) + continue; + + /* no timeout for this transfer? */ + if (!timerisset(&transfer->timeout)) + continue; + + found = 1; + break; } - pthread_mutex_unlock(&ctx->flying_transfers_lock); + usbi_mutex_unlock(&ctx->flying_transfers_lock); if (!found) { - usbi_dbg("all URBs have already been processed for timeouts"); + usbi_dbg("no URB with timeout or all handled by OS; no timeout!"); return 0; } next_timeout = &transfer->timeout; - /* no timeout for next transfer */ - if (!timerisset(next_timeout)) { - usbi_dbg("no URBs with timeouts, no timeout!"); - return 0; - } - - r = clock_gettime(CLOCK_MONOTONIC, &cur_ts); + r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); if (r < 0) { usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); - return LIBUSB_ERROR_OTHER; + return 0; } TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts); - if (timercmp(&cur_tv, next_timeout, >=)) { + if (!timercmp(&cur_tv, next_timeout, <)) { usbi_dbg("first timeout already expired"); timerclear(tv); } else { @@ -1627,17 +2281,25 @@ API_EXPORTED int libusb_get_next_timeout(libusb_context *ctx, /** \ingroup poll * Register notification functions for file descriptor additions/removals. * These functions will be invoked for every new or removed file descriptor - * that libusb uses as an event source. + * that libusbx uses as an event source. * * To remove notifiers, pass NULL values for the function pointers. * + * Note that file descriptors may have been added even before you register + * these notifiers (e.g. at libusb_init() time). + * + * Additionally, note that the removal notifier may be called during + * libusb_exit() (e.g. when it is closing file descriptors that were opened + * and added to the poll set at libusb_init() time). If you don't want this, + * remove the notifiers immediately before calling libusb_exit(). + * * \param ctx the context to operate on, or NULL for the default context * \param added_cb pointer to function for addition notifications * \param removed_cb pointer to function for removal notifications * \param user_data User data to be passed back to callbacks (useful for * passing context information) */ -API_EXPORTED void libusb_set_pollfd_notifiers(libusb_context *ctx, +void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, void *user_data) { @@ -1659,9 +2321,9 @@ int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) usbi_dbg("add fd %d events %d", fd, events); ipollfd->pollfd.fd = fd; ipollfd->pollfd.events = events; - pthread_mutex_lock(&ctx->pollfds_lock); - list_add(&ipollfd->list, &ctx->pollfds); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_lock(&ctx->pollfds_lock); + list_add_tail(&ipollfd->list, &ctx->pollfds); + usbi_mutex_unlock(&ctx->pollfds_lock); if (ctx->fd_added_cb) ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); @@ -1675,8 +2337,8 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) int found = 0; usbi_dbg("remove fd %d", fd); - pthread_mutex_lock(&ctx->pollfds_lock); - list_for_each_entry(ipollfd, &ctx->pollfds, list) + usbi_mutex_lock(&ctx->pollfds_lock); + list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) if (ipollfd->pollfd.fd == fd) { found = 1; break; @@ -1684,12 +2346,12 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) if (!found) { usbi_dbg("couldn't find fd %d to remove", fd); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return; } list_del(&ipollfd->list); - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); free(ipollfd); if (ctx->fd_removed_cb) ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); @@ -1697,39 +2359,50 @@ void usbi_remove_pollfd(struct libusb_context *ctx, int fd) /** \ingroup poll * Retrieve a list of file descriptors that should be polled by your main loop - * as libusb event sources. + * as libusbx event sources. * * The returned list is NULL-terminated and should be freed with free() when * done. The actual list contents must not be touched. * + * As file descriptors are a Unix-specific concept, this function is not + * available on Windows and will always return NULL. + * * \param ctx the context to operate on, or NULL for the default context - * \returns a NULL-terminated list of libusb_pollfd structures, or NULL on - * error + * \returns a NULL-terminated list of libusb_pollfd structures + * \returns NULL on error + * \returns NULL on platforms where the functionality is not available */ -API_EXPORTED const struct libusb_pollfd **libusb_get_pollfds( +DEFAULT_VISIBILITY +const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( libusb_context *ctx) { +#ifndef OS_WINDOWS struct libusb_pollfd **ret = NULL; struct usbi_pollfd *ipollfd; size_t i = 0; size_t cnt = 0; USBI_GET_CONTEXT(ctx); - pthread_mutex_lock(&ctx->pollfds_lock); - list_for_each_entry(ipollfd, &ctx->pollfds, list) + usbi_mutex_lock(&ctx->pollfds_lock); + list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) cnt++; ret = calloc(cnt + 1, sizeof(struct libusb_pollfd *)); if (!ret) goto out; - list_for_each_entry(ipollfd, &ctx->pollfds, list) + list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) ret[i++] = (struct libusb_pollfd *) ipollfd; ret[cnt] = NULL; out: - pthread_mutex_unlock(&ctx->pollfds_lock); + usbi_mutex_unlock(&ctx->pollfds_lock); return (const struct libusb_pollfd **) ret; +#else + usbi_err(ctx, "external polling of libusbx's internal descriptors "\ + "is not yet supported on Windows platforms"); + return NULL; +#endif } /* Backends call this from handle_events to report disconnection of a device. @@ -1745,7 +2418,7 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle) /* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE * status code. - * + * * this is a bit tricky because: * 1. we can't do transfer completion while holding flying_transfers_lock * 2. the transfers list can change underneath us - if we were to build a @@ -1757,14 +2430,14 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle) */ while (1) { - pthread_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock); + usbi_mutex_lock(&HANDLE_CTX(handle)->flying_transfers_lock); to_cancel = NULL; - list_for_each_entry(cur, &HANDLE_CTX(handle)->flying_transfers, list) - if (__USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == handle) { + list_for_each_entry(cur, &HANDLE_CTX(handle)->flying_transfers, list, struct usbi_transfer) + if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == handle) { to_cancel = cur; break; } - pthread_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock); + usbi_mutex_unlock(&HANDLE_CTX(handle)->flying_transfers_lock); if (!to_cancel) break; @@ -1774,4 +2447,3 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle) } } -