aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorBalint Seeber <balint.seeber@ettus.com>2015-07-27 15:16:49 -0700
committerMartin Braun <martin.braun@ettus.com>2015-08-03 10:11:44 -0700
commit4ed2b26d512ed8c8e78fbbfcf25a3560fd8c7102 (patch)
tree940764e665d503f50a293ac8d50ca1fb0b605544 /host/lib
parente1672fa7eedb00a977c39b7e80bb18521493b524 (diff)
downloaduhd-4ed2b26d512ed8c8e78fbbfcf25a3560fd8c7102.tar.gz
uhd-4ed2b26d512ed8c8e78fbbfcf25a3560fd8c7102.tar.bz2
uhd-4ed2b26d512ed8c8e78fbbfcf25a3560fd8c7102.zip
b200: Change init sequence to catch bad USB states
- Fixes USB hang issues on OS X - Uses usb_errors
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/transport/libusb1_base.cpp15
-rw-r--r--host/lib/transport/libusb1_base.hpp4
-rw-r--r--host/lib/transport/libusb1_zero_copy.cpp4
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp34
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp12
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