diff options
Diffstat (limited to 'host/lib/transport/libusb1_base.cpp')
-rw-r--r-- | host/lib/transport/libusb1_base.cpp | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index d4ec874f1..8bd0f4354 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2013 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 @@ -19,10 +19,13 @@ #include <uhd/exception.hpp> #include <uhd/utils/msg.hpp> #include <uhd/utils/log.hpp> +#include <uhd/utils/tasks.hpp> #include <uhd/types/dict.hpp> #include <boost/weak_ptr.hpp> #include <boost/thread/mutex.hpp> #include <boost/foreach.hpp> +#include <boost/bind.hpp> +#include <cstdlib> #include <iostream> using namespace uhd; @@ -36,9 +39,11 @@ public: libusb_session_impl(void){ UHD_ASSERT_THROW(libusb_init(&_context) == 0); libusb_set_debug(_context, debug_level); + task_handler = task::make(boost::bind(&libusb_session_impl::libusb_event_handler_task, this, _context)); } ~libusb_session_impl(void){ + task_handler.reset(); libusb_exit(_context); } @@ -48,6 +53,21 @@ public: private: libusb_context *_context; + task::sptr task_handler; + + /* + * Task to handle libusb events. There should only be one thread per libusb_context handling events. + * Using more than one thread can result in excessive CPU usage in kernel space (presumably from locking/waiting). + * The libusb documentation says it is safe, which it is, but it neglects to state the cost in CPU usage. + * Just don't do it! + */ + UHD_INLINE void libusb_event_handler_task(libusb_context *context) + { + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100000; + libusb_handle_events_timeout(context, &tv); + } }; libusb::session::sptr libusb::session::get_global_session(void){ @@ -59,6 +79,15 @@ libusb::session::sptr libusb::session::get_global_session(void){ //create a new global session sptr new_global_session(new libusb_session_impl()); global_session = new_global_session; + + //set logging if envvar is set + const char *level_string = getenv("LIBUSB_DEBUG_LEVEL"); + if (level_string != NULL) + { + const int level = int(level_string[0] - '0'); //easy conversion to integer + if (level >= 0 and level <= 3) libusb_set_debug(new_global_session->get_context(), level); + } + return new_global_session; } @@ -137,8 +166,13 @@ public: return _desc; } - std::string get_ascii_serial(void) const{ - if (this->get().iSerialNumber == 0) return ""; + std::string get_ascii_property(const std::string &what) const + { + boost::uint8_t off = 0; + if (what == "serial") off = this->get().iSerialNumber; + if (what == "product") off = this->get().iProduct; + if (what == "manufacturer") off = this->get().iManufacturer; + if (off == 0) return ""; libusb::device_handle::sptr handle( libusb::device_handle::get_cached_handle(_dev) @@ -146,7 +180,7 @@ public: unsigned char buff[512]; ssize_t ret = libusb_get_string_descriptor_ascii( - handle->get(), this->get().iSerialNumber, buff, sizeof(buff) + handle->get(), off, buff, sizeof(buff) ); if (ret < 0) return ""; //on error, just return empty string @@ -240,7 +274,15 @@ public: } std::string get_serial(void) const{ - return libusb::device_descriptor::make(this->get_device())->get_ascii_serial(); + return libusb::device_descriptor::make(this->get_device())->get_ascii_property("serial"); + } + + std::string get_manufacturer() const{ + return libusb::device_descriptor::make(this->get_device())->get_ascii_property("manufacturer"); + } + + std::string get_product() const{ + return libusb::device_descriptor::make(this->get_device())->get_ascii_property("product"); } boost::uint16_t get_vendor_id(void) const{ @@ -251,6 +293,10 @@ public: return libusb::device_descriptor::make(this->get_device())->get().idProduct; } + bool firmware_loaded() { + return (get_manufacturer() == "Ettus Research LLC"); + } + private: libusb::device::sptr _dev; //always keep a reference to device }; |