diff options
author | ttsou | 2009-08-25 14:53:34 -0400 |
---|---|---|
committer | ttsou | 2009-09-15 18:06:27 -0400 |
commit | 0854c4604fcbdb64c74e4b93b87ac07be3d75f55 (patch) | |
tree | 87e5e80a7c38cd6a1d3f27b2a2e1e64e385ec2eb /usrp | |
parent | b5aa407ec2b1bdebc1c950a9428789fe50327776 (diff) | |
download | gnuradio-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.h | 1 | ||||
-rw-r--r-- | usrp/host/include/usrp/usrp_prims.h | 15 | ||||
-rw-r--r-- | usrp/host/lib/fusb.h | 4 | ||||
-rw-r--r-- | usrp/host/lib/fusb_libusb1.cc | 67 | ||||
-rw-r--r-- | usrp/host/lib/fusb_libusb1.h | 8 | ||||
-rw-r--r-- | usrp/host/lib/fusb_sysconfig_libusb1.cc | 6 | ||||
-rw-r--r-- | usrp/host/lib/usrp_basic.cc | 24 | ||||
-rw-r--r-- | usrp/host/lib/usrp_prims.cc | 60 |
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; |