Revision: 139138 https://trac.macports.org/changeset/139138 Author: michaelld@macports.org Date: 2015-08-03 13:04:05 -0700 (Mon, 03 Aug 2015) Log Message: ----------- uhd-devel: better temporary patch, with more fixes. Modified Paths: -------------- trunk/dports/science/uhd/Portfile Added Paths: ----------- trunk/dports/science/uhd/files/patch-b200_squash.diff Removed Paths: ------------- trunk/dports/science/uhd/files/patch-b200-fix_initial_loading.diff trunk/dports/science/uhd/files/patch-b200-fixes-LIBUSB_ERROR_PIPE-on-OS-X.diff Modified: trunk/dports/science/uhd/Portfile =================================================================== --- trunk/dports/science/uhd/Portfile 2015-08-03 19:18:49 UTC (rev 139137) +++ trunk/dports/science/uhd/Portfile 2015-08-03 20:04:05 UTC (rev 139138) @@ -49,14 +49,13 @@ conflicts uhd github.setup EttusResearch uhd 0c7d748bbf6c282d3f1c759201e40f35f26133ca version 20150730 + revision 1 checksums rmd160 250ed5a0480f232d9ea07db82473345d20b3e0b2 \ sha256 707ea2ff2fa49b5999d9693ba44049d6b60288137e6d6acf3fe2d5125e5329ad # temporary patch to fix startup USB errors - patchfiles-append \ - patch-b200-fixes-LIBUSB_ERROR_PIPE-on-OS-X.diff \ - patch-b200-fix_initial_loading.diff + patchfiles-append patch-b200_squash.diff # overload the github livecheck URL with the maint branch, # when it is more advanced; comment out for master. Deleted: trunk/dports/science/uhd/files/patch-b200-fix_initial_loading.diff =================================================================== --- trunk/dports/science/uhd/files/patch-b200-fix_initial_loading.diff 2015-08-03 19:18:49 UTC (rev 139137) +++ trunk/dports/science/uhd/files/patch-b200-fix_initial_loading.diff 2015-08-03 20:04:05 UTC (rev 139138) @@ -1,21 +0,0 @@ ---- host/lib/usrp/b200/b200_impl.cpp.orig -+++ host/lib/usrp/b200/b200_impl.cpp -@@ -125,8 +125,7 @@ static device_addrs_t b200_find(const device_addr_t &hint) - // so that re-enumeration after fw load can occur successfully. - // This requirement is a courtesy of libusb1.0 on windows. - size_t found = 0; -- std::vector<usb_device_handle::sptr> b200_device_handles = get_b200_device_handles(hint); -- BOOST_FOREACH(usb_device_handle::sptr handle, b200_device_handles) { -+ BOOST_FOREACH(usb_device_handle::sptr handle, get_b200_device_handles(hint)) { - //extract the firmware path for the b200 - std::string b200_fw_image; - try{ -@@ -157,7 +156,7 @@ static device_addrs_t b200_find(const device_addr_t &hint) - //search for the device until found or timeout - while (boost::get_system_time() < timeout_time and b200_addrs.empty() and found != 0) - { -- BOOST_FOREACH(usb_device_handle::sptr handle, b200_device_handles) -+ BOOST_FOREACH(usb_device_handle::sptr handle, get_b200_device_handles(hint)) - { - usb_control::sptr control; - try{control = usb_control::make(handle, 0);} Deleted: trunk/dports/science/uhd/files/patch-b200-fixes-LIBUSB_ERROR_PIPE-on-OS-X.diff =================================================================== --- trunk/dports/science/uhd/files/patch-b200-fixes-LIBUSB_ERROR_PIPE-on-OS-X.diff 2015-08-03 19:18:49 UTC (rev 139137) +++ trunk/dports/science/uhd/files/patch-b200-fixes-LIBUSB_ERROR_PIPE-on-OS-X.diff 2015-08-03 20:04:05 UTC (rev 139138) @@ -1,273 +0,0 @@ ---- host/include/uhd/exception.hpp.orig -+++ host/include/uhd/exception.hpp -@@ -98,6 +98,14 @@ namespace uhd{ - virtual void dynamic_throw(void) const; - }; - -+ struct UHD_API usb_error : runtime_error{ -+ int _code; -+ usb_error(int code, const std::string &what); -+ virtual unsigned code(void) const; -+ virtual usb_error *dynamic_clone(void) const; -+ virtual void dynamic_throw(void) const; -+ }; -+ - struct UHD_API not_implemented_error : runtime_error{ - not_implemented_error(const std::string &what); - virtual unsigned code(void) const; ---- host/lib/exception.cpp.orig -+++ host/lib/exception.cpp -@@ -38,8 +38,15 @@ make_exception_impl("KeyError", key_error, lookup_err - make_exception_impl("TypeError", type_error, exception) - make_exception_impl("ValueError", value_error, exception) - make_exception_impl("RuntimeError", runtime_error, exception) -+//make_exception_impl("USBError", usb_error, runtime_error) - make_exception_impl("NotImplementedError", not_implemented_error, runtime_error) - make_exception_impl("EnvironmentError", environment_error, exception) - make_exception_impl("IOError", io_error, environment_error) - make_exception_impl("OSError", os_error, environment_error) - make_exception_impl("SystemError", system_error, exception) -+ -+usb_error::usb_error(int code, const std::string &what): -+ runtime_error(str(boost::format("%s %d: %s") % "USBError" % code % what)){_code = code;} -+unsigned usb_error::code(void) const{return _code;} \ -+usb_error *usb_error::dynamic_clone(void) const{return new usb_error(*this);} \ -+void usb_error::dynamic_throw(void) const{throw *this;} ---- host/lib/transport/libusb1_zero_copy.cpp.orig -+++ host/lib/transport/libusb1_zero_copy.cpp -@@ -155,7 +155,7 @@ public: - result.is_recv = _is_recv; - #endif - const int ret = libusb_submit_transfer(_lut); -- if (ret != 0) throw uhd::runtime_error(str(boost::format( -+ if (ret != 0) throw uhd::usb_error(ret, str(boost::format( - "usb %s submit failed: %s") % _name % libusb_error_name(ret))); - } - -@@ -266,17 +266,26 @@ public: - _all_luts.push_back(lut); - } - -- //initial release for all buffers -- for (size_t i = 0; i < get_num_frames(); i++) -+ size_t i = 0; -+ //try - { -- libusb_zero_copy_mb &mb = *(_mb_pool[i]); -- if (is_recv) mb.release(); -- else -+ //initial release for all buffers -+ for (; i < get_num_frames(); i++) - { -- mb.result.completed = 1; -- _enqueued.push_back(&mb); -+ //UHD_MSG(status) << "Releasing " << i << std::endl; -+ libusb_zero_copy_mb &mb = *(_mb_pool[i]); -+ if (is_recv) mb.release(); -+ else -+ { -+ mb.result.completed = 1; -+ _enqueued.push_back(&mb); -+ } - } - } -+ //catch (uhd::runtime_error& e) -+ { -+ // UHD_MSG(status) << "Releasing " << i << ":" << e.what() << std::endl; -+ } - } - - ~libusb_zero_copy_single(void) ---- host/lib/usrp/b200/b200_impl.cpp.orig -+++ host/lib/usrp/b200/b200_impl.cpp -@@ -37,6 +37,9 @@ - #include <ctime> - #include <cmath> - -+#include <uhd/transport/usb_zero_copy.hpp> -+#include "../../transport/libusb1_base.hpp" -+ - using namespace uhd; - using namespace uhd::usrp; - using namespace uhd::transport; -@@ -194,7 +197,44 @@ static device_addrs_t b200_find(const device_addr_t &hint) - **********************************************************************/ - static device::sptr b200_make(const device_addr_t &device_addr) - { -- return device::sptr(new b200_impl(device_addr)); -+ b200_impl* p = NULL; -+ -+ for (int i = 0; i < 2; ++i) -+ { -+ p = new b200_impl(); -+ int ret; -+ -+ ret = p->make(device_addr); -+ if (ret == LIBUSB_SUCCESS) -+ break; -+ -+ { -+ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( -+ boost::static_pointer_cast<libusb::special_handle>(p->get_handle())->get_device() -+ )); -+ -+ ret = libusb_clear_halt(dev_handle->get(), 8 | 0x80); -+ UHD_MSG(status) << "Ctrl Recv clear: " << libusb_error_name(ret) << std::endl; -+ ret = libusb_clear_halt(dev_handle->get(), 4 | 0x00); -+ UHD_MSG(status) << "Ctrl Send clear: " << libusb_error_name(ret) << std::endl; -+ -+ ret = libusb_clear_halt(dev_handle->get(), 6 | 0x80); -+ UHD_MSG(status) << "Data Recv clear: " << libusb_error_name(ret) << std::endl; -+ ret = libusb_clear_halt(dev_handle->get(), 2 | 0x00); -+ UHD_MSG(status) << "Data Send clear: " << libusb_error_name(ret) << std::endl; -+ -+ ret = libusb_reset_device(dev_handle->get()); -+ UHD_MSG(status) << "Dev Reset: " << libusb_error_name(ret) << std::endl; -+ } -+ -+ delete p; -+ p = NULL; -+ } -+ -+ if (p == NULL) -+ throw uhd::runtime_error("USB error"); -+ -+ return device::sptr(p); - } - - UHD_STATIC_BLOCK(register_b200_device) -@@ -205,10 +245,14 @@ UHD_STATIC_BLOCK(register_b200_device) - /*********************************************************************** - * Structors - **********************************************************************/ --b200_impl::b200_impl(const device_addr_t &device_addr) : -+b200_impl::b200_impl(void) : - _revision(0), - _tick_rate(0.0) // Forces a clock initialization at startup - { -+} -+ -+int b200_impl::make(const uhd::device_addr_t& device_addr) -+{ - _tree = property_tree::make(); - _type = device::USRP; - const fs_path mb_path = "/mboards/0"; -@@ -262,17 +306,17 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : - std::vector<usb_device_handle::sptr> device_list = usb_device_handle::get_device_list(vid_pid_pair_list); - - //locate the matching handle in the device list -- usb_device_handle::sptr handle; -+ //usb_device_handle::sptr _handle; - BOOST_FOREACH(usb_device_handle::sptr dev_handle, device_list) { - if (dev_handle->get_serial() == device_addr["serial"]){ -- handle = dev_handle; -+ _handle = dev_handle; - break; - } - } -- UHD_ASSERT_THROW(handle.get() != NULL); //better be found -+ UHD_ASSERT_THROW(_handle.get() != NULL); //better be found - - //create control objects -- usb_control::sptr control = usb_control::make(handle, 0); -+ usb_control::sptr control = usb_control::make(_handle, 0); - _iface = b200_iface::make(control); - this->check_fw_compat(); //check after making - -@@ -360,12 +404,22 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : - ctrl_xport_args["send_frame_size"] = min_frame_size; - ctrl_xport_args["num_send_frames"] = "16"; - -- _ctrl_transport = usb_zero_copy::make( -- handle, -- 4, 8, //interface, endpoint -- 3, 4, //interface, endpoint -- ctrl_xport_args -- ); -+ UHD_MSG(status) << "Creating ctrl transport..." << std::endl; -+ try -+ { -+ _ctrl_transport = usb_zero_copy::make( -+ _handle, -+ 4, 8, //interface, endpoint -+ 3, 4, //interface, endpoint -+ ctrl_xport_args -+ ); -+ } -+ catch (const uhd::usb_error& e) -+ { -+ UHD_MSG(status) << e.what() << std::endl; -+ return e.code(); -+ } -+ UHD_MSG(status) << "Flusing ctrl recv buff..." << std::endl; - while (_ctrl_transport->get_recv_buff(0.0)){} //flush ctrl xport - _tree->create<double>(mb_path / "link_max_rate").set((usb_speed == 3) ? B200_MAX_RATE_USB3 : B200_MAX_RATE_USB2); - -@@ -442,12 +496,22 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : - data_xport_args["send_frame_size"] = device_addr.get("send_frame_size", "8192"); - data_xport_args["num_send_frames"] = device_addr.get("num_send_frames", "16"); - -- _data_transport = usb_zero_copy::make( -- handle, // identifier -- 2, 6, // IN interface, endpoint -- 1, 2, // OUT interface, endpoint -- data_xport_args // param hints -- ); -+ UHD_MSG(status) << "Creating data transport..." << std::endl; -+ try -+ { -+ _data_transport = usb_zero_copy::make( -+ _handle, // identifier -+ 2, 6, // IN interface, endpoint -+ 1, 2, // OUT interface, endpoint -+ data_xport_args // param hints -+ ); -+ } -+ catch (const uhd::usb_error& e) -+ { -+ UHD_MSG(status) << e.what() << std::endl; -+ return e.code(); -+ } -+ UHD_MSG(status) << "Flusing data recv buff..." << std::endl; - while (_data_transport->get_recv_buff(0.0)){} //flush ctrl xport - _demux = recv_packet_demuxer_3000::make(_data_transport); - -@@ -624,6 +688,9 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : - _tree->access<std::string>(mb_path / "time_source/value").set("internal"); - } - -+ _handle.reset(); -+ -+ return LIBUSB_SUCCESS; - } - - b200_impl::~b200_impl(void) ---- host/lib/usrp/b200/b200_impl.hpp.orig -+++ host/lib/usrp/b200/b200_impl.hpp -@@ -91,9 +91,13 @@ class b200_impl : public uhd::device - { - public: - //structors -- b200_impl(const uhd::device_addr_t &); -+ b200_impl(void); - ~b200_impl(void); - -+ int make(const uhd::device_addr_t &); -+ uhd::transport::usb_device_handle::sptr get_handle(void) const -+ { return _handle; } -+ - //the io interface - uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); - uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); -@@ -107,6 +111,8 @@ public: - void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = ""); - - private: -+ uhd::transport::usb_device_handle::sptr _handle; -+ - b200_type_t _b200_type; - size_t _revision; - --- -2.3.1 - Added: trunk/dports/science/uhd/files/patch-b200_squash.diff =================================================================== --- trunk/dports/science/uhd/files/patch-b200_squash.diff (rev 0) +++ trunk/dports/science/uhd/files/patch-b200_squash.diff 2015-08-03 20:04:05 UTC (rev 139138) @@ -0,0 +1,1374 @@ +--- host/include/uhd/exception.hpp.orig ++++ host/include/uhd/exception.hpp +@@ -98,6 +98,14 @@ namespace uhd{ + virtual void dynamic_throw(void) const; + }; + ++ struct UHD_API usb_error : runtime_error{ ++ int _code; ++ usb_error(int code, const std::string &what); ++ virtual unsigned code(void) const { return _code; }; ++ virtual usb_error *dynamic_clone(void) const; ++ virtual void dynamic_throw(void) const; ++ }; ++ + struct UHD_API not_implemented_error : runtime_error{ + not_implemented_error(const std::string &what); + virtual unsigned code(void) const; +--- host/lib/exception.cpp.orig ++++ host/lib/exception.cpp +@@ -43,3 +43,8 @@ make_exception_impl("EnvironmentError", environment_error, exception) + make_exception_impl("IOError", io_error, environment_error) + make_exception_impl("OSError", os_error, environment_error) + make_exception_impl("SystemError", system_error, exception) ++ ++usb_error::usb_error(int code, const std::string &what): ++ runtime_error(str(boost::format("%s %d: %s") % "USBError" % code % what)), _code(code) {} ++usb_error *usb_error::dynamic_clone(void) const{return new usb_error(*this);} \ ++void usb_error::dynamic_throw(void) const{throw *this;} +--- host/lib/transport/libusb1_base.cpp.orig ++++ host/lib/transport/libusb1_base.cpp +@@ -251,6 +251,21 @@ public: + _claimed.push_back(interface); + } + ++ void clear_endpoints(unsigned char recv_endpoint, unsigned char send_endpoint) ++ { ++ int ret; ++ ret = libusb_clear_halt(this->get(), recv_endpoint | 0x80); ++ UHD_LOG << "usb device handle: recv endpoint clear: " << libusb_error_name(ret) << std::endl; ++ ret = libusb_clear_halt(this->get(), send_endpoint | 0x00); ++ UHD_LOG << "usb device handle: send endpoint clear: " << libusb_error_name(ret) << std::endl; ++ } ++ ++ void reset_device(void) ++ { ++ int ret = libusb_reset_device(this->get()); ++ UHD_LOG << "usb device handle: dev Reset: " << libusb_error_name(ret) << std::endl; ++ } ++ + private: + libusb::device::sptr _dev; //always keep a reference to device + libusb_device_handle *_handle; +--- host/lib/transport/libusb1_base.hpp.orig ++++ host/lib/transport/libusb1_base.hpp +@@ -135,6 +135,10 @@ namespace libusb { + * Control interface: 0 + */ + virtual void claim_interface(int) = 0; ++ ++ virtual void clear_endpoints(unsigned char recv_endpoint, unsigned char send_endpoint) = 0; ++ ++ virtual void reset_device(void) = 0; + }; + + /*! +--- host/lib/transport/libusb1_zero_copy.cpp.orig ++++ host/lib/transport/libusb1_zero_copy.cpp +@@ -148,14 +148,14 @@ public: + + UHD_INLINE void submit(void) + { +- _lut->length = (_is_recv)? _frame_size : size(); //always set length ++ _lut->length = (_is_recv)? _frame_size : size(); //always set length + #ifdef UHD_TXRX_DEBUG_PRINTS + result.start_time = boost::get_system_time().time_of_day().total_microseconds(); + result.buff_num = num(); + result.is_recv = _is_recv; + #endif + const int ret = libusb_submit_transfer(_lut); +- if (ret != 0) throw uhd::runtime_error(str(boost::format( ++ if (ret != 0) throw uhd::usb_error(ret, str(boost::format( + "usb %s submit failed: %s") % _name % libusb_error_name(ret))); + } + +--- host/lib/usrp/b200/b200_impl.cpp.orig ++++ host/lib/usrp/b200/b200_impl.cpp +@@ -37,6 +37,8 @@ + #include <ctime> + #include <cmath> + ++#include "../../transport/libusb1_base.hpp" ++ + using namespace uhd; + using namespace uhd::usrp; + using namespace uhd::transport; +@@ -125,8 +127,7 @@ static device_addrs_t b200_find(const device_addr_t &hint) + // so that re-enumeration after fw load can occur successfully. + // This requirement is a courtesy of libusb1.0 on windows. + size_t found = 0; +- std::vector<usb_device_handle::sptr> b200_device_handles = get_b200_device_handles(hint); +- BOOST_FOREACH(usb_device_handle::sptr handle, b200_device_handles) { ++ BOOST_FOREACH(usb_device_handle::sptr handle, get_b200_device_handles(hint)) { + //extract the firmware path for the b200 + std::string b200_fw_image; + try{ +@@ -157,7 +158,7 @@ static device_addrs_t b200_find(const device_addr_t &hint) + //search for the device until found or timeout + while (boost::get_system_time() < timeout_time and b200_addrs.empty() and found != 0) + { +- BOOST_FOREACH(usb_device_handle::sptr handle, b200_device_handles) ++ BOOST_FOREACH(usb_device_handle::sptr handle, get_b200_device_handles(hint)) + { + usb_control::sptr control; + try{control = usb_control::make(handle, 0);} +@@ -195,7 +196,24 @@ static device_addrs_t b200_find(const device_addr_t &hint) + **********************************************************************/ + static device::sptr b200_make(const device_addr_t &device_addr) + { +- return device::sptr(new b200_impl(device_addr)); ++ uhd::transport::usb_device_handle::sptr handle; ++ ++ // We try twice, because the first time, the link might be in a bad state ++ // and we might need to reset the link, but if that didn't help, trying ++ // a third time is pointless. ++ try { ++ return device::sptr(new b200_impl(device_addr, handle)); ++ } ++ catch (const uhd::usb_error &e) { ++ libusb::device_handle::sptr dev_handle(libusb::device_handle::get_cached_handle( ++ boost::static_pointer_cast<libusb::special_handle>(handle)->get_device() ++ )); ++ dev_handle->clear_endpoints(B200_USB_CTRL_RECV_ENDPOINT, B200_USB_CTRL_SEND_ENDPOINT); ++ dev_handle->clear_endpoints(B200_USB_DATA_RECV_ENDPOINT, B200_USB_DATA_SEND_ENDPOINT); ++ dev_handle->reset_device(); ++ } ++ ++ return device::sptr(new b200_impl(device_addr, handle)); + } + + UHD_STATIC_BLOCK(register_b200_device) +@@ -206,7 +224,7 @@ UHD_STATIC_BLOCK(register_b200_device) + /*********************************************************************** + * Structors + **********************************************************************/ +-b200_impl::b200_impl(const device_addr_t &device_addr) : ++b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::sptr &handle) : + _revision(0), + _tick_rate(0.0) // Forces a clock initialization at startup + { +@@ -263,7 +281,6 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : + std::vector<usb_device_handle::sptr> device_list = usb_device_handle::get_device_list(vid_pid_pair_list); + + //locate the matching handle in the device list +- usb_device_handle::sptr handle; + BOOST_FOREACH(usb_device_handle::sptr dev_handle, device_list) { + if (dev_handle->get_serial() == device_addr["serial"]){ + handle = dev_handle; +@@ -361,10 +378,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : + ctrl_xport_args["send_frame_size"] = min_frame_size; + ctrl_xport_args["num_send_frames"] = "16"; + ++ // This may throw a uhd::usb_error, which will be caught by b200_make(). + _ctrl_transport = usb_zero_copy::make( + handle, +- 4, 8, //interface, endpoint +- 3, 4, //interface, endpoint ++ B200_USB_CTRL_RECV_INTERFACE, B200_USB_CTRL_RECV_ENDPOINT, //interface, endpoint ++ B200_USB_CTRL_SEND_INTERFACE, B200_USB_CTRL_SEND_ENDPOINT, //interface, endpoint + ctrl_xport_args + ); + while (_ctrl_transport->get_recv_buff(0.0)){} //flush ctrl xport +@@ -443,10 +461,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) : + data_xport_args["send_frame_size"] = device_addr.get("send_frame_size", "8192"); + data_xport_args["num_send_frames"] = device_addr.get("num_send_frames", "16"); + ++ // This may throw a uhd::usb_error, which will be caught by b200_make(). + _data_transport = usb_zero_copy::make( + handle, // identifier +- 2, 6, // IN interface, endpoint +- 1, 2, // OUT interface, endpoint ++ B200_USB_DATA_RECV_INTERFACE, B200_USB_DATA_RECV_ENDPOINT, //interface, endpoint ++ B200_USB_DATA_SEND_INTERFACE, B200_USB_DATA_SEND_ENDPOINT, //interface, endpoint + data_xport_args // param hints + ); + while (_data_transport->get_recv_buff(0.0)){} //flush ctrl xport +--- host/lib/usrp/b200/b200_impl.hpp.orig ++++ host/lib/usrp/b200/b200_impl.hpp +@@ -78,6 +78,16 @@ static const boost::uint32_t B200_RX_GPS_UART_SID = FLIP_SID(B200_TX_GPS_UART_SI + static const boost::uint32_t B200_LOCAL_CTRL_SID = 0x00000040; + static const boost::uint32_t B200_LOCAL_RESP_SID = FLIP_SID(B200_LOCAL_CTRL_SID); + ++static const unsigned char B200_USB_CTRL_RECV_INTERFACE = 4; ++static const unsigned char B200_USB_CTRL_RECV_ENDPOINT = 8; ++static const unsigned char B200_USB_CTRL_SEND_INTERFACE = 3; ++static const unsigned char B200_USB_CTRL_SEND_ENDPOINT = 4; ++ ++static const unsigned char B200_USB_DATA_RECV_INTERFACE = 2; ++static const unsigned char B200_USB_DATA_RECV_ENDPOINT = 6; ++static const unsigned char B200_USB_DATA_SEND_INTERFACE = 1; ++static const unsigned char B200_USB_DATA_SEND_ENDPOINT = 2; ++ + /* + * VID/PID pairs for all B2xx products + */ +@@ -96,7 +106,7 @@ class b200_impl : public uhd::device + { + public: + //structors +- b200_impl(const uhd::device_addr_t &); ++ b200_impl(const uhd::device_addr_t &, uhd::transport::usb_device_handle::sptr &handle); + ~b200_impl(void); + + //the io interface +--- host/utils/b2xx_side_channel.py.orig ++++ host/utils/b2xx_side_channel.py +@@ -16,25 +16,27 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see <http://www.gnu.org/licenses/>. + # ++""" ++Tool to read log buffers from the FX3. Use to debug USB connection issues. ++Requires PyUSB 1.0. ++""" + + import sys + import time + import struct +- + from optparse import OptionParser ++import serial + + try: + import usb.core + import usb.util + except Exception as e: +- print "Failed to import module 'usb'." +- print "Please make sure you have PyUSB installed and in your PYTHONPATH." +- print "PyUSB PyPI website: https://pypi.python.org/pypi/pyusb" +- print "To install, download from the website or use 'pip install pysusb'" ++ print("Failed to import module 'usb'.") ++ print("Please make sure you have PyUSB installed and in your PYTHONPATH.") ++ print("PyUSB PyPI website: https://pypi.python.org/pypi/pyusb") ++ print("To install, download from the website or use 'pip install pyusb'") + exit(1) + +-import serial +- + VRT_OUT = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_OUT + VRT_IN = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_IN + +@@ -62,7 +64,7 @@ VRQS[B200_VREQ_FLUSH_DATA_EPS] = 'B200_VREQ_FLUSH_DATA_EPS' + B200_VREQ_AD9361_LOOPBACK = 0x92 + VRQS[B200_VREQ_AD9361_LOOPBACK] = 'B200_VREQ_AD9361_LOOPBACK' + +-COUNTER_MAGIC = 0x10024001 ++COUNTER_MAGIC = 0x10024001 + """ + typedef struct Counters { + int magic; +@@ -162,6 +164,10 @@ USB_PHY_ERROR_REGISTERS = [ + + USB_ERROR_COUNTERS += USB_PHY_ERROR_REGISTERS + ++PIB_COUNTERS = [ ++ 'socket_inactive' ++] ++ + COUNTERS = [ + 'magic', + +@@ -177,7 +183,13 @@ COUNTERS = [ + + 'heap_size', + +- 'resume_count' ++ 'resume_count', ++ 'state_transition_count', ++ 'invalid_gpif_state', ++ ('thread_0', PIB_COUNTERS), ++ ('thread_1', PIB_COUNTERS), ++ ('thread_2', PIB_COUNTERS), ++ ('thread_3', PIB_COUNTERS), + ] + + USB_EVENTS = {} +@@ -243,6 +255,101 @@ LTSSM_STATES[0x1c] = ['111XX', "(none)"] + LTSSM_STATES[0x1f] = ['111XX', "(none)"] + LTSSM_STATES[0x2c] = ['101100', "Cypress/Intel workaround"] + ++CF_NONE = 0 ++CF_TX_SWING = 1 << 0 ++CF_TX_DEEMPHASIS = 1 << 1 ++CF_DISABLE_USB2 = 1 << 2 ++CF_ENABLE_AS_SUPERSPEED = 1 << 3 ++CF_PPORT_DRIVE_STRENGTH = 1 << 4 ++CF_DMA_BUFFER_SIZE = 1 << 5 ++CF_DMA_BUFFER_COUNT = 1 << 6 ++CF_MANUAL_DMA = 1 << 7 ++CF_SB_BAUD_DIV = 1 << 8 ++ ++CF_RE_ENUM = 1 << 31 ++ ++""" ++typedef struct Config { ++ int tx_swing; // [90] [65] 45 ++ int tx_deemphasis; // 0x11 ++ int disable_usb2; // 0 ++ int enable_as_superspeed; // 1 ++ int pport_drive_strength; // CY_U3P_DS_THREE_QUARTER_STRENGTH ++ int dma_buffer_size; // [USB3] (max) ++ int dma_buffer_count; // [USB3] 1 ++ int manual_dma; // 0 ++ int sb_baud_div; // 434*2 ++} CONFIG, *PCONFIG; ++ ++typedef struct ConfigMod { ++ int flags; ++ CONFIG config; ++} CONFIG_MOD, *PCONFIG_MOD; ++""" ++ ++class Config(): ++ def __init__(self, ++ tx_swing=None, tx_deemphasis=None, disable_usb2=None, enable_as_superspeed=None, ++ pport_drive_strength=None, ++ dma_buffer_size=None, dma_buffer_count=None, manual_dma=None, ++ sb_baud_div=None, ++ raw=None): ++ self.tx_swing = tx_swing ++ self.tx_deemphasis = tx_deemphasis ++ self.disable_usb2 = disable_usb2 ++ self.enable_as_superspeed = enable_as_superspeed ++ self.pport_drive_strength = pport_drive_strength ++ self.dma_buffer_size = dma_buffer_size ++ self.dma_buffer_count = dma_buffer_count ++ self.manual_dma = manual_dma ++ self.sb_baud_div = sb_baud_div ++ self._count = 9 ++ ++ if raw: ++ (self.tx_swing, ++ self.tx_deemphasis, ++ self.disable_usb2, ++ self.enable_as_superspeed, ++ self.pport_drive_strength, ++ self.dma_buffer_size, ++ self.dma_buffer_count, ++ self.manual_dma, ++ self.sb_baud_div) = struct.unpack("i"*self._count, raw) ++ def pack(self): ++ return struct.pack("i"*self._count, ++ self.tx_swing, ++ self.tx_deemphasis, ++ self.disable_usb2, ++ self.enable_as_superspeed, ++ self.pport_drive_strength, ++ self.dma_buffer_size, ++ self.dma_buffer_count, ++ self.manual_dma, ++ self.sb_baud_div) ++ def __str__(self): ++ return self.to_string() ++ def to_string(self, flags=-1): ++ s = "" ++ if flags & CF_TX_SWING: ++ s += "tx_swing = %s\n" % (self.tx_swing) ++ if flags & CF_TX_DEEMPHASIS: ++ s += "tx_deemphasis = %s\n" % (self.tx_deemphasis) ++ if flags & CF_DISABLE_USB2: ++ s += "disable_usb2 = %s\n" % (self.disable_usb2) ++ if flags & CF_ENABLE_AS_SUPERSPEED: ++ s += "enable_as_superspeed = %s\n" % (self.enable_as_superspeed) ++ if flags & CF_PPORT_DRIVE_STRENGTH: ++ s += "pport_drive_strength = %s\n" % (self.pport_drive_strength) ++ if flags & CF_DMA_BUFFER_SIZE: ++ s += "dma_buffer_size = %s\n" % (self.dma_buffer_size) ++ if flags & CF_DMA_BUFFER_COUNT: ++ s += "dma_buffer_count = %s\n" % (self.dma_buffer_count) ++ if flags & CF_MANUAL_DMA: ++ s += "manual_dma = %s\n" % (self.manual_dma) ++ if flags & CF_SB_BAUD_DIV: ++ s += "sb_baud_div = %s\n" % (self.sb_baud_div) ++ return s ++ + def _parse_usb_event_log(data): + l = [] + for d in data: +@@ -252,11 +359,11 @@ def _parse_usb_event_log(data): + #l += [(USB_EVENTS[0x80][0] + "+%i" % (d & ~0x80), USB_EVENTS[0x80][1])] + ltssm_key = (d & ~0x80) + ltssm_val = "(unknown)" +- if LTSSM_STATES.has_key(ltssm_key): ++ if ltssm_key in LTSSM_STATES: + ltssm_val = LTSSM_STATES[ltssm_key][1] + ltssm_val = "LTSSM: " + ltssm_val + l += [(USB_EVENTS[0x80][0] + "+%i" % (d & ~0x80), ltssm_val)] +- elif USB_EVENTS.has_key(d): ++ elif d in USB_EVENTS: + l += [USB_EVENTS[d]] + #else: + # l += [("?", "?")] +@@ -313,8 +420,8 @@ class counter_set(): + try: + vals = struct.unpack(self._fmt_str, data) + self._update(vals) +- except Exception, e: +- print e ++ except Exception as e: ++ print(("While updating counter set '%s':" % self._name), e) + + def __str__(self): + return self.to_string() +@@ -346,7 +453,7 @@ class usb_device(): + self.timeout = 2000 + + def open(self, idVendor, idProduct): +- print "Finding %04x:%04x..." % (idVendor, idProduct) ++ print("Finding %04x:%04x..." % (idVendor, idProduct)) + self.dev = usb.core.find(idVendor=idVendor, idProduct=idProduct) + if self.dev is None: + raise ValueError('Device not found: %04x:%04x' % (idVendor, idProduct)) +@@ -362,7 +469,7 @@ class usb_device(): + + #self.dev.set_configuration() # This will throw as device is already claimed + +- print "Opened %04x:%04x" % (idVendor, idProduct) ++ print("Opened %04x:%04x" % (idVendor, idProduct)) + + #self.dev.ctrl_transfer(0x21, 0x09, 0, 0, [0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00] ) + #self.dev.ctrl_transfer(bmRequestType, bRequest, wValue=0, wIndex=0, data_or_wLength = None, timeout = None +@@ -379,40 +486,41 @@ class usb_device(): + l = [] + try: + l = self.dev.ctrl_transfer(VRT_IN, B200_VREQ_GET_USB_SPEED, 0, 0, 1) +- except usb.core.USBError, e: ++ except usb.core.USBError as e: + if e.errno == 32: +- print e ++ print(e) ++ print("Is the firmware loaded?") + sys.exit(0) + if len(l) > 0: + self.usb_speed = l[0] +- print "Operating at USB", self.usb_speed ++ print("Operating at USB", self.usb_speed) + break + else: +- print "Retrying..." ++ print("Retrying...") + #if self.usb_speed == 3: + # self.max_buffer_size = 512 +- print "Max buffer size:", self.max_buffer_size +- print ++ print("Max buffer size:", self.max_buffer_size) ++ print() + + def _handle_error(self, e, vrt): + if e.errno == 19: # No such device + raise e + vrt_str = "0x%02x" % (vrt) +- if VRQS.has_key(vrt): ++ if vrt in VRQS: + vrt_str += " (%s)" % (VRQS[vrt]) +- print "%s: %s" % (vrt_str, str(e)) ++ print("%s: %s" % (vrt_str, str(e))) + + def vrt_get(self, vrt): + try: + return self.dev.ctrl_transfer(VRT_IN, vrt, 0, 0, self.max_buffer_size, self.timeout) +- except usb.core.USBError, e: ++ except usb.core.USBError as e: + self._handle_error(e, vrt) + return [] + + def vrt_set(self, vrt, data=""): + try: + return self.dev.ctrl_transfer(VRT_OUT, vrt, 0, 0, data, self.timeout) +- except usb.core.USBError, e: ++ except usb.core.USBError as e: + self._handle_error(e, vrt) + return None + +@@ -428,7 +536,11 @@ class usb_device(): + last = 0 + while raw[last] != 0: + try: +- idx = raw.index(0, last) ++ try: ++ idx = raw.index(0, last) ++ except ValueError as e: ++ print("No null termination in log buffer (length: %d, last null: %d)" % (len(raw), last)) ++ break + self.log_index += 1 + line = "".join(map(chr, raw[last:idx])) + #print "[%05i %05i] %s" % (self.log_index, self.log_read_count, line) +@@ -439,8 +551,8 @@ class usb_device(): + last = idx + 1 + if last >= len(raw): + break +- except Exception, e: +- print e ++ except Exception as e: ++ print("Exception while parsing log buffer:", e) + break + return lines + +@@ -450,8 +562,8 @@ class usb_device(): + return + for l in lines: + #print l +- print "[%05i %05i] %s" % (l[0], self.log_read_count, l[1]) +- print ++ print("[%05i %05i] %s" % (l[0], self.log_read_count, l[1])) ++ print() + + def get_counters(self): + data = self.vrt_get(B200_VREQ_GET_COUNTERS) +@@ -462,8 +574,8 @@ class usb_device(): + + def print_counters(self): + self.get_counters() +- print "[%05i]" % (self.counters_read_count) +- print self.counters ++ print("[%05i]" % (self.counters_read_count)) ++ print(self.counters) + + def get_usb_event_log(self): + data = self.vrt_get(B200_VREQ_GET_USB_EVENT_LOG) +@@ -480,8 +592,8 @@ class usb_device(): + l = self.get_usb_event_log() + if len(l) == 0: + return +- print "\n".join(map(lambda x: ("[%05i] " % (self.usb_event_log_read_count)) + x[0] + ":\t" + x[1], l)) +- print ++ print("\n".join([("[%05i] " % (self.usb_event_log_read_count)) + x[0] + ":\t" + x[1] for x in l])) ++ print() + + def run_log(dev, options): + items = [ +@@ -489,8 +601,8 @@ def run_log(dev, options): + (options.counters, dev.print_counters), + (options.usb_events, dev.print_usb_event_log) + ] +- items = filter(lambda x: x[0] > 0, items) +- smallest_interval = min(map(lambda x: x[0], items)) ++ items = [x for x in items if x[0] > 0] ++ smallest_interval = min([x[0] for x in items]) + time_now = time.time() + last = [time_now]*len(items) + +@@ -506,7 +618,7 @@ def run_log(dev, options): + if time_now < (time_last + items[i][0]): + continue + if options.clear_screen and not cleared: +- print chr(27) + "[2J" ++ print(chr(27) + "[2J") + cleared = True + #print items[i][1] + items[i][1]() +@@ -535,9 +647,9 @@ def recv_serial_data(ser): + data = data[0:-2] + if data == "": + #print "[Received an empty line]" +- print ++ print() + elif data[0] == ' ': +- print time_now_str, data[1:] ++ print(time_now_str, data[1:]) + elif data[0] == 'U': + data = data[1:] + cur_type = 0 +@@ -553,20 +665,20 @@ def recv_serial_data(ser): + i = ord(c) - ord('A') + cur_type = 2 + else: +- print time_now_str, "[Unknown type: '%s' (0x%02x) in '%s']" % (c, ord(c), data) ++ print(time_now_str, "[Unknown type: '%s' (0x%02x) in '%s']" % (c, ord(c), data)) + + elif cur_type == 1: + i = ord(c) - ord('a') + if (i < 0) or (i >= len(USB_PHY_ERROR_REGISTERS)): +- print time_now_str, "[Unknown PHY error register index: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i, data) ++ print(time_now_str, "[Unknown PHY error register index: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i, data)) + else: +- print time_now_str, USB_PHY_ERROR_REGISTERS[i] ++ print(time_now_str, USB_PHY_ERROR_REGISTERS[i]) + cur_type = 0 + + elif cur_type == 2: + i2 = ord(c) - ord('A') + if (c < 'A') or (c > 'P'): +- print time_now_str, "[Unknown second USB event part: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i2, data) ++ print(time_now_str, "[Unknown second USB event part: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i2, data)) + else: + i = (i << 4) | i2 + usb_events += [i] +@@ -578,11 +690,14 @@ def recv_serial_data(ser): + if len(usb_events) > 0: + usb_event_log_read_count += 1 + l = _parse_usb_event_log(usb_events) +- print "\n".join(map(lambda x: time_now_str + ("[%05i] " % (usb_event_log_read_count)) + x[0] + ":\t" + x[1], l)) ++ print("\n".join([time_now_str + ("[%05i] " % (usb_event_log_read_count)) + x[0] + ":\t" + x[1] for x in l])) ++ #print ++ + data = "" + + def main(): + parser = OptionParser(usage="%prog: [options]") #option_class=eng_option, ++ + parser.add_option("-v", "--vid", type="string", default="0x2500", help="VID [default=%default]") + parser.add_option("-p", "--pid", type="string", default="0x0020", help="PID [default=%default]") + parser.add_option("-t", "--tty", type="string", default=None, help="TTY [default=%default]") +@@ -597,26 +712,34 @@ def main(): + parser.add_option("-R", "--reset-counters", action="store_true", default=False, help="Reset counters [default=%default]") + parser.add_option("-f", "--flush-data-eps", action="store_true", default=False, help="Flush data endpoints [default=%default]") + parser.add_option("-L", "--fe-loopback", type="int", default=None, help="Change AD9361 digital loopback [default=%default]") ++ + (options, args) = parser.parse_args() + + if options.tty is not None and options.tty != "": + while True: + try: + ser = serial.Serial(port=options.tty, baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=None) # timeout: None (blocking), 0 (non-blocking) +- print "Opened", options.tty ++ print("Opened", options.tty) ++ + try: + recv_serial_data(ser) + except KeyboardInterrupt: + break + except Exception as e: +- print e ++ print("Unable to open serial port:", e) + break + else: + dev = usb_device() ++ + while True: + try: + dev.open(idVendor=hex_to_int(options.vid), idProduct=hex_to_int(options.pid)) + ++ raw_config = dev.vrt_get(B200_VREQ_GET_CONFIG) ++ current_config = Config(raw=raw_config) ++ print("Current config:") ++ print(current_config) ++ + if options.flush_data_eps: + dev.vrt_set(B200_VREQ_FLUSH_DATA_EPS) + if options.sb_baud_div is not None: +@@ -627,17 +750,68 @@ def main(): + dev.vrt_set(B200_VREQ_CLEAR_COUNTERS) + if options.fe_loopback is not None: + dev.vrt_set(B200_VREQ_AD9361_LOOPBACK, struct.pack('B', int(options.fe_loopback))) ++ options.cmd = options.cmd.strip() + if len(options.cmd) == 0: + run_log(dev, options) +- pass + else: +- pass ++ cmds = options.cmd.split(',') ++ flags = 0 ++ for cmd in cmds: ++ cmd = cmd.strip() ++ if len(cmd) == 0: ++ continue ++ parts = cmd.split(' ') ++ action = parts[0].lower() ++ try: ++ if action == "txswing": ++ current_config.tx_swing = int(parts[1]) ++ flags |= CF_TX_SWING ++ elif action == "txdeemph": ++ current_config.tx_deemphasis = int(parts[1]) ++ flags |= CF_TX_DEEMPHASIS ++ elif action == "ss": ++ current_config.enable_as_superspeed = int(parts[1]) ++ flags |= CF_ENABLE_AS_SUPERSPEED ++ elif action == "disableusb2": ++ current_config.disable_usb2 = int(parts[1]) ++ flags |= CF_DISABLE_USB2 ++ elif action == "pportdrive": ++ current_config.pport_drive_strength = int(parts[1]) ++ flags |= CF_PPORT_DRIVE_STRENGTH ++ elif action == "dmasize": ++ current_config.dma_buffer_size = int(parts[1]) ++ flags |= CF_DMA_BUFFER_SIZE ++ elif action == "dmacount": ++ current_config.dma_buffer_count = int(parts[1]) ++ flags |= CF_DMA_BUFFER_COUNT ++ elif action == "manualdma": ++ current_config.manual_dma = int(parts[1]) ++ flags |= CF_MANUAL_DMA ++ elif action == "sbbauddiv": ++ current_config.sb_baud_div = int(parts[1]) ++ flags |= CF_SB_BAUD_DIV ++ elif action == "reenum": ++ flags |= CF_RE_ENUM ++ else: ++ print("'%s' not implemented" % (action)) ++ except Exception as e: ++ print("Exception while handling action '%s'" % (action), e) ++ if flags != 0: ++ print("New config to be set:") ++ print(current_config.to_string(flags)) ++ #print current_config ++ #print "Update flags: 0x%x" % (flags) ++ new_config = struct.pack("I", flags) + current_config.pack() ++ dev.vrt_set(B200_VREQ_SET_CONFIG, new_config) ++ else: ++ print("Not updating config") + break + except usb.core.USBError as e: + if e.errno == 19: # No such device + pass +- print e ++ print(e) + break ++ + return 0 + + if __name__ == '__main__': +--- tools/b200/b2x0_side_channel.py ++++ /dev/null +@@ -1,650 +0,0 @@ +-#!/usr/bin/env python +-# -*- coding: utf-8 -*- +-# +-# Copyright 2013-2014 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/>. +-# +-""" +-Tool to read log buffers from the FX3. Use to debug USB connection issues. +-Requires PyUSB 1.0. +-""" +- +-import sys +-import time +-import struct +-from optparse import OptionParser +-import serial +- +-try: +- import usb.core +- import usb.util +-except Exception as e: +- print "Failed to import usb - please have pyusb in your PYTHONPATH" +- raise e +- +-VRT_OUT = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_OUT +-VRT_IN = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_IN +- +-VRQS = {} +-B200_VREQ_GET_LOG = 0x23 +-VRQS[B200_VREQ_GET_LOG] = 'B200_VREQ_GET_LOG' +-B200_VREQ_GET_COUNTERS = 0x24 +-VRQS[B200_VREQ_GET_COUNTERS] = 'B200_VREQ_GET_COUNTERS' +-B200_VREQ_CLEAR_COUNTERS = 0x25 +-VRQS[B200_VREQ_CLEAR_COUNTERS] = 'B200_VREQ_CLEAR_COUNTERS' +-B200_VREQ_GET_USB_EVENT_LOG = 0x26 +-VRQS[B200_VREQ_GET_USB_EVENT_LOG] = 'B200_VREQ_GET_USB_EVENT_LOG' +-B200_VREQ_SET_CONFIG = 0x27 +-VRQS[B200_VREQ_SET_CONFIG] = 'B200_VREQ_SET_CONFIG' +-B200_VREQ_GET_CONFIG = 0x28 +-VRQS[B200_VREQ_GET_CONFIG] = 'B200_VREQ_GET_CONFIG' +-B200_VREQ_GET_USB_SPEED = 0x80 +-VRQS[B200_VREQ_GET_USB_SPEED] ='B200_VREQ_GET_USB_SPEED' +-B200_VREQ_WRITE_SB = 0x29 +-VRQS[B200_VREQ_WRITE_SB] = 'B200_VREQ_WRITE_SB' +-B200_VREQ_SET_SB_BAUD_DIV = 0x30 +-VRQS[B200_VREQ_SET_SB_BAUD_DIV] = 'B200_VREQ_SET_SB_BAUD_DIV' +-B200_VREQ_FLUSH_DATA_EPS = 0x31 +-VRQS[B200_VREQ_FLUSH_DATA_EPS] = 'B200_VREQ_FLUSH_DATA_EPS' +-B200_VREQ_AD9361_LOOPBACK = 0x92 +-VRQS[B200_VREQ_AD9361_LOOPBACK] = 'B200_VREQ_AD9361_LOOPBACK' +- +-COUNTER_MAGIC = 0x10024001 +-""" +-typedef struct Counters { +- int magic; +- +- DMA_COUNTERS dma_to_host; +- DMA_COUNTERS dma_from_host; +- +- int log_overrun_count; +- +- int usb_error_update_count; +- USB_ERROR_COUNTERS usb_error_counters; +- +- int usb_ep_underrun_count; +- +- int heap_size; +-} COUNTERS, *PCOUNTERS; +- +-typedef struct USBErrorCounters { +- int phy_error_count; +- int link_error_count; +- +- int PHY_LOCK_EV; +- int TRAINING_ERROR_EV; +- int RX_ERROR_CRC32_EV; +- int RX_ERROR_CRC16_EV; +- int RX_ERROR_CRC5_EV; +- int PHY_ERROR_DISPARITY_EV; +- int PHY_ERROR_EB_UND_EV; +- int PHY_ERROR_EB_OVR_EV; +- int PHY_ERROR_DECODE_EV; +-} USB_ERROR_COUNTERS, *PUSB_ERROR_COUNTERS; +- +-typedef struct DMACounters { +- int XFER_CPLT; +- int SEND_CPLT; +- int RECV_CPLT; +- int PROD_EVENT; +- int CONS_EVENT; +- int ABORTED; +- int ERROR; +- int PROD_SUSP; +- int CONS_SUSP; +- +- int BUFFER_MARKER; +- int BUFFER_EOP; +- int BUFFER_ERROR; +- int BUFFER_OCCUPIED; +- +- int last_count; +- int last_size; +- +- int last_sid; +- int bad_sid_count; +- +- int resume_count; +-} DMA_COUNTERS, *PDMA_COUNTERS; +-""" +-DMA_COUNTERS = [ +- 'XFER_CPLT', +- 'SEND_CPLT', +- 'RECV_CPLT', +- 'PROD_EVENT', +- 'CONS_EVENT', +- 'ABORTED', +- 'ERROR', +- 'PROD_SUSP', +- 'CONS_SUSP', +- +- 'BUFFER_MARKER', +- 'BUFFER_EOP', +- 'BUFFER_ERROR', +- 'BUFFER_OCCUPIED', +- +- 'last_count', +- 'last_size', +- +- 'last_sid', +- 'bad_sid_count' +-] +- +-USB_ERROR_COUNTERS = [ +- 'phy_error_count', +- 'link_error_count' +-] +- +-USB_PHY_ERROR_REGISTERS = [ +- 'PHY_LOCK_EV', +- 'TRAINING_ERROR_EV', +- 'RX_ERROR_CRC32_EV', +- 'RX_ERROR_CRC16_EV', +- 'RX_ERROR_CRC5_EV', +- 'PHY_ERROR_DISPARITY_EV', +- 'PHY_ERROR_EB_UND_EV', +- 'PHY_ERROR_EB_OVR_EV', +- 'PHY_ERROR_DECODE_EV' +-] +- +-USB_ERROR_COUNTERS += USB_PHY_ERROR_REGISTERS +- +-COUNTERS = [ +- 'magic', +- +- ('dma_to_host', DMA_COUNTERS), +- ('dma_from_host', DMA_COUNTERS), +- +- 'log_overrun_count', +- +- 'usb_error_update_count', +- ('usb_error_counters', USB_ERROR_COUNTERS), +- +- 'usb_ep_underrun_count', +- +- 'heap_size', +- +- 'resume_count' +-] +- +-USB_EVENTS = {} +-USB_EVENTS[0x01] = ('CYU3P_USB_LOG_VBUS_OFF' , 'Indicates VBus turned off.') +-USB_EVENTS[0x02] = ('CYU3P_USB_LOG_VBUS_ON' , 'Indicates VBus turned on.') +-USB_EVENTS[0x03] = ('CYU3P_USB_LOG_USB2_PHY_OFF' , 'Indicates that the 2.0 PHY has been turned off.') +-USB_EVENTS[0x04] = ('CYU3P_USB_LOG_USB3_PHY_OFF' , 'Indicates that the 3.0 PHY has been turned off.') +-USB_EVENTS[0x05] = ('CYU3P_USB_LOG_USB2_PHY_ON' , 'Indicates that the 2.0 PHY has been turned on.') +-USB_EVENTS[0x06] = ('CYU3P_USB_LOG_USB3_PHY_ON' , 'Indicates that the 3.0 PHY has been turned on.') +-USB_EVENTS[0x10] = ('CYU3P_USB_LOG_USBSS_DISCONNECT' , 'Indicates that the USB 3.0 link has been disabled.') +-USB_EVENTS[0x11] = ('CYU3P_USB_LOG_USBSS_RESET' , 'Indicates that a USB 3.0 reset (warm/hot) has happened.') +-USB_EVENTS[0x12] = ('CYU3P_USB_LOG_USBSS_CONNECT' , 'Indicates that USB 3.0 Rx Termination has been detected.') +-USB_EVENTS[0x14] = ('CYU3P_USB_LOG_USBSS_CTRL' , 'Indicates that a USB 3.0 control request has been received.') +-USB_EVENTS[0x15] = ('CYU3P_USB_LOG_USBSS_STATUS' , 'Indicates completion of status stage for a 3.0 control request.') +-USB_EVENTS[0x16] = ('CYU3P_USB_LOG_USBSS_ACKSETUP' , 'Indicates that the CyU3PUsbAckSetup API has been called.') +-USB_EVENTS[0x21] = ('CYU3P_USB_LOG_LGO_U1' , 'Indicates that a LGO_U1 command has been received.') +-USB_EVENTS[0x22] = ('CYU3P_USB_LOG_LGO_U2' , 'Indicates that a LGO_U2 command has been received.') +-USB_EVENTS[0x23] = ('CYU3P_USB_LOG_LGO_U3' , 'Indicates that a LGO_U3 command has been received.') +-USB_EVENTS[0x40] = ('CYU3P_USB_LOG_USB2_SUSP' , 'Indicates that a USB 2.0 suspend condition has been detected.') +-USB_EVENTS[0x41] = ('CYU3P_USB_LOG_USB2_RESET' , 'Indicates that a USB 2.0 bus reset has been detected.') +-USB_EVENTS[0x42] = ('CYU3P_USB_LOG_USB2_HSGRANT' , 'Indicates that the USB High-Speed handshake has been completed.') +-USB_EVENTS[0x44] = ('CYU3P_USB_LOG_USB2_CTRL' , 'Indicates that a FS/HS control request has been received.') +-USB_EVENTS[0x45] = ('CYU3P_USB_LOG_USB2_STATUS' , 'Indicates completion of status stage for a FS/HS control transfer.') +-USB_EVENTS[0x50] = ('CYU3P_USB_LOG_USB_FALLBACK' , 'Indicates that the USB connection is dropping from 3.0 to 2.0') +-USB_EVENTS[0x51] = ('CYU3P_USB_LOG_USBSS_ENABLE' , 'Indicates that a USB 3.0 connection is being attempted again.') +-USB_EVENTS[0x52] = ('CYU3P_USB_LOG_USBSS_LNKERR' , 'The number of link errors has crossed the threshold.') +-USB_EVENTS[0x80] = ('CYU3P_USB_LOG_LTSSM_CHG' , 'Base of values that indicate a USB 3.0 LTSSM state change.') +- +-LTSSM_STATES = {} +-LTSSM_STATES[0x00] = ['00000', "SS.Disabled"] +-LTSSM_STATES[0x01] = ['00001', "Rx.Detect.Reset"] +-LTSSM_STATES[0x02] = ['00010', "Rx.Detect.Active"] +-LTSSM_STATES[0x03] = ['00011', "Rx.Detect.Quiet"] +-LTSSM_STATES[0x04] = ['00100', "SS.Inactive.Quiet"] +-LTSSM_STATES[0x05] = ['00101', "SS.Inactive.Disconnect.Detect"] +-LTSSM_STATES[0x06] = ['00110', "Hot Reset.Active"] +-LTSSM_STATES[0x07] = ['00111', "Hot Reset.Exit"] +-LTSSM_STATES[0x08] = ['01000', "Polling.LFPS"] +-LTSSM_STATES[0x09] = ['01001', "Polling.RxEQ"] +-LTSSM_STATES[0x0a] = ['01010', "Polling.Active"] +-LTSSM_STATES[0x0b] = ['01011', "Polling.Configuration"] +-LTSSM_STATES[0x0c] = ['01100', "Polling.Idle"] +-LTSSM_STATES[0x0d] = ['01101', "(none)"] +-#LTSSM_STATES[0x0X] = ['0111X', "(none)"] +-LTSSM_STATES[0x0e] = ['0111X', "(none)"] +-LTSSM_STATES[0x0f] = ['0111X', "(none)"] +-LTSSM_STATES[0x10] = ['10000', "U0"] +-LTSSM_STATES[0x11] = ['10001', "U1"] +-LTSSM_STATES[0x12] = ['10010', "U2"] +-LTSSM_STATES[0x13] = ['10011', "U3"] +-LTSSM_STATES[0x14] = ['10100', "Loopback.Active"] +-LTSSM_STATES[0x15] = ['10101', "Loopback.Exit"] +-LTSSM_STATES[0x16] = ['10110', "(none)"] +-LTSSM_STATES[0x17] = ['10111', "Compliance"] +-LTSSM_STATES[0x18] = ['11000', "Recovery.Active"] +-LTSSM_STATES[0x19] = ['11001', "Recovery.Configuration"] +-LTSSM_STATES[0x1a] = ['11010', "Recovery.Idle"] +-LTSSM_STATES[0x1b] = ['11011', "(none)"] +-#LTSSM_STATES[0x1X] = ['111XX', "(none)"] +-LTSSM_STATES[0x1c] = ['111XX', "(none)"] +-LTSSM_STATES[0x1d] = ['111XX', "(none)"] +-LTSSM_STATES[0x1c] = ['111XX', "(none)"] +-LTSSM_STATES[0x1f] = ['111XX', "(none)"] +-LTSSM_STATES[0x2c] = ['101100', "Cypress/Intel workaround"] +- +-def _parse_usb_event_log(data): +- l = [] +- for d in data: +- if d == 0x14 or d == 0x15 or d == 0x16: # CTRL, STATUS, ACKSETUP +- continue +- elif (d & 0x80): +- #l += [(USB_EVENTS[0x80][0] + "+%i" % (d & ~0x80), USB_EVENTS[0x80][1])] +- ltssm_key = (d & ~0x80) +- ltssm_val = "(unknown)" +- if LTSSM_STATES.has_key(ltssm_key): +- ltssm_val = LTSSM_STATES[ltssm_key][1] +- ltssm_val = "LTSSM: " + ltssm_val +- l += [(USB_EVENTS[0x80][0] + "+%i" % (d & ~0x80), ltssm_val)] +- elif USB_EVENTS.has_key(d): +- l += [USB_EVENTS[d]] +- #else: +- # l += [("?", "?")] +- return l +- +-class counter_set(): +- def __init__(self, counters, name='(top)'): +- self._counters = counters +- self._counter_names = [] +- self._name = name +- for c in counters: +- o = 0 +- default_value = False +- if isinstance(c, str): +- name = c +- default_value = True +- elif isinstance(c, tuple): +- name = c[0] +- o = counter_set(c[1]) +- elif isinstance(c, dict): +- raise Exception('Not implemented yet') +- else: +- raise Exception('Unknown counter format') +- setattr(self, name, o) +- self._counter_names += [(name, default_value)] +- self._fmt_str = self._get_struct_format() +- +- def _get_struct_format(self): +- fmt_str = "" +- for name, default_value in self._counter_names: +- if default_value: +- fmt_str += "i" +- else: +- o = getattr(self, name) +- fmt_str += o._get_struct_format() +- return fmt_str +- +- def _update(self, data, parents=[]): +- if len(data) == 0: +- raise Exception('Ran out of data entering %s' % (self._name)) +- #return [] +- for name, default_value in self._counter_names: +- if default_value: +- if len(data) == 0: +- raise Exception('Ran out of data setting %s in %s' % (name, self._name)) +- setattr(self, name, data[0]) +- data = data[1:] +- else: +- o = getattr(self, name) +- data = o._update(data, parents+[self]) +- return data +- +- def update(self, data): +- try: +- vals = struct.unpack(self._fmt_str, data) +- self._update(vals) +- except Exception, e: +- print e +- +- def __str__(self): +- return self.to_string() +- +- def to_string(self, parents=[]): +- s = "" +- cnt = 0 +- for name, default_value in self._counter_names: +- o = getattr(self, name) +- if default_value: +- if cnt > 0: +- s += "\t" +- s += "%s: %05i" % (name, o) +- cnt += 1 +- else: +- if cnt > 0: +- s += "\n" +- s += "\t"*(len(parents) + 1) +- s += o.to_string(parents+[self]) +- cnt = 0 +- s += "\n" +- return s +- +-class usb_device(): +- def __init__(self): +- #self.max_buffer_size = 64 # Default to USB2 +- self.max_buffer_size = 1024*4 # Apparently it'll frag bigger packets +- self.counters = counter_set(COUNTERS) +- self.timeout = 2000 +- +- def open(self, idVendor, idProduct): +- print "Finding %04x:%04x..." % (idVendor, idProduct) +- self.dev = usb.core.find(idVendor=idVendor, idProduct=idProduct) +- if self.dev is None: +- raise ValueError('Device not found: %04x:%04x' % (idVendor, idProduct)) +- +- self.log_index = 0 +- self.log_read_count = 0 +- self.usb_event_log_read_count = 0 +- self.counters_read_count = 0 +- +- #if self.dev.is_kernel_driver_active(0): +- # print "Detaching kernel driver..." +- # self.dev.detach_kernel_driver(0) +- +- #self.dev.set_configuration() # This will throw as device is already claimed +- +- print "Opened %04x:%04x" % (idVendor, idProduct) +- +- #self.dev.ctrl_transfer(0x21, 0x09, 0, 0, [0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00] ) +- #self.dev.ctrl_transfer(bmRequestType, bRequest, wValue=0, wIndex=0, data_or_wLength = None, timeout = None +- +- #res = self.dev.ctrl_transfer(VRT_IN, 0x83, 0, 0, 1024) +- # Can give 1024 byte size for IN, result will be actual payload size +- # Invalid VREQ results in usb.core.USBError 32 Pipe error +- #print res +- +- #res = self.dev.ctrl_transfer(VRT_IN, B200_VREQ_GET_USB_SPEED, 0, 0, 1) +- #self.usb_speed = res[0] +- while True: +- #l = self.vrt_get(B200_VREQ_GET_USB_SPEED) +- l = [] +- try: +- l = self.dev.ctrl_transfer(VRT_IN, B200_VREQ_GET_USB_SPEED, 0, 0, 1) +- except usb.core.USBError, e: +- if e.errno == 32: +- print e +- sys.exit(0) +- if len(l) > 0: +- self.usb_speed = l[0] +- print "Operating at USB", self.usb_speed +- break +- else: +- print "Retrying..." +- #if self.usb_speed == 3: +- # self.max_buffer_size = 512 +- print "Max buffer size:", self.max_buffer_size +- print +- +- def _handle_error(self, e, vrt): +- if e.errno == 19: # No such device +- raise e +- vrt_str = "0x%02x" % (vrt) +- if VRQS.has_key(vrt): +- vrt_str += " (%s)" % (VRQS[vrt]) +- print "%s: %s" % (vrt_str, str(e)) +- +- def vrt_get(self, vrt): +- try: +- return self.dev.ctrl_transfer(VRT_IN, vrt, 0, 0, self.max_buffer_size, self.timeout) +- except usb.core.USBError, e: +- self._handle_error(e, vrt) +- return [] +- +- def vrt_set(self, vrt, data=""): +- try: +- return self.dev.ctrl_transfer(VRT_OUT, vrt, 0, 0, data, self.timeout) +- except usb.core.USBError, e: +- self._handle_error(e, vrt) +- return None +- +- def get_log(self, with_log_index=True): +- lines = [] +- raw = self.vrt_get(B200_VREQ_GET_LOG) +- if len(raw) == 0: +- return lines +- if raw[0] == 0: +- return lines +- self.log_read_count += 1 +- raw = list(raw) +- last = 0 +- while raw[last] != 0: +- try: +- idx = raw.index(0, last) +- self.log_index += 1 +- line = "".join(map(chr, raw[last:idx])) +- #print "[%05i %05i] %s" % (self.log_index, self.log_read_count, line) +- if with_log_index: +- lines += [(self.log_index, line)] +- else: +- lines += [line] +- last = idx + 1 +- if last >= len(raw): +- break +- except Exception, e: +- print e +- break +- return lines +- +- def print_log(self): +- lines = self.get_log() +- if len(lines) == 0: +- return +- for l in lines: +- #print l +- print "[%05i %05i] %s" % (l[0], self.log_read_count, l[1]) +- print +- +- def get_counters(self): +- data = self.vrt_get(B200_VREQ_GET_COUNTERS) +- if len(data) == 0: +- return +- self.counters_read_count += 1 +- self.counters.update(data) +- +- def print_counters(self): +- self.get_counters() +- print "[%05i]" % (self.counters_read_count) +- print self.counters +- +- def get_usb_event_log(self): +- data = self.vrt_get(B200_VREQ_GET_USB_EVENT_LOG) +- if len(data) == 0: +- return [] +- if len(data) == self.max_buffer_size: # ZLP when no new events have been recorded +- return [] +- if len(data) > 64: +- raise Exception("USB event log data len = %i" % (len(data))) +- self.usb_event_log_read_count += 1 +- return _parse_usb_event_log(data) +- +- def print_usb_event_log(self): +- l = self.get_usb_event_log() +- if len(l) == 0: +- return +- print "\n".join(map(lambda x: ("[%05i] " % (self.usb_event_log_read_count)) + x[0] + ":\t" + x[1], l)) +- print +- +-def run_log(dev, options): +- items = [ +- (options.log, dev.print_log), +- (options.counters, dev.print_counters), +- (options.usb_events, dev.print_usb_event_log) +- ] +- items = filter(lambda x: x[0] > 0, items) +- smallest_interval = min(map(lambda x: x[0], items)) +- time_now = time.time() +- last = [time_now]*len(items) +- +- try: +- for i in items: +- if i[0] < 0: +- i[1]() +- while True: +- time_now = time.time() +- cleared = False +- for i in range(len(items)): +- time_last = last[i] +- if time_now < (time_last + items[i][0]): +- continue +- if options.clear_screen and not cleared: +- print chr(27) + "[2J" +- cleared = True +- #print items[i][1] +- items[i][1]() +- last[i] = time.time() +- time.sleep(smallest_interval) +- except KeyboardInterrupt: +- return +- +-def hex_to_int(s): +- radix = 10 +- s = s.lower() +- if (len(s) > 1 and s[0] == 'x') or (len(s) > 2 and s[0:2] == "0x"): +- radix = 16 +- return int(s, radix) +- +-def recv_serial_data(ser): +- data = "" +- usb_event_log_read_count = 0 +- time_start = time.time() +- while True: +- c = ser.read() +- data += c +- #if c == '\n': +- if len(data) >= 2 and data[-2:] == "\r\n": +- time_now_str = "[%06d]" % (int(time.time() - time_start)) +- data = data[0:-2] +- if data == "": +- #print "[Received an empty line]" +- print +- elif data[0] == ' ': +- print time_now_str, data[1:] +- elif data[0] == 'U': +- data = data[1:] +- cur_type = 0 +- i = 0 +- usb_events = [] +- while len(data) > 0: +- c = data[0] +- +- if cur_type == 0: +- if c == 'a': +- cur_type = 1 +- elif (c >= 'A') and (c <= 'P'): +- i = ord(c) - ord('A') +- cur_type = 2 +- else: +- print time_now_str, "[Unknown type: '%s' (0x%02x) in '%s']" % (c, ord(c), data) +- +- elif cur_type == 1: +- i = ord(c) - ord('a') +- if (i < 0) or (i >= len(USB_PHY_ERROR_REGISTERS)): +- print time_now_str, "[Unknown PHY error register index: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i, data) +- else: +- print time_now_str, USB_PHY_ERROR_REGISTERS[i] +- cur_type = 0 +- +- elif cur_type == 2: +- i2 = ord(c) - ord('A') +- if (c < 'A') or (c > 'P'): +- print time_now_str, "[Unknown second USB event part: '%s' (0x%02x) (%d) in '%s']" % (c, ord(c), i2, data) +- else: +- i = (i << 4) | i2 +- usb_events += [i] +- +- cur_type = 0 +- +- data = data[1:] +- +- if len(usb_events) > 0: +- usb_event_log_read_count += 1 +- l = _parse_usb_event_log(usb_events) +- print "\n".join(map(lambda x: time_now_str + ("[%05i] " % (usb_event_log_read_count)) + x[0] + ":\t" + x[1], l)) +- #print +- +- data = "" +- +-def main(): +- parser = OptionParser(usage="%prog: [options]") #option_class=eng_option, +- +- parser.add_option("-v", "--vid", type="string", default="0x2500", help="VID [default=%default]") +- parser.add_option("-p", "--pid", type="string", default="0x0020", help="PID [default=%default]") +- parser.add_option("-t", "--tty", type="string", default=None, help="TTY [default=%default]") +- parser.add_option("-c", "--cmd", type="string", default="", help="Command (empty opens prompt)") +- parser.add_option("-n", "--counters", type="float", default="5.0", help="Counter print interval [default=%default]") +- parser.add_option("-l", "--log", type="float", default="0.25", help="Log print interval [default=%default]") +- parser.add_option("-e", "--usb-events", type="float", default="0.25", help="USB event log print interval [default=%default]") +- parser.add_option("-s", "--sb", type="string", default=None, help="Settings Bus write message [default=%default]") +- parser.add_option("-d", "--sb-baud-div", type="int", default=None, help="Settings Bus baud rate divisor [default=%default]") +- parser.add_option("-b", "--sb-baud", type="int", default=None, help="Settings Bus baud rate [default=%default]") +- parser.add_option("-r", "--clear-screen", action="store_true", default=False, help="Clear screen [default=%default]") +- parser.add_option("-R", "--reset-counters", action="store_true", default=False, help="Reset counters [default=%default]") +- parser.add_option("-f", "--flush-data-eps", action="store_true", default=False, help="Flush data endpoints [default=%default]") +- parser.add_option("-L", "--fe-loopback", type="int", default=None, help="Change AD9361 digital loopback [default=%default]") +- +- (options, args) = parser.parse_args() +- +- if options.tty is not None and options.tty != "": +- while True: +- try: +- ser = serial.Serial(port=options.tty, baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=None) # timeout: None (blocking), 0 (non-blocking) +- print "Opened", options.tty +- +- try: +- recv_serial_data(ser) +- except KeyboardInterrupt: +- break +- except Exception, e: +- print e +- break +- else: +- dev = usb_device() +- +- while True: +- try: +- dev.open(idVendor=hex_to_int(options.vid), idProduct=hex_to_int(options.pid)) +- if options.flush_data_eps: +- dev.vrt_set(B200_VREQ_FLUSH_DATA_EPS) +- if options.sb_baud_div is not None: +- dev.vrt_set(B200_VREQ_SET_SB_BAUD_DIV, struct.pack('H', options.sb_baud_div)) +- if options.sb is not None and len(options.sb) > 0: +- dev.vrt_set(B200_VREQ_WRITE_SB, " " + options.sb) +- if options.reset_counters: +- dev.vrt_set(B200_VREQ_CLEAR_COUNTERS) +- if options.fe_loopback is not None: +- dev.vrt_set(B200_VREQ_AD9361_LOOPBACK, struct.pack('B', int(options.fe_loopback))) +- if len(options.cmd) == 0: +- run_log(dev, options) +- pass +- else: +- pass +- +- break +- except usb.core.USBError, e: +- if e.errno == 19: # No such device +- pass +- print e +- break +- +- return 0 +- +-if __name__ == '__main__': +- main()