diff options
| -rw-r--r-- | host/include/uhd/transport/usb_device_handle.hpp | 6 | ||||
| -rw-r--r-- | host/lib/transport/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_base.cpp | 289 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_base.hpp | 162 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_control.cpp | 74 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_device_handle.cpp | 118 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_zero_copy.cpp | 83 | 
7 files changed, 367 insertions, 366 deletions
diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index 735a3acbe..9bb7db9c4 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -61,12 +61,6 @@ public:      virtual boost::uint16_t get_product_id() const = 0;      /*! -     * Return the device's USB address -     * \return a Product ID -     */ -    virtual boost::uint16_t get_device_addr() const = 0; - -    /*!       * Return a vector of USB devices on this host        * \return a vector of USB device handles that match vid and pid       */ diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 48b6e9677..61616d077 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -31,7 +31,6 @@ IF(LIBUSB_FOUND)          ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_zero_copy.cpp          ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.cpp          ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.hpp -        ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp      )      IF(MSVC) #include our custom stdint for libusb          INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/transport/msvc) diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index cd3e4adcf..5ff996642 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -17,107 +17,242 @@  #include "libusb1_base.hpp"  #include <uhd/utils/assert.hpp> +#include <uhd/types/dict.hpp> +#include <boost/weak_ptr.hpp> +#include <boost/foreach.hpp>  #include <iostream>  using namespace uhd::transport; -/********************************************************** - * Helper Methods - **********************************************************/ - -/********************************************************** - * libusb namespace  - **********************************************************/ -void libusb::init(libusb_context **ctx, int debug_level) -{ -    UHD_ASSERT_THROW(libusb_init(ctx) == 0); -    libusb_set_debug(*ctx, debug_level); +/*********************************************************************** + * libusb session + **********************************************************************/ +class libusb_session_impl : public libusb::session{ +public: +    libusb_session_impl(void){ +        UHD_ASSERT_THROW(libusb_init(&_context) == 0); +        libusb_set_debug(_context, debug_level); +    } + +    ~libusb_session_impl(void){ +        libusb_exit(_context); +    } + +    libusb_context *get_context(void) const{ +        return _context; +    } + +private: +    libusb_context *_context; +}; + +libusb::session::sptr libusb::session::get_global_session(void){ +    static boost::weak_ptr<session> global_session; + +    //not expired -> get existing session +    if (not global_session.expired()) return global_session.lock(); + +    //create a new global session +    sptr new_global_session(new libusb_session_impl()); +    global_session = new_global_session; +    return new_global_session;  } -libusb_device_handle *libusb::open_device(libusb_context *ctx, -                                          usb_device_handle::sptr handle) -{ -    libusb_device_handle *dev_handle = NULL; -    libusb_device **libusb_dev_list; -    size_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list); +/*********************************************************************** + * libusb device + **********************************************************************/ +class libusb_device_impl : public libusb::device{ +public: +    libusb_device_impl(libusb_device *dev){ +        _session = libusb::session::get_global_session(); +        _dev = dev; +    } -    //find and open the USB device  -    for (size_t i = 0; i < dev_cnt; i++) { -        libusb_device *dev = libusb_dev_list[i]; +    ~libusb_device_impl(void){ +        libusb_unref_device(this->get()); +    } -        if (compare_device(dev, handle)) { -            if (libusb_open(dev, &dev_handle) == 0) break; -        } +    libusb_device *get(void) const{ +        return _dev;      } -    libusb_free_device_list(libusb_dev_list, true); -    if(dev_handle == NULL) -        throw std::runtime_error("USB: cannot open device handle"); -    return dev_handle; -} +private: +    libusb::session::sptr _session; //always keep a reference to session +    libusb_device *_dev; +}; + +/*********************************************************************** + * libusb device list + **********************************************************************/ +class libusb_device_list_impl : public libusb::device_list{ +public: +    libusb_device_list_impl(void){ +        libusb::session::sptr sess = libusb::session::get_global_session(); -//note: changed order of checks so it only tries to get_serial and get_device_address if vid and pid match -//doing this so it doesn't try to open the device if it's not ours -bool libusb::compare_device(libusb_device *dev, -                            usb_device_handle::sptr handle) -{ -    std::string serial         = handle->get_serial(); -    boost::uint16_t vendor_id  = handle->get_vendor_id(); -    boost::uint16_t product_id = handle->get_product_id(); -    boost::uint16_t device_addr = handle->get_device_addr(); - -    libusb_device_descriptor libusb_desc; -    if (libusb_get_device_descriptor(dev, &libusb_desc) != 0) -        return false; -    if (vendor_id != libusb_desc.idVendor) -        return false; -    if (product_id != libusb_desc.idProduct) -        return false; -    if (serial != get_serial(dev)) -        return false; -    if (device_addr != libusb_get_device_address(dev)) -        return false; - -    return true; +        //allocate a new list of devices +        libusb_device** dev_list; +        ssize_t ret = libusb_get_device_list(sess->get_context(), &dev_list); +        if (ret < 0) throw std::runtime_error("cannot enumerate usb devices"); + +        //fill the vector of device references +        for (size_t i = 0; i < size_t(ret); i++) _devs.push_back( +            libusb::device::sptr(new libusb_device_impl(dev_list[i])) +        ); + +        //free the device list but dont unref (done in ~device) +        libusb_free_device_list(dev_list, false/*dont unref*/); +    } + +    size_t size(void) const{ +        return _devs.size(); +    } + +    libusb::device::sptr at(size_t i) const{ +        return _devs.at(i); +    } + +private: +    std::vector<libusb::device::sptr> _devs; +}; + +libusb::device_list::sptr libusb::device_list::make(void){ +    return sptr(new libusb_device_list_impl());  } +/*********************************************************************** + * libusb device descriptor + **********************************************************************/ +class libusb_device_descriptor_impl : public libusb::device_descriptor{ +public: +    libusb_device_descriptor_impl(libusb::device::sptr dev){ +        _dev = dev; +        UHD_ASSERT_THROW(libusb_get_device_descriptor(_dev->get(), &_desc) == 0); +    } -bool libusb::open_interface(libusb_device_handle *dev_handle, -                            int interface) -{ -    int ret = libusb_claim_interface(dev_handle, interface); -    if (ret < 0) { -        std::cerr << "error: libusb_claim_interface() " << ret << std::endl; -        return false; +    const libusb_device_descriptor &get(void) const{ +        return _desc;      } -    else { -        return true; + +    std::string get_ascii_serial(void) const{ +        if (this->get().iSerialNumber == 0) return ""; + +        libusb::device_handle::sptr handle( +            libusb::device_handle::get_cached_handle(_dev) +        ); + +        unsigned char buff[512]; +        ssize_t ret = libusb_get_string_descriptor_ascii( +            handle->get(), this->get().iSerialNumber, buff, sizeof(buff) +        ); +        if (ret < 0) return ""; //on error, just return empty string + +        return std::string((char *)buff, ret);      } + +private: +    libusb::device::sptr _dev; //always keep a reference to device +    libusb_device_descriptor _desc; +}; + +libusb::device_descriptor::sptr libusb::device_descriptor::make(device::sptr dev){ +    return sptr(new libusb_device_descriptor_impl(dev));  } +/*********************************************************************** + * libusb device handle + **********************************************************************/ +class libusb_device_handle_impl : public libusb::device_handle{ +public: +    libusb_device_handle_impl(libusb::device::sptr dev){ +        _dev = dev; +        UHD_ASSERT_THROW(libusb_open(_dev->get(), &_handle) == 0); +    } + +    ~libusb_device_handle_impl(void){ +        //release all claimed interfaces +        for (size_t i = 0; i < _claimed.size(); i++){ +            libusb_release_interface(this->get(), _claimed[i]); +        } +        libusb_close(_handle); +    } + +    libusb_device_handle *get(void) const{ +        return _handle; +    } -std::string libusb::get_serial(libusb_device *dev) -{ -    unsigned char buff[32]; +    void claim_interface(int interface){ +        UHD_ASSERT_THROW(libusb_claim_interface(this->get(), interface) == 0); +        _claimed.push_back(interface); +    } -    libusb_device_descriptor desc; -    if (libusb_get_device_descriptor(dev, &desc) < 0) -        return ""; +private: +    libusb::device::sptr _dev; //always keep a reference to device +    libusb_device_handle *_handle; +    std::vector<int> _claimed; +}; -    if (desc.iSerialNumber == 0) -        return ""; +libusb::device_handle::sptr libusb::device_handle::get_cached_handle(device::sptr dev){ +    static uhd::dict<libusb_device *, boost::weak_ptr<device_handle> > handles; -    //open the device because we have to -    libusb_device_handle *dev_handle; -    if (libusb_open(dev, &dev_handle) < 0) -        return ""; +    //not expired -> get existing session +    if (handles.has_key(dev->get()) and not handles[dev->get()].expired()){ +        return handles[dev->get()].lock(); +    } -    if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, -                                           buff, sizeof(buff)) < 0) { -        return ""; +    //create a new global session +    sptr new_handle(new libusb_device_handle_impl(dev)); +    handles[dev->get()] = new_handle; +    return new_handle; +} + +/*********************************************************************** + * libusb special handle + **********************************************************************/ +class libusb_special_handle_impl : public libusb::special_handle{ +public: +    libusb_special_handle_impl(libusb::device::sptr dev){ +        _dev = dev;      } -    libusb_close(dev_handle); +    libusb::device::sptr get_device(void) const{ +        return _dev; +    } + +    std::string get_serial(void) const{ +        return libusb::device_descriptor::make(this->get_device())->get_ascii_serial(); +    } + +    boost::uint16_t get_vendor_id(void) const{ +        return libusb::device_descriptor::make(this->get_device())->get().idVendor; +    } + +    boost::uint16_t get_product_id(void) const{ +        return libusb::device_descriptor::make(this->get_device())->get().idProduct; +    } + +private: +    libusb::device::sptr _dev; //always keep a reference to device +}; + +libusb::special_handle::sptr libusb::special_handle::make(device::sptr dev){ +    return sptr(new libusb_special_handle_impl(dev)); +} + +/*********************************************************************** + * list device handles implementations + **********************************************************************/ +std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list( +    boost::uint16_t vid, boost::uint16_t pid +){ +    std::vector<usb_device_handle::sptr> handles; + +    libusb::device_list::sptr dev_list = libusb::device_list::make(); +    for (size_t i = 0; i < dev_list->size(); i++){ +        usb_device_handle::sptr handle = libusb::special_handle::make(dev_list->at(i)); +        if (handle->get_vendor_id() == vid and handle->get_product_id() == pid){ +            handles.push_back(handle); +        } +    } -    return (char*) buff; +    return handles;  } diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 484bcf3d9..47d078cde 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -19,74 +19,122 @@  #define INCLUDED_LIBUHD_TRANSPORT_LIBUSB_HPP  #include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp>  #include <uhd/transport/usb_device_handle.hpp>  #include <libusb-1.0/libusb.h>  namespace uhd { namespace transport {  namespace libusb { -    /* -     * Initialize libusb and set debug level -     * Takes a pointer to context pointer because that's -     * how libusb rolls. Debug levels. -     *      -     *   Level 0: no messages ever printed by the library (default) -     *   Level 1: error messages are printed to stderr -     *   Level 2: warning and error messages are printed to stderr -     *   Level 3: informational messages are printed to stdout, warning -     *            and error messages are printed to stderr -     * -     * \param ctx pointer to context pointer -     * \param debug_level + +    /*! +     * This session class holds a global libusb context for this process. +     * The get global session call will create a new context if none exists. +     * When all references to session are destroyed, the context will be freed.       */ -    void init(libusb_context **ctx, int debug_level); - -    /* -     * Open the device specified by a generic handle -     * Find the libusb_device cooresponding to the generic handle -     * and open it for I/O, which returns a libusb_device_handle -     * ready for an interface -     * \param ctx the libusb context used for init -     * \return a libusb_device_handle ready for action  +    class session : boost::noncopyable { +    public: +        typedef boost::shared_ptr<session> sptr; + +        /*! +         *   Level 0: no messages ever printed by the library (default) +         *   Level 1: error messages are printed to stderr +         *   Level 2: warning and error messages are printed to stderr +         *   Level 3: informational messages are printed to stdout, warning +         *            and error messages are printed to stderr +         */ +        static const int debug_level = 0; + +        //! get a shared pointer to the global session +        static sptr get_global_session(void); + +        //! get the underlying libusb context pointer +        virtual libusb_context *get_context(void) const = 0; +    }; + +    /*! +     * Holds a device pointer with a reference to the session.       */ -    libusb_device_handle *open_device(libusb_context *ctx, -                                      usb_device_handle::sptr handle); - -    /* -     * Compare a libusb device with a generic handle  -     * Check the descriptors and open the device to check the -     * serial number string. Compare values against the given -     * handle. The libusb context is already implied in the -     * libusb_device. -     * \param dev a libusb_device pointer -     * \param handle a generic handle specifier -     * \return true if handle and device match, false otherwise +    class device : boost::noncopyable { +    public: +        typedef boost::shared_ptr<device> sptr; + +        //! get the underlying device pointer +        virtual libusb_device *get(void) const = 0; +    }; + +    /*! +     * This device list class holds a device list that will be +     * automatically freed when the last reference is destroyed.       */ -    bool compare_device(libusb_device *dev, usb_device_handle::sptr handle); - -    /* -     * Open an interface to the device -     * This is a logical operation for operating system housekeeping as -     * nothing is sent over the bus. The interface much correspond -     * to the USB device descriptors. -     * \param dev_handle libusb handle to an opened device -     * \param interface integer of the interface to use -     * \return true on success, false on error +    class device_list : boost::noncopyable { +    public: +        typedef boost::shared_ptr<device_list> sptr; + +        //! make a new device list +        static sptr make(void); + +        //! the number of devices in this list +        virtual size_t size() const = 0; + +        //! get the device pointer at a particular index +        virtual device::sptr at(size_t index) const = 0; +    }; + +    /*! +     * Holds a device descriptor and a reference to the device.       */ -    bool open_interface(libusb_device_handle *dev_handle, int interface); - -    /* -     * Get serial number  -     * The standard USB device descriptor contains an index to an -     * actual serial number string descriptor. The index is readily -     * readble, but the string descriptor requires probing the device. -     * Because this call attempts to open the device, it may not -     * succeed because not all USB devices are readily opened. -     * The default language is used for the request (English). -     * \param dev a libusb_device pointer -     * \return string serial number or 0 on error or unavailablity +    class device_descriptor : boost::noncopyable { +    public: +        typedef boost::shared_ptr<device_descriptor> sptr; + +        //! make a new descriptor from a device reference +        static sptr make(device::sptr); + +        //! get the underlying device descriptor +        virtual const libusb_device_descriptor &get(void) const = 0; + +        virtual std::string get_ascii_serial(void) const = 0; +    }; + +    /*! +     * Holds a device handle and a reference to the device.       */ -    std::string get_serial(libusb_device *dev); +    class device_handle : boost::noncopyable { +    public: +        typedef boost::shared_ptr<device_handle> sptr; + +        //! get a cached handle or make a new one given the device +        static sptr get_cached_handle(device::sptr); + +        //! get the underlying device handle +        virtual libusb_device_handle *get(void) const = 0; + +        /*! +         * Open USB interfaces for control using magic value +         * IN interface:      2 +         * OUT interface:     1 +         * Control interface: 0 +         */ +        virtual void claim_interface(int) = 0; +    }; + +    /*! +     * The special handle is our internal implementation of the +     * usb device handle which is used publicly to identify a device. +     */ +    class special_handle : public usb_device_handle { +    public: +        typedef boost::shared_ptr<special_handle> sptr; + +        //! make a new special handle from device +        static sptr make(device::sptr); + +        //! get the underlying device reference +        virtual device::sptr get_device(void) const = 0; +    }; +  }  }} //namespace diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp index be9b51111..c989a788c 100644 --- a/host/lib/transport/libusb1_control.cpp +++ b/host/lib/transport/libusb1_control.cpp @@ -20,7 +20,6 @@  using namespace uhd::transport; -const int libusb_debug_level = 0;  const int libusb_timeout = 0;  /*********************************************************************** @@ -28,69 +27,38 @@ const int libusb_timeout = 0;   **********************************************************************/  class libusb_control_impl : public usb_control {  public: -    libusb_control_impl(usb_device_handle::sptr handle); -    ~libusb_control_impl(); +    libusb_control_impl(libusb::device_handle::sptr handle): +        _handle(handle) +    { +        _handle->claim_interface(0 /* control interface */); +    }      size_t submit(boost::uint8_t request_type,                    boost::uint8_t request,                    boost::uint16_t value,                    boost::uint16_t index,                    unsigned char *buff, -                  boost::uint16_t length);  +                  boost::uint16_t length +    ){ +        return libusb_control_transfer(_handle->get(), +                                       request_type, +                                       request, +                                       value, +                                       index, +                                       buff, +                                       length, +                                       libusb_timeout); +    }  private: -    libusb_context       *_ctx; -    libusb_device_handle *_dev_handle; +    libusb::device_handle::sptr _handle;  }; - -libusb_control_impl::libusb_control_impl(usb_device_handle::sptr handle) -{ -    _ctx = NULL; -    libusb::init(&_ctx, libusb_debug_level); - -    // Find and open the libusb_device corresponding to the -    // given handle and return the libusb_device_handle -    // that can be used for I/O purposes. -    _dev_handle = libusb::open_device(_ctx, handle); - -    // Open USB interfaces for control using magic value -    // IN interface:      2 -    // OUT interface:     1 -    // Control interface: 0 -    libusb::open_interface(_dev_handle, 0); -} - - -libusb_control_impl::~libusb_control_impl() -{ -    libusb_close(_dev_handle); -    libusb_exit(_ctx); -} - - -size_t libusb_control_impl::submit(boost::uint8_t request_type, -                                   boost::uint8_t request, -                                   boost::uint16_t value, -                                   boost::uint16_t index,  -                                   unsigned char *buff, -                                   boost::uint16_t length)  -{ -    return libusb_control_transfer(_dev_handle, -                                   request_type, -                                   request, -                                   value, -                                   index, -                                   buff,  -                                   length,  -                                   libusb_timeout); -} - -  /***********************************************************************   * USB control public make functions   **********************************************************************/ -usb_control::sptr usb_control::make(usb_device_handle::sptr handle) -{ -    return sptr(new libusb_control_impl(handle)); +usb_control::sptr usb_control::make(usb_device_handle::sptr handle){ +    return sptr(new libusb_control_impl(libusb::device_handle::get_cached_handle( +        boost::static_pointer_cast<libusb::special_handle>(handle)->get_device() +    )));  } diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp deleted file mode 100644 index 6bef37ed2..000000000 --- a/host/lib/transport/libusb1_device_handle.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#include "libusb1_base.hpp" -#include <uhd/utils/assert.hpp> -#include <iostream> - -using namespace uhd::transport; - -const int libusb_debug_level = 0; - -/**************************************************************** - * libusb USB device handle implementation class - ***************************************************************/ -class libusb1_device_handle_impl : public usb_device_handle { -public: -    libusb1_device_handle_impl(std::string serial, -                               boost::uint16_t product_id, -                               boost::uint16_t vendor_id, -                               boost::uint16_t device_addr) -      : _serial(serial), _product_id(product_id),  -        _vendor_id(vendor_id), _device_addr(device_addr) -    { -        /* NOP */ -    } - -    ~libusb1_device_handle_impl() -    { -        /* NOP */ -    } - -    std::string get_serial() const -    { -        return _serial; -    } - -    boost::uint16_t get_vendor_id() const -    { -        return _vendor_id; -    } - - -    boost::uint16_t get_product_id() const -    { -        return _product_id; -    } - -    boost::uint16_t get_device_addr() const -    { -        return _device_addr; -    } - -private: -    std::string     _serial; -    boost::uint16_t _product_id; -    boost::uint16_t _vendor_id; -    boost::uint16_t _device_addr; -}; - - -usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) -{ -    libusb_device_descriptor desc; - -    if (libusb_get_device_descriptor(dev, &desc) < 0) { -        throw std::runtime_error("USB: failed to get device descriptor"); -    } - -    std::string     serial      = libusb::get_serial(dev); -    boost::uint16_t product_id  = desc.idProduct; -    boost::uint16_t vendor_id   = desc.idVendor; -    boost::uint16_t device_addr = libusb_get_device_address(dev); - -    return usb_device_handle::sptr(new libusb1_device_handle_impl( -        serial, -        product_id, -        vendor_id, -        device_addr)); -} - -std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list(boost::uint16_t vid, boost::uint16_t pid) -{ -    libusb_context *ctx = NULL; -    libusb_device** libusb_device_list; -    std::vector<usb_device_handle::sptr> device_handle_list; -    libusb_device_descriptor desc; - -    libusb::init(&ctx, libusb_debug_level); - -    size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list); -    for (size_t i = 0; i < dev_size; i++) { -        libusb_device *dev = libusb_device_list[i]; -        if(libusb_get_device_descriptor(dev, &desc) != 0) { -            continue; //just try the next device, do not throw -        } -        if(desc.idVendor == vid && desc.idProduct == pid) { -            device_handle_list.push_back(make_usb_device_handle(dev)); -        } -    } - -    libusb_free_device_list(libusb_device_list, true); -    libusb_exit(ctx); -    return device_handle_list;  -} diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index b3a160462..41cd4b3fc 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -24,7 +24,6 @@  using namespace uhd::transport; -const int libusb_debug_level = 0;  const int libusb_timeout = 0;  /*********************************************************************** @@ -57,8 +56,8 @@ void pp_transfer(libusb_transfer *lut)   **********************************************************************/  class usb_endpoint {  private: -    libusb_device_handle *_dev_handle; -    libusb_context *_ctx; +    libusb::device_handle::sptr _handle; +    libusb::session::sptr _session;      int  _endpoint;      bool _input; @@ -90,9 +89,8 @@ private:      void print_transfer_status(libusb_transfer *lut);  public: -    usb_endpoint(libusb_device_handle *dev_handle, -                 libusb_context *ctx, int endpoint, bool input, -                 size_t transfer_size, size_t num_transfers); +    usb_endpoint(libusb::device_handle::sptr handle, libusb::session::sptr sess, +                 int endpoint, bool input, size_t transfer_size, size_t num_transfers);      ~usb_endpoint(); @@ -143,11 +141,11 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut)   * submit the transfers so that they're ready to return when   * data is available.    */ -usb_endpoint::usb_endpoint(libusb_device_handle *dev_handle, -                          libusb_context *ctx, int endpoint, bool input, -                          size_t transfer_size, size_t num_transfers) -    : _dev_handle(dev_handle), -      _ctx(ctx), _endpoint(endpoint), _input(input), +usb_endpoint::usb_endpoint( +    libusb::device_handle::sptr handle, libusb::session::sptr sess, +    int endpoint, bool input, size_t transfer_size, size_t num_transfers) +    : _handle(handle), _session(sess), +      _endpoint(endpoint), _input(input),        _transfer_size(transfer_size), _num_transfers(num_transfers)  {      unsigned int i; @@ -203,7 +201,7 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len)      unsigned int endpoint = ((_endpoint & 0x7f) | (_input ? 0x80 : 0));      libusb_fill_bulk_transfer(lut,                // transfer -                              _dev_handle,        // dev_handle +                              _handle->get(),     // dev_handle                                endpoint,           // endpoint                                buff,               // buffer                                buff_len,           // length @@ -356,7 +354,7 @@ bool usb_endpoint::reap_pending_list()  {      int retval; -    if ((retval = libusb_handle_events(_ctx)) < 0) { +    if ((retval = libusb_handle_events(_session->get_context())) < 0) {          std::cerr << "error: libusb_handle_events: " << retval << std::endl;          return false;      } @@ -383,7 +381,7 @@ bool usb_endpoint::reap_pending_list_timeout()      size_t pending_list_size = _pending_list.size(); -    if ((retval = libusb_handle_events_timeout(_ctx, &tv)) < 0) { +    if ((retval = libusb_handle_events_timeout(_session->get_context(), &tv)) < 0) {          std::cerr << "error: libusb_handle_events: " << retval << std::endl;          return false;      } @@ -613,11 +611,8 @@ private:      usb_endpoint          *_rx_ep;      usb_endpoint          *_tx_ep; -    // Maintain libusb values -    libusb_context       *_rx_ctx; -    libusb_context       *_tx_ctx; -    libusb_device_handle *_rx_dev_handle; -    libusb_device_handle *_tx_dev_handle; +    libusb::device_handle::sptr _handle; +    libusb::session::sptr _session;      size_t _recv_buff_size;      size_t _send_buff_size; @@ -626,7 +621,7 @@ private:  public:      typedef boost::shared_ptr<libusb_zero_copy_impl> sptr; -    libusb_zero_copy_impl(usb_device_handle::sptr handle, +    libusb_zero_copy_impl(libusb::device_handle::sptr handle,                            unsigned int rx_endpoint,                            unsigned int tx_endpoint,                            size_t recv_buff_size, @@ -646,44 +641,27 @@ public:   * Initializes libusb, opens devices, and sets up interfaces for I/O.   * Finally, creates endpoints for asynchronous I/O.    */ -libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle, +libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle,                                               unsigned int rx_endpoint,                                               unsigned int tx_endpoint,                                               size_t buff_size,                                               size_t block_size) - : _rx_ctx(NULL), _tx_ctx(NULL), _rx_dev_handle(NULL), _tx_dev_handle(NULL), + : _handle(handle), _session(libusb::session::get_global_session()),     _recv_buff_size(block_size), _send_buff_size(block_size),     _num_frames(buff_size / block_size)  { -    // Initialize libusb with separate contexts to allow -    // thread safe operation of transmit and receive  -    libusb::init(&_rx_ctx, libusb_debug_level); -    libusb::init(&_tx_ctx, libusb_debug_level); - -    UHD_ASSERT_THROW((_rx_ctx != NULL) && (_tx_ctx != NULL)); - -    // Find and open the libusb_device corresponding to the -    // given handle and return the libusb_device_handle -    // that can be used for I/O purposes. -    _rx_dev_handle = libusb::open_device(_rx_ctx, handle); -    _tx_dev_handle = libusb::open_device(_tx_ctx, handle); - -    // Open USB interfaces for tx/rx using magic values. -    // IN interface:      2 -    // OUT interface:     1 -    // Control interface: 0 -    libusb::open_interface(_rx_dev_handle, 2); -    libusb::open_interface(_tx_dev_handle, 1); - -    _rx_ep = new usb_endpoint(_rx_dev_handle,  // libusb device_handle -                              _rx_ctx,         // libusb context +    _handle->claim_interface(2 /*in interface*/); +    _handle->claim_interface(1 /*out interface*/); + +    _rx_ep = new usb_endpoint(_handle,         // libusb device_handle +                              _session,        // libusb session w/ context                                rx_endpoint,     // USB endpoint number                                true,            // IN endpoint                                _recv_buff_size, // buffer size per transfer                                 _num_frames);    // number of libusb transfers -    _tx_ep = new usb_endpoint(_tx_dev_handle,  // libusb device_handle -                              _tx_ctx,         // libusb context +    _tx_ep = new usb_endpoint(_handle,         // libusb device_handle +                              _session,        // libusb session w/ context                                tx_endpoint,     // USB endpoint number                                false,           // OUT endpoint                                _send_buff_size, // buffer size per transfer @@ -694,13 +672,7 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle,  libusb_zero_copy_impl::~libusb_zero_copy_impl()  {      delete _rx_ep; -    delete _tx_ep;  - -    libusb_close(_rx_dev_handle); -    libusb_close(_tx_dev_handle); - -    libusb_exit(_rx_ctx); -    libusb_exit(_tx_ctx); +    delete _tx_ep;  } @@ -755,7 +727,10 @@ usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle,                                          size_t block_size)  { -    return sptr(new libusb_zero_copy_impl(handle, +    libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( +        boost::static_pointer_cast<libusb::special_handle>(handle)->get_device() +    )); +    return sptr(new libusb_zero_copy_impl(dev_handle,                                            rx_endpoint,                                            tx_endpoint,                                            buff_size,   | 
