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;
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
* 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
* 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
*/
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.
struct libusb_device_handle;
+struct libusb_context;
class fusb_ephandle;
/*!
/*!
* \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).
// 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
}
}
+/*
+ * 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 ()
{
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;
}
bool
fusb_ephandle_libusb1::start ()
{
-
if (d_started)
return true;
}
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;
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;
}
// ------------------------------------------------------------------------
int
fusb_ephandle_libusb1::write (const void *buffer, int nbytes)
{
-
if (!d_started) // doesn't matter here, but keeps semantics constant
return -1;
d_write_work_in_progress = 0;
}
- return nbytes;
+ return n;
}
#else
return lut;
}
- // Do work, reap transfers, etc.
- libusb_handle_events(NULL);
+ if (!d_devhandle->_reap (true))
+ return 0;
}
}
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,
#include <list>
struct libusb_transfer;
+struct libusb_context;
+
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 ();
public:
// CREATORS
- fusb_devhandle_libusb1 (libusb_device_handle *udh);
+ fusb_devhandle_libusb1 (libusb_device_handle *udh, libusb_context *ctx);
virtual ~fusb_devhandle_libusb1 ();
// MANIPULATORS
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
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 ()
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)
*/
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");
_write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode
_write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs
+
}
void
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
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);
fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n");
return false;
}
-
+
return true;
}
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);
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
// ----------------------------------------------------------------
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)
}
}
+/*
+ * The list needs to be freed. Right just release it if nothing is found.
+ */
+
libusb_free_device_list(list, 1);
+
return 0; // not found
}
}
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;
}
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;
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;
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)
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;