From d0ad24c4c9ef12b1b4e1425867b7753e11f9d432 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Mon, 15 Nov 2010 22:18:49 +0300 Subject: Break iface list functions into iface functions Break interface list functions into interface functions and use list iteration macro instead. --- include/uhd/iface.h | 158 +++++++++++++------------- lib/iface.c | 317 ++++++++++++++++++++++++---------------------------- src/usbhid-dump.c | 74 +++++++----- 3 files changed, 275 insertions(+), 274 deletions(-) diff --git a/include/uhd/iface.h b/include/uhd/iface.h index 72c5ca7..cc25361 100644 --- a/include/uhd/iface.h +++ b/include/uhd/iface.h @@ -72,8 +72,8 @@ extern bool uhd_iface_valid(const uhd_iface *iface); /** * Create a new interface. * - * @param handle Device handle. - * @param number Interface number. + * @param handle Device handle. + * @param number Interface number. * @param int_in_ep_addr Interrupt in endpoint address. * @param int_in_ep_maxp Interrupt in endpoint maximum packet size. * @@ -92,143 +92,151 @@ extern uhd_iface *uhd_iface_new(libusb_device_handle *handle, extern void uhd_iface_free(uhd_iface *iface); /** - * Check if an interface list is valid. + * Detach an interface from its kernel driver (if any). * - * @param list Interface list to check. + * @param iface The interface to detach. * - * @return True if the interface list is valid, false otherwise. + * @return Libusb error code. */ -extern bool uhd_iface_list_valid(const uhd_iface *list); +extern enum libusb_error uhd_iface_detach(uhd_iface *iface); /** - * Check if an interface list is empty. + * Attach an interface to its kernel driver (if detached before). * - * @param list Interface list to check. + * @param iface The interface to attach. * - * @return True if the interface list is empty, false otherwise. + * @return Libusb error code. */ -static inline bool -uhd_iface_list_empty(const uhd_iface *list) -{ - return list == NULL; -} +extern enum libusb_error uhd_iface_attach(uhd_iface *iface); /** - * Calculate length of an interface list. + * Claim an interface. * - * @param list The list to calculate length of. + * @param iface The interface to claim. * - * @return The list length. + * @return Libusb error code. */ -extern size_t uhd_iface_list_len(const uhd_iface *list); +extern enum libusb_error uhd_iface_claim(uhd_iface *iface); /** - * Free an interface list. + * Set idle duration on an interface; ignore errors indicating missing + * support. * - * @param list The interface list to free. + * @param iface The interface to set idle duration on. + * @param duration The duration in 4 ms steps starting from 4 ms. + * @param timeout The request timeout, ms. + * + * @return Libusb error code. */ -extern void uhd_iface_list_free(uhd_iface *list); - +extern enum libusb_error uhd_iface_set_idle( + const uhd_iface *iface, + uint8_t duration, + unsigned int timeout); /** - * Fetch a list of HID interfaces from a device. + * Set HID protocol on an interface; ignore errors indicating missing + * support. * - * @param handle The device handle to fetch interface list from. - * @param plist Location for the resulting list head; could be NULL. + * @param iface The interface to set idle duration on. + * @param report True for "report" protocol, false for "boot" protocol. + * @param timeout The request timeout, ms. * * @return Libusb error code. */ -enum libusb_error -uhd_iface_list_new_from_dev(libusb_device_handle *handle, - uhd_iface **plist); +extern enum libusb_error uhd_iface_set_protocol( + const uhd_iface *iface, + bool report, + unsigned int timeout); /** - * Filter an interface list by an optional interface number, resulting - * either in an empty, a single-interface, or an unmodified list. + * Clear halt condition on the input interrupt endpoint of an interface. * - * @param plist The original list head. - * @param number The interface number to match against, or a negative - * integer meaning there is no restriction. + * @param iface The interface to clear halt condition on. * - * @return The resulting list head + * @return Libusb error code. */ -extern uhd_iface *uhd_iface_list_fltr_by_num(uhd_iface *list, - int number); +extern enum libusb_error uhd_iface_clear_halt(uhd_iface *iface); /** - * Detach all interfaces in a list from their kernel drivers (if any). + * Release an interface (if claimed before). * - * @param list The list of interfaces to detach. + * @param iface The interface to release. * * @return Libusb error code. */ -extern enum libusb_error uhd_iface_list_detach(uhd_iface *list); +extern enum libusb_error uhd_iface_release(uhd_iface *iface); /** - * Attach all interfaces in a list to their kernel drivers (if were detached - * before). + * Check if an interface list is valid. * - * @param list The list of interfaces to attach. + * @param list Interface list to check. * - * @return Libusb error code. + * @return True if the interface list is valid, false otherwise. */ -extern enum libusb_error uhd_iface_list_attach(uhd_iface *list); +extern bool uhd_iface_list_valid(const uhd_iface *list); /** - * Claim all interfaces in a list. + * Check if an interface list is empty. * - * @param list The list of interfaces to claim. + * @param list Interface list to check. * - * @return Libusb error code. + * @return True if the interface list is empty, false otherwise. */ -extern enum libusb_error uhd_iface_list_claim(uhd_iface *list); +static inline bool +uhd_iface_list_empty(const uhd_iface *list) +{ + return list == NULL; +} /** - * Set idle duration on all interfaces in a list; ignore errors indicating - * missing support. + * Calculate length of an interface list. * - * @param list The list of interfaces to set idle duration on. - * @param duration The duration in 4 ms steps starting from 4 ms. - * @param timeout The request timeout, ms. + * @param list The list to calculate length of. * - * @return Libusb error code. + * @return The list length. */ -extern enum libusb_error uhd_iface_list_set_idle( - const uhd_iface *list, - uint8_t duration, - unsigned int timeout); +extern size_t uhd_iface_list_len(const uhd_iface *list); /** - * Set HID protocol on all interfaces in a list; ignore errors indicating - * missing support. + * Free an interface list. * - * @param list The list of interfaces to set idle duration on. - * @param report True for "report" protocol, false for "boot" protocol. - * @param timeout The request timeout, ms. + * @param list The interface list to free. + */ +extern void uhd_iface_list_free(uhd_iface *list); + +/** + * Iterate over an interface list. * - * @return Libusb error code. + * @param _iface Loop interface variable. + * @param _list Interface list to iterate over. */ -extern enum libusb_error uhd_iface_list_set_protocol( - const uhd_iface *list, - bool report, - unsigned int timeout); +#define UHD_IFACE_LIST_FOR_EACH(_iface, _list) \ + for (_iface = _list; _iface != NULL; _iface = _iface->next) /** - * Clear halt condition on input interrupt endpoints of all interfaces. + * Fetch a list of HID interfaces from a device. * - * @param list The list of interfaces to clear halt condition on. + * @param handle The device handle to fetch interface list from. + * @param plist Location for the resulting list head; could be NULL. * * @return Libusb error code. */ -extern enum libusb_error uhd_iface_list_clear_halt(uhd_iface *list); +enum libusb_error +uhd_iface_list_new_from_dev(libusb_device_handle *handle, + uhd_iface **plist); + /** - * Release all interfaces in a list (if were claimed before). + * Filter an interface list by an optional interface number, resulting + * either in an empty, a single-interface, or an unmodified list. * - * @param list The list of interfaces to release. + * @param plist The original list head. + * @param number The interface number to match against, or a negative + * integer meaning there is no restriction. * - * @return Libusb error code. + * @return The resulting list head */ -extern enum libusb_error uhd_iface_list_release(uhd_iface *list); +extern uhd_iface *uhd_iface_list_fltr_by_num(uhd_iface *list, + int number); #ifdef __cplusplus } /* extern "C" */ diff --git a/lib/iface.c b/lib/iface.c index 3c8cb80..85dfcd8 100644 --- a/lib/iface.c +++ b/lib/iface.c @@ -74,6 +74,155 @@ uhd_iface_free(uhd_iface *iface) } +enum libusb_error +uhd_iface_detach(uhd_iface *iface) +{ + enum libusb_error err; + + assert(uhd_iface_valid(iface)); + + err = libusb_detach_kernel_driver(iface->handle, iface->number); + if (err == LIBUSB_SUCCESS) + iface->detached = true; + else if (err != LIBUSB_ERROR_NOT_FOUND) + return err; + + return LIBUSB_SUCCESS; +} + + +enum libusb_error +uhd_iface_attach(uhd_iface *iface) +{ + enum libusb_error err; + + assert(uhd_iface_valid(iface)); + + if (iface->detached) + { + err = libusb_attach_kernel_driver(iface->handle, iface->number); + if (err != LIBUSB_SUCCESS) + return err; + iface->detached = false; + } + + return LIBUSB_SUCCESS; +} + + +enum libusb_error +uhd_iface_claim(uhd_iface *iface) +{ + enum libusb_error err; + + assert(uhd_iface_valid(iface)); + + err = libusb_claim_interface(iface->handle, iface->number); + if (err != LIBUSB_SUCCESS) + return err; + + iface->claimed = true; + + return LIBUSB_SUCCESS; +} + + +enum libusb_error +uhd_iface_release(uhd_iface *iface) +{ + enum libusb_error err; + + assert(uhd_iface_valid(iface)); + + err = libusb_release_interface(iface->handle, iface->number); + if (err != LIBUSB_SUCCESS) + return err; + + iface->claimed = false; + + return LIBUSB_SUCCESS; +} + + +enum libusb_error +uhd_iface_clear_halt(uhd_iface *iface) +{ + enum libusb_error err; + + assert(uhd_iface_valid(iface)); + + err = libusb_clear_halt(iface->handle, iface->int_in_ep_addr); + if (err != LIBUSB_SUCCESS) + return err; + + return LIBUSB_SUCCESS; +} + + +enum libusb_error +uhd_iface_set_idle(const uhd_iface *iface, + uint8_t duration, + unsigned int timeout) +{ + int rc; + + assert(uhd_iface_valid(iface)); + + rc = libusb_control_transfer(iface->handle, + /* host->device, class, interface */ + 0x21, + /* Set_Idle */ + 0x0A, + /* duration for all report IDs */ + duration << 8, + /* interface */ + iface->number, + NULL, 0, + timeout); + /* + * Ignoring EPIPE, which means a STALL handshake, which is OK on + * control pipes and indicates request is not supported. + * See USB 2.0 spec, 8.4.5 Handshake Packets + */ + if (rc < 0 && rc != LIBUSB_ERROR_PIPE) + return rc; + + return LIBUSB_SUCCESS; +} + + +enum libusb_error +uhd_iface_set_protocol(const uhd_iface *iface, + bool report, + unsigned int timeout) +{ + int rc; + + assert(uhd_iface_valid(iface)); + + rc = libusb_control_transfer(iface->handle, + /* host->device, class, interface */ + 0x21, + /* Set_Protocol */ + 0x0B, + /* 0 - boot, 1 - report */ + report ? 1 : 0, + /* interface */ + iface->number, + NULL, 0, + timeout); + /* + * Ignoring EPIPE, which means a STALL handshake, which is OK on + * control pipes and indicates request is not supported. + * See USB 2.0 spec, 8.4.5 Handshake Packets + */ + if (rc < 0 && rc != LIBUSB_ERROR_PIPE) + return rc; + + return LIBUSB_SUCCESS; +} + + bool uhd_iface_list_valid(const uhd_iface *list) { @@ -224,171 +373,3 @@ uhd_iface_list_fltr_by_num(uhd_iface *list, } -enum libusb_error -uhd_iface_list_detach(uhd_iface *list) -{ - enum libusb_error err; - - assert(uhd_iface_list_valid(list)); - - for (; list != NULL; list = list->next) - { - err = libusb_detach_kernel_driver(list->handle, list->number); - if (err == LIBUSB_SUCCESS) - list->detached = true; - else if (err != LIBUSB_ERROR_NOT_FOUND) - return err; - } - - return LIBUSB_SUCCESS; -} - - -enum libusb_error -uhd_iface_list_attach(uhd_iface *list) -{ - enum libusb_error err; - - assert(uhd_iface_list_valid(list)); - - for (; list != NULL; list = list->next) - if (list->detached) - { - err = libusb_attach_kernel_driver(list->handle, list->number); - if (err != LIBUSB_SUCCESS) - return err; - list->detached = false; - } - - return LIBUSB_SUCCESS; -} - - -enum libusb_error -uhd_iface_list_claim(uhd_iface *list) -{ - enum libusb_error err; - - assert(uhd_iface_list_valid(list)); - - for (; list != NULL; list = list->next) - { - err = libusb_claim_interface(list->handle, list->number); - if (err != LIBUSB_SUCCESS) - return err; - - list->claimed = true; - } - - return LIBUSB_SUCCESS; -} - - -enum libusb_error -uhd_iface_list_clear_halt(uhd_iface *list) -{ - enum libusb_error err; - - assert(uhd_iface_list_valid(list)); - - for (; list != NULL; list = list->next) - { - err = libusb_clear_halt(list->handle, list->int_in_ep_addr); - if (err != LIBUSB_SUCCESS) - return err; - } - - return LIBUSB_SUCCESS; -} - - -enum libusb_error -uhd_iface_list_set_idle(const uhd_iface *list, - uint8_t duration, - unsigned int timeout) -{ - int rc; - - assert(uhd_iface_list_valid(list)); - - for (; list != NULL; list = list->next) - { - rc = libusb_control_transfer(list->handle, - /* host->device, class, interface */ - 0x21, - /* Set_Idle */ - 0x0A, - /* duration for all report IDs */ - duration << 8, - /* interface */ - list->number, - NULL, 0, - timeout); - /* - * Ignoring EPIPE, which means a STALL handshake, which is OK on - * control pipes and indicates request is not supported. - * See USB 2.0 spec, 8.4.5 Handshake Packets - */ - if (rc < 0 && rc != LIBUSB_ERROR_PIPE) - return rc; - } - - return LIBUSB_SUCCESS; -} - - -enum libusb_error -uhd_iface_list_set_protocol(const uhd_iface *list, - bool report, - unsigned int timeout) -{ - int rc; - - assert(uhd_iface_list_valid(list)); - - for (; list != NULL; list = list->next) - { - rc = libusb_control_transfer(list->handle, - /* host->device, class, interface */ - 0x21, - /* Set_Protocol */ - 0x0B, - /* 0 - boot, 1 - report */ - report ? 1 : 0, - /* interface */ - list->number, - NULL, 0, - timeout); - /* - * Ignoring EPIPE, which means a STALL handshake, which is OK on - * control pipes and indicates request is not supported. - * See USB 2.0 spec, 8.4.5 Handshake Packets - */ - if (rc < 0 && rc != LIBUSB_ERROR_PIPE) - return rc; - } - - return LIBUSB_SUCCESS; -} - - -enum libusb_error -uhd_iface_list_release(uhd_iface *list) -{ - enum libusb_error err; - - assert(uhd_iface_list_valid(list)); - - for (; list != NULL; list = list->next) - if (list->claimed) - { - err = libusb_release_interface(list->handle, list->number); - if (err != LIBUSB_SUCCESS) - return err; - list->claimed = false; - } - - return LIBUSB_SUCCESS; -} - - diff --git a/src/usbhid-dump.c b/src/usbhid-dump.c index 1f16bb2..999d406 100644 --- a/src/usbhid-dump.c +++ b/src/usbhid-dump.c @@ -69,15 +69,29 @@ goto cleanup; \ } while (0) -#define LIBUSB_ERROR_CLEANUP(_fmt, _args...) \ - ERROR_CLEANUP(_fmt ": %s", ##_args, libusb_strerror(err)) - #define FAILURE_CLEANUP(_fmt, _args...) \ ERROR_CLEANUP("Failed to " _fmt, ##_args) +#define LIBUSB_ERROR_CLEANUP(_fmt, _args...) \ + ERROR_CLEANUP(_fmt ": %s", ##_args, libusb_strerror(err)) + #define LIBUSB_FAILURE_CLEANUP(_fmt, _args...) \ LIBUSB_ERROR_CLEANUP("Failed to " _fmt, ##_args) +#define LIBUSB_WATCH(_expr, _fmt, _args...) \ + do { \ + err = _expr; \ + if (err != LIBUSB_SUCCESS) \ + LIBUSB_FAILURE(_fmt, ##_args); \ + } while (0) + +#define LIBUSB_GUARD(_expr, _fmt, _args...) \ + do { \ + err = _expr; \ + if (err != LIBUSB_SUCCESS) \ + LIBUSB_FAILURE_CLEANUP(_fmt, ##_args); \ + } while (0) + /**< Number of the signal causing the exit */ static volatile sig_atomic_t exit_signum = 0; @@ -285,15 +299,15 @@ dump_iface_list_stream(libusb_context *ctx, uhd_iface *list) uhd_iface *iface; bool submitted = false; - /* Set report protocol on all interfaces */ - err = uhd_iface_list_set_protocol(list, true, TIMEOUT); - if (err != LIBUSB_SUCCESS) - LIBUSB_ERROR_CLEANUP("set report protocol"); - - /* Set infinite idle duration on all interfaces */ - err = uhd_iface_list_set_idle(list, 0, TIMEOUT); - if (err != LIBUSB_SUCCESS) - LIBUSB_ERROR_CLEANUP("set infinite idle duration"); + UHD_IFACE_LIST_FOR_EACH(iface, list) + { + /* Set report protocol */ + LIBUSB_GUARD(uhd_iface_set_protocol(list, true, TIMEOUT), + "set report protocol on an interface"); + /* Set infinite idle duration */ + LIBUSB_GUARD(uhd_iface_set_idle(list, 0, TIMEOUT), + "set infinite idle duration on an interface"); + } /* Calculate number of interfaces and thus transfers */ transfer_num = uhd_iface_list_len(list); @@ -485,6 +499,7 @@ run(bool dump_descriptor, libusb_context *ctx = NULL; libusb_device_handle *handle = NULL; uhd_iface *iface_list = NULL; + uhd_iface *iface; /* Initialize libusb context */ err = libusb_init(&ctx); @@ -509,16 +524,14 @@ run(bool dump_descriptor, if (uhd_iface_list_empty(iface_list)) ERROR_CLEANUP("No matching HID interfaces"); - /* Detach interfaces */ - err = uhd_iface_list_detach(iface_list); - if (err != LIBUSB_SUCCESS) - LIBUSB_FAILURE_CLEANUP("detach the interface(s) from " - "the kernel drivers"); - - /* Claim interfaces */ - err = uhd_iface_list_claim(iface_list); - if (err != LIBUSB_SUCCESS) - LIBUSB_FAILURE_CLEANUP("claim the interface(s)"); + /* Detach and claim the interfaces */ + UHD_IFACE_LIST_FOR_EACH(iface, iface_list) + { + LIBUSB_GUARD(uhd_iface_detach(iface), + "detach an interface from the kernel driver"); + LIBUSB_GUARD(uhd_iface_claim(iface), + "claim an interface"); + } /* Run with the prepared interface list */ result = (!dump_descriptor || dump_iface_list_descriptor(iface_list)) && @@ -528,15 +541,14 @@ run(bool dump_descriptor, cleanup: - /* Release the interfaces back */ - err = uhd_iface_list_release(iface_list); - if (err != LIBUSB_SUCCESS) - LIBUSB_FAILURE("release the interface(s)"); - - /* Attach interfaces back */ - err = uhd_iface_list_attach(iface_list); - if (err != LIBUSB_SUCCESS) - LIBUSB_FAILURE("attach the interface(s) to the kernel drivers"); + /* Release and attach the interfaces back */ + UHD_IFACE_LIST_FOR_EACH(iface, iface_list) + { + LIBUSB_GUARD(uhd_iface_release(iface), + "release an interface"); + LIBUSB_GUARD(uhd_iface_attach(iface), + "attach an interface to the kernel driver"); + } /* Free the interface list */ uhd_iface_list_free(iface_list); -- cgit v1.2.1