From c62085a66bd97f389f49167492f7dccfb0b02976 Mon Sep 17 00:00:00 2001 From: ttsou Date: Thu, 27 Aug 2009 18:13:54 -0400 Subject: [PATCH] first shot at re-adding libusb-0.12 support --- config/usrp_fusb_tech.m4 | 6 +- config/usrp_libusb.m4 | 4 +- usrp/host/include/usrp/usrp_basic.h | 12 +- usrp/host/include/usrp/usrp_prims.h | 96 ++-- usrp/host/lib/Makefile.am | 14 +- usrp/host/lib/fusb.h | 8 + usrp/host/lib/fusb_sysconfig_linux.cc | 6 + .../{usrp_basic.cc => usrp_basic_common.cc} | 89 +-- usrp/host/lib/usrp_basic_libusb.cc | 146 +++++ .../{usrp_prims.cc => usrp_prims_common.cc} | 544 +++--------------- usrp/host/lib/usrp_prims_libusb.cc | 490 ++++++++++++++++ 11 files changed, 810 insertions(+), 605 deletions(-) rename usrp/host/lib/{usrp_basic.cc => usrp_basic_common.cc} (92%) create mode 100644 usrp/host/lib/usrp_basic_libusb.cc rename usrp/host/lib/{usrp_prims.cc => usrp_prims_common.cc} (59%) create mode 100644 usrp/host/lib/usrp_prims_libusb.cc diff --git a/config/usrp_fusb_tech.m4 b/config/usrp_fusb_tech.m4 index bda6f5af..196799e3 100644 --- a/config/usrp_fusb_tech.m4 +++ b/config/usrp_fusb_tech.m4 @@ -37,9 +37,9 @@ AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[ [x_have_usbdevice_fs_h=yes], [x_have_usbdevice_fs_h=no]) if test x${x_have_usbdevice_fs_h} = xyes; then - FUSB_TECH=libusb1 + FUSB_TECH=linux else - FUSB_TECH=libusb1 + FUSB_TECH=generic fi ;; darwin*) @@ -69,7 +69,7 @@ AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[ AM_CONDITIONAL(FUSB_TECH_darwin, test x$FUSB_TECH = xdarwin) AM_CONDITIONAL(FUSB_TECH_win32, test x$FUSB_TECH = xwin32) AM_CONDITIONAL(FUSB_TECH_generic, test x$FUSB_TECH = xgeneric) - AM_CONDITIONAL(FUSB_TECH_libusb1, test x$FUSB_TECH = xlibusb1) AM_CONDITIONAL(FUSB_TECH_linux, test x$FUSB_TECH = xlinux) + AM_CONDITIONAL(FUSB_TECH_libusb1, test x$FUSB_TECH = xlibusb1) AM_CONDITIONAL(FUSB_TECH_ra_wb, test x$FUSB_TECH = xra_wb) ]) diff --git a/config/usrp_libusb.m4 b/config/usrp_libusb.m4 index 503df51e..cb3130c8 100644 --- a/config/usrp_libusb.m4 +++ b/config/usrp_libusb.m4 @@ -19,10 +19,10 @@ dnl Boston, MA 02110-1301, USA. AC_DEFUN([USRP_LIBUSB], [ libusbok=yes - PKG_CHECK_MODULES(USB, libusb-1.0, [], [ + PKG_CHECK_MODULES(USB, libusb, [], [ AC_LANG_PUSH(C) - AC_CHECK_HEADERS([libusb.h], [], [libusbok=no; AC_MSG_RESULT([USRP requires libusb1. usb.h not found. See http://libusb.sf.net])]) + AC_CHECK_HEADERS([usb.h], [], [libusbok=no; AC_MSG_RESULT([USRP requires libusb. usb.h not found. See http://libusb.sf.net])]) save_LIBS="$LIBS" case "$host_os" in diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h index 2430ff5c..3ec73411 100644 --- a/usrp/host/include/usrp/usrp_basic.h +++ b/usrp/host/include/usrp/usrp_basic.h @@ -46,7 +46,15 @@ #include #include +#if 1 +struct usb_dev_handle; +struct usb_device; +typedef struct usb_dev_handle libusb_device_handle; +typedef struct usb_device libusb_device; +#else struct libusb_device_handle; +#endif + class fusb_devhandle; class fusb_ephandle; @@ -65,7 +73,7 @@ protected: void shutdown_daughterboards(); protected: - struct libusb_device_handle *d_udh; + 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 @@ -92,7 +100,7 @@ protected: usrp_basic (int which_board, - struct libusb_device_handle *open_interface (struct libusb_device *dev), + libusb_device_handle *open_interface (libusb_device *dev), const std::string fpga_filename = "", const std::string firmware_filename = ""); diff --git a/usrp/host/include/usrp/usrp_prims.h b/usrp/host/include/usrp/usrp_prims.h index 05ad0046..bd7779b6 100644 --- a/usrp/host/include/usrp/usrp_prims.h +++ b/usrp/host/include/usrp/usrp_prims.h @@ -41,8 +41,16 @@ static const int USRP_HASH_SIZE = 16; enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; +#if 1 +struct usb_dev_handle; +struct usb_device; +typedef struct usb_dev_handle libusb_device_handle; +typedef struct usb_device libusb_device; +#else struct libusb_device_handle; struct libusb_device; +#endif + struct libusb_context; /*! @@ -54,6 +62,8 @@ struct libusb_context; */ libusb_context* usrp_one_time_init (bool new_context); +void usrp_one_time_init (); + /* * force a rescan of the buses and devices */ @@ -69,18 +79,18 @@ 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, libusb_context *ctx = NULL); +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 -bool usrp_usrp1_p (struct libusb_device *q); //< is this a USRP Rev 1 -bool usrp_usrp2_p (struct libusb_device *q); //< is this a USRP Rev 2 -int usrp_hw_rev (struct libusb_device *q); //< return h/w rev code +bool usrp_usrp_p (libusb_device *q); //< is this a USRP +bool usrp_usrp0_p (libusb_device *q); //< is this a USRP Rev 0 +bool usrp_usrp1_p (libusb_device *q); //< is this a USRP Rev 1 +bool usrp_usrp2_p (libusb_device *q); //< is this a USRP Rev 2 +int usrp_hw_rev (libusb_device *q); //< return h/w rev code -bool usrp_fx2_p (struct libusb_device *q); //< is this an unconfigured Cypress FX2 +bool usrp_fx2_p (libusb_device *q); //< is this an unconfigured Cypress FX2 -bool usrp_unconfigured_usrp_p (struct libusb_device *q); //< some kind of unconfigured USRP -bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configured USRP +bool usrp_unconfigured_usrp_p (libusb_device *q); //< some kind of unconfigured USRP +bool usrp_configured_usrp_p (libusb_device *q); //< some kind of configured USRP /*! * \brief given a libusb_device return an instance of the appropriate libusb_device_handle @@ -91,14 +101,14 @@ bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configur * If interface can't be opened, or is already claimed by some other * process, 0 is returned. */ -struct libusb_device_handle *usrp_open_cmd_interface (struct libusb_device *dev); -struct libusb_device_handle *usrp_open_rx_interface (struct libusb_device *dev); -struct libusb_device_handle *usrp_open_tx_interface (struct libusb_device *dev); +libusb_device_handle *usrp_open_cmd_interface (libusb_device *dev); +libusb_device_handle *usrp_open_rx_interface (libusb_device *dev); +libusb_device_handle *usrp_open_tx_interface (libusb_device *dev); /*! * \brief close interface. */ -bool usrp_close_interface (struct libusb_device_handle *udh); +bool usrp_close_interface (libusb_device_handle *udh); /*! * \brief load intel hex format file into USRP/Cypress FX2 (8051). @@ -110,7 +120,7 @@ bool usrp_close_interface (struct libusb_device_handle *udh); */ usrp_load_status_t -usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool force); +usrp_load_firmware (libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load intel hex format file into USRP FX2 (8051). @@ -123,13 +133,13 @@ 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, libusb_context *ctx); +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx = NULL); /*! * \brief load fpga configuration bitstream */ usrp_load_status_t -usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, bool force); +usrp_load_fpga (libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load the regular firmware and fpga bitstream in the Nth USRP. @@ -145,54 +155,54 @@ bool usrp_load_standard_bits (int nth, bool force, * \brief copy the given \p hash into the USRP hash slot \p which. * The usrp implements two hash slots, 0 and 1. */ -bool usrp_set_hash (struct libusb_device_handle *udh, int which, +bool usrp_set_hash (libusb_device_handle *udh, int which, const unsigned char hash[USRP_HASH_SIZE]); /*! * \brief retrieve the \p hash from the USRP hash slot \p which. * The usrp implements two hash slots, 0 and 1. */ -bool usrp_get_hash (struct libusb_device_handle *udh, int which, +bool usrp_get_hash (libusb_device_handle *udh, int which, unsigned char hash[USRP_HASH_SIZE]); -bool usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value); -bool usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value); -bool usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_led (struct libusb_device_handle *udh, int which, bool on); +bool usrp_write_fpga_reg (libusb_device_handle *udh, int reg, int value); +bool usrp_read_fpga_reg (libusb_device_handle *udh, int reg, int *value); +bool usrp_set_fpga_reset (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (libusb_device_handle *udh, bool on); +bool usrp_set_led (libusb_device_handle *udh, int which, bool on); -bool usrp_check_rx_overrun (struct libusb_device_handle *udh, bool *overrun_p); -bool usrp_check_tx_underrun (struct libusb_device_handle *udh, bool *underrun_p); +bool usrp_check_rx_overrun (libusb_device_handle *udh, bool *overrun_p); +bool usrp_check_tx_underrun (libusb_device_handle *udh, bool *underrun_p); // i2c_read and i2c_write are limited to a maximum len of 64 bytes. -bool usrp_i2c_write (struct libusb_device_handle *udh, int i2c_addr, +bool usrp_i2c_write (libusb_device_handle *udh, int i2c_addr, const void *buf, int len); -bool usrp_i2c_read (struct libusb_device_handle *udh, int i2c_addr, +bool usrp_i2c_read (libusb_device_handle *udh, int i2c_addr, void *buf, int len); // spi_read and spi_write are limited to a maximum of 64 bytes // See usrp_spi_defs.h for more info -bool usrp_spi_write (struct libusb_device_handle *udh, +bool usrp_spi_write (libusb_device_handle *udh, int optional_header, int enables, int format, const void *buf, int len); -bool usrp_spi_read (struct libusb_device_handle *udh, +bool usrp_spi_read (libusb_device_handle *udh, int optional_header, int enables, int format, void *buf, int len); -bool usrp_9862_write (struct libusb_device_handle *udh, +bool usrp_9862_write (libusb_device_handle *udh, int which_codec, // [0, 1] int regno, // [0, 63] int value); // [0, 255] -bool usrp_9862_read (struct libusb_device_handle *udh, +bool usrp_9862_read (libusb_device_handle *udh, int which_codec, // [0, 1] int regno, // [0, 63] unsigned char *value); // [0, 255] @@ -203,28 +213,28 @@ bool usrp_9862_read (struct libusb_device_handle *udh, * \p buf contains alternating register_number, register_value pairs. * \p len must be even and is the length of buf in bytes. */ -bool usrp_9862_write_many (struct libusb_device_handle *udh, int which_codec, +bool usrp_9862_write_many (libusb_device_handle *udh, int which_codec, const unsigned char *buf, int len); /*! * \brief write specified regs to all 9862's in the system */ -bool usrp_9862_write_many_all (struct libusb_device_handle *udh, +bool usrp_9862_write_many_all (libusb_device_handle *udh, const unsigned char *buf, int len); // Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard. // Which EEPROM is determined by i2c_addr. See i2c_addr.h -bool usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, +bool usrp_eeprom_write (libusb_device_handle *udh, int i2c_addr, int eeprom_offset, const void *buf, int len); // Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard. // Which EEPROM is determined by i2c_addr. See i2c_addr.h -bool usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, +bool usrp_eeprom_read (libusb_device_handle *udh, int i2c_addr, int eeprom_offset, void *buf, int len); @@ -246,7 +256,7 @@ bool usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, * binary values. Although dacs 0, 1 and 2 are 8-bit and dac 3 is 12-bit, * the interface is in terms of 12-bit values [0,4095] */ -bool usrp_write_aux_dac (struct libusb_device_handle *uhd, int slot, +bool usrp_write_aux_dac (libusb_device_handle *uhd, int slot, int which_dac, int value); /*! @@ -256,7 +266,7 @@ bool usrp_write_aux_dac (struct libusb_device_handle *uhd, int slot, * \p which_adc: [0,1] which of the two adcs to read * \p *value: return value, 12-bit straight binary. */ -bool usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, +bool usrp_read_aux_adc (libusb_device_handle *udh, int slot, int which_adc, int *value); @@ -279,13 +289,13 @@ struct usrp_dboard_eeprom { * \brief Read and return parsed daughterboard eeprom */ usrp_dbeeprom_status_t -usrp_read_dboard_eeprom (struct libusb_device_handle *udh, +usrp_read_dboard_eeprom (libusb_device_handle *udh, int slot_id, usrp_dboard_eeprom *eeprom); /*! * \brief write ADC/DAC offset calibration constants to d'board eeprom */ -bool usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, +bool usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, short offset0, short offset1); /*! @@ -294,6 +304,6 @@ bool usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, * Note that this only works on a configured usrp. * \returns non-zero length string iff successful. */ -std::string usrp_serial_number(struct libusb_device_handle *udh); +std::string usrp_serial_number(libusb_device_handle *udh); #endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index e7c3f34c..4dd47595 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -78,7 +78,9 @@ win32_CODE = \ linux_CODE = \ fusb_linux.cc \ - fusb_sysconfig_linux.cc + fusb_sysconfig_linux.cc \ + usrp_prims_libusb.cc \ + usrp_basic_libusb.cc ra_wb_CODE = \ fusb_ra_wb.cc \ @@ -86,7 +88,9 @@ ra_wb_CODE = \ libusb1_CODE = \ fusb_libusb1.cc \ - fusb_sysconfig_libusb1.cc + fusb_sysconfig_libusb1.cc \ + usrp_prims_libusb1.cc \ + usrp_basic_libusb1.cc # # include each _CODE entry here... @@ -103,17 +107,17 @@ EXTRA_libusrp_la_SOURCES = \ libusrp_la_common_SOURCES = \ fusb.cc \ md5.c \ - usrp_basic.cc \ + usrp_basic_common.cc \ usrp_config.cc \ usrp_dbid.cc \ usrp_local_sighandler.cc \ - usrp_prims.cc \ + usrp_prims_common.cc \ usrp_standard.cc \ db_boards.cc \ db_base.cc \ db_basic.cc \ db_tv_rx.cc \ - db_tv_rx_mimo.cc \ + db_tv_rx_mimo.cc \ db_flexrf.cc \ db_flexrf_mimo.cc \ db_dbs_rx.cc \ diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index fbd65120..24d2bee6 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -26,7 +26,13 @@ #define _FUSB_H_ +#if 1 +struct usb_dev_handle; +typedef struct usb_dev_handle libusb_device_handle; +#else struct libusb_device_handle; +#endif + struct libusb_context; class fusb_ephandle; @@ -120,6 +126,8 @@ public: static fusb_devhandle *make_devhandle (libusb_device_handle *udh, libusb_context *ctx); + static fusb_devhandle *make_devhandle (libusb_device_handle *udh); + /*! * \brief Returns max block size in bytes (hard limit). */ diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc index 3c2f5937..8f56f61e 100644 --- a/usrp/host/lib/fusb_sysconfig_linux.cc +++ b/usrp/host/lib/fusb_sysconfig_linux.cc @@ -33,6 +33,12 @@ fusb_sysconfig::make_devhandle (usb_dev_handle *udh) return new fusb_devhandle_linux (udh); } +fusb_devhandle * +fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) +{ + return new fusb_devhandle_linux (udh); +} + int fusb_sysconfig::max_block_size () { return MAX_BLOCK_SIZE; diff --git a/usrp/host/lib/usrp_basic.cc b/usrp/host/lib/usrp_basic_common.cc similarity index 92% rename from usrp/host/lib/usrp_basic.cc rename to usrp/host/lib/usrp_basic_common.cc index 3a036889..2579827e 100644 --- a/usrp/host/lib/usrp_basic.cc +++ b/usrp/host/lib/usrp_basic_common.cc @@ -31,7 +31,6 @@ #include "fpga_regs_standard.h" #include "fusb.h" #include "db_boards.h" -#include #include #include #include @@ -39,6 +38,12 @@ #include #include +#if 1 +#include +#else +#include +#endif + using namespace ad9862; #define NELEM(x) (sizeof (x) / sizeof (x[0])) @@ -55,20 +60,20 @@ static const double POLLING_INTERVAL = 0.1; // seconds //////////////////////////////////////////////////////////////// -static struct libusb_device_handle * -open_rx_interface (struct libusb_device *dev) +static libusb_device_handle * +open_rx_interface (libusb_device *dev) { - struct libusb_device_handle *udh = usrp_open_rx_interface (dev); + libusb_device_handle *udh = usrp_open_rx_interface (dev); if (udh == 0){ fprintf (stderr, "usrp_basic_rx: can't open rx interface\n"); } return udh; } -static struct libusb_device_handle * -open_tx_interface (struct libusb_device *dev) +static libusb_device_handle * +open_tx_interface (libusb_device *dev) { - struct libusb_device_handle *udh = usrp_open_tx_interface (dev); + libusb_device_handle *udh = usrp_open_tx_interface (dev); if (udh == 0){ fprintf (stderr, "usrp_basic_tx: can't open tx interface\n"); } @@ -102,60 +107,6 @@ static unsigned char common_regs[] = { REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 }; - -usrp_basic::usrp_basic (int which_board, - struct libusb_device_handle * - open_interface (struct libusb_device *dev), - const std::string fpga_filename, - const std::string firmware_filename) - : 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) -{ - /* - * SWAG: Scientific Wild Ass Guess. - * - * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. - * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., - * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the - * actual rate. This doesn't change our throughput, that's determined by the signal - * processing code in the FPGA (which we know nothing about), and the system limits - * determined by libusb, fusb_*, and the underlying drivers. - */ - memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); - - d_ctx = usrp_one_time_init(true); - - 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, 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"); - } - - if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ - fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); - throw std::runtime_error ("usrp_basic/bad_rev"); - } - - if ((d_udh = open_interface (dev)) == 0) - throw std::runtime_error ("usrp_basic/open_interface"); - - // initialize registers that are common to rx and tx - - if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ - fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); - throw std::runtime_error ("usrp_basic/init_9862"); - } - - _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode - _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs - -} - void usrp_basic::shutdown_daughterboards() { @@ -167,22 +118,6 @@ usrp_basic::shutdown_daughterboards() d_db[i][j]->shutdown(); } -usrp_basic::~usrp_basic () -{ - // shutdown_daughterboards(); // call from ~usrp_basic_{tx,rx} - - d_db.resize(0); // forget db shared ptrs - - if (d_udh) - libusb_close (d_udh); - - // Each object should be running in it's own context. If running in default - // (NULL) context then something went wrong. - - assert (d_ctx != NULL); - libusb_exit (d_ctx); -} - void usrp_basic::init_db(usrp_basic_sptr u) { diff --git a/usrp/host/lib/usrp_basic_libusb.cc b/usrp/host/lib/usrp_basic_libusb.cc new file mode 100644 index 00000000..296890b6 --- /dev/null +++ b/usrp/host/lib/usrp_basic_libusb.cc @@ -0,0 +1,146 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2008,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "usrp/usrp_prims.h" +#include "usrp_interfaces.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include "fusb.h" +#include "db_boards.h" +#include +#include +#include +#include +#include +#include +#include + + +using namespace ad9862; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// These set the buffer size used for each end point using the fast +// usb interface. The kernel ends up locking down this much memory. + +static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size(); +static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; + + +static const double POLLING_INTERVAL = 0.1; // seconds + + +////////////////////////////////////////////////////////////////// +// +// usrp_basic +// +//////////////////////////////////////////////////////////////// + + +// Given: +// CLKIN = 64 MHz +// CLKSEL pin = high +// +// These settings give us: +// CLKOUT1 = CLKIN = 64 MHz +// CLKOUT2 = CLKIN = 64 MHz +// ADC is clocked at 64 MHz +// DAC is clocked at 128 MHz + +static unsigned char common_regs[] = { + REG_GENERAL, 0, + REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC + | DLL_MULT_2X + | DLL_FAST), + REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, + REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 +}; + + +usrp_basic::usrp_basic (int which_board, + struct usb_dev_handle * + open_interface (struct usb_device *dev), + const std::string fpga_filename, + const std::string firmware_filename) + : d_udh (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) +{ + /* + * SWAG: Scientific Wild Ass Guess. + * + * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. + * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., + * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the + * actual rate. This doesn't change our throughput, that's determined by the signal + * processing code in the FPGA (which we know nothing about), and the system limits + * determined by libusb, fusb_*, and the underlying drivers. + */ + memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); + + usrp_one_time_init (); + + if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) + throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); + + struct usb_device *dev = usrp_find_device (which_board); + if (dev == 0){ + fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); + throw std::runtime_error ("usrp_basic/usrp_find_device"); + } + + if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ + fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); + throw std::runtime_error ("usrp_basic/bad_rev"); + } + + if ((d_udh = open_interface (dev)) == 0) + throw std::runtime_error ("usrp_basic/open_interface"); + + // initialize registers that are common to rx and tx + + if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ + fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); + throw std::runtime_error ("usrp_basic/init_9862"); + } + + _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode + _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs +} + +usrp_basic::~usrp_basic () +{ + // shutdown_daughterboards(); // call from ~usrp_basic_{tx,rx} + + d_db.resize(0); // forget db shared ptrs + + if (d_udh) + usb_close (d_udh); +} + diff --git a/usrp/host/lib/usrp_prims.cc b/usrp/host/lib/usrp_prims_common.cc similarity index 59% rename from usrp/host/lib/usrp_prims.cc rename to usrp/host/lib/usrp_prims_common.cc index d651a452..4b695bec 100644 --- a/usrp/host/lib/usrp_prims.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -30,7 +30,6 @@ #include "usrp_i2c_addr.h" #include "fpga_regs_common.h" #include "fpga_regs_standard.h" -#include #include #include #include @@ -42,6 +41,12 @@ #include #include +#if 1 +#include +#else +#include +#endif + extern "C" { #include "md5.h" }; @@ -61,10 +66,23 @@ static const int hash_slot_addr[2] = { static const char *default_firmware_filename = "std.ihx"; static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; +/* + * Forward Declarations + */ + +bool _usrp_configured_p (libusb_device *q); +libusb_device_handle *usrp_open_interface(libusb_device *dev, + int interface, + int altinterface); +bool write_internal_ram (libusb_device_handle *udh, unsigned char *buf, + int start_addr, size_t len); +int write_cmd (libusb_device_handle *udh, int request, int value, + int index, unsigned char *bytes, int len); + #include "std_paths.h" #include -static char * +char * find_file (const char *filename, int hw_rev) { const char **sp = std_paths; @@ -87,7 +105,7 @@ find_file (const char *filename, int hw_rev) return 0; } -static const char * +const char * get_proto_filename(const std::string user_filename, const char *env_var, const char *def) { if (user_filename.length() != 0) @@ -101,250 +119,65 @@ get_proto_filename(const std::string user_filename, const char *env_var, const c } -static void power_down_9862s (struct libusb_device_handle *udh); - -libusb_context * -usrp_one_time_init (bool new_context) -{ - - static bool first = true; - libusb_context *ctx = NULL; - int ret; - - // 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; - 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 -usrp_rescan () -{ - // deprecated? -} +void power_down_9862s (libusb_device_handle *udh); // ---------------------------------------------------------------- -/* - * q must be a real USRP, not an FX2. Return its hardware rev number. - */ -int -usrp_hw_rev (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return desc.bcdDevice & 0x00FF; -} - -/* - * q must be a real USRP, not an FX2. Return true if it's configured. - */ -static bool -_usrp_configured_p (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return (desc.bcdDevice & 0xFF00) != 0; -} - bool -usrp_usrp_p (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return (desc.idVendor == USB_VID_FSF - && desc.idProduct == USB_PID_FSF_USRP); -} - -bool -usrp_fx2_p (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return (desc.idVendor == USB_VID_CYPRESS - && desc.idProduct == USB_PID_CYPRESS_FX2); -} - -bool -usrp_usrp0_p (struct libusb_device *q) +usrp_usrp0_p (libusb_device *q) { return usrp_usrp_p (q) && usrp_hw_rev (q) == 0; } bool -usrp_usrp1_p (struct libusb_device *q) +usrp_usrp1_p (libusb_device *q) { return usrp_usrp_p (q) && usrp_hw_rev (q) == 1; } bool -usrp_usrp2_p (struct libusb_device *q) +usrp_usrp2_p (libusb_device *q) { return usrp_usrp_p (q) && usrp_hw_rev (q) == 2; } bool -usrp_unconfigured_usrp_p (struct libusb_device *q) +usrp_unconfigured_usrp_p (libusb_device *q) { return usrp_usrp_p (q) && !_usrp_configured_p (q); } bool -usrp_configured_usrp_p (struct libusb_device *q) +usrp_configured_usrp_p (libusb_device *q) { return usrp_usrp_p (q) && _usrp_configured_p (q); } -// ---------------------------------------------------------------- - -struct libusb_device * -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 (false); - assert (ctx != NULL); - - size_t cnt = libusb_get_device_list(ctx, &list); - size_t i = 0; - - if (cnt < 0) - fprintf(stderr, "usrp: libusb_get_device_list failed %d\n", cnt); - - for (i = 0; i < cnt; i++) { - q = list[i]; - if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))) { - if (n_found == nth) // return this one - return q; - n_found++; // keep looking - } - } - -/* - * 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 struct libusb_device_handle * -usrp_open_interface (struct libusb_device *dev, int interface, int altinterface) -{ - struct libusb_device_handle *udh; - int ret; - - if (libusb_open (dev, &udh) < 0) - return 0; - - if (dev != libusb_get_device (udh)){ - fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); - abort (); - } - - if ((ret = libusb_claim_interface (udh, interface)) < 0) { - fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); - fprintf (stderr, "%d\n", ret); - libusb_close (udh); - return 0; - } - - if ((ret = libusb_set_interface_alt_setting (udh, interface, - altinterface)) < 0) { - fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); - fprintf (stderr, "%d\n", ret); - libusb_release_interface (udh, interface); - libusb_close (udh); - return 0; - } - - return udh; -} - -struct libusb_device_handle * -usrp_open_cmd_interface (struct libusb_device *dev) +libusb_device_handle * +usrp_open_cmd_interface (libusb_device *dev) { return usrp_open_interface (dev, USRP_CMD_INTERFACE, USRP_CMD_ALTINTERFACE); } -struct libusb_device_handle * -usrp_open_rx_interface (struct libusb_device *dev) +libusb_device_handle * +usrp_open_rx_interface (libusb_device *dev) { return usrp_open_interface (dev, USRP_RX_INTERFACE, USRP_RX_ALTINTERFACE); } -struct libusb_device_handle * -usrp_open_tx_interface (struct libusb_device *dev) +libusb_device_handle * +usrp_open_tx_interface (libusb_device *dev) { return usrp_open_interface (dev, USRP_TX_INTERFACE, USRP_TX_ALTINTERFACE); } -bool -usrp_close_interface (struct libusb_device_handle *udh) -{ - // returns void - libusb_close(udh); - return 0; -} - -// ---------------------------------------------------------------- -// write internal ram using Cypress vendor extension - -static bool -write_internal_ram (struct libusb_device_handle *udh, unsigned char *buf, - int start_addr, size_t len) -{ - int addr; - int n; - int a; - int quanta = MAX_EP0_PKTSIZE; - - for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ - n = len + start_addr - addr; - if (n > quanta) - n = quanta; - - a = libusb_control_transfer (udh, 0x40, 0xA0, - addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000); - - if (a < 0){ - fprintf(stderr,"write_internal_ram failed: %u\n", a); - return false; - } - } - return true; -} // ---------------------------------------------------------------- // whack the CPUCS register using the upload RAM vendor extension static bool -reset_cpu (struct libusb_device_handle *udh, bool reset_p) +reset_cpu (libusb_device_handle *udh, bool reset_p) { unsigned char v; @@ -360,7 +193,7 @@ reset_cpu (struct libusb_device_handle *udh, bool reset_p) // Load intel format file into cypress FX2 (8051) static bool -_usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, +_usrp_load_firmware (libusb_device_handle *udh, const char *filename, unsigned char hash[USRP_HASH_SIZE]) { FILE *f = fopen (filename, "ra"); @@ -438,34 +271,11 @@ _usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, return false; } -// ---------------------------------------------------------------- -// write vendor extension command to USRP - -static int -write_cmd (struct libusb_device_handle *udh, - int request, int value, int index, - unsigned char *bytes, int len) -{ - int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT; - - int r = libusb_control_transfer(udh, requesttype, request, value, index, - (unsigned char *) bytes, len, 1000); - - if (r < 0){ - // we get EPIPE if the firmware stalls the endpoint. - if (r != LIBUSB_ERROR_PIPE) { - fprintf (stderr, "libusb_control_transfer failed: %i\n", r); - } - } - - return r; -} - // ---------------------------------------------------------------- // load fpga static bool -_usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, +_usrp_load_fpga (libusb_device_handle *udh, const char *filename, unsigned char hash[USRP_HASH_SIZE]) { bool ok = true; @@ -543,46 +353,22 @@ _usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, // ---------------------------------------------------------------- bool -usrp_set_led (struct libusb_device_handle *udh, int which, bool on) +usrp_set_led (libusb_device_handle *udh, int which, bool on) { int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0); return r == 0; } -bool -usrp_set_hash (struct libusb_device_handle *udh, int which, - const unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware down load command to jam it in. - int r = libusb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} bool -usrp_get_hash (struct libusb_device_handle *udh, int which, - unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware upload command to fetch it. - int r = libusb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} - -static bool -usrp_set_switch (struct libusb_device_handle *udh, int cmd_byte, bool on) +usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on) { return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0; } - -static bool -usrp1_fpga_write (struct libusb_device_handle *udh, +bool +usrp1_fpga_write (libusb_device_handle *udh, int regno, int value) { // on the rev1 usrp, we use the generic spi_write interface @@ -600,8 +386,8 @@ usrp1_fpga_write (struct libusb_device_handle *udh, buf, sizeof (buf)); } -static bool -usrp1_fpga_read (struct libusb_device_handle *udh, +bool +usrp1_fpga_read (libusb_device_handle *udh, int regno, int *value) { *value = 0; @@ -619,56 +405,32 @@ usrp1_fpga_read (struct libusb_device_handle *udh, } -bool -usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value) -{ - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_write (udh, reg, value); - } -} - -bool -usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value) -{ - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_read (udh, reg, value); - } -} - bool -usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on) +usrp_set_fpga_reset (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on); } bool -usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on) +usrp_set_fpga_tx_enable (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on); } bool -usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on) +usrp_set_fpga_rx_enable (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on); } bool -usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on) +usrp_set_fpga_tx_reset (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on); } bool -usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on) +usrp_set_fpga_rx_reset (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on); } @@ -695,11 +457,11 @@ compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE]) } static usrp_load_status_t -usrp_conditionally_load_something (struct libusb_device_handle *udh, +usrp_conditionally_load_something (libusb_device_handle *udh, const char *filename, bool force, int slot, - bool loader (struct libusb_device_handle *, + bool loader (libusb_device_handle *, const char *, unsigned char [USRP_HASH_SIZE])) { @@ -728,7 +490,7 @@ usrp_conditionally_load_something (struct libusb_device_handle *udh, } usrp_load_status_t -usrp_load_firmware (struct libusb_device_handle *udh, +usrp_load_firmware (libusb_device_handle *udh, const char *filename, bool force) { @@ -738,7 +500,7 @@ usrp_load_firmware (struct libusb_device_handle *udh, } usrp_load_status_t -usrp_load_fpga (struct libusb_device_handle *udh, +usrp_load_fpga (libusb_device_handle *udh, const char *filename, bool force) { @@ -747,30 +509,7 @@ usrp_load_fpga (struct libusb_device_handle *udh, _usrp_load_fpga); } -static libusb_device_handle * -open_nth_cmd_interface (int nth, libusb_context *ctx) -{ - - 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; - } - - struct libusb_device_handle *udh; - - udh = usrp_open_cmd_interface (udev); - if (udh == 0){ - // FIXME this could be because somebody else has it open. - // We should delay and retry... - fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); - return 0; - } - - return udh; - } - -static bool +bool our_nanosleep (const struct timespec *delay) { struct timespec new_delay = *delay; @@ -798,45 +537,7 @@ mdelay (int millisecs) return our_nanosleep (&ts); } -usrp_load_status_t -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; - - usrp_load_status_t s = usrp_load_firmware (udh, filename, force); - usrp_close_interface (udh); - - switch (s){ - - case ULS_ALREADY_LOADED: // nothing changed... - return ULS_ALREADY_LOADED; - break; - - case ULS_OK: - // we loaded firmware successfully. - - // It's highly likely that the board will renumerate (simulate a - // disconnect/reconnect sequence), invalidating our current - // handle. - - // FIXME. Turn this into a loop that rescans until we refind ourselves - - struct timespec t; // delay for 1 second - t.tv_sec = 2; - t.tv_nsec = 0; - our_nanosleep (&t); - - return ULS_OK; - - default: - case ULS_ERROR: // some kind of problem - return ULS_ERROR; - } -} - -static void +void load_status_msg (usrp_load_status_t s, const char *type, const char *filename) { char *e = getenv("USRP_VERBOSE"); @@ -860,72 +561,7 @@ 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, - 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, false, ctx); - if (udev == 0){ - fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); - return false; - } - hw_rev = usrp_hw_rev (udev); - } - - // start by loading the firmware - - proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", - default_firmware_filename); - filename = find_file(proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find firmware: %s\n", proto_filename); - return false; - } - s = usrp_load_firmware_nth (nth, filename, force, ctx); - load_status_msg (s, "firmware", filename); - - if (s == ULS_ERROR) - return false; - - // if we actually loaded firmware, we must reload fpga ... - if (s == ULS_OK) - force = true; - - // now move on to the fpga configuration bitstream - - proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", - default_fpga_filename); - filename = find_file (proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); - return false; - } - struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); - if (udh == 0) - return false; - - s = usrp_load_fpga (udh, filename, force); - usrp_close_interface (udh); - load_status_msg (s, "fpga bitstream", filename); - - if (s == ULS_ERROR) - return false; - - return true; -} - -bool -_usrp_get_status (struct libusb_device_handle *udh, int which, bool *trouble) +_usrp_get_status (libusb_device_handle *udh, int which, bool *trouble) { unsigned char status; *trouble = true; @@ -939,20 +575,20 @@ _usrp_get_status (struct libusb_device_handle *udh, int which, bool *trouble) } bool -usrp_check_rx_overrun (struct libusb_device_handle *udh, bool *overrun_p) +usrp_check_rx_overrun (libusb_device_handle *udh, bool *overrun_p) { return _usrp_get_status (udh, GS_RX_OVERRUN, overrun_p); } bool -usrp_check_tx_underrun (struct libusb_device_handle *udh, bool *underrun_p) +usrp_check_tx_underrun (libusb_device_handle *udh, bool *underrun_p) { return _usrp_get_status (udh, GS_TX_UNDERRUN, underrun_p); } bool -usrp_i2c_write (struct libusb_device_handle *udh, int i2c_addr, +usrp_i2c_write (libusb_device_handle *udh, int i2c_addr, const void *buf, int len) { if (len < 1 || len > MAX_EP0_PKTSIZE) @@ -964,7 +600,7 @@ usrp_i2c_write (struct libusb_device_handle *udh, int i2c_addr, bool -usrp_i2c_read (struct libusb_device_handle *udh, int i2c_addr, +usrp_i2c_read (libusb_device_handle *udh, int i2c_addr, void *buf, int len) { if (len < 1 || len > MAX_EP0_PKTSIZE) @@ -975,7 +611,7 @@ usrp_i2c_read (struct libusb_device_handle *udh, int i2c_addr, } bool -usrp_spi_write (struct libusb_device_handle *udh, +usrp_spi_write (libusb_device_handle *udh, int optional_header, int enables, int format, const void *buf, int len) { @@ -990,7 +626,7 @@ usrp_spi_write (struct libusb_device_handle *udh, bool -usrp_spi_read (struct libusb_device_handle *udh, +usrp_spi_read (libusb_device_handle *udh, int optional_header, int enables, int format, void *buf, int len) { @@ -1004,7 +640,7 @@ usrp_spi_read (struct libusb_device_handle *udh, } bool -usrp_9862_write (struct libusb_device_handle *udh, int which_codec, +usrp_9862_write (libusb_device_handle *udh, int which_codec, int regno, int value) { if (0) @@ -1022,7 +658,7 @@ usrp_9862_write (struct libusb_device_handle *udh, int which_codec, } bool -usrp_9862_read (struct libusb_device_handle *udh, int which_codec, +usrp_9862_read (libusb_device_handle *udh, int which_codec, int regno, unsigned char *value) { return usrp_spi_read (udh, 0x80 | (regno & 0x3f), @@ -1032,7 +668,7 @@ usrp_9862_read (struct libusb_device_handle *udh, int which_codec, } bool -usrp_9862_write_many (struct libusb_device_handle *udh, +usrp_9862_write_many (libusb_device_handle *udh, int which_codec, const unsigned char *buf, int len) @@ -1053,7 +689,7 @@ usrp_9862_write_many (struct libusb_device_handle *udh, bool -usrp_9862_write_many_all (struct libusb_device_handle *udh, +usrp_9862_write_many_all (libusb_device_handle *udh, const unsigned char *buf, int len) { // FIXME handle 2/2 and 4/4 versions @@ -1064,31 +700,11 @@ usrp_9862_write_many_all (struct libusb_device_handle *udh, return result; } -static void -power_down_9862s (struct libusb_device_handle *udh) -{ - static const unsigned char regs[] = { - REG_RX_PWR_DN, 0x01, // everything - REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both - REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled - }; - - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: - break; - - default: - usrp_9862_write_many_all (udh, regs, sizeof (regs)); - break; - } -} - - static const int EEPROM_PAGESIZE = 16; bool -usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, +usrp_eeprom_write (libusb_device_handle *udh, int i2c_addr, int eeprom_offset, const void *buf, int len) { unsigned char cmd[2]; @@ -1113,7 +729,7 @@ usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, } bool -usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, +usrp_eeprom_read (libusb_device_handle *udh, int i2c_addr, int eeprom_offset, void *buf, int len) { unsigned char *p = (unsigned char *) buf; @@ -1175,7 +791,7 @@ tx_slot_p (int slot) } bool -usrp_write_aux_dac (struct libusb_device_handle *udh, int slot, +usrp_write_aux_dac (libusb_device_handle *udh, int slot, int which_dac, int value) { int which_codec; @@ -1206,7 +822,7 @@ usrp_write_aux_dac (struct libusb_device_handle *udh, int slot, bool -usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, +usrp_read_aux_adc (libusb_device_handle *udh, int slot, int which_adc, int *value) { *value = 0; @@ -1285,7 +901,7 @@ set_chksum (unsigned char *buf) } static usrp_dbeeprom_status_t -read_dboard_eeprom (struct libusb_device_handle *udh, +read_dboard_eeprom (libusb_device_handle *udh, int slot_id, unsigned char *buf) { int i2c_addr = slot_to_i2c_addr (slot_id); @@ -1309,7 +925,7 @@ read_dboard_eeprom (struct libusb_device_handle *udh, } usrp_dbeeprom_status_t -usrp_read_dboard_eeprom (struct libusb_device_handle *udh, +usrp_read_dboard_eeprom (libusb_device_handle *udh, int slot_id, usrp_dboard_eeprom *eeprom) { unsigned char buf[DB_EEPROM_CLEN]; @@ -1329,7 +945,7 @@ usrp_read_dboard_eeprom (struct libusb_device_handle *udh, } bool -usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, +usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, short offset0, short offset1) { unsigned char buf[DB_EEPROM_CLEN]; @@ -1347,21 +963,3 @@ usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, return usrp_eeprom_write (udh, slot_to_i2c_addr (slot_id), 0, buf, sizeof (buf)); } - -std::string -usrp_serial_number(struct libusb_device_handle *udh) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(libusb_get_device(udh), &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - unsigned char iserial = desc.iSerialNumber; - if (iserial == 0) - return ""; - - unsigned char buf[1024]; - if (libusb_get_string_descriptor_ascii(udh, iserial, buf, sizeof(buf)) < 0) - return ""; - - return (char*) buf; -} diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc new file mode 100644 index 00000000..841d447a --- /dev/null +++ b/usrp/host/lib/usrp_prims_libusb.cc @@ -0,0 +1,490 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2006,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "usrp/usrp_prims.h" +#include "usrp_commands.h" +#include "usrp_ids.h" +#include "usrp_i2c_addr.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include +#include +#include +#include +#include +#include +#include +#include // FIXME should check with autoconf (nanosleep) +#include +#include +#include + +extern "C" { +#include "md5.h" +}; + +#define VERBOSE 0 + +using namespace ad9862; + +/* + * Forward Declarations + */ + +bool our_nanosleep (const struct timespec *delay); +const char *get_proto_filename (const std::string user_filename, + const char *env_var, + const char *def); +char *find_file (const char *filename, int hw_rev); +void load_status_msg (usrp_load_status_t s, const char *type, + const char *filename); +bool usrp1_fpga_write (libusb_device_handle *udh, int regno, int value); +bool usrp1_fpga_read (libusb_device_handle *udh, int regno, int *value); +bool usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on); + +bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on); + + + +static const int FIRMWARE_HASH_SLOT = 0; +static const int FPGA_HASH_SLOT = 1; + +static const int hash_slot_addr[2] = { + USRP_HASH_SLOT_0_ADDR, + USRP_HASH_SLOT_1_ADDR +}; + +static const char *default_firmware_filename = "std.ihx"; +static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; + +#include "std_paths.h" +#include + +void +usrp_one_time_init () +{ + static bool first = true; + + if (first){ + first = false; + usb_init (); // usb library init + usb_find_busses (); + usb_find_devices (); + } +} + +void +usrp_rescan () +{ + usb_find_busses (); + usb_find_devices (); +} + +// ---------------------------------------------------------------- + +/* + * q must be a real USRP, not an FX2. Return its hardware rev number. + */ +int +usrp_hw_rev (struct usb_device *q) +{ + return q->descriptor.bcdDevice & 0x00FF; +} + +/* + * q must be a real USRP, not an FX2. Return true if it's configured. + */ +static bool +_usrp_configured_p (struct usb_device *q) +{ + return (q->descriptor.bcdDevice & 0xFF00) != 0; +} + +bool +usrp_usrp_p (struct usb_device *q) +{ + return (q->descriptor.idVendor == USB_VID_FSF + && q->descriptor.idProduct == USB_PID_FSF_USRP); +} + +bool +usrp_fx2_p (struct usb_device *q) +{ + return (q->descriptor.idVendor == USB_VID_CYPRESS + && q->descriptor.idProduct == USB_PID_CYPRESS_FX2); +} + +// ---------------------------------------------------------------- + +struct usb_device * +usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) +{ + struct usb_bus *p; + struct usb_device *q; + int n_found = 0; + + usrp_one_time_init (); + + p = usb_get_busses(); + while (p != NULL){ + q = p->devices; + while (q != NULL){ + if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){ + if (n_found == nth) // return this one + return q; + n_found++; // keep looking + } + q = q->next; + } + p = p->next; + } + return 0; // not found +} + +struct usb_dev_handle * +usrp_open_interface (struct usb_device *dev, int interface, int altinterface) +{ + struct usb_dev_handle *udh = usb_open (dev); + if (udh == 0) + return 0; + + if (dev != usb_device (udh)){ + fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); + abort (); + } + +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + // There's no get get_configuration function, and with some of the newer kernels + // setting the configuration, even if to the same value, hoses any other processes + // that have it open. Hence we opt to not set it at all (We've only + // got a single configuration anyway). This may hose the win32 stuff... + + // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06 + if (usb_set_configuration (udh, 1) < 0){ + /* + * Ignore this error. + * + * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that + * it returns -EBUSY if _any_ of the interfaces of a device are open. + * We've only got a single configuration, so setting it doesn't even seem + * like it should be required. + */ + } +#endif + + if (usb_claim_interface (udh, interface) < 0){ + fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); + fprintf (stderr, "%s\n", usb_strerror()); + usb_close (udh); + return 0; + } + + if (usb_set_altinterface (udh, altinterface) < 0){ + fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); + fprintf (stderr, "%s\n", usb_strerror()); + usb_release_interface (udh, interface); + usb_close (udh); + return 0; + } + + return udh; +} + +bool +usrp_close_interface (struct usb_dev_handle *udh) +{ + // we're assuming that closing an interface automatically releases it. + return usb_close (udh) == 0; +} + +// ---------------------------------------------------------------- +// write internal ram using Cypress vendor extension + +bool +write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf, + int start_addr, size_t len) +{ + int addr; + int n; + int a; + int quanta = MAX_EP0_PKTSIZE; + + for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ + n = len + start_addr - addr; + if (n > quanta) + n = quanta; + + a = usb_control_msg (udh, 0x40, 0xA0, + addr, 0, (char *)(buf + (addr - start_addr)), n, 1000); + + if (a < 0){ + fprintf(stderr,"write_internal_ram failed: %s\n", usb_strerror()); + return false; + } + } + return true; +} + + +// ---------------------------------------------------------------- +// write vendor extension command to USRP + +int +write_cmd (struct usb_dev_handle *udh, + int request, int value, int index, + unsigned char *bytes, int len) +{ + int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT; + + int r = usb_control_msg (udh, requesttype, request, value, index, + (char *) bytes, len, 1000); + if (r < 0){ + // we get EPIPE if the firmware stalls the endpoint. + if (errno != EPIPE) + fprintf (stderr, "usb_control_msg failed: %s\n", usb_strerror ()); + } + + return r; +} + + +bool +usrp_set_hash (struct usb_dev_handle *udh, int which, + const unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware down load command to jam it in. + int r = usb_control_msg (udh, 0x40, 0xa0, hash_slot_addr[which], 0, + (char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_get_hash (struct usb_dev_handle *udh, int which, + unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware upload command to fetch it. + int r = usb_control_msg (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, + (char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value) +{ + switch (usrp_hw_rev (usb_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_write (udh, reg, value); + } +} + +bool +usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value) +{ + switch (usrp_hw_rev (usb_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_read (udh, reg, value); + } +} + + + + +static usb_dev_handle * +open_nth_cmd_interface (int nth) +{ + struct usb_device *udev = usrp_find_device (nth); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return 0; + } + + struct usb_dev_handle *udh; + + udh = usrp_open_cmd_interface (udev); + if (udh == 0){ + // FIXME this could be because somebody else has it open. + // We should delay and retry... + fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); + usb_strerror (); + return 0; + } + + return udh; +} + + +usrp_load_status_t +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx){ + struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + if (udh == 0) + return ULS_ERROR; + + usrp_load_status_t s = usrp_load_firmware (udh, filename, force); + usrp_close_interface (udh); + + switch (s){ + + case ULS_ALREADY_LOADED: // nothing changed... + return ULS_ALREADY_LOADED; + break; + + case ULS_OK: + // we loaded firmware successfully. + + // It's highly likely that the board will renumerate (simulate a + // disconnect/reconnect sequence), invalidating our current + // handle. + + // FIXME. Turn this into a loop that rescans until we refind ourselves + + struct timespec t; // delay for 1 second + t.tv_sec = 2; + t.tv_nsec = 0; + our_nanosleep (&t); + + usb_find_busses (); // rescan busses and devices + usb_find_devices (); + + return ULS_OK; + + default: + case ULS_ERROR: // some kind of problem + return ULS_ERROR; + } +} + +bool +usrp_load_standard_bits (int nth, bool force, + const std::string fpga_filename, + const std::string firmware_filename, + libusb_context *ctx) +{ + usrp_load_status_t s; + const char *filename; + const char *proto_filename; + int hw_rev; + + // first, figure out what hardware rev we're dealing with + { + struct usb_device *udev = usrp_find_device (nth); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return false; + } + hw_rev = usrp_hw_rev (udev); + } + + // start by loading the firmware + + proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", + default_firmware_filename); + filename = find_file(proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find firmware: %s\n", proto_filename); + return false; + } + + s = usrp_load_firmware_nth (nth, filename, force); + load_status_msg (s, "firmware", filename); + + if (s == ULS_ERROR) + return false; + + // if we actually loaded firmware, we must reload fpga ... + if (s == ULS_OK) + force = true; + + // now move on to the fpga configuration bitstream + + proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", + default_fpga_filename); + filename = find_file (proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); + return false; + } + + struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + if (udh == 0) + return false; + + s = usrp_load_fpga (udh, filename, force); + usrp_close_interface (udh); + load_status_msg (s, "fpga bitstream", filename); + + if (s == ULS_ERROR) + return false; + + return true; +} + +void +power_down_9862s (struct usb_dev_handle *udh) +{ + static const unsigned char regs[] = { + REG_RX_PWR_DN, 0x01, // everything + REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both + REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled + }; + + switch (usrp_hw_rev (usb_device (udh))){ + case 0: + break; + + default: + usrp_9862_write_many_all (udh, regs, sizeof (regs)); + break; + } +} + + +std::string +usrp_serial_number(struct usb_dev_handle *udh) +{ + unsigned char iserial = usb_device(udh)->descriptor.iSerialNumber; + if (iserial == 0) + return ""; + + char buf[1024]; + if (usb_get_string_simple(udh, iserial, buf, sizeof(buf)) < 0) + return ""; + + return buf; +} -- 2.30.2