diff options
Diffstat (limited to 'host/lib')
| -rw-r--r-- | host/lib/transport/libusb1_base.cpp | 15 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_base.hpp | 4 | ||||
| -rw-r--r-- | host/lib/transport/libusb1_zero_copy.cpp | 4 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 34 | ||||
| -rw-r--r-- | host/lib/usrp/b200/b200_impl.hpp | 12 | 
5 files changed, 59 insertions, 10 deletions
| diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 0baf8dc76..9635d34b0 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/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; diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index b00946614..2e16dc176 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/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;      };      /*! diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 1ac02d16f..465adc95e 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/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)));      } diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 3445f125b..f5129bc24 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/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; @@ -194,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) @@ -205,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  { @@ -262,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; @@ -360,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 @@ -442,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 diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 52ecb98f2..cbd51426d 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/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 | 
