summaryrefslogtreecommitdiff
path: root/usrp
diff options
context:
space:
mode:
authorttsou2009-08-25 14:53:34 -0400
committerttsou2009-09-15 18:06:27 -0400
commit0854c4604fcbdb64c74e4b93b87ac07be3d75f55 (patch)
tree87e5e80a7c38cd6a1d3f27b2a2e1e64e385ec2eb /usrp
parentb5aa407ec2b1bdebc1c950a9428789fe50327776 (diff)
downloadgnuradio-0854c4604fcbdb64c74e4b93b87ac07be3d75f55.tar.gz
gnuradio-0854c4604fcbdb64c74e4b93b87ac07be3d75f55.tar.bz2
gnuradio-0854c4604fcbdb64c74e4b93b87ac07be3d75f55.zip
Fix for simultaneous tx-rx using libusb_contexts
Diffstat (limited to 'usrp')
-rw-r--r--usrp/host/include/usrp/usrp_basic.h1
-rw-r--r--usrp/host/include/usrp/usrp_prims.h15
-rw-r--r--usrp/host/lib/fusb.h4
-rw-r--r--usrp/host/lib/fusb_libusb1.cc67
-rw-r--r--usrp/host/lib/fusb_libusb1.h8
-rw-r--r--usrp/host/lib/fusb_sysconfig_libusb1.cc6
-rw-r--r--usrp/host/lib/usrp_basic.cc24
-rw-r--r--usrp/host/lib/usrp_prims.cc60
8 files changed, 112 insertions, 73 deletions
diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h
index c79908a86..2430ff5c4 100644
--- a/usrp/host/include/usrp/usrp_basic.h
+++ b/usrp/host/include/usrp/usrp_basic.h
@@ -66,6 +66,7 @@ protected:
protected:
struct libusb_device_handle *d_udh;
+ struct libusb_context *d_ctx;
int d_usb_data_rate; // bytes/sec
int d_bytes_per_poll; // how often to poll for overruns
bool d_verbose;
diff --git a/usrp/host/include/usrp/usrp_prims.h b/usrp/host/include/usrp/usrp_prims.h
index df410b408..05ad0046e 100644
--- a/usrp/host/include/usrp/usrp_prims.h
+++ b/usrp/host/include/usrp/usrp_prims.h
@@ -43,12 +43,16 @@ enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED };
struct libusb_device_handle;
struct libusb_device;
+struct libusb_context;
/*!
* \brief initialize libusb; probe busses and devices.
- * Safe to call more than once.
+ * If new_context is set to true, initiate and returns new libusb_context.
+ * If new_context is set to false, intiate default context if not already
+ * initiated and return NULL. It is NOT safe to call more than once with
+ * new_context set to true since a new context is initiated each time.
*/
-void usrp_one_time_init ();
+libusb_context* usrp_one_time_init (bool new_context);
/*
* force a rescan of the buses and devices
@@ -65,7 +69,7 @@ void usrp_rescan ();
* configured USRP (firmware loaded)
* unconfigured Cypress FX2 (only if fx2_ok_p is true)
*/
-struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false);
+struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, libusb_context *ctx = NULL);
bool usrp_usrp_p (struct libusb_device *q); //< is this a USRP
bool usrp_usrp0_p (struct libusb_device *q); //< is this a USRP Rev 0
@@ -119,7 +123,7 @@ usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool
* then rescans the busses and devices.
*/
usrp_load_status_t
-usrp_load_firmware_nth (int nth, const char *filename, bool force);
+usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx);
/*!
* \brief load fpga configuration bitstream
@@ -134,7 +138,8 @@ usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, bool for
*/
bool usrp_load_standard_bits (int nth, bool force,
const std::string fpga_filename = "",
- const std::string firmware_filename = "");
+ const std::string firmware_filename = "",
+ libusb_context *ctx = NULL);
/*!
* \brief copy the given \p hash into the USRP hash slot \p which.
diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h
index bfe34d5b8..fbd651204 100644
--- a/usrp/host/lib/fusb.h
+++ b/usrp/host/lib/fusb.h
@@ -27,6 +27,7 @@
struct libusb_device_handle;
+struct libusb_context;
class fusb_ephandle;
/*!
@@ -116,7 +117,8 @@ public:
/*!
* \brief returns fusb_devhandle or throws if trouble
*/
- static fusb_devhandle *make_devhandle (libusb_device_handle *udh);
+ static fusb_devhandle *make_devhandle (libusb_device_handle *udh,
+ libusb_context *ctx);
/*!
* \brief Returns max block size in bytes (hard limit).
diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc
index 07e05c230..0559022bb 100644
--- a/usrp/host/lib/fusb_libusb1.cc
+++ b/usrp/host/lib/fusb_libusb1.cc
@@ -124,8 +124,9 @@ alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint,
// device handle
// ------------------------------------------------------------------------
-fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh)
- : fusb_devhandle (udh), d_teardown (false)
+fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh,
+ libusb_context *ctx)
+ : fusb_devhandle (udh), d_ctx (ctx), d_teardown (false)
{
// that's it
}
@@ -258,6 +259,24 @@ fusb_devhandle_libusb1::_cancel_lut (libusb_transfer *lut)
}
+/*
+ * Reimplementing _reap for context use and compatibiliy with libusb-0.12.
+ * Returns false on error, true otherwise.
+ */
+
+bool
+fusb_devhandle_libusb1::_reap (bool ok_to_block_p)
+{
+ int ret;
+
+ if ((ret = libusb_handle_events(d_ctx)) < 0) {
+ fprintf (stderr, "fusb::_reap libusb_handle_events()\n");
+ return false;
+ }
+
+ return true;
+}
+
void
fusb_devhandle_libusb1::_wait_for_completion ()
{
@@ -267,17 +286,9 @@ fusb_devhandle_libusb1::_wait_for_completion ()
tv.tv_sec = 1;
tv.tv_usec = 0;
- // The regular libusb_handle_events sets a hardcoded timeout of 2
- // seconds. Most of these calls should be changed to appropriate block / non-
- // blocking version using libusb_handle_events_timeout. This was just a test
- // usage.
-
- while (!d_pending_rqsts.empty ()) {
- if ((ret = libusb_handle_events_timeout(NULL, &tv)) < 0) {
- fprintf (stderr, "fusb: libusb_handle_events error %d\n", ret);
- break;
- }
- }
+ while (!d_pending_rqsts.empty ())
+ if (!_reap(true))
+ break;
}
@@ -346,7 +357,6 @@ fusb_ephandle_libusb1::~fusb_ephandle_libusb1 ()
bool
fusb_ephandle_libusb1::start ()
{
-
if (d_started)
return true;
@@ -390,12 +400,7 @@ fusb_ephandle_libusb1::stop ()
}
d_devhandle->_cancel_pending_rqsts (this);
-
- // Do work, reap transfers, etc.
- if (libusb_handle_events(NULL) < 0) {
- perror ("fusb::libusb_handle_events");
- return false;
- }
+ d_devhandle->_reap (false);
while (1) {
libusb_transfer *lut;
@@ -405,15 +410,13 @@ fusb_ephandle_libusb1::stop ()
if (d_free_list.size () == (unsigned) d_nblocks)
break;
- if (libusb_handle_events(NULL) < 0) {
- perror ("fusb::libusb_handle_events");
- return false;
- }
+ if (!d_devhandle->_reap(true))
+ break;
}
d_started = false;
- return true;
+ return true;
}
// ------------------------------------------------------------------------
@@ -425,7 +428,6 @@ fusb_ephandle_libusb1::stop ()
int
fusb_ephandle_libusb1::write (const void *buffer, int nbytes)
{
-
if (!d_started) // doesn't matter here, but keeps semantics constant
return -1;
@@ -456,7 +458,7 @@ fusb_ephandle_libusb1::write (const void *buffer, int nbytes)
d_write_work_in_progress = 0;
}
- return nbytes;
+ return n;
}
#else
@@ -515,8 +517,8 @@ fusb_ephandle_libusb1::get_write_work_in_progress ()
return lut;
}
- // Do work, reap transfers, etc.
- libusb_handle_events(NULL);
+ if (!d_devhandle->_reap (true))
+ return 0;
}
}
@@ -603,10 +605,9 @@ fusb_ephandle_libusb1::reload_read_buffer ()
while (1) {
- while ((lut = completed_list_get ()) == 0 ) {
- if (libusb_handle_events(NULL) < 0)
- fprintf (stderr, "fusb: libusb_handle_events\n");
- }
+ while ((lut = completed_list_get ()) == 0 )
+ if (!d_devhandle->_reap(true))
+ return false;
if (lut->status != LIBUSB_TRANSFER_COMPLETED) {
fprintf (stderr, "fust: (rd status %d) %s\n", lut->status,
diff --git a/usrp/host/lib/fusb_libusb1.h b/usrp/host/lib/fusb_libusb1.h
index 1661b7ab8..4bc49aafb 100644
--- a/usrp/host/lib/fusb_libusb1.h
+++ b/usrp/host/lib/fusb_libusb1.h
@@ -27,6 +27,8 @@
#include <list>
struct libusb_transfer;
+struct libusb_context;
+
class fusb_ephandle_libusb1;
/*!
@@ -35,7 +37,8 @@ class fusb_ephandle_libusb1;
class fusb_devhandle_libusb1 : public fusb_devhandle
{
private:
- std::list<libusb_transfer*> d_pending_rqsts;
+ std::list<libusb_transfer*> d_pending_rqsts;
+ libusb_context *d_ctx;
void pending_add (struct libusb_transfer *lut);
struct libusb_transfer * pending_get ();
@@ -44,7 +47,7 @@ private:
public:
// CREATORS
- fusb_devhandle_libusb1 (libusb_device_handle *udh);
+ fusb_devhandle_libusb1 (libusb_device_handle *udh, libusb_context *ctx);
virtual ~fusb_devhandle_libusb1 ();
// MANIPULATORS
@@ -54,6 +57,7 @@ public:
bool _submit_lut (libusb_transfer *);
bool _cancel_lut (libusb_transfer *);
void _cancel_pending_rqsts (fusb_ephandle_libusb1 *eph);
+ bool _reap (bool ok_to_block_p);
void _wait_for_completion ();
// accessors to work from callback context
diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc
index e0d9458e1..c82bfe9a1 100644
--- a/usrp/host/lib/fusb_sysconfig_libusb1.cc
+++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc
@@ -27,10 +27,12 @@ static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit
static const int DEFAULT_BLOCK_SIZE = 4 * 1024;
static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB
+struct libusb_context;
+
fusb_devhandle *
-fusb_sysconfig::make_devhandle (libusb_device_handle *udh)
+fusb_sysconfig::make_devhandle (libusb_device_handle *udh, libusb_context *ctx)
{
- return new fusb_devhandle_libusb1 (udh);
+ return new fusb_devhandle_libusb1 (udh, ctx);
}
int fusb_sysconfig::max_block_size ()
diff --git a/usrp/host/lib/usrp_basic.cc b/usrp/host/lib/usrp_basic.cc
index a8b44edab..3a0368894 100644
--- a/usrp/host/lib/usrp_basic.cc
+++ b/usrp/host/lib/usrp_basic.cc
@@ -108,7 +108,7 @@ usrp_basic::usrp_basic (int which_board,
open_interface (struct libusb_device *dev),
const std::string fpga_filename,
const std::string firmware_filename)
- : d_udh (0),
+ : d_udh (0), d_ctx (0),
d_usb_data_rate (16000000), // SWAG, see below
d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)),
d_verbose (false), d_fpga_master_clock_freq(64000000), d_db(2)
@@ -125,12 +125,12 @@ usrp_basic::usrp_basic (int which_board,
*/
memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows));
- usrp_one_time_init ();
+ d_ctx = usrp_one_time_init(true);
- if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename))
+ if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename, d_ctx))
throw std::runtime_error ("usrp_basic/usrp_load_standard_bits");
- struct libusb_device *dev = usrp_find_device (which_board);
+ struct libusb_device *dev = usrp_find_device (which_board, false, d_ctx);
if (dev == 0){
fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board);
throw std::runtime_error ("usrp_basic/usrp_find_device");
@@ -153,6 +153,7 @@ usrp_basic::usrp_basic (int which_board,
_write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode
_write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs
+
}
void
@@ -175,12 +176,11 @@ usrp_basic::~usrp_basic ()
if (d_udh)
libusb_close (d_udh);
- // There's no reference count on the number of times libusb is initialized.
- // libusb_init can be called multiple times, but libusb_exit shuts down
- // everything. Leave libusb running for now. Need to add a count so that it
- // exits nicely.
+ // Each object should be running in it's own context. If running in default
+ // (NULL) context then something went wrong.
- //libusb_exit (NULL);
+ assert (d_ctx != NULL);
+ libusb_exit (d_ctx);
}
void
@@ -819,7 +819,7 @@ usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nbl
if (fusb_nblocks == 0)
fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size);
- d_devhandle = fusb_sysconfig::make_devhandle (d_udh);
+ d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx);
d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true,
fusb_block_size, fusb_nblocks);
@@ -870,7 +870,7 @@ usrp_basic_rx::start ()
fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n");
return false;
}
-
+
return true;
}
@@ -1222,7 +1222,7 @@ usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nbl
if (fusb_nblocks == 0)
fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size);
- d_devhandle = fusb_sysconfig::make_devhandle (d_udh);
+ d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx);
d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false,
fusb_block_size, fusb_nblocks);
diff --git a/usrp/host/lib/usrp_prims.cc b/usrp/host/lib/usrp_prims.cc
index e1e3e3074..d651a4529 100644
--- a/usrp/host/lib/usrp_prims.cc
+++ b/usrp/host/lib/usrp_prims.cc
@@ -103,15 +103,30 @@ get_proto_filename(const std::string user_filename, const char *env_var, const c
static void power_down_9862s (struct libusb_device_handle *udh);
-void
-usrp_one_time_init ()
+libusb_context *
+usrp_one_time_init (bool new_context)
{
+
static bool first = true;
+ libusb_context *ctx = NULL;
+ int ret;
- if (first){
+ // On first call create default context in addition to any new requested
+ // context. The default context is probably useless in this form, but keep
+ // it for now due to compatibility reasons.
+
+ if (first) {
first = false;
- libusb_init (NULL); // usb library init
+ if ((ret = libusb_init (NULL)) < 0)
+ fprintf (stderr, "usrp: libusb_init failed %i\n", ret);
}
+
+ if (new_context) {
+ if ((ret = libusb_init (&ctx)) < 0)
+ fprintf (stderr, "usrp: libusb_init failed %i\n", ret);
+ }
+
+ return ctx;
}
void
@@ -204,16 +219,17 @@ usrp_configured_usrp_p (struct libusb_device *q)
// ----------------------------------------------------------------
struct libusb_device *
-usrp_find_device (int nth, bool fx2_ok_p)
+usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx)
{
libusb_device **list;
struct libusb_device *q;
int n_found = 0;
- usrp_one_time_init ();
-
- size_t cnt = libusb_get_device_list(NULL, &list);
+//usrp_one_time_init (false);
+ assert (ctx != NULL);
+
+ size_t cnt = libusb_get_device_list(ctx, &list);
size_t i = 0;
if (cnt < 0)
@@ -228,7 +244,12 @@ usrp_find_device (int nth, bool fx2_ok_p)
}
}
+/*
+ * The list needs to be freed. Right just release it if nothing is found.
+ */
+
libusb_free_device_list(list, 1);
+
return 0; // not found
}
@@ -727,9 +748,10 @@ usrp_load_fpga (struct libusb_device_handle *udh,
}
static libusb_device_handle *
-open_nth_cmd_interface (int nth)
+open_nth_cmd_interface (int nth, libusb_context *ctx)
{
- struct libusb_device *udev = usrp_find_device (nth);
+
+ struct libusb_device *udev = usrp_find_device (nth, false, ctx);
if (udev == 0){
fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
return 0;
@@ -777,8 +799,9 @@ mdelay (int millisecs)
}
usrp_load_status_t
-usrp_load_firmware_nth (int nth, const char *filename, bool force){
- struct libusb_device_handle *udh = open_nth_cmd_interface (nth);
+usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx)
+{
+ struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx);
if (udh == 0)
return ULS_ERROR;
@@ -839,16 +862,19 @@ load_status_msg (usrp_load_status_t s, const char *type, const char *filename)
bool
usrp_load_standard_bits (int nth, bool force,
const std::string fpga_filename,
- const std::string firmware_filename)
+ const std::string firmware_filename,
+ libusb_context *ctx)
{
usrp_load_status_t s;
const char *filename;
const char *proto_filename;
int hw_rev;
+ assert (ctx != NULL);
+
// first, figure out what hardware rev we're dealing with
{
- struct libusb_device *udev = usrp_find_device (nth);
+ struct libusb_device *udev = usrp_find_device (nth, false, ctx);
if (udev == 0){
fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth);
return false;
@@ -865,8 +891,7 @@ usrp_load_standard_bits (int nth, bool force,
fprintf (stderr, "Can't find firmware: %s\n", proto_filename);
return false;
}
-
- s = usrp_load_firmware_nth (nth, filename, force);
+ s = usrp_load_firmware_nth (nth, filename, force, ctx);
load_status_msg (s, "firmware", filename);
if (s == ULS_ERROR)
@@ -885,8 +910,7 @@ usrp_load_standard_bits (int nth, bool force,
fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename);
return false;
}
-
- struct libusb_device_handle *udh = open_nth_cmd_interface (nth);
+ struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx);
if (udh == 0)
return false;