summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/docs/usrp1.rst27
-rw-r--r--host/include/uhd/transport/usb_zero_copy.hpp24
-rw-r--r--host/lib/transport/libusb1_zero_copy.cpp140
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp26
4 files changed, 137 insertions, 80 deletions
diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst
index 3c1431d30..7cf447719 100644
--- a/host/docs/usrp1.rst
+++ b/host/docs/usrp1.rst
@@ -95,6 +95,27 @@ Notice that the subdevice name is always specified in the 3 possible cases.
B:B
+
+------------------------------------------------------------------------
+Change USB transfer parameters
+------------------------------------------------------------------------
+The advanced user may manipulate parameters of the usb bulk transfers
+for various reasons, such as lowering latency or increasing buffer size.
+By default, the UHD will use values for these parameters
+that are known to perform well on a variety of systems.
+
+The following device address can be used to manipulate USB bulk transfers:
+
+* **recv_xfer_size:** the size of each receive bulk transfer in bytes
+* **recv_num_xfers:** the number of simultaneous receive bulk transfers
+* **send_xfer_size:** the size of each send bulk transfer in bytes
+* **send_num_xfers:** the number of simultaneous send bulk transfers
+
+Example, set the args string to the following:
+::
+
+ serial=12345678, recv_num_xfers=16
+
------------------------------------------------------------------------
OS Specific Notes
------------------------------------------------------------------------
@@ -113,3 +134,9 @@ so that non-root users may access the device:
sudo mv tmpfile /etc/udev/rules.d/10-usrp.rules
sudo udevadm control --reload-rules
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Install libusb driver on Windows
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+On Windows, a driver must be installed the first time the USRP1 is attached to the host computer.
+A download link for this driver can be found on the Ettus Research UHD wiki page.
+Download and unpack the driver, and direct the Windows driver install wizard to the *.inf file.
diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp
index 75232c22a..61bf380ba 100644
--- a/host/include/uhd/transport/usb_zero_copy.hpp
+++ b/host/include/uhd/transport/usb_zero_copy.hpp
@@ -45,16 +45,22 @@ public:
* The underlying implementation may be platform specific.
*
* \param handle a device handle that uniquely identifying the device
- * \param rx_endpoint an integer specifiying an IN endpoint number
- * \param tx_endpoint an integer specifiying an OUT endpoint number
- * \param buff_size total number of bytes of buffer space to allocate
- * \param block_size number of bytes allocated for each I/O transaction
+ * \param recv_endpoint an integer specifiying an IN endpoint number
+ * \param send_endpoint an integer specifiying an OUT endpoint number
+ * \param recv_xfer_size the number of bytes for each receive transfer
+ * \param recv_num_xfers the number of simultaneous receive transfers
+ * \param send_xfer_size the number of bytes for each send transfer
+ * \param send_num_xfers the number of simultaneous send transfers
*/
- static sptr make(usb_device_handle::sptr handle,
- unsigned int rx_endpoint,
- unsigned int tx_endpoint,
- size_t buff_size = 0,
- size_t block_size = 0);
+ static sptr make(
+ usb_device_handle::sptr handle,
+ unsigned int recv_endpoint,
+ unsigned int send_endpoint,
+ size_t recv_xfer_size = 0,
+ size_t recv_num_xfers = 0,
+ size_t send_xfer_size = 0,
+ size_t send_num_xfers = 0
+ );
};
}} //namespace
diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp
index b089d11e0..f2dcff6b5 100644
--- a/host/lib/transport/libusb1_zero_copy.cpp
+++ b/host/lib/transport/libusb1_zero_copy.cpp
@@ -30,6 +30,9 @@ using namespace uhd::transport;
const int libusb_timeout = 0;
+static const size_t DEFAULT_NUM_XFERS = 16; //num xfers
+static const size_t DEFAULT_XFER_SIZE = 32*512; //bytes
+
/***********************************************************************
* Helper functions
***********************************************************************/
@@ -56,7 +59,7 @@ void pp_transfer(libusb_transfer *lut)
* create a bidirectional interface. It is a zero copy implementation
* with respect to libusb, however, each send and recv requires a copy
* operation from kernel to userspace; this is due to the usbfs
- * interface provided by the kernel.
+ * interface provided by the kernel.
**********************************************************************/
class usb_endpoint {
public:
@@ -107,7 +110,7 @@ private:
//! a list of shared arrays for the transfer buffers
std::vector<boost::shared_array<boost::uint8_t> > _buffers;
- // Calls for processing asynchronous I/O
+ // Calls for processing asynchronous I/O
libusb_transfer *allocate_transfer(int buff_len);
void print_transfer_status(libusb_transfer *lut);
};
@@ -142,7 +145,7 @@ void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){
* Constructor
* Allocate libusb transfers and mark as free. For IN endpoints,
* submit the transfers so that they're ready to return when
- * data is available.
+ * data is available.
*/
usb_endpoint::usb_endpoint(
libusb::device_handle::sptr handle,
@@ -194,7 +197,7 @@ usb_endpoint::~usb_endpoint(void){
/*
- * Allocate a libusb transfer
+ * Allocate a libusb transfer
* The allocated transfer - and buffer it contains - is repeatedly
* submitted, reaped, and reused and should not be freed until shutdown.
* \param buff_len size of the individual buffer held by each transfer
@@ -225,7 +228,7 @@ libusb_transfer *usb_endpoint::allocate_transfer(int buff_len){
* Asynchonous transfer submission
* Submit a libusb transfer to libusb add pending status
* \param lut pointer to libusb_transfer
- * \return true on success or false on error
+ * \return true on success or false on error
*/
void usb_endpoint::submit(libusb_transfer *lut){
UHD_ASSERT_THROW(libusb_submit_transfer(lut) == 0);
@@ -281,14 +284,14 @@ libusb_transfer *usb_endpoint::get_lut_with_wait(size_t timeout_ms){
}
/***********************************************************************
- * Managed buffers
+ * Managed buffers
**********************************************************************/
/*
* Libusb managed receive buffer
* Construct a recv buffer from a libusb transfer. The memory held by
* the libusb transfer is exposed through the managed buffer interface.
* Upon destruction, the transfer and buffer are resubmitted to the
- * endpoint for further use.
+ * endpoint for further use.
*/
class libusb_managed_recv_buffer_impl : public managed_recv_buffer {
public:
@@ -307,7 +310,7 @@ public:
private:
const boost::asio::const_buffer &get() const
{
- return _buff;
+ return _buff;
}
libusb_transfer *_lut;
@@ -327,9 +330,8 @@ private:
class libusb_managed_send_buffer_impl : public managed_send_buffer {
public:
libusb_managed_send_buffer_impl(libusb_transfer *lut,
- usb_endpoint::sptr endpoint,
- size_t buff_size)
- : _buff(lut->buffer, buff_size), _committed(false)
+ usb_endpoint::sptr endpoint)
+ : _buff(lut->buffer, lut->length), _committed(false)
{
_lut = lut;
_endpoint = endpoint;
@@ -349,7 +351,7 @@ public:
std::cerr << "UHD: send buffer already committed" << std::endl;
return 0;
}
-
+
UHD_ASSERT_THROW(num_bytes <= boost::asio::buffer_size(_buff));
_lut->length = num_bytes;
@@ -369,7 +371,7 @@ public:
private:
const boost::asio::mutable_buffer &get() const
{
- return _buff;
+ return _buff;
}
libusb_transfer *_lut;
@@ -385,61 +387,71 @@ private:
class libusb_zero_copy_impl : public usb_zero_copy
{
private:
- usb_endpoint::sptr _rx_ep, _tx_ep;
-
libusb::device_handle::sptr _handle;
-
- size_t _recv_buff_size;
- size_t _send_buff_size;
- size_t _num_frames;
+ size_t _recv_num_frames, _send_num_frames;
+ usb_endpoint::sptr _recv_ep, _send_ep;
public:
typedef boost::shared_ptr<libusb_zero_copy_impl> sptr;
- libusb_zero_copy_impl(libusb::device_handle::sptr handle,
- unsigned int rx_endpoint,
- unsigned int tx_endpoint,
- size_t recv_buff_size,
- size_t send_buff_size);
+ libusb_zero_copy_impl(
+ libusb::device_handle::sptr handle,
+ unsigned int recv_endpoint, unsigned int send_endpoint,
+ size_t recv_xfer_size, size_t recv_num_xfers,
+ size_t send_xfer_size, size_t send_num_xfers
+ );
managed_recv_buffer::sptr get_recv_buff(void);
managed_send_buffer::sptr get_send_buff(void);
- size_t get_num_recv_frames(void) const { return _num_frames; }
- size_t get_num_send_frames(void) const { return _num_frames; }
+ size_t get_num_recv_frames(void) const { return _recv_num_frames; }
+ size_t get_num_send_frames(void) const { return _send_num_frames; }
};
/*
* Constructor
* Initializes libusb, opens devices, and sets up interfaces for I/O.
- * Finally, creates endpoints for asynchronous I/O.
+ * Finally, creates endpoints for asynchronous I/O.
*/
-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)
- : _handle(handle),
- _recv_buff_size(block_size), _send_buff_size(block_size),
- _num_frames(buff_size / block_size)
-{
- _handle->claim_interface(2 /*in interface*/);
+libusb_zero_copy_impl::libusb_zero_copy_impl(
+ libusb::device_handle::sptr handle,
+ unsigned int recv_endpoint, unsigned int send_endpoint,
+ size_t recv_xfer_size, size_t recv_num_xfers,
+ size_t send_xfer_size, size_t send_num_xfers
+){
+ _handle = handle;
+
+ //if the sizes are left at 0 (automatic) -> use the defaults
+ if (recv_xfer_size == 0) recv_xfer_size = DEFAULT_XFER_SIZE;
+ if (recv_num_xfers == 0) recv_num_xfers = DEFAULT_NUM_XFERS;
+ if (send_xfer_size == 0) send_xfer_size = DEFAULT_XFER_SIZE;
+ if (send_num_xfers == 0) send_num_xfers = DEFAULT_NUM_XFERS;
+
+ //sanity check the transfer sizes
+ UHD_ASSERT_THROW(recv_xfer_size % 512 == 0);
+ UHD_ASSERT_THROW(send_xfer_size % 512 == 0);
+
+ //store the num xfers for the num frames count
+ _recv_num_frames = recv_num_xfers;
+ _send_num_frames = send_num_xfers;
+
+ _handle->claim_interface(2 /*in interface*/);
_handle->claim_interface(1 /*out interface*/);
- _rx_ep = usb_endpoint::sptr(new usb_endpoint(
+ _recv_ep = usb_endpoint::sptr(new usb_endpoint(
_handle, // libusb device_handle
- rx_endpoint, // USB endpoint number
+ recv_endpoint, // USB endpoint number
true, // IN endpoint
- _recv_buff_size, // buffer size per transfer
- _num_frames // number of libusb transfers
+ recv_xfer_size, // buffer size per transfer
+ recv_num_xfers // number of libusb transfers
));
- _tx_ep = usb_endpoint::sptr(new usb_endpoint(
+ _send_ep = usb_endpoint::sptr(new usb_endpoint(
_handle, // libusb device_handle
- tx_endpoint, // USB endpoint number
+ send_endpoint, // USB endpoint number
false, // OUT endpoint
- _send_buff_size, // buffer size per transfer
- _num_frames // number of libusb transfers
+ send_xfer_size, // buffer size per transfer
+ send_num_xfers // number of libusb transfers
));
}
@@ -447,17 +459,17 @@ libusb_zero_copy_impl::libusb_zero_copy_impl(libusb::device_handle::sptr handle,
* Construct a managed receive buffer from a completed libusb transfer
* (happy with buffer full of data) obtained from the receive endpoint.
* Return empty pointer if no transfer is available (timeout or error).
- * \return pointer to a managed receive buffer
+ * \return pointer to a managed receive buffer
*/
managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){
- libusb_transfer *lut = _rx_ep->get_lut_with_wait(/* TODO timeout API */);
+ libusb_transfer *lut = _recv_ep->get_lut_with_wait(/* TODO timeout API */);
if (lut == NULL) {
return managed_recv_buffer::sptr();
}
else {
return managed_recv_buffer::sptr(
new libusb_managed_recv_buffer_impl(lut,
- _rx_ep));
+ _recv_ep));
}
}
@@ -466,38 +478,36 @@ managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff(void){
* Construct a managed send buffer from a free libusb transfer (with
* empty buffer). Return empty pointer of no transfer is available
* (timeout or error).
- * \return pointer to a managed send buffer
+ * \return pointer to a managed send buffer
*/
managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff(void){
- libusb_transfer *lut = _tx_ep->get_lut_with_wait(/* TODO timeout API */);
+ libusb_transfer *lut = _send_ep->get_lut_with_wait(/* TODO timeout API */);
if (lut == NULL) {
return managed_send_buffer::sptr();
}
else {
return managed_send_buffer::sptr(
new libusb_managed_send_buffer_impl(lut,
- _tx_ep,
- _send_buff_size));
+ _send_ep));
}
}
-
/***********************************************************************
* USB zero_copy make functions
**********************************************************************/
-usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle,
- unsigned int rx_endpoint,
- unsigned int tx_endpoint,
- size_t buff_size,
- size_t block_size)
-
-{
+usb_zero_copy::sptr usb_zero_copy::make(
+ usb_device_handle::sptr handle,
+ unsigned int recv_endpoint, unsigned int send_endpoint,
+ size_t recv_xfer_size, size_t recv_num_xfers,
+ size_t send_xfer_size, size_t send_num_xfers
+){
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,
- block_size));
+ return sptr(new libusb_zero_copy_impl(
+ dev_handle,
+ recv_endpoint, send_endpoint,
+ recv_xfer_size, recv_num_xfers,
+ send_xfer_size, send_num_xfers
+ ));
}
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index b4c23bf12..793e3027d 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -30,6 +30,7 @@
#include <boost/assign/list_of.hpp>
#include <boost/filesystem.hpp>
#include <boost/thread/thread.hpp>
+#include <boost/lexical_cast.hpp>
#include <iostream>
using namespace uhd;
@@ -107,6 +108,15 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
/***********************************************************************
* Make
**********************************************************************/
+template<typename output_type> static output_type cast_from_dev_addr(
+ const device_addr_t &device_addr,
+ const std::string &key,
+ output_type def_val
+){
+ return (device_addr.has_key(key))?
+ boost::lexical_cast<output_type>(device_addr[key]) : def_val;
+}
+
static device::sptr usrp1_make(const device_addr_t &device_addr)
{
//extract the FPGA path for the USRP1
@@ -130,11 +140,15 @@ static device::sptr usrp1_make(const device_addr_t &device_addr)
usrp_ctrl = usrp_ctrl::make(ctrl_transport);
usrp_ctrl->usrp_load_fpga(usrp1_fpga_image);
- data_transport = usb_zero_copy::make(handle, // identifier
- 6, // IN endpoint
- 2, // OUT endpoint
- 2 * (1 << 20), // buffer size
- 16384); // transfer size
+ data_transport = usb_zero_copy::make(
+ handle, // identifier
+ 6, // IN endpoint
+ 2, // OUT endpoint
+ size_t(cast_from_dev_addr<double>(device_addr, "recv_xfer_size", 0)),
+ size_t(cast_from_dev_addr<double>(device_addr, "recv_num_xfers", 0)),
+ size_t(cast_from_dev_addr<double>(device_addr, "send_xfer_size", 0)),
+ size_t(cast_from_dev_addr<double>(device_addr, "send_num_xfers", 0))
+ );
break;
}
}
@@ -173,7 +187,7 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport,
//initialize the mboard
mboard_init();
- //initialize the dboards
+ //initialize the dboards
dboard_init();
//initialize the dsps