diff --git a/host/common/include/thread.h b/host/common/include/thread.h new file mode 100644 index 000000000..d7dcb7112 --- /dev/null +++ b/host/common/include/thread.h @@ -0,0 +1,69 @@ +/** + * @file thread.h + * + * @brief Threading portability and debug wrappers + * + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (c) 2014 Nuand LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef BLADERF_THREAD_H_ +#define BLADERF_THREAD_H_ + +/* Currently, only pthreads is supported. In the future, native windows threads + * may be used; one of the objectives of this file is to ease that transistion. + */ +#include +#include "rel_assert.h" + +#define MUTEX pthread_mutex_t + +#ifdef ENABLE_LOCK_CHECKS +# define MUTEX_INIT(m) do { \ + int status; \ + pthread_mutexattr_t mutex_attr; \ + status = pthread_mutexattr_init(&mutex_attr); \ + assert(status == 0 && "Mutex attr init failure"); \ + status = pthread_mutexattr_settype(&mutex_attr, \ + PTHREAD_MUTEX_ERRORCHECK); \ + assert(status == 0 && "Mutex attr setype failure"); \ + status = pthread_mutex_init(m, &mutex_attr); \ + assert(status == 0 && "Mutex init failure"); \ + } while (0) + +# define MUTEX_LOCK(m) do { \ + int status = pthread_mutex_lock(m); \ + assert(status == 0 && "Mutex lock failure");\ + } while (0) + +# define MUTEX_UNLOCK(m) do { \ + int status = pthread_mutex_unlock(m); \ + assert(status == 0 && "Mutex unlock failure");\ + } while (0) + +#else +# define MUTEX_INIT(m) pthread_mutex_init(m, NULL) +# define MUTEX_LOCK(m) pthread_mutex_lock(m) +# define MUTEX_UNLOCK(m) pthread_mutex_unlock(m) +#endif + +#endif diff --git a/host/libraries/libbladeRF/CMakeLists.txt b/host/libraries/libbladeRF/CMakeLists.txt index 17673ccf7..dcd22ec10 100644 --- a/host/libraries/libbladeRF/CMakeLists.txt +++ b/host/libraries/libbladeRF/CMakeLists.txt @@ -17,6 +17,10 @@ else(MSVC) endif() endif(MSVC) +if (NOT HAVE_THREADS) + message(FATAL_ERROR "pthreads not found. This is required to build libbladeRF.") +endif() + ################################################################################ # Version information ################################################################################ @@ -69,16 +73,16 @@ if(NOT ${BUILD_DOCUMENTATION}) set(BUILD_LIBBLADERF_DOCUMENTATION OFF) endif() -option(ENABLE_LIBBLADERF_SYNC - "Enable the libbladeRF synchronous data interface. Requires pthreads." - ${HAVE_THREADS} -) - option(ENABLE_LIBBLADERF_SYNC_LOG_VERBOSE "Enable log_verbose() calls in the sync interface's data path. Note that this may harm performance." OFF ) +option(ENABLE_LOCK_CHECKS + "Enable checks for lock acquisition failures (e.g., deadlock)" + OFF +) + ############################## # Backend Support ############################## @@ -128,6 +132,9 @@ if(ENABLE_LIBBLADERF_LOGGING) add_definitions(-DLOGGING_ENABLED) endif() +if(ENABLE_LOCK_CHECKS) + add_definitions(-DENABLE_LOCK_CHECKS) +endif() if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" ) @@ -179,18 +186,9 @@ if(ENABLE_BACKEND_LIBUSB) endif(NOT LIBUSB_FOUND) endif(ENABLE_BACKEND_LIBUSB) -if(ENABLE_LIBBLADERF_SYNC) - if(MSVC) - set(LIBBLADERF_INCLUDES ${LIBBLADERF_INCLUDES} - ${LIBPTHREADSWIN32_INCLUDE_DIRS}) - endif() - - add_definitions(-DENABLE_LIBBLADERF_SYNC) - - if(ENABLE_LIBBLADERF_SYNC_LOG_VERBOSE AND ENABLE_LIBBLADERF_LOGGING) - add_definitions(-DENABLE_LIBBLADERF_SYNC_LOG_VERBOSE) - endif() -endif(ENABLE_LIBBLADERF_SYNC) +if(ENABLE_LIBBLADERF_SYNC_LOG_VERBOSE AND ENABLE_LIBBLADERF_LOGGING) + add_definitions(-DENABLE_LIBBLADERF_SYNC_LOG_VERBOSE) +endif() include_directories(${LIBBLADERF_INCLUDES}) @@ -205,6 +203,7 @@ set(LIBBLADERF_SOURCE src/config.c src/dc_cal_table.c src/file_ops.c + src/fpga.c src/lms.c src/si5338.c src/xb.c @@ -212,7 +211,10 @@ set(LIBBLADERF_SOURCE src/device_identifier.c src/devinfo.c src/flash.c + src/flash_fields.c src/image.c + src/sync.c + src/sync_worker.c src/version_compat.c ${BLADERF_HOST_COMMON_SOURCE_DIR}/sha256.c ${BLADERF_HOST_COMMON_SOURCE_DIR}/conversions.c @@ -239,23 +241,16 @@ if(ENABLE_BACKEND_LINUX_DRIVER) set(LIBBLADERF_SOURCE ${LIBBLADERF_SOURCE} src/backend/linux.c) endif() -if(ENABLE_LIBBLADERF_SYNC) +if(BLADERF_OS_OSX) set(LIBBLADERF_SOURCE ${LIBBLADERF_SOURCE} - src/sync.c - src/sync_worker.c + ${BLADERF_HOST_COMMON_SOURCE_DIR}/osx/clock_gettime.c ) +endif() - if(BLADERF_OS_OSX) - set(LIBBLADERF_SOURCE ${LIBBLADERF_SOURCE} - ${BLADERF_HOST_COMMON_SOURCE_DIR}/osx/clock_gettime.c - ) - endif() - - if(MSVC) - set(LIBBLADERF_SOURCE ${LIBBLADERF_SOURCE} - ${BLADERF_HOST_COMMON_SOURCE_DIR}/windows/clock_gettime.c - ) - endif() +if(MSVC) + set(LIBBLADERF_SOURCE ${LIBBLADERF_SOURCE} + ${BLADERF_HOST_COMMON_SOURCE_DIR}/windows/clock_gettime.c + ) endif() add_library(libbladerf_shared SHARED ${LIBBLADERF_SOURCE}) diff --git a/host/libraries/libbladeRF/include/libbladeRF.h b/host/libraries/libbladeRF/include/libbladeRF.h index f5a50484e..9d92d8ffe 100644 --- a/host/libraries/libbladeRF/include/libbladeRF.h +++ b/host/libraries/libbladeRF/include/libbladeRF.h @@ -84,9 +84,10 @@ extern "C" { /** * @defgroup FN_INIT Initialization/deinitialization * - * @bug These functions are not currently thread-safe. This will be addressed - * in future revisions of the library. The caller is responsible for ensuring - * these functions are called in a thread-safe manner. + * The functions in this section provide the ability query available devices, + * initialize them, and deinitialize them. They are not guaranteed to be + * thread-safe; the caller is responsible for ensuring they are executed + * atomically. * * @{ */ @@ -215,7 +216,7 @@ int CALL_CONV bladerf_open(struct bladerf **device, /** * Close device * - * @note Failing to close a device may result in memory leaks. + * @note Failing to close a device will result in memory leaks. * * @post device is deallocated and may no longer be used. * @@ -230,6 +231,10 @@ void CALL_CONV bladerf_close(struct bladerf *device); /** * @defgroup FN_DEVINFO Device identifier information functions * + * As the functions in this section do not operate on a device, there are no + * internal thread-safety concerns. The caller only needs to ensure the + * function parameters are not modified while these functions are executing. + * * @{ */ @@ -245,13 +250,10 @@ void CALL_CONV bladerf_init_devinfo(struct bladerf_devinfo *info); /** * Fill out a provided bladerf_devinfo structure, given an open device handle. + * This function is thread-safe. * * @pre dev must be a valid device handle. * - * @bug This function is not currently thread-safe. This will be addressed - * in future revisions of the library. The caller is responsible for ensuring - * this function are called in a thread-safe manner. - * * @param[in] dev Device handle previously obtained with bladerf_open() * @param[out] info Device information populated by this function * @@ -320,10 +322,8 @@ const char * CALL_CONV bladerf_backend_str(bladerf_backend backend); /** * @defgroup FN_CTRL Device control and configuration * - * @bug These functions are not currently thread-safe. This will be addressed - * in future revisions of the library. The caller is responsible for ensuring - * these functions are called in a thread-safe manner. Generally, this implies - * locking access to a device handle when making control/configuration calls. + * This section provides functions pertaining to accessing, controlling, and + * configuring various device options and parameters. * * @{ */ @@ -1101,7 +1101,10 @@ int CALL_CONV bladerf_xb200_get_path(struct bladerf *dev, /** @} (End of FN_CTRL) */ /** - * @defgroup FMT_META Formats and Metadata + * @defgroup FMT_META Sample Formats and Metadata + * + * This section defines the available sample formats and metadata flags. + * * @{ */ @@ -1222,30 +1225,6 @@ struct bladerf_metadata { * and to only use this interface if the former is found to not yield suitable * performance. * - * When using this interface, one must be aware of thread-safety implications. - * Internally, this interface does not enforce thread-safe access to device - * handles; API users are responsible for this. - * - * However, it easy to avoid thread-safety issues if the following guidelines are - * adhered to: - * - Divide threads that access the bladeRF device into two types: control and - * data streaming. - * - * - Only perform device configuration and control calls from the control - * thread(s). If multiple threads are performing control calls, lock accesses - * to device handles. Here, "control calls" effectively includes all API - * calls take a bladerf device handle, except for: bladerf_init_stream(), - * bladerf_stream(), and bladerf_deinit_stream(). These three calls are "data - * streaming" calls. - * - * - Only access a bladerf_stream within a streaming thread context, and only - * use the data streaming calls in this context. - * - * - Do not make API calls from stream callbacks. - * - * bladerf_submit_stream_buffer() is a special case, as this will acquire a - * per-stream lock before submitting a buffer for transfer. - * * @{ */ @@ -1276,12 +1255,6 @@ struct bladerf_stream; * single approach of returning buffers or returning * BLADERF_STREAM_NO_DATA and submitting buffers later -- but not both. * - * In most use-cases, stream callbacks will be executing in a thread that is - * separate from the thread used to configure device parameters. Because this - * interface does not currently ensure thread safe accesses to devices, - * callbacks being handled in different threads must not make make API - * calls. - * * When running in a full-duplex mode of operation with simultaneous TX and RX * stream threads, be aware that one module's callback may occur in the context * of another module's thread. The API user is responsible for ensuring their @@ -1318,7 +1291,6 @@ struct bladerf_stream; * which should be `num_samples` in size, * BLADERF_STREAM_SHUTDOWN, or BLADERF_STREAM_NO_DATA. * - * */ typedef void *(*bladerf_stream_cb)(struct bladerf *dev, struct bladerf_stream *stream, @@ -1357,15 +1329,14 @@ typedef void *(*bladerf_stream_cb)(struct bladerf *dev, * Sample\ Rate > \frac{\#\ Transfers}{Timeout} \times Buffer\ Size * @f] * + * ...where Sample Rate is in samples per second, and Timeout is in seconds. + * * To account for general system overhead, it is recommended to multiply the * righthand side by 1.1 to 1.25. * * While increasing the number of buffers available provides additional * elasticity, be aware that it also increases latency. * - * @bug This function is not currently thread-safe. Callers should ensure other - * threads are not accessing the `dev` handle when this call is made. - * * @param[out] stream Upon success, this will be updated to contain * a stream handle (i.e., address) * @@ -1482,10 +1453,6 @@ void CALL_CONV bladerf_deinit_stream(struct bladerf_stream *stream); /** * Set stream transfer timeout in milliseconds * - * @bug This call is not threadsafe; this will be addressed in future - * versions of the library. Callers should ensure no other threads - * are accessing the specified device handle when this call is made. - * * @param dev Device handle * @param module Module to adjust * @param timeout Timeout in milliseconds @@ -1501,10 +1468,6 @@ int CALL_CONV bladerf_set_stream_timeout(struct bladerf *dev, /** * Get transfer timeout in milliseconds * - * @bug This call is not threadsafe; this will be addressed in future - * versions of the library. Callers should ensure no other threads - * are accessing the specified device handle when this call is made. - * * @param[in] dev Device handle * @param[in] module Module to adjust * @param[out] timeout On success, updated with current transfer @@ -1530,11 +1493,6 @@ int CALL_CONV bladerf_get_stream_timeout(struct bladerf *dev, * Under the hood, this interface spawns worker threads to handle an * asynchronous stream and perform thread-safe buffer management. * - * This interface requires libbladeRF to be built with pthreads support. Without - * pthreads support, all functions in this section of the API will return an - * BLADERF_ERR_UNSUPPORTED. - * - * * Below is the general process for using this interface: * * @code{.c} @@ -1600,6 +1558,8 @@ int CALL_CONV bladerf_get_stream_timeout(struct bladerf *dev, * to bladerf_sync_config() for the BLADERF_MODULE_TX module, enable the TX * module via bladerf_enable_module(), and then make calls to bladerf_sync_tx(). * + * These functions are thread-safe. + * * @{ */ @@ -1624,10 +1584,6 @@ int CALL_CONV bladerf_get_stream_timeout(struct bladerf *dev, * The `num_buffers` parameter should generally be increased as the amount of * work done between bladerf_sync_rx() or bladerf_sync_tx() calls increases. * - * @bug This call is not threadsafe; this will be addressed in future - * versions of the library. Callers should ensure no other threads - * are accessing the specified device handle when this call is made. - * * @param dev Device to configure * * @param module Module to use with synchronous interface @@ -1747,9 +1703,8 @@ int CALL_CONV bladerf_sync_rx(struct bladerf *dev, /** * @defgroup FN_INFO Device info * - * @bug These functions are not currently thread-safe. This will be addressed - * in future revisions of the library. The caller is responsible for ensuring - * these functions are called in a thread-safe manner. + * These functions provide the ability to query various pieces of information + * from an attached device. They are thread-safe. * * @{ */ @@ -1867,9 +1822,8 @@ bladerf_dev_speed CALL_CONV bladerf_device_speed(struct bladerf *dev); /** * @defgroup FN_PROG Device loading and programming * - * @bug These functions are not currently thread-safe. This will be addressed - * in future revisions of the library. The caller is responsible for ensuring - * these functions are called in a thread-safe manner. + * These functions provide the ability to load and program devices + * on the bladeRF board. They are thread-safe. * * @{ */ @@ -1935,8 +1889,6 @@ int CALL_CONV bladerf_device_reset(struct bladerf *dev); /** * Jump to FX3 bootloader * - * @note This also causes the device to jump to the FX3 bootloader - * * @param dev Device handle * * @return 0 on success, value from \ref RETCODES list on failure @@ -2000,7 +1952,7 @@ void CALL_CONV bladerf_log_set_verbosity(bladerf_log_level level); * @defgroup FN_IMAGE Flash image format * * This section contains a file format and associated routines for storing - * and loading flash contents with metadata + * and loading flash contents with metadata. * * @{ */ @@ -2208,19 +2160,15 @@ int CALL_CONV bladerf_image_read(struct bladerf_image *image, const char *file); * @defgroup LOW_LEVEL Low-level development and testing routines * * In a most cases, higher-level routines should be used. These routines are - * only intended to support development and testing. Treat these routines as - * if they may disappear in future revision of the API; do not depend on them - * for any long-term software. + * only intended to support development and testing. * * Use these routines with great care, and be sure to reference the relevant - * schematics, datasheets, and source code (e.g., firmware and hdl). + * schematics, data sheets, and source code (i.e., firmware and hdl). * * Be careful when mixing these calls with higher-level routines that manipulate * the same registers/settings. * - * @bug These functions are not currently thread-safe. This will be addressed - * in future revisions of the library. The caller is responsible for ensuring - * these functions are called in a thread-safe manner. + * These functions are thread-safe. * * @{ */ @@ -2544,9 +2492,7 @@ int CALL_CONV bladerf_calibrate_dc(struct bladerf *dev, * functions: * https://github.com/nuand/bladeRF/wiki/FX3-Firmware#spi-flash-layout * - * @bug These functions are not currently thread-safe. This will be addressed - * in future revisions of the library. The caller is responsible for ensuring - * these functions are called in a thread-safe manner. + * These functions are thread-safe. * * @{ */ diff --git a/host/libraries/libbladeRF/src/async.c b/host/libraries/libbladeRF/src/async.c index 964891ef4..29e67e431 100644 --- a/host/libraries/libbladeRF/src/async.c +++ b/host/libraries/libbladeRF/src/async.c @@ -56,10 +56,7 @@ int async_init_stream(struct bladerf_stream **stream, return BLADERF_ERR_MEM; } - if (pthread_mutex_init(&lstream->lock, NULL) != 0) { - free(lstream); - return BLADERF_ERR_UNEXPECTED; - } + MUTEX_INIT(&lstream->lock); if (pthread_cond_init(&lstream->can_submit_buffer, NULL) != 0) { free(lstream); @@ -145,11 +142,11 @@ int async_run_stream(struct bladerf_stream *stream, bladerf_module module) int status; struct bladerf *dev = stream->dev; - pthread_mutex_lock(&stream->lock); + MUTEX_LOCK(&stream->lock); stream->module = module; stream->state = STREAM_RUNNING; pthread_cond_signal(&stream->stream_started); - pthread_mutex_unlock(&stream->lock); + MUTEX_UNLOCK(&stream->lock); status = dev->fn->stream(stream, module); @@ -164,7 +161,7 @@ int async_submit_stream_buffer(struct bladerf_stream *stream, int status = 0; struct timespec timeout_abs; - pthread_mutex_lock(&stream->lock); + MUTEX_LOCK(&stream->lock); if (buffer != BLADERF_STREAM_SHUTDOWN) { if (stream->state != STREAM_RUNNING && timeout_ms != 0) { @@ -200,7 +197,7 @@ int async_submit_stream_buffer(struct bladerf_stream *stream, status = stream->dev->fn->submit_stream_buffer(stream, buffer, timeout_ms); error: - pthread_mutex_unlock(&stream->lock); + MUTEX_UNLOCK(&stream->lock); return status; } diff --git a/host/libraries/libbladeRF/src/async.h b/host/libraries/libbladeRF/src/async.h index 4e7a80dec..5e240010a 100644 --- a/host/libraries/libbladeRF/src/async.h +++ b/host/libraries/libbladeRF/src/async.h @@ -48,7 +48,7 @@ struct bladerf_stream { size_t num_buffers; void **buffers; - pthread_mutex_t lock; + MUTEX lock; /* The following items must be accessed atomically */ int error_code; diff --git a/host/libraries/libbladeRF/src/backend/usb/libusb.c b/host/libraries/libbladeRF/src/backend/usb/libusb.c index 4f7f10d53..bb112f03e 100644 --- a/host/libraries/libbladeRF/src/backend/usb/libusb.c +++ b/host/libraries/libbladeRF/src/backend/usb/libusb.c @@ -652,7 +652,7 @@ static void LIBUSB_CALL lusb_stream_cb(struct libusb_transfer *transfer) /* Currently unused - zero out for out own debugging sanity... */ memset(&metadata, 0, sizeof(metadata)); - pthread_mutex_lock(&stream->lock); + MUTEX_LOCK(&stream->lock); transfer_i = transfer_idx(stream_data, transfer); assert(stream_data->transfer_status[transfer_i] == TRANSFER_IN_FLIGHT || @@ -758,7 +758,7 @@ static void LIBUSB_CALL lusb_stream_cb(struct libusb_transfer *transfer) } } - pthread_mutex_unlock(&stream->lock); + MUTEX_UNLOCK(&stream->lock); } /* Precondition: A transfer is available. */ @@ -899,7 +899,7 @@ static int lusb_stream(void *driver, struct bladerf_stream *stream, /* Currently unused, so zero it out for a sanity check when debugging */ memset(&metadata, 0, sizeof(metadata)); - pthread_mutex_lock(&stream->lock); + MUTEX_LOCK(&stream->lock); /* Set up initial set of buffers */ for (i = 0; i < stream_data->num_transfers; i++) { @@ -942,7 +942,7 @@ static int lusb_stream(void *driver, struct bladerf_stream *stream, } } } - pthread_mutex_unlock(&stream->lock); + MUTEX_UNLOCK(&stream->lock); /* This loop is required so libusb can do callbacks and whatnot */ while (stream->state != STREAM_DONE) { diff --git a/host/libraries/libbladeRF/src/bladerf.c b/host/libraries/libbladeRF/src/bladerf.c index 87d2fc572..1730a4864 100644 --- a/host/libraries/libbladeRF/src/bladerf.c +++ b/host/libraries/libbladeRF/src/bladerf.c @@ -40,51 +40,8 @@ #include "dc_cal_table.h" #include "config.h" #include "version_compat.h" - -static inline int fpga_version_check_and_warn(struct bladerf *dev) -{ - int status = version_check_fpga(dev); - -#if LOGGING_ENABLED - const unsigned int fw_maj = dev->fw_version.major; - const unsigned int fw_min = dev->fw_version.minor; - const unsigned int fw_pat = dev->fw_version.patch; - const unsigned int fpga_maj = dev->fpga_version.major; - const unsigned int fpga_min = dev->fpga_version.minor; - const unsigned int fpga_pat = dev->fpga_version.patch; - unsigned int req_maj, req_min, req_pat; - struct bladerf_version req; - - if (status == BLADERF_ERR_UPDATE_FPGA) { - version_required_fpga(dev, &req); - req_maj = req.major; - req_min = req.minor; - req_pat = req.patch; - - log_warning("FPGA v%u.%u.%u was detected. Firmware v%u.%u.%u " - "requires FPGA v%u.%u.%u or later. Please load a " - "different FPGA version before continuing.\n\n", - fpga_maj, fpga_min, fpga_pat, - fw_maj, fw_min, fw_pat, - req_maj, req_min, req_pat); - } else if (status == BLADERF_ERR_UPDATE_FW) { - version_required_fw(dev, &req, true); - req_maj = req.major; - req_min = req.minor; - req_pat = req.patch; - - log_warning("FPGA v%u.%u.%u was detected, which requires firmware " - "v%u.%u.%u or later. The device firmware is currently " - "v%u.%u.%u. Please upgrade the device firmware before " - "continuing.\n\n", - fpga_maj, fpga_min, fpga_pat, - req_maj, req_min, req_pat, - fw_maj, fw_min, fw_pat); - } -#endif - - return status; -} +#include "fpga.h" +#include "flash_fields.h" /*------------------------------------------------------------------------------ * Device discovery & initialization/deinitialization @@ -131,6 +88,10 @@ int bladerf_open_with_devinfo(struct bladerf **opened_device, return BLADERF_ERR_MEM; } + MUTEX_INIT(&dev->ctrl_lock); + MUTEX_INIT(&dev->sync_lock[BLADERF_MODULE_RX]); + MUTEX_INIT(&dev->sync_lock[BLADERF_MODULE_TX]); + dev->fpga_version.describe = calloc(1, BLADERF_VERSION_STR_MAX + 1); if (dev->fpga_version.describe == NULL) { free(dev); @@ -196,28 +157,28 @@ int bladerf_open_with_devinfo(struct bladerf **opened_device, /* VCTCXO trim and FPGA size are non-fatal indicators that we've * trashed the calibration region of flash. If these were made fatal, * we wouldn't be able to open the device to restore them. */ - status = bladerf_get_and_cache_vctcxo_trim(dev); + status = get_and_cache_vctcxo_trim(dev); if (status < 0) { log_warning("Failed to get VCTCXO trim value: %s\n", bladerf_strerror(status)); } - status = bladerf_get_and_cache_fpga_size(dev); + status = get_and_cache_fpga_size(dev); if (status < 0) { log_warning("Failed to get FPGA size %s\n", bladerf_strerror(status)); } - status = bladerf_is_fpga_configured(dev); + status = FPGA_IS_CONFIGURED(dev); if (status > 0) { /* If the FPGA version check fails, just warn, but don't error out. * * If an error code caused this function to bail out, it would prevent a * user from being able to unload and reflash a bitstream being * "autoloaded" from SPI flash. */ - fpga_version_check_and_warn(dev); + fpga_check_version(dev); - status = bladerf_init_device(dev); + status = init_device(dev); if (status != 0) { goto error; } @@ -262,10 +223,9 @@ void bladerf_close(struct bladerf *dev) { if (dev) { -#ifdef ENABLE_LIBBLADERF_SYNC + MUTEX_LOCK(&dev->ctrl_lock); sync_deinit(dev->sync[BLADERF_MODULE_RX]); sync_deinit(dev->sync[BLADERF_MODULE_TX]); -#endif dev->fn->close(dev); @@ -275,6 +235,7 @@ void bladerf_close(struct bladerf *dev) dc_cal_tbl_free(dev->cal.dc_rx); dc_cal_tbl_free(dev->cal.dc_tx); + MUTEX_UNLOCK(&dev->ctrl_lock); free(dev); } } @@ -292,22 +253,24 @@ int bladerf_enable_module(struct bladerf *dev, (m == BLADERF_MODULE_RX) ? "RX" : "TX", enable ? "True" : "False") ; -#ifdef ENABLE_LIBBLADERF_SYNC + MUTEX_LOCK(&dev->ctrl_lock); + if (enable == false) { sync_deinit(dev->sync[m]); dev->sync[m] = NULL; } -#endif lms_enable_rffe(dev, m, enable); status = dev->fn->enable_module(dev, m, enable); + MUTEX_UNLOCK(&dev->ctrl_lock); return status; } int bladerf_set_loopback(struct bladerf *dev, bladerf_loopback l) { int status; + MUTEX_LOCK(&dev->ctrl_lock); if (l == BLADERF_LB_FIRMWARE) { /* Firmware loopback was fully implemented in FW v1.7.1 @@ -316,7 +279,8 @@ int bladerf_set_loopback(struct bladerf *dev, bladerf_loopback l) if (version_less_than(&dev->fw_version, 1, 7, 1)) { log_warning("Firmware v1.7.1 or later is required " "to use firmware loopback.\n\n"); - return BLADERF_ERR_UPDATE_FW; + status = BLADERF_ERR_UPDATE_FW; + goto out; } else { /* Samples won't reach the LMS when the device is in firmware * loopback mode. By placing the LMS into a loopback mode, we ensure @@ -325,10 +289,10 @@ int bladerf_set_loopback(struct bladerf *dev, bladerf_loopback l) */ status = lms_set_loopback_mode(dev, BLADERF_LB_RF_LNA3); if (status != 0) { - return status; + goto out; } - return dev->fn->set_firmware_loopback(dev, true); + status = dev->fn->set_firmware_loopback(dev, true); } } else { @@ -343,19 +307,23 @@ int bladerf_set_loopback(struct bladerf *dev, bladerf_loopback l) * try to avoid unnecessarily interrupting things...*/ status = dev->fn->get_firmware_loopback(dev, &fw_lb_enabled); if (status != 0) { - return status; + goto out; } if (fw_lb_enabled) { status = dev->fn->set_firmware_loopback(dev, false); if (status != 0) { - return status; + goto out; } } } - return lms_set_loopback_mode(dev, l); + status = lms_set_loopback_mode(dev, l); } + +out: + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_get_loopback(struct bladerf *dev, bladerf_loopback *l) @@ -363,6 +331,8 @@ int bladerf_get_loopback(struct bladerf *dev, bladerf_loopback *l) int status = BLADERF_ERR_UNEXPECTED; *l = BLADERF_LB_NONE; + MUTEX_LOCK(&dev->ctrl_lock); + if (version_greater_or_equal(&dev->fw_version, 1, 7, 1)) { bool fw_lb_enabled; status = dev->fn->get_firmware_loopback(dev, &fw_lb_enabled); @@ -375,169 +345,201 @@ int bladerf_get_loopback(struct bladerf *dev, bladerf_loopback *l) status = lms_get_loopback_mode(dev, l); } + MUTEX_UNLOCK(&dev->ctrl_lock); return status; } -int bladerf_set_rational_sample_rate(struct bladerf *dev, bladerf_module module, struct bladerf_rational_rate *rate, struct bladerf_rational_rate *actual) +int bladerf_set_rational_sample_rate(struct bladerf *dev, bladerf_module module, + struct bladerf_rational_rate *rate, + struct bladerf_rational_rate *actual) { - return si5338_set_rational_sample_rate(dev, module, rate, actual); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = si5338_set_rational_sample_rate(dev, module, rate, actual); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } -int bladerf_set_sample_rate(struct bladerf *dev, bladerf_module module, uint32_t rate, uint32_t *actual) +int bladerf_set_sample_rate(struct bladerf *dev, bladerf_module module, + uint32_t rate, uint32_t *actual) { - return si5338_set_sample_rate(dev, module, rate, actual); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = si5338_set_sample_rate(dev, module, rate, actual); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } -int bladerf_get_rational_sample_rate(struct bladerf *dev, bladerf_module module, struct bladerf_rational_rate *rate) +int bladerf_get_rational_sample_rate(struct bladerf *dev, bladerf_module module, + struct bladerf_rational_rate *rate) { - return si5338_get_rational_sample_rate(dev, module, rate); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = si5338_get_rational_sample_rate(dev, module, rate); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } -int bladerf_get_sample_rate(struct bladerf *dev, bladerf_module module, unsigned int *rate) +int bladerf_get_sample_rate(struct bladerf *dev, bladerf_module module, + unsigned int *rate) { - return si5338_get_sample_rate(dev, module, rate); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = si5338_get_sample_rate(dev, module, rate); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_get_sampling(struct bladerf *dev, bladerf_sampling *sampling) { - return lms_get_sampling(dev, sampling); + int status = 0; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_get_sampling(dev, sampling); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_sampling(struct bladerf *dev, bladerf_sampling sampling) { - return lms_select_sampling(dev, sampling); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_select_sampling(dev, sampling); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_txvga2(struct bladerf *dev, int gain) { - return lms_txvga2_set_gain(dev, gain); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_txvga2_set_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_get_txvga2(struct bladerf *dev, int *gain) { - return lms_txvga2_get_gain(dev, gain); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_txvga2_get_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_txvga1(struct bladerf *dev, int gain) { - return lms_txvga1_set_gain(dev, gain); -} + int status; + MUTEX_LOCK(&dev->ctrl_lock); -int bladerf_get_txvga1(struct bladerf *dev, int *gain) -{ - return lms_txvga1_get_gain(dev, gain); + status = lms_txvga1_set_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } -int bladerf_set_tx_gain_combo(struct bladerf *dev, int txvga1, int txvga2) +int bladerf_get_txvga1(struct bladerf *dev, int *gain) { int status; + MUTEX_LOCK(&dev->ctrl_lock); - status = bladerf_set_txvga1(dev, txvga1); - if (status < 0) - return status; + status = lms_txvga1_get_gain(dev, gain); - return bladerf_set_txvga2(dev, txvga2); + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } -int bladerf_set_tx_gain(struct bladerf *dev, int gain) -{ - if (gain < 0) - gain = 0; - if (gain <= BLADERF_TXVGA2_GAIN_MAX) { - return bladerf_set_tx_gain_combo(dev, - BLADERF_TXVGA1_GAIN_MIN, - gain); - } else if (gain <= ((BLADERF_TXVGA1_GAIN_MAX - BLADERF_TXVGA1_GAIN_MIN) + BLADERF_TXVGA2_GAIN_MAX)) { - return bladerf_set_tx_gain_combo(dev, - BLADERF_TXVGA1_GAIN_MIN + gain - BLADERF_TXVGA2_GAIN_MAX, - BLADERF_TXVGA2_GAIN_MAX); - } - return bladerf_set_tx_gain_combo(dev, - BLADERF_TXVGA1_GAIN_MAX, - BLADERF_TXVGA2_GAIN_MAX); -} int bladerf_set_lna_gain(struct bladerf *dev, bladerf_lna_gain gain) { - return lms_lna_set_gain(dev, gain); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_lna_set_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_get_lna_gain(struct bladerf *dev, bladerf_lna_gain *gain) { - return lms_lna_get_gain(dev, gain); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_lna_get_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_rxvga1(struct bladerf *dev, int gain) { - return lms_rxvga1_set_gain(dev, gain); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_rxvga1_set_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_get_rxvga1(struct bladerf *dev, int *gain) { - return lms_rxvga1_get_gain(dev, gain); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_rxvga1_get_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_rxvga2(struct bladerf *dev, int gain) { - return lms_rxvga2_set_gain(dev, gain); -} + int status; + MUTEX_LOCK(&dev->ctrl_lock); -int bladerf_get_rxvga2(struct bladerf *dev, int *gain) -{ - return lms_rxvga2_get_gain(dev, gain); + status = lms_rxvga2_set_gain(dev, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } -int bladerf_set_rx_gain_combo(struct bladerf *dev, bladerf_lna_gain lnagain, int rxvga1, int rxvga2) +int bladerf_get_rxvga2(struct bladerf *dev, int *gain) { int status; - status = bladerf_set_lna_gain(dev, lnagain); - if (status < 0) - return status; + MUTEX_LOCK(&dev->ctrl_lock); - status = bladerf_set_rxvga1(dev, rxvga1); - if (status < 0) - return status; + status = lms_rxvga2_get_gain(dev, gain); - return bladerf_set_rxvga2(dev, rxvga2); -} - -int bladerf_set_rx_gain(struct bladerf *dev, int gain) -{ - if (gain <= BLADERF_LNA_GAIN_MID_DB) { - return bladerf_set_rx_gain_combo(dev, - BLADERF_LNA_GAIN_BYPASS, - BLADERF_RXVGA1_GAIN_MIN, - BLADERF_RXVGA2_GAIN_MIN); - } else if (gain <= BLADERF_LNA_GAIN_MID_DB + BLADERF_RXVGA1_GAIN_MIN) { - return bladerf_set_rx_gain_combo(dev, - BLADERF_LNA_GAIN_MID_DB, - BLADERF_RXVGA1_GAIN_MIN, - BLADERF_RXVGA2_GAIN_MIN); - } else if (gain <= (BLADERF_LNA_GAIN_MAX_DB + BLADERF_RXVGA1_GAIN_MAX)) { - return bladerf_set_rx_gain_combo(dev, - BLADERF_LNA_GAIN_MID, - gain - BLADERF_LNA_GAIN_MID_DB, - BLADERF_RXVGA2_GAIN_MIN); - } else if (gain < (BLADERF_LNA_GAIN_MAX_DB + BLADERF_RXVGA1_GAIN_MAX + BLADERF_RXVGA2_GAIN_MAX)) { - return bladerf_set_rx_gain_combo(dev, - BLADERF_LNA_GAIN_MAX, - BLADERF_RXVGA1_GAIN_MAX, - gain - (BLADERF_LNA_GAIN_MAX_DB + BLADERF_RXVGA1_GAIN_MAX)); - } - return bladerf_set_rx_gain_combo(dev, - BLADERF_LNA_GAIN_MAX, - BLADERF_RXVGA1_GAIN_MAX, - BLADERF_RXVGA2_GAIN_MAX); + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } + int bladerf_set_gain(struct bladerf *dev, bladerf_module mod, int gain) { - if (mod == BLADERF_MODULE_TX) { - return bladerf_set_tx_gain(dev, gain); - } else if (mod == BLADERF_MODULE_RX) { - return bladerf_set_rx_gain(dev, gain); - } + int status; + MUTEX_LOCK(&dev->ctrl_lock); - return BLADERF_ERR_UNEXPECTED; + status = set_gain(dev, mod, gain); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_bandwidth(struct bladerf *dev, bladerf_module module, @@ -547,6 +549,8 @@ int bladerf_set_bandwidth(struct bladerf *dev, bladerf_module module, int status; lms_bw bw; + MUTEX_LOCK(&dev->ctrl_lock); + if (bandwidth < BLADERF_BANDWIDTH_MIN) { bandwidth = BLADERF_BANDWIDTH_MIN; log_info("Clamping bandwidth to %dHz\n", bandwidth); @@ -559,7 +563,7 @@ int bladerf_set_bandwidth(struct bladerf *dev, bladerf_module module, status = lms_lpf_enable(dev, module, true); if (status != 0) { - return status; + goto out; } status = lms_set_bandwidth(dev, module, bw); @@ -571,14 +575,20 @@ int bladerf_set_bandwidth(struct bladerf *dev, bladerf_module module, } } +out: + MUTEX_UNLOCK(&dev->ctrl_lock); return status; } int bladerf_get_bandwidth(struct bladerf *dev, bladerf_module module, unsigned int *bandwidth) { + int status; lms_bw bw; - const int status = lms_get_bandwidth( dev, module, &bw); + + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_get_bandwidth( dev, module, &bw); if (status == 0) { *bandwidth = lms_bw2uint(bw); @@ -586,159 +596,79 @@ int bladerf_get_bandwidth(struct bladerf *dev, bladerf_module module, *bandwidth = 0; } + MUTEX_UNLOCK(&dev->ctrl_lock); return status; } int bladerf_set_lpf_mode(struct bladerf *dev, bladerf_module module, bladerf_lpf_mode mode) { - return lms_lpf_set_mode(dev, module, mode); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_lpf_set_mode(dev, module, mode); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_get_lpf_mode(struct bladerf *dev, bladerf_module module, bladerf_lpf_mode *mode) { - return lms_lpf_get_mode(dev, module, mode); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_lpf_get_mode(dev, module, mode); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_select_band(struct bladerf *dev, bladerf_module module, unsigned int frequency) { int status; - uint32_t gpio; - uint32_t band; - - if (frequency < BLADERF_FREQUENCY_MIN) { - frequency = BLADERF_FREQUENCY_MIN; - log_info("Clamping frequency to %uHz\n", frequency); - } else if (frequency > BLADERF_FREQUENCY_MAX) { - frequency = BLADERF_FREQUENCY_MAX; - log_info("Clamping frequency to %uHz\n", frequency); - } + MUTEX_LOCK(&dev->ctrl_lock); - band = (frequency >= BLADERF_BAND_HIGH) ? 1 : 2; + status = select_band(dev, module, frequency); - status = lms_select_band(dev, module, frequency); - if (status != 0) { - return status; - } - - status = bladerf_config_gpio_read(dev, &gpio); - if (status != 0) { - return status; - } - - gpio &= ~(module == BLADERF_MODULE_TX ? (3 << 3) : (3 << 5)); - gpio |= (module == BLADERF_MODULE_TX ? (band << 3) : (band << 5)); - - return bladerf_config_gpio_write(dev, gpio); + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_frequency(struct bladerf *dev, bladerf_module module, unsigned int frequency) { int status; - bladerf_xb attached; - int16_t dc_i, dc_q; - const struct dc_cal_tbl *dc_cal = - (module == BLADERF_MODULE_RX) ? dev->cal.dc_rx : dev->cal.dc_tx; - - status = bladerf_expansion_get_attached(dev, &attached); - if (status) - return status; - if (attached == BLADERF_XB_200) { - if (frequency < BLADERF_FREQUENCY_MIN) { - status = bladerf_xb200_set_path(dev, module, BLADERF_XB200_MIX); - if (status) - return status; - status = bladerf_xb200_auto_filter_selection(dev, module, frequency); - if (status) - return status; - frequency = 1248000000 - frequency; - } else { - status = bladerf_xb200_set_path(dev, module, BLADERF_XB200_BYPASS); - if (status) - return status; - } - } - - status = lms_set_frequency(dev, module, frequency); - if (status != 0) { - return status; - } - - status = bladerf_select_band(dev, module, frequency); - if (status != 0) { - return status; - } + MUTEX_LOCK(&dev->ctrl_lock); - if (dc_cal != NULL) { - dc_cal_tbl_vals(dc_cal, frequency, &dc_i, &dc_q); - - status = dev->fn->set_correction(dev, module, - BLADERF_CORR_LMS_DCOFF_I, dc_i); - if (status != 0) { - return status; - } - - status = dev->fn->set_correction(dev, module, - BLADERF_CORR_LMS_DCOFF_Q, dc_q); - if (status != 0) { - return status; - } - - log_verbose("Set %s DC offset cal (I, Q) to: (%d, %d)\n", - (module == BLADERF_MODULE_RX) ? "RX" : "TX", dc_i, dc_q); - } + status = set_frequency(dev, module, frequency); + MUTEX_UNLOCK(&dev->ctrl_lock); return status; } int bladerf_get_frequency(struct bladerf *dev, bladerf_module module, unsigned int *frequency) { - bladerf_xb attached; - bladerf_xb200_path path; - struct lms_freq f; - int rv = 0; - - rv = lms_get_frequency( dev, module, &f ); - if (rv != 0) { - return rv; - } - - if( f.x == 0 ) { - *frequency = 0 ; - rv = BLADERF_ERR_INVAL; - } else { - *frequency = lms_frequency_to_hz(&f); - } - if (rv != 0) { - return rv; - } + int status; + MUTEX_LOCK(&dev->ctrl_lock); - rv = bladerf_expansion_get_attached(dev, &attached); - if (rv != 0) { - return rv; - } - if (attached == BLADERF_XB_200) { - rv = bladerf_xb200_get_path(dev, module, &path); - if (rv != 0) { - return rv; - } - if (path == BLADERF_XB200_MIX) { - *frequency = 1248000000 - *frequency; - } - } + status = get_frequency(dev, module, frequency); - return rv; + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_set_stream_timeout(struct bladerf *dev, bladerf_module module, unsigned int timeout) { + if (dev) { + MUTEX_LOCK(&dev->ctrl_lock); dev->transfer_timeout[module] = timeout; + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; + } else { return BLADERF_ERR_INVAL; } @@ -747,27 +677,44 @@ int bladerf_set_stream_timeout(struct bladerf *dev, bladerf_module module, int bladerf_get_stream_timeout(struct bladerf *dev, bladerf_module module, unsigned int *timeout) { if (dev) { + MUTEX_LOCK(&dev->ctrl_lock); *timeout = dev->transfer_timeout[module]; + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; } else { return BLADERF_ERR_INVAL; } } -int CALL_CONV bladerf_sync_config(struct bladerf *dev, - bladerf_module module, - bladerf_format format, - unsigned int num_buffers, - unsigned int buffer_size, - unsigned int num_transfers, - unsigned int stream_timeout) +int bladerf_sync_config(struct bladerf *dev, + bladerf_module module, + bladerf_format format, + unsigned int num_buffers, + unsigned int buffer_size, + unsigned int num_transfers, + unsigned int stream_timeout) { -#ifdef ENABLE_LIBBLADERF_SYNC - return sync_init(dev, module, format, num_buffers, buffer_size, - num_transfers, stream_timeout); -#else - return BLADERF_ERR_UNSUPPORTED; -#endif + int status; + + switch (module) { + case BLADERF_MODULE_RX: + case BLADERF_MODULE_TX: + break; + + default: + return BLADERF_ERR_INVAL; + } + + MUTEX_LOCK(&dev->ctrl_lock); + MUTEX_LOCK(&dev->sync_lock[module]); + + status = sync_init(dev, module, format, num_buffers, buffer_size, + num_transfers, stream_timeout); + + MUTEX_UNLOCK(&dev->sync_lock[module]); + MUTEX_UNLOCK(&dev->ctrl_lock); + + return status; } int bladerf_sync_tx(struct bladerf *dev, @@ -775,11 +722,13 @@ int bladerf_sync_tx(struct bladerf *dev, struct bladerf_metadata *metadata, unsigned int timeout_ms) { -#ifdef ENABLE_LIBBLADERF_SYNC - return sync_tx(dev, samples, num_samples, metadata, timeout_ms); -#else - return BLADERF_ERR_UNSUPPORTED; -#endif + int status; + + MUTEX_LOCK(&dev->sync_lock[BLADERF_MODULE_TX]); + status = sync_tx(dev, samples, num_samples, metadata, timeout_ms); + MUTEX_UNLOCK(&dev->sync_lock[BLADERF_MODULE_TX]); + + return status; } int bladerf_sync_rx(struct bladerf *dev, @@ -787,11 +736,13 @@ int bladerf_sync_rx(struct bladerf *dev, struct bladerf_metadata *metadata, unsigned int timeout_ms) { -#ifdef ENABLE_LIBBLADERF_SYNC - return sync_rx(dev, samples, num_samples, metadata, timeout_ms); -#else - return BLADERF_ERR_UNSUPPORTED; -#endif + int status; + + MUTEX_LOCK(&dev->sync_lock[BLADERF_MODULE_RX]); + status = sync_rx(dev, samples, num_samples, metadata, timeout_ms); + MUTEX_UNLOCK(&dev->sync_lock[BLADERF_MODULE_RX]); + + return status; } int bladerf_init_stream(struct bladerf_stream **stream, @@ -804,11 +755,20 @@ int bladerf_init_stream(struct bladerf_stream **stream, size_t num_transfers, void *data) { - return async_init_stream(stream, dev, callback, buffers, num_buffers, - format, samples_per_buffer, num_transfers, data); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = async_init_stream(stream, dev, callback, buffers, num_buffers, + format, samples_per_buffer, num_transfers, data); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } -/* Reminder: No device control calls may be made here */ +/* Reminder: No device control calls may be made down through bladerf_stream or + * bladerf_submit_stream_buffer here downward, as we can't + * hold the control lock. + */ int bladerf_stream(struct bladerf_stream *stream, bladerf_module module) { return async_run_stream(stream, module); @@ -823,7 +783,11 @@ int bladerf_submit_stream_buffer(struct bladerf_stream *stream, void bladerf_deinit_stream(struct bladerf_stream *stream) { - async_deinit_stream(stream); + if (stream && stream->dev) { + MUTEX_LOCK(&stream->dev->ctrl_lock); + async_deinit_stream(stream); + MUTEX_UNLOCK(&stream->dev->ctrl_lock); + } } @@ -833,42 +797,61 @@ void bladerf_deinit_stream(struct bladerf_stream *stream) int bladerf_get_serial(struct bladerf *dev, char *serial) { + MUTEX_LOCK(&dev->ctrl_lock); strcpy(serial, dev->ident.serial); + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; } int bladerf_get_vctcxo_trim(struct bladerf *dev, uint16_t *trim) { + MUTEX_LOCK(&dev->ctrl_lock); *trim = dev->dac_trim; + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; } int bladerf_get_fpga_size(struct bladerf *dev, bladerf_fpga_size *size) { + MUTEX_LOCK(&dev->ctrl_lock); *size = dev->fpga_size; + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; } int bladerf_fw_version(struct bladerf *dev, struct bladerf_version *version) { + MUTEX_LOCK(&dev->ctrl_lock); memcpy(version, &dev->fw_version, sizeof(*version)); + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; } int bladerf_is_fpga_configured(struct bladerf *dev) { - return dev->fn->is_fpga_configured(dev); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = FPGA_IS_CONFIGURED(dev); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_fpga_version(struct bladerf *dev, struct bladerf_version *version) { + MUTEX_LOCK(&dev->ctrl_lock); memcpy(version, &dev->fpga_version, sizeof(*version)); + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; } bladerf_dev_speed bladerf_device_speed(struct bladerf *dev) { - return dev->usb_speed; + MUTEX_LOCK(&dev->ctrl_lock); + bladerf_dev_speed speed = dev->usb_speed; + MUTEX_UNLOCK(&dev->ctrl_lock); + return speed; } /*------------------------------------------------------------------------------ @@ -878,33 +861,62 @@ bladerf_dev_speed bladerf_device_speed(struct bladerf *dev) int bladerf_erase_flash(struct bladerf *dev, uint32_t erase_block, uint32_t count) { - return flash_erase(dev, erase_block, count); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = flash_erase(dev, erase_block, count); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_read_flash(struct bladerf *dev, uint8_t *buf, uint32_t page, uint32_t count) { - return flash_read(dev, buf, page, count); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = flash_read(dev, buf, page, count); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_write_flash(struct bladerf *dev, const uint8_t *buf, uint32_t page, uint32_t count) { - return flash_write(dev, buf, page, count); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = flash_write(dev, buf, page, count); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_device_reset(struct bladerf *dev) { - return dev->fn->device_reset(dev); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->device_reset(dev); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_jump_to_bootloader(struct bladerf *dev) { + int status; + if (!dev->fn->jump_to_bootloader) { return BLADERF_ERR_UNSUPPORTED; } - return dev->fn->jump_to_bootloader(dev); + MUTEX_LOCK(&dev->ctrl_lock); + status = dev->fn->jump_to_bootloader(dev); + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } static inline bool valid_fw_size(size_t len) @@ -922,13 +934,15 @@ static inline bool valid_fw_size(size_t len) int bladerf_flash_firmware(struct bladerf *dev, const char *firmware_file) { int status; - uint8_t *buf; + uint8_t *buf = NULL; size_t buf_size; const char env_override[] = "BLADERF_SKIP_FW_SIZE_CHECK"; + MUTEX_LOCK(&dev->ctrl_lock); + status = file_read_buffer(firmware_file, &buf, &buf_size); if (status != 0) { - return status; + goto out; } /* Sanity check firmware length. @@ -946,59 +960,20 @@ int bladerf_flash_firmware(struct bladerf *dev, const char *firmware_file) status = flash_write_fx3_fw(dev, &buf, buf_size); } +out: + MUTEX_UNLOCK(&dev->ctrl_lock); free(buf); return status; } -static inline bool valid_fpga_size(size_t len) -{ - if (len < (1 * 1024 * 1024)) { - return false; - } else if (len > BLADERF_FLASH_BYTE_LEN_FPGA) { - return false; - } else { - return true; - } -} - int bladerf_load_fpga(struct bladerf *dev, const char *fpga_file) { - uint8_t *buf = NULL; - size_t buf_size; int status; + MUTEX_LOCK(&dev->ctrl_lock); - /* TODO sanity check FPGA: - * - Check for x40 vs x115 and verify FPGA image size - * - Known header/footer on images? - * - Checksum/hash? - */ - status = file_read_buffer(fpga_file, &buf, &buf_size); - if (status != 0) { - goto error; - } + status = fpga_load_from_file(dev, fpga_file); - if (!valid_fpga_size(buf_size)) { - status = BLADERF_ERR_INVAL; - goto error; - } - - status = dev->fn->load_fpga(dev, buf, buf_size); - if (status != 0) { - goto error; - } - - status = fpga_version_check_and_warn(dev); - if (status != 0) { - goto error; - } - - status = bladerf_init_device(dev); - if (status != 0) { - goto error; - } - -error: - free(buf); + MUTEX_UNLOCK(&dev->ctrl_lock); return status; } @@ -1006,29 +981,23 @@ int bladerf_load_fpga(struct bladerf *dev, const char *fpga_file) int bladerf_flash_fpga(struct bladerf *dev, const char *fpga_file) { int status; - uint8_t *buf = NULL; - size_t buf_size; - const char env_override[] = "BLADERF_SKIP_FPGA_SIZE_CHECK"; + MUTEX_LOCK(&dev->ctrl_lock); - status = file_read_buffer(fpga_file, &buf, &buf_size); - if (status == 0) { - if (!getenv(env_override) && !valid_fpga_size(buf_size)) { - log_info("Detected potentially invalid firmware file.\n"); - log_info("Define BLADERF_SKIP_FPGA_SIZE_CHECK in your evironment " - "to skip this check.\n"); - status = BLADERF_ERR_INVAL; - } else { - status = flash_write_fpga_bitstream(dev, &buf, buf_size); - } - } + status = fpga_write_to_flash(dev, fpga_file); - free(buf); + MUTEX_UNLOCK(&dev->ctrl_lock); return status; } int bladerf_erase_stored_fpga(struct bladerf *dev) { - return flash_erase_fpga(dev); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = flash_erase_fpga(dev); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } @@ -1104,7 +1073,9 @@ void bladerf_init_devinfo(struct bladerf_devinfo *info) int bladerf_get_devinfo(struct bladerf *dev, struct bladerf_devinfo *info) { if (dev) { + MUTEX_LOCK(&dev->ctrl_lock); memcpy(info, &dev->ident, sizeof(struct bladerf_devinfo)); + MUTEX_UNLOCK(&dev->ctrl_lock); return 0; } else { return BLADERF_ERR_INVAL; @@ -1156,12 +1127,24 @@ const char * bladerf_backend_str(bladerf_backend backend) int bladerf_si5338_read(struct bladerf *dev, uint8_t address, uint8_t *val) { - return dev->fn->si5338_read(dev,address,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->si5338_read(dev,address,val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_si5338_write(struct bladerf *dev, uint8_t address, uint8_t val) { - return dev->fn->si5338_write(dev,address,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->si5338_write(dev,address,val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } /*------------------------------------------------------------------------------ @@ -1170,24 +1153,48 @@ int bladerf_si5338_write(struct bladerf *dev, uint8_t address, uint8_t val) int bladerf_lms_read(struct bladerf *dev, uint8_t address, uint8_t *val) { - return dev->fn->lms_read(dev,address,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->lms_read(dev,address,val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_lms_write(struct bladerf *dev, uint8_t address, uint8_t val) { - return dev->fn->lms_write(dev,address,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->lms_write(dev,address,val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_lms_set_dc_cals(struct bladerf *dev, const struct bladerf_lms_dc_cals *dc_cals) { - return lms_set_dc_cals(dev, dc_cals); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_set_dc_cals(dev, dc_cals); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_lms_get_dc_cals(struct bladerf *dev, struct bladerf_lms_dc_cals *dc_cals) { - return lms_get_dc_cals(dev, dc_cals); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_get_dc_cals(dev, dc_cals); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } /*------------------------------------------------------------------------------ @@ -1196,11 +1203,20 @@ int bladerf_lms_get_dc_cals(struct bladerf *dev, int bladerf_config_gpio_read(struct bladerf *dev, uint32_t *val) { - return dev->fn->config_gpio_read(dev,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = CONFIG_GPIO_READ(dev, val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_config_gpio_write(struct bladerf *dev, uint32_t val) { + int status; + MUTEX_LOCK(&dev->ctrl_lock); + /* If we're connected at HS, we need to use smaller DMA transfers */ if (dev->usb_speed == BLADERF_DEVICE_SPEED_HIGH ) { val |= BLADERF_GPIO_FEATURE_SMALL_DMA_XFER; @@ -1208,25 +1224,120 @@ int bladerf_config_gpio_write(struct bladerf *dev, uint32_t val) val &= ~BLADERF_GPIO_FEATURE_SMALL_DMA_XFER; } else { log_warning("Encountered unknown USB speed in %s\n", __FUNCTION__); - return BLADERF_ERR_UNEXPECTED; + status = BLADERF_ERR_UNEXPECTED; + goto out; } - return dev->fn->config_gpio_write(dev,val); + status = CONFIG_GPIO_WRITE(dev, val); + +out: + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; + +} + +/*------------------------------------------------------------------------------ + * Expansion board configuration + *----------------------------------------------------------------------------*/ +int bladerf_expansion_attach(struct bladerf *dev, bladerf_xb xb) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = xb_attach(dev, xb); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; +} + +int bladerf_expansion_get_attached(struct bladerf *dev, bladerf_xb *xb) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = xb_get_attached(dev, xb); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; +} + +int bladerf_xb200_set_filterbank(struct bladerf *dev, + bladerf_module mod, + bladerf_xb200_filter filter) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = xb200_set_filterbank(dev, mod, filter); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; +} + +int bladerf_xb200_get_filterbank(struct bladerf *dev, + bladerf_module module, + bladerf_xb200_filter *filter) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = xb200_get_filterbank(dev, module, filter); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; +} + +int bladerf_xb200_set_path(struct bladerf *dev, + bladerf_module module, + bladerf_xb200_path path) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = xb200_set_path(dev, module, path); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; +} + +int bladerf_xb200_get_path(struct bladerf *dev, + bladerf_module module, + bladerf_xb200_path *path) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = xb200_get_path(dev, module, path); + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } + /*------------------------------------------------------------------------------ * Expansion board GPIO register read / write functions *----------------------------------------------------------------------------*/ int bladerf_expansion_gpio_read(struct bladerf *dev, uint32_t *val) { - return dev->fn->expansion_gpio_read(dev,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = XB_GPIO_READ(dev, val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_expansion_gpio_write(struct bladerf *dev, uint32_t val) { - return dev->fn->expansion_gpio_write(dev,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = XB_GPIO_WRITE(dev, val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } /*------------------------------------------------------------------------------ @@ -1235,12 +1346,24 @@ int bladerf_expansion_gpio_write(struct bladerf *dev, uint32_t val) int bladerf_expansion_gpio_dir_read(struct bladerf *dev, uint32_t *val) { - return dev->fn->expansion_gpio_dir_read(dev,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = XB_GPIO_DIR_READ(dev, val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_expansion_gpio_dir_write(struct bladerf *dev, uint32_t val) { - return dev->fn->expansion_gpio_dir_write(dev,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = XB_GPIO_DIR_WRITE(dev, val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } /*------------------------------------------------------------------------------ @@ -1249,13 +1372,25 @@ int bladerf_expansion_gpio_dir_write(struct bladerf *dev, uint32_t val) int bladerf_set_correction(struct bladerf *dev, bladerf_module module, bladerf_correction corr, int16_t value) { - return dev->fn->set_correction(dev, module, corr, value); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->set_correction(dev, module, corr, value); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } int bladerf_get_correction(struct bladerf *dev, bladerf_module module, bladerf_correction corr, int16_t *value) { - return dev->fn->get_correction(dev, module, corr, value); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->get_correction(dev, module, corr, value); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } /*------------------------------------------------------------------------------ @@ -1263,7 +1398,13 @@ int bladerf_get_correction(struct bladerf *dev, bladerf_module module, *----------------------------------------------------------------------------*/ int bladerf_get_timestamp(struct bladerf *dev, bladerf_module module, uint64_t *value) { - return dev->fn->get_timestamp(dev,module,value); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = dev->fn->get_timestamp(dev,module,value); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } /*------------------------------------------------------------------------------ @@ -1272,7 +1413,13 @@ int bladerf_get_timestamp(struct bladerf *dev, bladerf_module module, uint64_t * int bladerf_dac_write(struct bladerf *dev, uint16_t val) { - return dev->fn->dac_write(dev,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = DAC_WRITE(dev, val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } @@ -1282,13 +1429,25 @@ int bladerf_dac_write(struct bladerf *dev, uint16_t val) int bladerf_xb_spi_write(struct bladerf *dev, uint32_t val) { - return dev->fn->xb_spi(dev,val); + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = XB_SPI_WRITE(dev, val); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; } /*------------------------------------------------------------------------------ * DC Calibration routines *----------------------------------------------------------------------------*/ - int bladerf_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) - { - return lms_calibrate_dc(dev, module); - } +int bladerf_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + status = lms_calibrate_dc(dev, module); + + MUTEX_UNLOCK(&dev->ctrl_lock); + return status; +} diff --git a/host/libraries/libbladeRF/src/bladerf_priv.c b/host/libraries/libbladeRF/src/bladerf_priv.c index f6cf1d3c0..a7667fe96 100644 --- a/host/libraries/libbladeRF/src/bladerf_priv.c +++ b/host/libraries/libbladeRF/src/bladerf_priv.c @@ -25,12 +25,12 @@ #include "bladerf_priv.h" #include "backend/backend.h" -#include "bladeRF.h" #include "lms.h" +#include "si5338.h" #include "log.h" #include "dc_cal_table.h" +#include "xb.h" -#define OTP_BUFFER_SIZE 256 /* TODO Check for truncation (e.g., odd # bytes)? */ size_t bytes_to_c16_samples(size_t n_bytes) @@ -44,13 +44,13 @@ size_t c16_samples_to_bytes(size_t n_samples) return n_samples * 2 * sizeof(int16_t); } -int bladerf_init_device(struct bladerf *dev) +int init_device(struct bladerf *dev) { int status; uint32_t val; /* Readback the GPIO values to see if they are default or already set */ - status = bladerf_config_gpio_read( dev, &val ); + status = CONFIG_GPIO_READ( dev, &val ); if (status != 0) { log_debug("Failed to read GPIO config %s\n", bladerf_strerror(status)); return status; @@ -60,7 +60,7 @@ int bladerf_init_device(struct bladerf *dev) log_verbose( "Default GPIO value found - initializing device\n" ); /* Set the GPIO pins to enable the LMS and select the low band */ - status = bladerf_config_gpio_write(dev, 0x57); + status = CONFIG_GPIO_WRITE(dev, 0x57); if (status != 0) { return status; } @@ -77,59 +77,59 @@ int bladerf_init_device(struct bladerf *dev) } /* Set the internal LMS register to enable RX and TX */ - status = bladerf_lms_write(dev, 0x05, 0x3e); + status = LMS_WRITE(dev, 0x05, 0x3e); if (status != 0) { return status; } /* LMS FAQ: Improve TX spurious emission performance */ - status = bladerf_lms_write(dev, 0x47, 0x40); + status = LMS_WRITE(dev, 0x47, 0x40); if (status != 0) { return status; } /* LMS FAQ: Improve ADC performance */ - status = bladerf_lms_write(dev, 0x59, 0x29); + status = LMS_WRITE(dev, 0x59, 0x29); if (status != 0) { return status; } /* LMS FAQ: Common mode voltage for ADC */ - status = bladerf_lms_write(dev, 0x64, 0x36); + status = LMS_WRITE(dev, 0x64, 0x36); if (status != 0) { return status; } /* LMS FAQ: Higher LNA Gain */ - status = bladerf_lms_write(dev, 0x79, 0x37); + status = LMS_WRITE(dev, 0x79, 0x37); if (status != 0) { return status; } /* Set a default samplerate */ - status = bladerf_set_sample_rate(dev, BLADERF_MODULE_TX, 1000000, NULL); + status = si5338_set_sample_rate(dev, BLADERF_MODULE_TX, 1000000, NULL); if (status != 0) { return status; } - status = bladerf_set_sample_rate(dev, BLADERF_MODULE_RX, 1000000, NULL); + status = si5338_set_sample_rate(dev, BLADERF_MODULE_RX, 1000000, NULL); if (status != 0) { return status; } /* Set a default frequency of 1GHz */ - status = bladerf_set_frequency(dev, BLADERF_MODULE_TX, 1000000000); + status = set_frequency(dev, BLADERF_MODULE_TX, 1000000000); if (status != 0) { return status; } - status = bladerf_set_frequency(dev, BLADERF_MODULE_RX, 1000000000); + status = set_frequency(dev, BLADERF_MODULE_RX, 1000000000); if (status != 0) { return status; } /* Set the calibrated VCTCXO DAC value */ - status = bladerf_dac_write(dev, dev->dac_trim); + status = DAC_WRITE(dev, dev->dac_trim); if (status != 0) { return status; } @@ -138,198 +138,137 @@ int bladerf_init_device(struct bladerf *dev) return 0; } -/****** - * CRC16 implementation from http://softwaremonkey.org/Code/CRC16 - */ -typedef unsigned char byte; /* 8 bit unsigned */ -typedef unsigned short int word; /* 16 bit unsigned */ - -static word crc16mp(word crcval, void *data_p, word count) { - /* CRC-16 Routine for processing multiple part data blocks. - * Pass 0 into 'crcval' for first call for any given block; for - * subsequent calls pass the CRC returned by the previous call. */ - word xx; - byte *ptr= (byte *)data_p; - - while (count-- > 0) { - crcval=(word)(crcval^(word)(((word)*ptr++)<<8)); - for (xx=0;xx<8;xx++) { - if(crcval&0x8000) { crcval=(word)((word)(crcval<<1)^0x1021); } - else { crcval=(word)(crcval<<1); } - } +int select_band(struct bladerf *dev, bladerf_module module, + unsigned int frequency) +{ + int status; + uint32_t gpio; + uint32_t band; + + if (frequency < BLADERF_FREQUENCY_MIN) { + frequency = BLADERF_FREQUENCY_MIN; + log_info("Clamping frequency to %uHz\n", frequency); + } else if (frequency > BLADERF_FREQUENCY_MAX) { + frequency = BLADERF_FREQUENCY_MAX; + log_info("Clamping frequency to %uHz\n", frequency); } - return(crcval); -} - -static int extract_field(char *ptr, int len, char *field, - char *val, size_t maxlen) { - int c; - unsigned char *ub, *end; - unsigned short a1, a2; - size_t flen, wlen; - - flen = strlen(field); - - ub = (unsigned char *)ptr; - end = ub + len; - while (ub < end) { - c = *ub; - if (c == 0xff) // flash and OTP are 0xff if they've never been written to - break; + band = (frequency >= BLADERF_BAND_HIGH) ? 1 : 2; - a1 = LE16_TO_HOST(*(unsigned short *)(&ub[c+1])); // read checksum - a2 = crc16mp(0, ub, c+1); // calculated checksum - - if (a1 == a2) { - if (!strncmp((char *)ub + 1, field, flen)) { - wlen = min_sz(c - flen, maxlen); - strncpy(val, (char *)ub + 1 + flen, wlen); - val[wlen] = 0; - return 0; - } - } else { - log_debug( "%s: Field checksum mismatch\n", __FUNCTION__); - return BLADERF_ERR_INVAL; - } - ub += c + 3; //skip past `c' bytes, 2 byte CRC field, and 1 byte len field + status = lms_select_band(dev, module, frequency); + if (status != 0) { + return status; } - return BLADERF_ERR_INVAL; -} -int encode_field(char *ptr, int len, int *idx, - const char *field, - const char *val) -{ - int vlen, flen, tlen; - flen = (int)strlen(field); - vlen = (int)strlen(val); - tlen = flen + vlen + 1; - - if (tlen >= 256 || *idx + tlen >= len) - return BLADERF_ERR_MEM; - - ptr[*idx] = flen + vlen; - strcpy(&ptr[*idx + 1], field); - strcpy(&ptr[*idx + 1 + flen], val); - *(unsigned short *)(&ptr[*idx + tlen ]) = HOST_TO_LE16(crc16mp(0, &ptr[*idx ], tlen)); - *idx += tlen + 2; - return 0; -} - -int add_field(char *buf, int buf_len, const char *field_name, const char *val) -{ - int dummy_idx = 0; - int i = 0; - int rv; - - /* skip to the end, ignoring crc (don't want to further corrupt partially - * corrupt data) */ - while(i < buf_len) { - uint8_t field_len = buf[i]; - - if(field_len == 0xff) - break; - - /* skip past `field_len' bytes, 2 byte CRC field, and 1 byte len - * field */ - i += field_len + 3; + status = CONFIG_GPIO_READ(dev, &gpio); + if (status != 0) { + return status; } + gpio &= ~(module == BLADERF_MODULE_TX ? (3 << 3) : (3 << 5)); + gpio |= (module == BLADERF_MODULE_TX ? (band << 3) : (band << 5)); - rv = encode_field(buf + i, buf_len - i, &dummy_idx, field_name, val); - if(rv < 0) - return rv; - - return 0; + return CONFIG_GPIO_WRITE(dev, gpio); } -int bladerf_get_otp_field(struct bladerf *dev, char *field, - char *data, size_t data_size) +int set_frequency(struct bladerf *dev, bladerf_module module, + unsigned int frequency) { int status; - char otp[OTP_BUFFER_SIZE]; - - memset(otp, 0xff, OTP_BUFFER_SIZE); + bladerf_xb attached; + int16_t dc_i, dc_q; + const struct dc_cal_tbl *dc_cal = + (module == BLADERF_MODULE_RX) ? dev->cal.dc_rx : dev->cal.dc_tx; - status = dev->fn->get_otp(dev, otp); - if (status < 0) + status = xb_get_attached(dev, &attached); + if (status) return status; - else - return extract_field(otp, OTP_BUFFER_SIZE, field, data, data_size); -} + if (attached == BLADERF_XB_200) { + if (frequency < BLADERF_FREQUENCY_MIN) { + status = xb200_set_path(dev, module, BLADERF_XB200_MIX); + if (status) + return status; + status = xb200_auto_filter_selection(dev, module, frequency); + if (status) + return status; + frequency = 1248000000 - frequency; + } else { + status = xb200_set_path(dev, module, BLADERF_XB200_BYPASS); + if (status) + return status; + } + } -int bladerf_get_cal_field(struct bladerf *dev, char *field, - char *data, size_t data_size) -{ - int status; - char cal[CAL_BUFFER_SIZE]; + status = lms_set_frequency(dev, module, frequency); + if (status != 0) { + return status; + } - status = dev->fn->get_cal(dev, cal); - if (status < 0) + status = select_band(dev, module, frequency); + if (status != 0) { return status; - else - return extract_field(cal, CAL_BUFFER_SIZE, field, data, data_size); -} + } -int bladerf_read_serial(struct bladerf *dev, char *serial_buf) -{ - int status; + if (dc_cal != NULL) { + dc_cal_tbl_vals(dc_cal, frequency, &dc_i, &dc_q); - status = bladerf_get_otp_field(dev, "S", serial_buf, - BLADERF_SERIAL_LENGTH - 1); + status = dev->fn->set_correction(dev, module, + BLADERF_CORR_LMS_DCOFF_I, dc_i); + if (status != 0) { + return status; + } - if (status < 0) { - log_info("Unable to fetch serial number. Defaulting to 0's.\n"); - memset(dev->ident.serial, '0', BLADERF_SERIAL_LENGTH - 1); + status = dev->fn->set_correction(dev, module, + BLADERF_CORR_LMS_DCOFF_Q, dc_q); + if (status != 0) { + return status; + } - /* Treat this as non-fatal */ - status = 0; + log_verbose("Set %s DC offset cal (I, Q) to: (%d, %d)\n", + (module == BLADERF_MODULE_RX) ? "RX" : "TX", dc_i, dc_q); } - serial_buf[BLADERF_SERIAL_LENGTH - 1] = '\0'; - return status; } -int bladerf_get_and_cache_vctcxo_trim(struct bladerf *dev) +int get_frequency(struct bladerf *dev, bladerf_module module, + unsigned int *frequency) { - int status; - bool ok; - int16_t trim; - char tmp[7] = { 0 }; + bladerf_xb attached; + bladerf_xb200_path path; + struct lms_freq f; + int rv = 0; - status = bladerf_get_cal_field(dev, "DAC", tmp, sizeof(tmp) - 1); - if (!status) { - trim = str2uint(tmp, 0, 0xffff, &ok); + rv = lms_get_frequency( dev, module, &f ); + if (rv != 0) { + return rv; } - if (!status && ok) { - dev->dac_trim = trim; + if( f.x == 0 ) { + *frequency = 0 ; + rv = BLADERF_ERR_INVAL; } else { - log_debug("Unable to fetch DAC trim. Defaulting to 0x8000\n"); - dev->dac_trim = 0x8000; + *frequency = lms_frequency_to_hz(&f); + } + if (rv != 0) { + return rv; } - return status; -} - -int bladerf_get_and_cache_fpga_size(struct bladerf *device) -{ - int status; - char tmp[7] = { 0 }; - - status = bladerf_get_cal_field(device, "B", tmp, sizeof(tmp) - 1); - - if (!strcmp("40", tmp)) { - device->fpga_size = BLADERF_FPGA_40KLE; - } else if(!strcmp("115", tmp)) { - device->fpga_size = BLADERF_FPGA_115KLE; - } else { - device->fpga_size = BLADERF_FPGA_UNKNOWN; + rv = xb_get_attached(dev, &attached); + if (rv != 0) { + return rv; + } + if (attached == BLADERF_XB_200) { + rv = xb200_get_path(dev, module, &path); + if (rv != 0) { + return rv; + } + if (path == BLADERF_XB200_MIX) { + *frequency = 1248000000 - *frequency; + } } - return status; + return rv; } int populate_abs_timeout(struct timespec *t, unsigned int timeout_ms) @@ -414,12 +353,12 @@ int load_calibration_table(struct bladerf *dev, const char *filename) /* Reset the module's frequency to kick off the application of the * new table entries */ - status = bladerf_get_frequency(dev, module, &frequency); + status = get_frequency(dev, module, &frequency); if (status != 0) { goto out; } - status = bladerf_set_frequency(dev, module, frequency); + status = set_frequency(dev, module, frequency); } else if (image->type == BLADERF_IMAGE_TYPE_RX_IQ_CAL || @@ -439,3 +378,102 @@ int load_calibration_table(struct bladerf *dev, const char *filename) bladerf_free_image(image); return status; } + +static inline int set_rx_gain_combo(struct bladerf *dev, + bladerf_lna_gain lnagain, + int rxvga1, int rxvga2) +{ + int status; + status = lms_lna_set_gain(dev, lnagain); + if (status < 0) { + return status; + } + + status = lms_rxvga1_set_gain(dev, rxvga1); + if (status < 0) { + return status; + } + + return lms_rxvga2_set_gain(dev, rxvga2); +} + +static int set_rx_gain(struct bladerf *dev, int gain) +{ + if (gain <= BLADERF_LNA_GAIN_MID_DB) { + return set_rx_gain_combo(dev, + BLADERF_LNA_GAIN_BYPASS, + BLADERF_RXVGA1_GAIN_MIN, + BLADERF_RXVGA2_GAIN_MIN); + } else if (gain <= BLADERF_LNA_GAIN_MID_DB + BLADERF_RXVGA1_GAIN_MIN) { + return set_rx_gain_combo(dev, + BLADERF_LNA_GAIN_MID_DB, + BLADERF_RXVGA1_GAIN_MIN, + BLADERF_RXVGA2_GAIN_MIN); + } else if (gain <= (BLADERF_LNA_GAIN_MAX_DB + BLADERF_RXVGA1_GAIN_MAX)) { + return set_rx_gain_combo(dev, + BLADERF_LNA_GAIN_MID, + gain - BLADERF_LNA_GAIN_MID_DB, + BLADERF_RXVGA2_GAIN_MIN); + } else if (gain < (BLADERF_LNA_GAIN_MAX_DB + BLADERF_RXVGA1_GAIN_MAX + BLADERF_RXVGA2_GAIN_MAX)) { + return set_rx_gain_combo(dev, + BLADERF_LNA_GAIN_MAX, + BLADERF_RXVGA1_GAIN_MAX, + gain - (BLADERF_LNA_GAIN_MAX_DB + BLADERF_RXVGA1_GAIN_MAX)); + } else { + return set_rx_gain_combo(dev, + BLADERF_LNA_GAIN_MAX, + BLADERF_RXVGA1_GAIN_MAX, + BLADERF_RXVGA2_GAIN_MAX); + } +} + +static inline int set_tx_gain_combo(struct bladerf *dev, int txvga1, int txvga2) +{ + int status; + + status = lms_txvga1_set_gain(dev, txvga1); + if (status == 0) { + status = lms_txvga2_set_gain(dev, txvga2); + } + + return status; +} + +static int set_tx_gain(struct bladerf *dev, int gain) +{ + int status; + MUTEX_LOCK(&dev->ctrl_lock); + + if (gain < 0) { + gain = 0; + } + + if (gain <= BLADERF_TXVGA2_GAIN_MAX) { + status = set_tx_gain_combo(dev, BLADERF_TXVGA1_GAIN_MIN, gain); + } else if (gain <= ((BLADERF_TXVGA1_GAIN_MAX - BLADERF_TXVGA1_GAIN_MIN) + BLADERF_TXVGA2_GAIN_MAX)) { + status = set_tx_gain_combo(dev, + BLADERF_TXVGA1_GAIN_MIN + gain - BLADERF_TXVGA2_GAIN_MAX, + BLADERF_TXVGA2_GAIN_MAX); + } else { + status =set_tx_gain_combo(dev, + BLADERF_TXVGA1_GAIN_MAX, + BLADERF_TXVGA2_GAIN_MAX); + } + + return status; +} + +int set_gain(struct bladerf *dev, bladerf_module module, int gain) +{ + int status; + + if (module == BLADERF_MODULE_TX) { + status = set_tx_gain(dev, gain); + } else if (module == BLADERF_MODULE_RX) { + status = set_rx_gain(dev, gain); + } else { + status = BLADERF_ERR_INVAL; + } + + return status; +} diff --git a/host/libraries/libbladeRF/src/bladerf_priv.h b/host/libraries/libbladeRF/src/bladerf_priv.h index 2917b4801..02e1b1670 100644 --- a/host/libraries/libbladeRF/src/bladerf_priv.h +++ b/host/libraries/libbladeRF/src/bladerf_priv.h @@ -31,6 +31,8 @@ #include #include +#include "bladeRF.h" +#include #include "host_config.h" #if BLADERF_OS_WINDOWS || BLADERF_OS_OSX @@ -39,6 +41,7 @@ #include #endif +#include "thread.h" #include "minmax.h" #include "conversions.h" #include "devinfo.h" @@ -52,6 +55,14 @@ * band should be selected */ #define BLADERF_BAND_HIGH (1500000000) +#define CONFIG_GPIO_WRITE(dev, val) dev->fn->config_gpio_write(dev, val) +#define CONFIG_GPIO_READ(dev, val) dev->fn->config_gpio_read(dev, val) + +#define CONFIG_GPIO_WRITE(dev, val) dev->fn->config_gpio_write(dev, val) +#define CONFIG_GPIO_READ(dev, val) dev->fn->config_gpio_read(dev, val) + +#define DAC_WRITE(dev, val) dev->fn->dac_write(dev, val) + /* Forward declaration for the function table */ struct bladerf; @@ -72,6 +83,15 @@ struct calibrations { struct bladerf { + /* Control lock - use this to ensure atomic access to control and + * configuration operations */ + MUTEX ctrl_lock; + + /* Ensure sync transfers occur atomically. If this is to be held in + * conjunction with ctrl_lock, ctrl_lock should be acquired BEFORE + * the relevant sync_lock[] */ + MUTEX sync_lock[NUM_MODULES]; + struct bladerf_devinfo ident; /* Identifying information */ uint16_t dac_trim; @@ -109,98 +129,53 @@ struct bladerf { * Initialize device registers - required after power-up, but safe * to call multiple times after power-up (e.g., multiple close and reopens) */ -int bladerf_init_device(struct bladerf *dev); - -/** - * - */ -size_t bytes_to_c16_samples(size_t n_bytes); -size_t c16_samples_to_bytes(size_t n_samples); - -/** - * Read data from one-time-programmabe (OTP) section of flash - * - * @param[in] dev Device handle - * @param[in] field OTP field - * @param[out] data Populated with retrieved data - * @param[in] data_size Size of the data to read - * - * 0 on success, BLADERF_ERR_* on failure - */ -int bladerf_get_otp_field(struct bladerf *device, char *field, - char *data, size_t data_size); - -/** - * Read data from calibration ("cal") section of flash - * - * @param[in] dev Device handle - * @param[in] field Cal field - * @param[out] data Populated with retrieved data - * @param[in] data_size Size of the data to read - * - * 0 on success, BLADERF_ERR_* on failure - */ -int bladerf_get_otp_field(struct bladerf *device, char *field, - char *data, size_t data_size); +int init_device(struct bladerf *dev); /** - * Retrieve the device serial from flash and store it in the provided buffer. - * - * @pre The provided buffer is BLADERF_SERIAL_LENGTH in size + * Configure the device for operation in the high or low band, based + * upon the provided frequency * - * @param[inout] dev Device handle. On success, serial field is updated + * @param dev Device handle + * @param module Module to configure + * @param frequency Desired frequency * - * 0 on success, BLADERF_ERR_* on failure + * @return 0 on success, BLADERF_ERR_* value on failure */ -int bladerf_read_serial(struct bladerf *device, char *serial_buf); +int select_band(struct bladerf *dev, bladerf_module module, + unsigned int frequency); /** - * Retrieve VCTCXO calibration value from flash and cache it in the - * provided device structure + * Tune to the specified frequency * - * @param[inout] dev Device handle. On success, trim field is updated + * @param dev Device handle + * @param module Module to configure + * @param frequency Desired frequency * - * 0 on success, BLADERF_ERR_* on failure + * @return 0 on success, BLADERF_ERR_* value on failure */ -int bladerf_get_and_cache_vctcxo_trim(struct bladerf *device); - +int set_frequency(struct bladerf *dev, bladerf_module module, + unsigned int frequency); /** - * Retrieve FPGA size variant from flash and cache it in the provided - * device structure + * Get the current frequency that the specified module is tuned to * - * @param[inout] dev Device handle. - * On success, fpga_size field is updated + * @param[in] dev Device handle + * @param[in] module Module to configure + * @param[out] frequency Desired frequency * - * 0 on success, BLADERF_ERR_* on failure + * @return 0 on success, BLADERF_ERR_* value on failure */ -int bladerf_get_and_cache_fpga_size(struct bladerf *device); +int get_frequency(struct bladerf *dev, bladerf_module module, + unsigned int *frequency); -/** - * Create data that can be read by extract_field() - * - * @param[in] ptr Pointer to data buffer that will contain encoded data - * @param[in] len Length of data buffer that will contain encoded data - * @param[inout] idx Pointer indicating next free byte inside of data - * buffer that will contain encoded data - * @param[in] field Key of value to be stored in encoded data buffer - * @param[in] val Value to be stored in encoded data buffer - * - * 0 on success, BLADERF_ERR_* on failure +/* + * Convert bytes to SC16Q11 samples */ -int encode_field(char *ptr, int len, int *idx, const char *field, - const char *val); +size_t bytes_to_c16_samples(size_t n_bytes); -/** - * Add kv association to data region readable by extract_field() - * - * @param[in] buf Buffer to add field to - * @param[in] len Length of `buf' in bytes - * @param[in] field Key of value to be stored in encoded data buffer - * @param[in] val Value associated with key `field' - * - * 0 on success, BLADERF_ERR_* on failure +/* + * Convert SC16A11 samples to bytes */ -int add_field(char *buf, int len, const char *field, const char *val); +size_t c16_samples_to_bytes(size_t n_samples); /** * Populate the provided timeval structure for the specified timeout @@ -222,4 +197,13 @@ int populate_abs_timeout(struct timespec *t_abs, unsigned int timeout_ms); */ int load_calibration_table(struct bladerf *dev, const char *filename); +/** + * Set system gain for the specified module + * + * @param dev Device handle + * @param module Module to configure + * @param gain Desired gain + */ +int set_gain(struct bladerf *dev, bladerf_module module, int gain); + #endif diff --git a/host/libraries/libbladeRF/src/config.c b/host/libraries/libbladeRF/src/config.c index caeeb5d85..429435356 100644 --- a/host/libraries/libbladeRF/src/config.c +++ b/host/libraries/libbladeRF/src/config.c @@ -21,6 +21,7 @@ #include #include "bladerf_priv.h" #include "dc_cal_table.h" +#include "fpga.h" #include "file_ops.h" #include "log.h" @@ -75,7 +76,7 @@ static inline int load_fpga(struct bladerf *dev) if (filename != NULL) { log_debug("Loading FPGA from: %s\n", filename); - status = bladerf_load_fpga(dev, filename); + status = fpga_load_from_file(dev, filename); } free(filename); @@ -124,7 +125,7 @@ int config_load_all(struct bladerf *dev) return status; } - status = bladerf_is_fpga_configured(dev); + status = dev->fn->is_fpga_configured(dev); if (status == 0) { status = load_fpga(dev); } else if (status > 0) { diff --git a/host/libraries/libbladeRF/src/flash.c b/host/libraries/libbladeRF/src/flash.c index 64340e8cf..cd52dfcd3 100644 --- a/host/libraries/libbladeRF/src/flash.c +++ b/host/libraries/libbladeRF/src/flash.c @@ -28,6 +28,7 @@ #include "bladerf_priv.h" #include "rel_assert.h" #include "flash.h" +#include "flash_fields.h" #include "log.h" static inline int check_eb_access(uint32_t erase_block, uint32_t count) diff --git a/host/libraries/libbladeRF/src/flash_fields.c b/host/libraries/libbladeRF/src/flash_fields.c new file mode 100644 index 000000000..5228c3dae --- /dev/null +++ b/host/libraries/libbladeRF/src/flash_fields.c @@ -0,0 +1,217 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 Nuand LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "bladerf_priv.h" +#include "flash_fields.h" +#include "flash.h" +#include "log.h" + +/****** + * CRC16 implementation from http://softwaremonkey.org/Code/CRC16 + */ +typedef unsigned char byte; /* 8 bit unsigned */ +typedef unsigned short int word; /* 16 bit unsigned */ + +static word crc16mp(word crcval, void *data_p, word count) { + /* CRC-16 Routine for processing multiple part data blocks. + * Pass 0 into 'crcval' for first call for any given block; for + * subsequent calls pass the CRC returned by the previous call. */ + word xx; + byte *ptr= (byte *)data_p; + + while (count-- > 0) { + crcval=(word)(crcval^(word)(((word)*ptr++)<<8)); + for (xx=0;xx<8;xx++) { + if(crcval&0x8000) { crcval=(word)((word)(crcval<<1)^0x1021); } + else { crcval=(word)(crcval<<1); } + } + } + return(crcval); +} + +static int extract_field(char *ptr, int len, char *field, + char *val, size_t maxlen) { + int c; + unsigned char *ub, *end; + unsigned short a1, a2; + size_t flen, wlen; + + flen = strlen(field); + + ub = (unsigned char *)ptr; + end = ub + len; + while (ub < end) { + c = *ub; + + if (c == 0xff) // flash and OTP are 0xff if they've never been written to + break; + + a1 = LE16_TO_HOST(*(unsigned short *)(&ub[c+1])); // read checksum + a2 = crc16mp(0, ub, c+1); // calculated checksum + + if (a1 == a2) { + if (!strncmp((char *)ub + 1, field, flen)) { + wlen = min_sz(c - flen, maxlen); + strncpy(val, (char *)ub + 1 + flen, wlen); + val[wlen] = 0; + return 0; + } + } else { + log_debug( "%s: Field checksum mismatch\n", __FUNCTION__); + return BLADERF_ERR_INVAL; + } + ub += c + 3; //skip past `c' bytes, 2 byte CRC field, and 1 byte len field + } + return BLADERF_ERR_INVAL; +} + +int encode_field(char *ptr, int len, int *idx, + const char *field, + const char *val) +{ + int vlen, flen, tlen; + flen = (int)strlen(field); + vlen = (int)strlen(val); + tlen = flen + vlen + 1; + + if (tlen >= 256 || *idx + tlen >= len) + return BLADERF_ERR_MEM; + + ptr[*idx] = flen + vlen; + strcpy(&ptr[*idx + 1], field); + strcpy(&ptr[*idx + 1 + flen], val); + *(unsigned short *)(&ptr[*idx + tlen ]) = HOST_TO_LE16(crc16mp(0, &ptr[*idx ], tlen)); + *idx += tlen + 2; + return 0; +} + +int add_field(char *buf, int buf_len, const char *field_name, const char *val) +{ + int dummy_idx = 0; + int i = 0; + int rv; + + /* skip to the end, ignoring crc (don't want to further corrupt partially + * corrupt data) */ + while(i < buf_len) { + uint8_t field_len = buf[i]; + + if(field_len == 0xff) + break; + + /* skip past `field_len' bytes, 2 byte CRC field, and 1 byte len + * field */ + i += field_len + 3; + } + + + rv = encode_field(buf + i, buf_len - i, &dummy_idx, field_name, val); + if(rv < 0) + return rv; + + return 0; +} + +int get_otp_field(struct bladerf *dev, char *field, + char *data, size_t data_size) +{ + int status; + char otp[OTP_BUFFER_SIZE]; + + memset(otp, 0xff, OTP_BUFFER_SIZE); + + status = dev->fn->get_otp(dev, otp); + if (status < 0) + return status; + else + return extract_field(otp, OTP_BUFFER_SIZE, field, data, data_size); +} + +int get_cal_field(struct bladerf *dev, char *field, + char *data, size_t data_size) +{ + int status; + char cal[CAL_BUFFER_SIZE]; + + status = dev->fn->get_cal(dev, cal); + if (status < 0) + return status; + else + return extract_field(cal, CAL_BUFFER_SIZE, field, data, data_size); +} + +int read_serial(struct bladerf *dev, char *serial_buf) +{ + int status; + + status = get_otp_field(dev, "S", serial_buf, BLADERF_SERIAL_LENGTH - 1); + + if (status < 0) { + log_info("Unable to fetch serial number. Defaulting to 0's.\n"); + memset(dev->ident.serial, '0', BLADERF_SERIAL_LENGTH - 1); + + /* Treat this as non-fatal */ + status = 0; + } + + serial_buf[BLADERF_SERIAL_LENGTH - 1] = '\0'; + + return status; +} + +int get_and_cache_vctcxo_trim(struct bladerf *dev) +{ + int status; + bool ok; + int16_t trim; + char tmp[7] = { 0 }; + + status = get_cal_field(dev, "DAC", tmp, sizeof(tmp) - 1); + if (!status) { + trim = str2uint(tmp, 0, 0xffff, &ok); + } + + if (!status && ok) { + dev->dac_trim = trim; + } else { + log_debug("Unable to fetch DAC trim. Defaulting to 0x8000\n"); + dev->dac_trim = 0x8000; + } + + return status; +} + +int get_and_cache_fpga_size(struct bladerf *device) +{ + int status; + char tmp[7] = { 0 }; + + status = get_cal_field(device, "B", tmp, sizeof(tmp) - 1); + + if (!strcmp("40", tmp)) { + device->fpga_size = BLADERF_FPGA_40KLE; + } else if(!strcmp("115", tmp)) { + device->fpga_size = BLADERF_FPGA_115KLE; + } else { + device->fpga_size = BLADERF_FPGA_UNKNOWN; + } + + return status; +} diff --git a/host/libraries/libbladeRF/src/flash_fields.h b/host/libraries/libbladeRF/src/flash_fields.h new file mode 100644 index 000000000..6b3eb31ca --- /dev/null +++ b/host/libraries/libbladeRF/src/flash_fields.h @@ -0,0 +1,101 @@ +/** + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 Nuand LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BLADERF_FLASH_FIELDS_H_ +#define BLADERF_FLASH_FIELDS_H_ + +#include "libbladeRF.h" + +#define OTP_BUFFER_SIZE 256 + +/** + * Read data from calibration ("cal") section of flash + * + * @param[in] dev Device handle + * @param[in] field Cal field + * @param[out] data Populated with retrieved data + * @param[in] data_size Size of the data to read + * + * 0 on success, BLADERF_ERR_* on failure + */ +int get_otp_field(struct bladerf *device, char *field, + char *data, size_t data_size); + +/** + * Retrieve the device serial from flash and store it in the provided buffer. + * + * @pre The provided buffer is BLADERF_SERIAL_LENGTH in size + * + * @param[inout] dev Device handle. On success, serial field is updated + * + * 0 on success, BLADERF_ERR_* on failure + */ +int read_serial(struct bladerf *device, char *serial_buf); + +/** + * Retrieve VCTCXO calibration value from flash and cache it in the + * provided device structure + * + * @param[inout] dev Device handle. On success, trim field is updated + * + * 0 on success, BLADERF_ERR_* on failure + */ +int get_and_cache_vctcxo_trim(struct bladerf *device); + +/** + * Retrieve FPGA size variant from flash and cache it in the provided + * device structure + * + * @param[inout] dev Device handle. + * On success, fpga_size field is updated + * + * 0 on success, BLADERF_ERR_* on failure + */ +int get_and_cache_fpga_size(struct bladerf *device); + +/** + * Create data that can be read by extract_field() + * + * @param[in] ptr Pointer to data buffer that will contain encoded data + * @param[in] len Length of data buffer that will contain encoded data + * @param[inout] idx Pointer indicating next free byte inside of data + * buffer that will contain encoded data + * @param[in] field Key of value to be stored in encoded data buffer + * @param[in] val Value to be stored in encoded data buffer + * + * 0 on success, BLADERF_ERR_* on failure + */ +int encode_field(char *ptr, int len, int *idx, const char *field, + const char *val); + +/** + * Add kv association to data region readable by extract_field() + * + * @param[in] buf Buffer to add field to + * @param[in] len Length of `buf' in bytes + * @param[in] field Key of value to be stored in encoded data buffer + * @param[in] val Value associated with key `field' + * + * 0 on success, BLADERF_ERR_* on failure + */ +int add_field(char *buf, int len, const char *field, const char *val); + +#endif diff --git a/host/libraries/libbladeRF/src/fpga.c b/host/libraries/libbladeRF/src/fpga.c new file mode 100644 index 000000000..e9cd3eb29 --- /dev/null +++ b/host/libraries/libbladeRF/src/fpga.c @@ -0,0 +1,150 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 Nuand LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "bladerf_priv.h" +#include "fpga.h" +#include "version_compat.h" +#include "file_ops.h" +#include "log.h" +#include "flash.h" + +int fpga_check_version(struct bladerf *dev) +{ + int status = version_check_fpga(dev); + +#if LOGGING_ENABLED + const unsigned int fw_maj = dev->fw_version.major; + const unsigned int fw_min = dev->fw_version.minor; + const unsigned int fw_pat = dev->fw_version.patch; + const unsigned int fpga_maj = dev->fpga_version.major; + const unsigned int fpga_min = dev->fpga_version.minor; + const unsigned int fpga_pat = dev->fpga_version.patch; + unsigned int req_maj, req_min, req_pat; + struct bladerf_version req; + + if (status == BLADERF_ERR_UPDATE_FPGA) { + version_required_fpga(dev, &req); + req_maj = req.major; + req_min = req.minor; + req_pat = req.patch; + + log_warning("FPGA v%u.%u.%u was detected. Firmware v%u.%u.%u " + "requires FPGA v%u.%u.%u or later. Please load a " + "different FPGA version before continuing.\n\n", + fpga_maj, fpga_min, fpga_pat, + fw_maj, fw_min, fw_pat, + req_maj, req_min, req_pat); + } else if (status == BLADERF_ERR_UPDATE_FW) { + version_required_fw(dev, &req, true); + req_maj = req.major; + req_min = req.minor; + req_pat = req.patch; + + log_warning("FPGA v%u.%u.%u was detected, which requires firmware " + "v%u.%u.%u or later. The device firmware is currently " + "v%u.%u.%u. Please upgrade the device firmware before " + "continuing.\n\n", + fpga_maj, fpga_min, fpga_pat, + req_maj, req_min, req_pat, + fw_maj, fw_min, fw_pat); + } +#endif + + return status; +} + +static inline bool valid_fpga_size(size_t len) +{ + if (len < (1 * 1024 * 1024)) { + return false; + } else if (len > BLADERF_FLASH_BYTE_LEN_FPGA) { + return false; + } else { + return true; + } +} + +int fpga_load_from_file(struct bladerf *dev, const char *fpga_file) +{ + uint8_t *buf = NULL; + size_t buf_size; + int status; + + /* TODO sanity check FPGA: + * - Check for x40 vs x115 and verify FPGA image size + * - Known header/footer on images? + * - Checksum/hash? + */ + status = file_read_buffer(fpga_file, &buf, &buf_size); + if (status != 0) { + goto error; + } + + if (!valid_fpga_size(buf_size)) { + status = BLADERF_ERR_INVAL; + goto error; + } + + status = dev->fn->load_fpga(dev, buf, buf_size); + if (status != 0) { + goto error; + } + + status = fpga_check_version(dev); + if (status != 0) { + goto error; + } + + status = init_device(dev); + if (status != 0) { + goto error; + } + +error: + free(buf); + return status; +} + +int fpga_write_to_flash(struct bladerf *dev, const char *fpga_file) +{ + int status; + size_t buf_size; + uint8_t *buf = NULL; + const char env_override[] = "BLADERF_SKIP_FPGA_SIZE_CHECK"; + + status = file_read_buffer(fpga_file, &buf, &buf_size); + if (status == 0) { + if (!getenv(env_override) && !valid_fpga_size(buf_size)) { + log_warning("Detected potentially invalid firmware file.\n"); + + /* You probably don't want to do this unless you know what you're + * doing. Only show this to users who have gone hunting for + * more information... */ + log_debug("Define BLADERF_SKIP_FPGA_SIZE_CHECK in your evironment " + "to skip this check.\n"); + status = BLADERF_ERR_INVAL; + } else { + status = flash_write_fpga_bitstream(dev, &buf, buf_size); + } + } + + free(buf); + return status; +} diff --git a/host/libraries/libbladeRF/src/fpga.h b/host/libraries/libbladeRF/src/fpga.h new file mode 100644 index 000000000..0b318d702 --- /dev/null +++ b/host/libraries/libbladeRF/src/fpga.h @@ -0,0 +1,68 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2014 Nuand LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BLADERF_FPGA_H_ +#define BLADERF_FPGA_H_ + +#include "bladerf_priv.h" + +#define FPGA_IS_CONFIGURED(dev) dev->fn->is_fpga_configured(dev) + +/** + * Test if a sufficiently new enough FPGA is being used and log warnings + * if not. + * + * @param dev Device handle + * + * @return 0 on success, + * BLADERF_ERR_UPDATE_FPGA if the device firmware requires a new FPGA, + * BLADERF_ERR_UPDATE_FW if the FPGA version being used requires, + * newer firmware, + * BLADERF_ERR_* values on other failures + */ +int fpga_check_version(struct bladerf *dev); + +/** + * Load an FPGA bitstream from the specified RBF + * + * @param dev Device handle + * @param fpga_file Path to an RBF file + * + * @return 0 on success, + * BLADERF_ERR_TIMEOUT generally occurs when attempting to load + * the wrong size FPGA image. + * BLADERF_ERR_* values on other failures + */ +int fpga_load_from_file(struct bladerf *dev, const char *fpga_file); + +/** + * Write an FPGA bitstream to the device's SPI flash. This will cause the + * FPGA to be autoloaded the next time the device is powered on. + * + * @param dev Device handle + * @param fpga_file Path to an RBF file + * + * @return 0 on success, + * BLADERF_ERR_* values on other failure + */ +int fpga_write_to_flash(struct bladerf *dev, const char *fpga_file); + +#endif diff --git a/host/libraries/libbladeRF/src/image.c b/host/libraries/libbladeRF/src/image.c index 5e5150827..72c4ea1b0 100644 --- a/host/libraries/libbladeRF/src/image.c +++ b/host/libraries/libbladeRF/src/image.c @@ -34,6 +34,7 @@ #include "log.h" #include "minmax.h" #include "file_ops.h" +#include "flash_fields.h" /* These two are used interchangeably - ensure they're the same! */ #if SHA256_DIGEST_SIZE != BLADERF_IMAGE_CHECKSUM_LEN diff --git a/host/libraries/libbladeRF/src/lms.c b/host/libraries/libbladeRF/src/lms.c index ac9704aeb..e099fd60a 100644 --- a/host/libraries/libbladeRF/src/lms.c +++ b/host/libraries/libbladeRF/src/lms.c @@ -211,14 +211,14 @@ static inline int lms_set(struct bladerf *dev, uint8_t addr, uint8_t mask) int status; uint8_t regval; - status = bladerf_lms_read(dev, addr, ®val); + status = LMS_READ(dev, addr, ®val); if (status != 0) { return status; } regval |= mask; - return bladerf_lms_write(dev, addr, regval); + return LMS_WRITE(dev, addr, regval); } static inline int lms_clr(struct bladerf *dev, uint8_t addr, uint8_t mask) @@ -226,14 +226,14 @@ static inline int lms_clr(struct bladerf *dev, uint8_t addr, uint8_t mask) int status; uint8_t regval; - status = bladerf_lms_read(dev, addr, ®val); + status = LMS_READ(dev, addr, ®val); if (status != 0) { return status; } regval &= ~mask; - return bladerf_lms_write(dev, addr, regval); + return LMS_WRITE(dev, addr, regval); } @@ -264,7 +264,7 @@ static int write_pll_config(struct bladerf *dev, bladerf_module module, addr = 0x25; } - status = bladerf_lms_read(dev, addr, ®val); + status = LMS_READ(dev, addr, ®val); if (status != 0) { return status; } @@ -283,7 +283,7 @@ static int write_pll_config(struct bladerf *dev, bladerf_module module, regval = (regval & ~0xfc) | (freqsel << 2); } - return bladerf_lms_write(dev, addr, regval); + return LMS_WRITE(dev, addr, regval); } @@ -293,7 +293,7 @@ int lms_lpf_enable(struct bladerf *dev, bladerf_module mod, bool enable) uint8_t data; const uint8_t reg = (mod == BLADERF_MODULE_RX) ? 0x54 : 0x34; - status = bladerf_lms_read(dev, reg, &data); + status = LMS_READ(dev, reg, &data); if (status != 0) { return status; } @@ -304,19 +304,19 @@ int lms_lpf_enable(struct bladerf *dev, bladerf_module mod, bool enable) data &= ~(1 << 1); } - status = bladerf_lms_write(dev, reg, data); + status = LMS_WRITE(dev, reg, data); if (status != 0) { return status; } /* Check to see if we are bypassed */ - status = bladerf_lms_read(dev, reg + 1, &data); + status = LMS_READ(dev, reg + 1, &data); if (status != 0) { return status; } else if (data & (1 << 6)) { /* Bypass is enabled; switch back to normal operation */ data &= ~(1 << 6); - status = bladerf_lms_write(dev, reg + 1, data); + status = LMS_WRITE(dev, reg + 1, data); } return status; @@ -330,12 +330,12 @@ int lms_lpf_get_mode(struct bladerf *dev, bladerf_module mod, uint8_t data_h, data_l; bool lpf_enabled, lpf_bypassed; - status = bladerf_lms_read(dev, reg, &data_l); + status = LMS_READ(dev, reg, &data_l); if (status != 0) { return status; } - status = bladerf_lms_read(dev, reg + 1, &data_h); + status = LMS_READ(dev, reg + 1, &data_h); if (status != 0) { return status; } @@ -365,12 +365,12 @@ int lms_lpf_set_mode(struct bladerf *dev, bladerf_module mod, const uint8_t reg = (mod == BLADERF_MODULE_RX) ? 0x54 : 0x34; uint8_t data_l, data_h; - status = bladerf_lms_read(dev, reg, &data_l); + status = LMS_READ(dev, reg, &data_l); if (status != 0) { return status; } - status = bladerf_lms_read(dev, reg + 1, &data_h); + status = LMS_READ(dev, reg + 1, &data_h); if (status != 0) { return status; } @@ -396,12 +396,12 @@ int lms_lpf_set_mode(struct bladerf *dev, bladerf_module mod, return BLADERF_ERR_INVAL; } - status = bladerf_lms_write(dev, reg, data_l); + status = LMS_WRITE(dev, reg, data_l); if (status != 0) { return status; } - status = bladerf_lms_write(dev, reg + 1, data_h); + status = LMS_WRITE(dev, reg + 1, data_h); return status; } @@ -411,7 +411,7 @@ int lms_set_bandwidth(struct bladerf *dev, bladerf_module mod, lms_bw bw) uint8_t data; const uint8_t reg = (mod == BLADERF_MODULE_RX) ? 0x54 : 0x34; - status = bladerf_lms_read(dev, reg, &data); + status = LMS_READ(dev, reg, &data); if (status != 0) { return status; } @@ -419,7 +419,7 @@ int lms_set_bandwidth(struct bladerf *dev, bladerf_module mod, lms_bw bw) data &= ~0x3c; /* Clear out previous bandwidth setting */ data |= (bw << 2); /* Apply new bandwidth setting */ - return bladerf_lms_write(dev, reg, data); + return LMS_WRITE(dev, reg, data); } @@ -430,7 +430,7 @@ int lms_get_bandwidth(struct bladerf *dev, bladerf_module mod, lms_bw *bw) uint8_t data; const uint8_t reg = (mod == BLADERF_MODULE_RX) ? 0x54 : 0x34; - status = bladerf_lms_read(dev, reg, &data); + status = LMS_READ(dev, reg, &data); if (status != 0) { return status; } @@ -492,7 +492,7 @@ int lms_dither_enable(struct bladerf *dev, bladerf_module mod, } /* Read what we currently have in there */ - status = bladerf_lms_read(dev, reg, &data); + status = LMS_READ(dev, reg, &data); if (status != 0) { return status; } @@ -513,7 +513,7 @@ int lms_dither_enable(struct bladerf *dev, bladerf_module mod, } /* Write it out */ - status = bladerf_lms_write(dev, reg, data); + status = LMS_WRITE(dev, reg, data); return status; } @@ -521,10 +521,10 @@ int lms_dither_enable(struct bladerf *dev, bladerf_module mod, int lms_soft_reset(struct bladerf *dev) { - int status = bladerf_lms_write(dev, 0x05, 0x12); + int status = LMS_WRITE(dev, 0x05, 0x12); if (status == 0) { - status = bladerf_lms_write(dev, 0x05, 0x32); + status = LMS_WRITE(dev, 0x05, 0x32); } return status; @@ -539,11 +539,11 @@ int lms_lna_set_gain(struct bladerf *dev, bladerf_lna_gain gain) if (gain == BLADERF_LNA_GAIN_BYPASS || gain == BLADERF_LNA_GAIN_MID || gain == BLADERF_LNA_GAIN_MAX) { - status = bladerf_lms_read(dev, 0x75, &data); + status = LMS_READ(dev, 0x75, &data); if (status == 0) { data &= ~(3 << 6); /* Clear out previous gain setting */ data |= ((gain & 3) << 6); /* Update gain value */ - status = bladerf_lms_write(dev, 0x75, data); + status = LMS_WRITE(dev, 0x75, data); } } else { @@ -558,7 +558,7 @@ int lms_lna_get_gain(struct bladerf *dev, bladerf_lna_gain *gain) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x75, &data); + status = LMS_READ(dev, 0x75, &data); if (status == 0) { data >>= 6; data &= 3; @@ -578,7 +578,7 @@ int lms_select_lna(struct bladerf *dev, lms_lna lna) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x75, &data); + status = LMS_READ(dev, 0x75, &data); if (status != 0) { return status; } @@ -586,7 +586,7 @@ int lms_select_lna(struct bladerf *dev, lms_lna lna) data &= ~(3 << 4); data |= ((lna & 3) << 4); - return bladerf_lms_write(dev, 0x75, data); + return LMS_WRITE(dev, 0x75, data); } int lms_get_lna(struct bladerf *dev, lms_lna *lna) @@ -594,7 +594,7 @@ int lms_get_lna(struct bladerf *dev, lms_lna *lna) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x75, &data); + status = LMS_READ(dev, 0x75, &data); if (status != 0) { *lna = LNA_NONE; return status; @@ -612,7 +612,7 @@ int lms_rxvga1_enable(struct bladerf *dev, bool enable) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x7d, &data); + status = LMS_READ(dev, 0x7d, &data); if (status != 0) { return status; } @@ -623,7 +623,7 @@ int lms_rxvga1_enable(struct bladerf *dev, bool enable) data |= (1 << 3); } - return bladerf_lms_write(dev, 0x7d, data); + return LMS_WRITE(dev, 0x7d, data); } /* Set the RFB_TIA_RXFE mixer gain */ @@ -637,14 +637,14 @@ int lms_rxvga1_set_gain(struct bladerf *dev, int gain) log_info("Clamping RXVGA1 gain to %ddB\n", gain); } - return bladerf_lms_write(dev, 0x76, rxvga1_lut_val2code[gain]); + return LMS_WRITE(dev, 0x76, rxvga1_lut_val2code[gain]); } /* Get the RFB_TIA_RXFE mixer gain */ int lms_rxvga1_get_gain(struct bladerf *dev, int *gain) { uint8_t data; - int status = bladerf_lms_read(dev, 0x76, &data); + int status = LMS_READ(dev, 0x76, &data); if (status == 0) { data &= 0x7f; @@ -664,7 +664,7 @@ int lms_rxvga2_enable(struct bladerf *dev, bool enable) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x64, &data); + status = LMS_READ(dev, 0x64, &data); if (status != 0) { return status; } @@ -675,7 +675,7 @@ int lms_rxvga2_enable(struct bladerf *dev, bool enable) data &= ~(1 << 1); } - return bladerf_lms_write(dev, 0x64, data); + return LMS_WRITE(dev, 0x64, data); } @@ -691,14 +691,14 @@ int lms_rxvga2_set_gain(struct bladerf *dev, int gain) } /* 3 dB per register code */ - return bladerf_lms_write(dev, 0x65, gain / 3); + return LMS_WRITE(dev, 0x65, gain / 3); } int lms_rxvga2_get_gain(struct bladerf *dev, int *gain) { uint8_t data; - const int status = bladerf_lms_read(dev, 0x65, &data); + const int status = LMS_READ(dev, 0x65, &data); if (status == 0) { /* 3 dB per code */ @@ -714,7 +714,7 @@ int lms_select_pa(struct bladerf *dev, lms_pa pa) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x44, &data); + status = LMS_READ(dev, 0x44, &data); /* Disable PA1, PA2, and AUX PA - we'll enable as requested below. */ data &= ~0x1C; @@ -744,7 +744,7 @@ int lms_select_pa(struct bladerf *dev, lms_pa pa) } if (status == 0) { - status = bladerf_lms_write(dev, 0x44, data); + status = LMS_WRITE(dev, 0x44, data); } return status; @@ -756,7 +756,7 @@ int lms_peakdetect_enable(struct bladerf *dev, bool enable) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x44, &data); + status = LMS_READ(dev, 0x44, &data); if (status == 0) { if (enable) { @@ -764,7 +764,7 @@ int lms_peakdetect_enable(struct bladerf *dev, bool enable) } else { data |= (1 << 0); } - status = bladerf_lms_write(dev, 0x44, data); + status = LMS_WRITE(dev, 0x44, data); } return status; @@ -776,7 +776,7 @@ int lms_enable_rffe(struct bladerf *dev, bladerf_module module, bool enable) uint8_t data; uint8_t addr = (module == BLADERF_MODULE_TX ? 0x40 : 0x70); - status = bladerf_lms_read(dev, addr, &data); + status = LMS_READ(dev, addr, &data); if (status == 0) { if (module == BLADERF_MODULE_TX) { @@ -793,7 +793,7 @@ int lms_enable_rffe(struct bladerf *dev, bladerf_module module, bool enable) } } - status = bladerf_lms_write(dev, addr, data); + status = LMS_WRITE(dev, addr, data); } return status; @@ -815,11 +815,11 @@ int lms_txvga2_set_gain(struct bladerf *dev, int gain_int) gain = gain_int; } - status = bladerf_lms_read(dev, 0x45, &data); + status = LMS_READ(dev, 0x45, &data); if (status == 0) { data &= ~(0x1f << 3); data |= ((gain & 0x1f) << 3); - status = bladerf_lms_write(dev, 0x45, data); + status = LMS_WRITE(dev, 0x45, data); } return status; @@ -830,7 +830,7 @@ int lms_txvga2_get_gain(struct bladerf *dev, int *gain) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x45, &data); + status = LMS_READ(dev, 0x45, &data); if (status == 0) { *gain = (data >> 3) & 0x1f; @@ -862,7 +862,7 @@ int lms_txvga1_set_gain(struct bladerf *dev, int gain_int) gain = (gain + 35); /* Since 0x41 is only VGA1GAIN, we don't need to RMW */ - return bladerf_lms_write(dev, 0x41, gain); + return LMS_WRITE(dev, 0x41, gain); } int lms_txvga1_get_gain(struct bladerf *dev, int *gain) @@ -870,7 +870,7 @@ int lms_txvga1_get_gain(struct bladerf *dev, int *gain) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x41, &data); + status = LMS_READ(dev, 0x41, &data); if (status == 0) { /* Clamp to max value */ data = data & 0x1f; @@ -888,7 +888,7 @@ static inline int enable_lna_power(struct bladerf *dev, bool enable) uint8_t regval; /* Magic test register to power down LNAs */ - status = bladerf_lms_read(dev, 0x7d, ®val); + status = LMS_READ(dev, 0x7d, ®val); if (status != 0) { return status; } @@ -899,13 +899,13 @@ static inline int enable_lna_power(struct bladerf *dev, bool enable) regval |= (1 << 0); } - status = bladerf_lms_write(dev, 0x7d, regval); + status = LMS_WRITE(dev, 0x7d, regval); if (status != 0) { return status; } /* Decode test registers */ - status = bladerf_lms_read(dev, 0x70, ®val); + status = LMS_READ(dev, 0x70, ®val); if (status != 0) { return status; } @@ -916,7 +916,7 @@ static inline int enable_lna_power(struct bladerf *dev, bool enable) regval |= (1 << 1); } - return bladerf_lms_write(dev, 0x70, regval); + return LMS_WRITE(dev, 0x70, regval); } /* Power up/down RF loopback switch */ @@ -925,7 +925,7 @@ static inline int enable_rf_loopback_switch(struct bladerf *dev, bool enable) int status; uint8_t regval; - status = bladerf_lms_read(dev, 0x0b, ®val); + status = LMS_READ(dev, 0x0b, ®val); if (status != 0) { return status; } @@ -936,7 +936,7 @@ static inline int enable_rf_loopback_switch(struct bladerf *dev, bool enable) regval &= ~(1 << 0); } - return bladerf_lms_write(dev, 0x0b, regval); + return LMS_WRITE(dev, 0x0b, regval); } @@ -1078,7 +1078,7 @@ static int loopback_rx(struct bladerf *dev, bladerf_loopback mode) } /* Select output buffer in RX PLL and select the desired LNA */ - status = bladerf_lms_read(dev, 0x25, ®val); + status = LMS_READ(dev, 0x25, ®val); if (status != 0) { return status; } @@ -1086,7 +1086,7 @@ static int loopback_rx(struct bladerf *dev, bladerf_loopback mode) regval &= ~0x03; regval |= lna; - status = bladerf_lms_write(dev, 0x25, regval); + status = LMS_WRITE(dev, 0x25, regval); if (status != 0) { return status; } @@ -1171,12 +1171,12 @@ static int loopback_path(struct bladerf *dev, bladerf_loopback mode) int status; uint8_t loopbben, lben_lbrf; - status = bladerf_lms_read(dev, 0x46, &loopbben); + status = LMS_READ(dev, 0x46, &loopbben); if (status != 0) { return status; } - status = bladerf_lms_read(dev, 0x08, &lben_lbrf); + status = LMS_READ(dev, 0x08, &lben_lbrf); if (status != 0) { return status; } @@ -1227,9 +1227,9 @@ static int loopback_path(struct bladerf *dev, bladerf_loopback mode) return BLADERF_ERR_INVAL; } - status = bladerf_lms_write(dev, 0x46, loopbben); + status = LMS_WRITE(dev, 0x46, loopbben); if (status == 0) { - status = bladerf_lms_write(dev, 0x08, lben_lbrf); + status = LMS_WRITE(dev, 0x08, lben_lbrf); } return status; @@ -1300,12 +1300,12 @@ int lms_get_loopback_mode(struct bladerf *dev, bladerf_loopback *loopback) uint8_t lben_lbrfen, loopbben; - status = bladerf_lms_read(dev, 0x08, &lben_lbrfen); + status = LMS_READ(dev, 0x08, &lben_lbrfen); if (status != 0) { return status; } - status = bladerf_lms_read(dev, 0x46, &loopbben); + status = LMS_READ(dev, 0x46, &loopbben); if (status != 0) { return status; } @@ -1362,10 +1362,10 @@ int lms_power_down(struct bladerf *dev) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x05, &data); + status = LMS_READ(dev, 0x05, &data); if (status == 0) { data &= ~(1 << 4); - status = bladerf_lms_write(dev, 0x05, data); + status = LMS_WRITE(dev, 0x05, data); } return status; @@ -1378,14 +1378,14 @@ int lms_pll_enable(struct bladerf *dev, bladerf_module mod, bool enable) const uint8_t reg = (mod == BLADERF_MODULE_RX) ? 0x24 : 0x14; uint8_t data; - status = bladerf_lms_read(dev, reg, &data); + status = LMS_READ(dev, reg, &data); if (status == 0) { if (enable) { data |= (1 << 3); } else { data &= ~(1 << 3); } - status = bladerf_lms_write(dev, reg, data); + status = LMS_WRITE(dev, reg, data); } return status; @@ -1397,14 +1397,14 @@ int lms_rx_enable(struct bladerf *dev, bool enable) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x05, &data); + status = LMS_READ(dev, 0x05, &data); if (status == 0) { if (enable) { data |= (1 << 2); } else { data &= ~(1 << 2); } - status = bladerf_lms_write(dev, 0x05, data); + status = LMS_WRITE(dev, 0x05, data); } return status; @@ -1416,7 +1416,7 @@ int lms_tx_enable(struct bladerf *dev, bool enable) int status; uint8_t data; - status = bladerf_lms_read(dev, 0x05, &data); + status = LMS_READ(dev, 0x05, &data); if (status == 0) { if (enable) { @@ -1424,7 +1424,7 @@ int lms_tx_enable(struct bladerf *dev, bool enable) } else { data &= ~(1 << 3); } - status = bladerf_lms_write(dev, 0x05, data); + status = LMS_WRITE(dev, 0x05, data); } return status; @@ -1462,14 +1462,14 @@ int lms_get_frequency(struct bladerf *dev, bladerf_module mod, int status; uint8_t data; - status = bladerf_lms_read(dev, base + 0, &data); + status = LMS_READ(dev, base + 0, &data); if (status != 0) { return status; } f->nint = ((uint16_t)data) << 1; - status = bladerf_lms_read(dev, base + 1, &data); + status = LMS_READ(dev, base + 1, &data); if (status != 0) { return status; } @@ -1477,21 +1477,21 @@ int lms_get_frequency(struct bladerf *dev, bladerf_module mod, f->nint |= (data & 0x80) >> 7; f->nfrac = ((uint32_t)data & 0x7f) << 16; - status = bladerf_lms_read(dev, base + 2, &data); + status = LMS_READ(dev, base + 2, &data); if (status != 0) { return status; } f->nfrac |= ((uint32_t)data)<<8; - status = bladerf_lms_read(dev, base + 3, &data); + status = LMS_READ(dev, base + 3, &data); if (status != 0) { return status; } f->nfrac |= data; - status = bladerf_lms_read(dev, base + 5, &data); + status = LMS_READ(dev, base + 5, &data); if (status != 0) { return status; } @@ -1515,19 +1515,19 @@ static inline int tune_vcocap(struct bladerf *dev, uint8_t base, uint8_t data) uint8_t vtune; int status; - status = bladerf_lms_read(dev, base + 9, &data); + status = LMS_READ(dev, base + 9, &data); if (status != 0) { return status; } data &= ~(0x3f); for (i = 0; i < 6; i++) { - status = bladerf_lms_write(dev, base + 9, vcocap | data); + status = LMS_WRITE(dev, base + 9, vcocap | data); if (status != 0) { return status; } - status = bladerf_lms_read(dev, base + 10, &vtune); + status = LMS_READ(dev, base + 10, &vtune); if (status != 0) { return status; } @@ -1560,12 +1560,12 @@ static inline int tune_vcocap(struct bladerf *dev, uint8_t base, uint8_t data) while (start_i > 0 && vtune != VCO_HIGH) { start_i -= 1; - status = bladerf_lms_write(dev, base + 9, start_i | data); + status = LMS_WRITE(dev, base + 9, start_i | data); if (status != 0) { return status; } - status = bladerf_lms_read(dev, base + 10, &vtune); + status = LMS_READ(dev, base + 10, &vtune); if (status != 0) { return status; } @@ -1576,12 +1576,12 @@ static inline int tune_vcocap(struct bladerf *dev, uint8_t base, uint8_t data) start_i += 1; log_verbose( "Found lower limit VCOCAP: %d\n", start_i ); - status = bladerf_lms_write(dev, base + 9, vcocap | data ); + status = LMS_WRITE(dev, base + 9, vcocap | data ); if (status != 0) { return status; } - status = bladerf_lms_read(dev, base + 10, &vtune); + status = LMS_READ(dev, base + 10, &vtune); if (status != 0) { return status; } @@ -1591,12 +1591,12 @@ static inline int tune_vcocap(struct bladerf *dev, uint8_t base, uint8_t data) while (stop_i < 64 && vtune != VCO_LOW) { stop_i += 1; - status = bladerf_lms_write(dev, base + 9, stop_i | data); + status = LMS_WRITE(dev, base + 9, stop_i | data); if (status != 0) { return status; } - status = bladerf_lms_read(dev, base + 10, &vtune); + status = LMS_READ(dev, base + 10, &vtune); if (status != 0) { return status; } @@ -1611,12 +1611,12 @@ static inline int tune_vcocap(struct bladerf *dev, uint8_t base, uint8_t data) log_verbose( "Goldilocks VCOCAP: %d\n", vcocap ); - status = bladerf_lms_write(dev, base + 9, vcocap | data ); + status = LMS_WRITE(dev, base + 9, vcocap | data ); if (status != 0) { return status; } - status = bladerf_lms_read(dev, base + 10, &vtune); + status = LMS_READ(dev, base + 10, &vtune); if (status != 0) { return status; } @@ -1689,10 +1689,10 @@ int lms_set_frequency(struct bladerf *dev, bladerf_module mod, uint32_t freq) lms_print_frequency(&f); /* Turn on the DSMs */ - status = bladerf_lms_read(dev, 0x09, &data); + status = LMS_READ(dev, 0x09, &data); if (status == 0) { data |= 0x05; - status = bladerf_lms_write(dev, 0x09, data); + status = LMS_WRITE(dev, 0x09, data); } if (status != 0) { @@ -1706,31 +1706,31 @@ int lms_set_frequency(struct bladerf *dev, bladerf_module mod, uint32_t freq) } data = nint >> 1; - status = bladerf_lms_write(dev, base + 0, data); + status = LMS_WRITE(dev, base + 0, data); if (status != 0) { goto lms_set_frequency_error; } data = ((nint & 1) << 7) | ((nfrac >> 16) & 0x7f); - status = bladerf_lms_write(dev, base + 1, data); + status = LMS_WRITE(dev, base + 1, data); if (status != 0) { goto lms_set_frequency_error; } data = ((nfrac >> 8) & 0xff); - status = bladerf_lms_write(dev, base + 2, data); + status = LMS_WRITE(dev, base + 2, data); if (status != 0) { goto lms_set_frequency_error; } data = (nfrac & 0xff); - status = bladerf_lms_write(dev, base + 3, data); + status = LMS_WRITE(dev, base + 3, data); if (status != 0) { goto lms_set_frequency_error; } /* Set the PLL Ichp, Iup and Idn currents */ - status = bladerf_lms_read(dev, base + 6, &data); + status = LMS_READ(dev, base + 6, &data); if (status != 0) { goto lms_set_frequency_error; } @@ -1738,12 +1738,12 @@ int lms_set_frequency(struct bladerf *dev, bladerf_module mod, uint32_t freq) data &= ~(0x1f); data |= 0x0c; - status = bladerf_lms_write(dev, base + 6, data); + status = LMS_WRITE(dev, base + 6, data); if (status != 0) { goto lms_set_frequency_error; } - status = bladerf_lms_read(dev, base + 7, &data); + status = LMS_READ(dev, base + 7, &data); if (status != 0) { goto lms_set_frequency_error; } @@ -1751,19 +1751,19 @@ int lms_set_frequency(struct bladerf *dev, bladerf_module mod, uint32_t freq) data &= ~(0x1f); // data |= 3; - status = bladerf_lms_write(dev, base + 7, data); + status = LMS_WRITE(dev, base + 7, data); if (status != 0) { goto lms_set_frequency_error; } - status = bladerf_lms_read(dev, base + 8, &data); + status = LMS_READ(dev, base + 8, &data); if (status != 0) { goto lms_set_frequency_error; } data &= ~(0x1f); // data |= 3; - status = bladerf_lms_write(dev, base + 8, data); + status = LMS_WRITE(dev, base + 8, data); if (status != 0) { goto lms_set_frequency_error; } @@ -1773,10 +1773,10 @@ int lms_set_frequency(struct bladerf *dev, bladerf_module mod, uint32_t freq) lms_set_frequency_error: /* Turn off the DSMs */ - dsm_status = bladerf_lms_read(dev, 0x09, &data); + dsm_status = LMS_READ(dev, 0x09, &data); if (dsm_status == 0) { data &= ~(0x05); - dsm_status = bladerf_lms_write(dev, 0x09, data); + dsm_status = LMS_WRITE(dev, 0x09, data); } return (status == 0) ? dsm_status : status; @@ -1789,7 +1789,7 @@ int lms_dump_registers(struct bladerf *dev) const uint16_t num_reg = sizeof(lms_reg_dumpset); for (i = 0; i < num_reg; i++) { - status = bladerf_lms_read(dev, lms_reg_dumpset[i], &data); + status = LMS_READ(dev, lms_reg_dumpset[i], &data); if (status != 0) { log_debug("Failed to read LMS @ 0x%02x\n", lms_reg_dumpset[i]); return status; @@ -1814,7 +1814,7 @@ static int lms_dc_cal_loop(struct bladerf *dev, uint8_t base, log_debug("Calibrating module %2.2x:%2.2x\n", base, cal_address); /* Set the calibration address for the block, and start it up */ - status = bladerf_lms_read(dev, base + 0x03, &val); + status = LMS_READ(dev, base + 0x03, &val); if (status != 0) { return status; } @@ -1822,25 +1822,25 @@ static int lms_dc_cal_loop(struct bladerf *dev, uint8_t base, val &= ~(0x07); val |= cal_address&0x07; - status = bladerf_lms_write(dev, base + 0x03, val); + status = LMS_WRITE(dev, base + 0x03, val); if (status != 0) { return status; } /* Set and latch the DC_CNTVAL */ - status = bladerf_lms_write(dev, base + 0x02, dc_cntval); + status = LMS_WRITE(dev, base + 0x02, dc_cntval); if (status != 0) { return status; } val |= (1 << 4); - status = bladerf_lms_write(dev, base + 0x03, val); + status = LMS_WRITE(dev, base + 0x03, val); if (status != 0) { return status; } val &= ~(1 << 4); - status = bladerf_lms_write(dev, base + 0x03, val); + status = LMS_WRITE(dev, base + 0x03, val); if (status != 0) { return status; } @@ -1848,13 +1848,13 @@ static int lms_dc_cal_loop(struct bladerf *dev, uint8_t base, /* Start the calibration by toggling DC_START_CLBR */ val |= (1 << 5); - status = bladerf_lms_write(dev, base + 0x03, val); + status = LMS_WRITE(dev, base + 0x03, val); if (status != 0) { return status; } val &= ~(1 << 5); - status = bladerf_lms_write(dev, base + 0x03, val); + status = LMS_WRITE(dev, base + 0x03, val); if (status != 0) { return status; } @@ -1862,7 +1862,7 @@ static int lms_dc_cal_loop(struct bladerf *dev, uint8_t base, /* Main loop checking the calibration */ for (i = 0 ; i < max_cal_count && !done; i++) { /* Read active low DC_CLBR_DONE */ - status = bladerf_lms_read(dev, base + 0x01, &val); + status = LMS_READ(dev, base + 0x01, &val); if (status != 0) { return status; } @@ -1872,7 +1872,7 @@ static int lms_dc_cal_loop(struct bladerf *dev, uint8_t base, done = true; /* Per LMS FAQ item 4.7, we should check DC_REG_VAL, as * DC_LOCK is not a reliable indicator */ - status = bladerf_lms_read(dev, base, dc_regval); + status = LMS_READ(dev, base, dc_regval); if (status == 0) { *dc_regval &= 0x3f; } @@ -1912,7 +1912,7 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) int rxvga2 = BLADERF_RXVGA2_GAIN_MIN; /* Save off the top level clock enables and LNA state */ - status = bladerf_lms_read(dev, 0x09, &clockenables); + status = LMS_READ(dev, 0x09, &clockenables); if (status != 0) { return status; } @@ -1953,7 +1953,7 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) } /* Enable the appropriate clock based on the module */ - status = bladerf_lms_write(dev, 0x09, clockenables | cal_clock); + status = LMS_WRITE(dev, 0x09, clockenables | cal_clock); if (status != 0) { return status; } @@ -1970,33 +1970,33 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) * up when performing DC calibration, and then powered down afterwards * to improve receiver linearity */ if (module == BLADERF_DC_CAL_RXVGA2) { - status = bladerf_lms_read(dev, 0x6e, &val); + status = LMS_READ(dev, 0x6e, &val); if (status != 0) { return status; } val &= ~(3 << 6); - status = bladerf_lms_write(dev, 0x6e, val); + status = LMS_WRITE(dev, 0x6e, val); if (status != 0) { return status; } } else { - status = bladerf_lms_read(dev, 0x5f, &val); + status = LMS_READ(dev, 0x5f, &val); if (status != 0) { return status; } val &= ~(1 << 7); - status = bladerf_lms_write(dev, 0x5f, val); + status = LMS_WRITE(dev, 0x5f, val); if (status != 0) { return status; } } /* Connect LNA to the external pads and internally terminate */ - status = bladerf_lms_read(dev, 0x71, ®0x71); + status = LMS_READ(dev, 0x71, ®0x71); if (status != 0) { return status; } @@ -2004,12 +2004,12 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) val = reg0x71; val &= ~(1 << 7); - status = bladerf_lms_write(dev, 0x71, val); + status = LMS_WRITE(dev, 0x71, val); if (status != 0) { return status; } - status = bladerf_lms_read(dev, 0x7c, ®0x7c); + status = LMS_READ(dev, 0x7c, ®0x7c); if (status != 0) { return status; } @@ -2017,52 +2017,52 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) val = reg0x7c; val |= (1 << 2); - status = bladerf_lms_write(dev, 0x7c, val); + status = LMS_WRITE(dev, 0x7c, val); if (status != 0) { return status; } /* Set maximum gain for everything, but save off current values */ - status = bladerf_get_lna_gain(dev, &lna_gain); + status = lms_lna_get_gain(dev, &lna_gain); if (status != 0) { return status; } - status = bladerf_set_lna_gain(dev, BLADERF_LNA_GAIN_MAX); + status = lms_lna_set_gain(dev, BLADERF_LNA_GAIN_MAX); if (status != 0) { return status; } - status = bladerf_get_rxvga1(dev, &rxvga1); + status = lms_rxvga1_get_gain(dev, &rxvga1); if (status != 0) { return status; } - status = bladerf_set_rxvga1(dev, BLADERF_RXVGA1_GAIN_MAX); + status = lms_rxvga1_set_gain(dev, BLADERF_RXVGA1_GAIN_MAX); if (status != 0) { return status; } - status = bladerf_get_rxvga2(dev, &rxvga2); + status = lms_rxvga2_get_gain(dev, &rxvga2); if (status != 0) { return status; } - status = bladerf_set_rxvga2(dev, BLADERF_RXVGA2_GAIN_MAX); + status = lms_rxvga2_set_gain(dev, BLADERF_RXVGA2_GAIN_MAX); if (status != 0) { return status; } } else if (module == BLADERF_DC_CAL_TX_LPF) { /* FAQ item 4.1 notes that the DAC should be turned off or set * to generate minimum DC */ - status = bladerf_lms_read(dev, 0x36, &val); + status = LMS_READ(dev, 0x36, &val); if (status != 0) { return status; } val |= (1 << 7); - status = bladerf_lms_write(dev, 0x36, val); + status = LMS_WRITE(dev, 0x36, val); if (status != 0) { return status; } @@ -2094,7 +2094,7 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) case 0: /* Set to direct control signals: RXVGA2 Decode = 1 */ - status = bladerf_lms_read(dev, 0x64, &val); + status = LMS_READ(dev, 0x64, &val); if (status != 0) { return status; } @@ -2103,14 +2103,14 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) val |= 1; val = 0x37; - status = bladerf_lms_write(dev, 0x64, val); + status = LMS_WRITE(dev, 0x64, val); if (status != 0) { return status; } /* VGA2GAINA = 0110, VGA2GAINB = 0 */ val = 6; - status = bladerf_lms_write(dev, 0x68, val); + status = LMS_WRITE(dev, 0x68, val); if (status != 0) { return status; } @@ -2119,7 +2119,7 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) case 2: /* VGA2GAINA = 0, VGA2GAINB = 0110 */ val = 6 << 4; - status = bladerf_lms_write(dev, 0x68, val); + status = LMS_WRITE(dev, 0x68, val); if (status != 0) { return status; } @@ -2127,7 +2127,7 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) case 4: /* Set to decode control signals: RXVGA2 Decode = 0 */ - status = bladerf_lms_read(dev, 0x64, &val); + status = LMS_READ(dev, 0x64, &val); if (status != 0) { return status; } @@ -2136,7 +2136,7 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) val &= (~1); val = 0x36; - status = bladerf_lms_write(dev, 0x64, val); + status = LMS_WRITE(dev, 0x64, val); if (status != 0) { return status; } @@ -2147,22 +2147,22 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) * written to TX/RX LPF DCCAL */ /* Set the DC level to RX and TX DCCAL modules */ - status = bladerf_lms_read(dev, 0x35, &val); + status = LMS_READ(dev, 0x35, &val); if (status == 0) { val &= ~(0x3f); val |= dc_regval; - status = bladerf_lms_write(dev, 0x35, val); + status = LMS_WRITE(dev, 0x35, val); } if (status != 0) { return status; } - status = bladerf_lms_read(dev, 0x55, &val); + status = LMS_READ(dev, 0x55, &val); if (status == 0) { val &= ~(0x3f); val |= dc_regval; - status = bladerf_lms_write(dev, 0x55, val); + status = LMS_WRITE(dev, 0x55, val); } if (status != 0) { @@ -2176,66 +2176,66 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) /* Disable DC comparators */ if (module == BLADERF_DC_CAL_RXVGA2) { - status = bladerf_lms_read(dev, 0x6e, &val); + status = LMS_READ(dev, 0x6e, &val); if (status != 0) { return status; } val |= (3 << 6); - status = bladerf_lms_write(dev, 0x6e, val); + status = LMS_WRITE(dev, 0x6e, val); if (status != 0) { return status; } } else { - status = bladerf_lms_read(dev, 0x5f, &val); + status = LMS_READ(dev, 0x5f, &val); if (status != 0) { return status; } val |= (1 << 7); - status = bladerf_lms_write(dev, 0x5f, val); + status = LMS_WRITE(dev, 0x5f, val); if (status != 0) { return status; } } /* Restore previously saved LNA Gain, VGA1 gain and VGA2 gain */ - status = bladerf_set_rxvga2(dev, rxvga2); + status = lms_rxvga2_set_gain(dev, rxvga2); if (status != 0) { return status; } - status = bladerf_set_rxvga1(dev, rxvga1); + status = lms_rxvga1_set_gain(dev, rxvga1); if (status != 0) { return status; } - status = bladerf_set_lna_gain(dev, lna_gain); + status = lms_lna_set_gain(dev, lna_gain); if (status != 0) { return status; } - status = bladerf_lms_write(dev, 0x71, reg0x71); + status = LMS_WRITE(dev, 0x71, reg0x71); if (status != 0) { return status; } - status = bladerf_lms_write(dev, 0x7c, reg0x7c); + status = LMS_WRITE(dev, 0x7c, reg0x7c); if (status != 0) { return status; } } else if (module == BLADERF_DC_CAL_TX_LPF) { /* Re-enable the DACs */ - status = bladerf_lms_read(dev, 0x36, &val); + status = LMS_READ(dev, 0x36, &val); if (status != 0) { return status; } val &= ~(1 << 7); - status = bladerf_lms_write(dev, 0x36, val); + status = LMS_WRITE(dev, 0x36, val); if (status != 0) { return status; } @@ -2247,7 +2247,7 @@ int lms_calibrate_dc(struct bladerf *dev, bladerf_cal_module module) return status; } - status = bladerf_lms_write(dev, 0x09, clockenables); + status = LMS_WRITE(dev, 0x09, clockenables); if (status != 0) { return status; } @@ -2307,31 +2307,31 @@ static int set_dc_cal_value(struct bladerf *dev, uint8_t base, uint8_t regval = (0x08 | dc_addr); /* Keep reset inactive, cal disable, load addr */ - status = bladerf_lms_write(dev, base + 3, regval); + status = LMS_WRITE(dev, base + 3, regval); if (status != 0) { return status; } /* Update DC_CNTVAL */ - status = bladerf_lms_write(dev, base + 2, new_value); + status = LMS_WRITE(dev, base + 2, new_value); if (status != 0) { return status; } /* Strobe DC_LOAD */ regval |= (1 << 4); - status = bladerf_lms_write(dev, base + 3, regval); + status = LMS_WRITE(dev, base + 3, regval); if (status != 0) { return status; } regval &= ~(1 << 4); - status = bladerf_lms_write(dev, base + 3, regval); + status = LMS_WRITE(dev, base + 3, regval); if (status != 0) { return status; } - status = bladerf_lms_read(dev, base, ®val); + status = LMS_READ(dev, base, ®val); if (status != 0) { return status; } @@ -2346,13 +2346,13 @@ static int get_dc_cal_value(struct bladerf *dev, uint8_t base, uint8_t regval; /* Keep reset inactive, cal disable, load addr */ - status = bladerf_lms_write(dev, base + 3, (0x08 | dc_addr)); + status = LMS_WRITE(dev, base + 3, (0x08 | dc_addr)); if (status != 0) { return status; } /* Fetch value from DC_REGVAL */ - status = bladerf_lms_read(dev, base, ®val); + status = LMS_READ(dev, base, ®val); if (status != 0) { *value = -1; return status; @@ -2588,56 +2588,56 @@ int lms_select_sampling(struct bladerf *dev, bladerf_sampling sampling) if (sampling == BLADERF_SAMPLING_INTERNAL) { /* Disconnect the ADC input from the outside world */ - status = bladerf_lms_read( dev, 0x09, &val ); + status = LMS_READ( dev, 0x09, &val ); if (status) { log_warning( "Could not read LMS to connect ADC to external pins\n" ); goto out; } val &= ~(1<<7); - status = bladerf_lms_write( dev, 0x09, val ); + status = LMS_WRITE( dev, 0x09, val ); if (status) { log_warning( "Could not write LMS to connect ADC to external pins\n" ); goto out; } /* Turn on RXVGA2 */ - status = bladerf_lms_read( dev, 0x64, &val ); + status = LMS_READ( dev, 0x64, &val ); if (status) { log_warning( "Could not read LMS to enable RXVGA2\n" ); goto out; } val |= (1<<1); - status = bladerf_lms_write( dev, 0x64, val ); + status = LMS_WRITE( dev, 0x64, val ); if (status) { log_warning( "Could not write LMS to enable RXVGA2\n" ); goto out; } } else if (sampling == BLADERF_SAMPLING_EXTERNAL) { /* Turn off RXVGA2 */ - status = bladerf_lms_read( dev, 0x64, &val ); + status = LMS_READ( dev, 0x64, &val ); if (status) { log_warning( "Could not read the LMS to disable RXVGA2\n" ); goto out; } val &= ~(1<<1); - status = bladerf_lms_write( dev, 0x64, val ); + status = LMS_WRITE( dev, 0x64, val ); if (status) { log_warning( "Could not write the LMS to disable RXVGA2\n" ); goto out; } /* Connect the external ADC pins to the internal ADC input */ - status = bladerf_lms_read( dev, 0x09, &val ); + status = LMS_READ( dev, 0x09, &val ); if (status) { log_warning( "Could not read the LMS to connect ADC to internal pins\n" ); goto out; } val |= (1<<7); - status = bladerf_lms_write( dev, 0x09, val ); + status = LMS_WRITE( dev, 0x09, val ); if (status) { log_warning( "Could not write the LMS to connect ADC to internal pins\n" ); } @@ -2654,14 +2654,14 @@ int lms_get_sampling(struct bladerf *dev, bladerf_sampling *sampling) int status = 0, external = 0; uint8_t val = 0; - status = bladerf_lms_read(dev, 0x09, &val); + status = LMS_READ(dev, 0x09, &val); if (status != 0) { log_warning("Could not read state of ADC pin connectivity\n"); goto out; } external = (val & (1 << 7)) ? 1 : 0; - status = bladerf_lms_read(dev, 0x64, &val); + status = LMS_READ(dev, 0x64, &val); if (status != 0) { log_warning( "Could not read RXVGA2 state\n" ); goto out; @@ -2684,5 +2684,4 @@ int lms_get_sampling(struct bladerf *dev, bladerf_sampling *sampling) out: return status; - } diff --git a/host/libraries/libbladeRF/src/lms.h b/host/libraries/libbladeRF/src/lms.h index 0b082533f..a80c83d81 100644 --- a/host/libraries/libbladeRF/src/lms.h +++ b/host/libraries/libbladeRF/src/lms.h @@ -26,6 +26,11 @@ #define LMS_H_ #include +#include "bladerf_priv.h" + +#define LMS_WRITE(dev, addr, value) dev->fn->lms_write(dev, addr, value) +#define LMS_READ(dev, addr, value) dev->fn->lms_read(dev, addr, value) + /** * Information about the frequency calculation for the LMS6002D PLL diff --git a/host/libraries/libbladeRF/src/si5338.c b/host/libraries/libbladeRF/src/si5338.c index ab9ac8eb3..1d456f25b 100644 --- a/host/libraries/libbladeRF/src/si5338.c +++ b/host/libraries/libbladeRF/src/si5338.c @@ -22,6 +22,7 @@ #include "rel_assert.h" #include "libbladeRF.h" +#include "si5338.h" #include "host_config.h" #include "bladerf_priv.h" #include "log.h" @@ -220,7 +221,7 @@ static int si5338_write_multisynth(struct bladerf *dev, struct si5338_multisynth log_debug( "Writing MS%d\n", ms->index ); /* Write out the enables */ - status = bladerf_si5338_read(dev, 36 + ms->index, &val); + status = SI5338_READ(dev, 36 + ms->index, &val); if (status < 0) { si5338_read_error(status, bladerf_strerror(status)); return status; @@ -228,7 +229,7 @@ static int si5338_write_multisynth(struct bladerf *dev, struct si5338_multisynth val &= ~(7); val |= ms->enable; log_debug( "Wrote enable register: 0x%2.2x\n", val ); - status = bladerf_si5338_write(dev, 36 + ms->index, val); + status = SI5338_WRITE(dev, 36 + ms->index, val); if (status < 0) { si5338_write_error(status, bladerf_strerror(status)); return status; @@ -236,7 +237,7 @@ static int si5338_write_multisynth(struct bladerf *dev, struct si5338_multisynth /* Write out the registers */ for (i = 0 ; i < 10 ; i++) { - status = bladerf_si5338_write(dev, ms->base + i, *(ms->regs+i)); + status = SI5338_WRITE(dev, ms->base + i, *(ms->regs+i)); if (status < 0) { si5338_write_error(status, bladerf_strerror(status)); return status; @@ -258,7 +259,7 @@ static int si5338_write_multisynth(struct bladerf *dev, struct si5338_multisynth log_debug( "Wrote r register: 0x%2.2x\n", val ); - status = bladerf_si5338_write(dev, 31 + ms->index, val); + status = SI5338_WRITE(dev, 31 + ms->index, val); if (status < 0) { si5338_write_error(status, bladerf_strerror(status)); } @@ -274,7 +275,7 @@ static int si5338_read_multisynth(struct bladerf *dev, struct si5338_multisynth log_debug( "Reading MS%d\n", ms->index ); /* Read the enable bits */ - status = bladerf_si5338_read(dev, 36 + ms->index, &val); + status = SI5338_READ(dev, 36 + ms->index, &val); if (status < 0) { si5338_read_error(status, bladerf_strerror(status)); return status ; @@ -284,7 +285,7 @@ static int si5338_read_multisynth(struct bladerf *dev, struct si5338_multisynth /* Read all of the multisynth registers */ for (i = 0; i < 10; i++) { - status = bladerf_si5338_read(dev, ms->base + i, ms->regs+i); + status = SI5338_READ(dev, ms->base + i, ms->regs+i); if (status < 0) { si5338_read_error(status, bladerf_strerror(status)); return status; @@ -293,7 +294,7 @@ static int si5338_read_multisynth(struct bladerf *dev, struct si5338_multisynth } /* Populate the RxDIV value from the register */ - status = bladerf_si5338_read(dev, 31 + ms->index, &val); + status = SI5338_READ(dev, 31 + ms->index, &val); if (status < 0) { si5338_read_error(status, bladerf_strerror(status)); return status; diff --git a/host/libraries/libbladeRF/src/si5338.h b/host/libraries/libbladeRF/src/si5338.h index c7311d870..00f53f2be 100644 --- a/host/libraries/libbladeRF/src/si5338.h +++ b/host/libraries/libbladeRF/src/si5338.h @@ -26,6 +26,10 @@ #define SI5338_H__ #include +#include "bladerf_priv.h" + +#define SI5338_READ(dev, addr, value) dev->fn->si5338_read(dev, addr, value) +#define SI5338_WRITE(dev, addr, value) dev->fn->si5338_write(dev, addr, value) // XXX document diff --git a/host/libraries/libbladeRF/src/sync.c b/host/libraries/libbladeRF/src/sync.c index bfade04cd..a255fff5d 100644 --- a/host/libraries/libbladeRF/src/sync.c +++ b/host/libraries/libbladeRF/src/sync.c @@ -15,10 +15,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef ENABLE_LIBBLADERF_SYNC -#error "Build configuration bug: this file should not be included in the build." -#endif - #include /* Only switch on the verbose debug prints in this file when we *really* want @@ -31,6 +27,7 @@ #endif #include "bladerf_priv.h" +#include "async.h" #include "sync.h" #include "sync_worker.h" #include "minmax.h" @@ -108,7 +105,7 @@ int sync_init(struct bladerf *dev, sync->stream_config.bytes_per_sample = bytes_per_sample; - pthread_mutex_init(&sync->buf_mgmt.lock, NULL); + MUTEX_INIT(&sync->buf_mgmt.lock); pthread_cond_init(&sync->buf_mgmt.buf_ready, NULL); sync->buf_mgmt.status = (sync_buffer_status*) malloc(num_buffers * sizeof(sync_buffer_status)); @@ -160,8 +157,8 @@ void sync_deinit(struct bladerf_sync *sync) if (sync != NULL) { if (sync->stream_config.module == BLADERF_MODULE_TX) { - bladerf_submit_stream_buffer(sync->worker->stream, - BLADERF_STREAM_SHUTDOWN, 0); + async_submit_stream_buffer(sync->worker->stream, + BLADERF_STREAM_SHUTDOWN, 0); } sync_worker_deinit(sync->worker, &sync->buf_mgmt.lock, @@ -255,11 +252,11 @@ int sync_rx(struct bladerf *dev, void *samples, unsigned num_samples, } case SYNC_STATE_RESET_BUF_MGMT: - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); /* When the RX stream starts up, it will submit the first T * transfers, so the consumer index must be reset to 0 */ b->cons_i = 0; - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); log_debug("%s: Reset buf_mgmt consumer index\n", __FUNCTION__); s->state = SYNC_STATE_START_WORKER; break; @@ -283,7 +280,7 @@ int sync_rx(struct bladerf *dev, void *samples, unsigned num_samples, break; case SYNC_STATE_WAIT_FOR_BUFFER: - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); /* Check the buffer state, as the worker may have produced one * since we last queried the status */ @@ -302,20 +299,20 @@ int sync_rx(struct bladerf *dev, void *samples, unsigned num_samples, } } - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); break; case SYNC_STATE_BUFFER_READY: - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); b->status[b->cons_i] = SYNC_BUFFER_PARTIAL; b->partial_off = 0; - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); s->state= SYNC_STATE_USING_BUFFER; break; case SYNC_STATE_USING_BUFFER: - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); buf_src = (uint8_t*)b->buffers[b->cons_i]; @@ -348,7 +345,7 @@ int sync_rx(struct bladerf *dev, void *samples, unsigned num_samples, s->state = SYNC_STATE_WAIT_FOR_BUFFER; } - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); break; } } @@ -417,7 +414,7 @@ int sync_tx(struct bladerf *dev, void *samples, unsigned int num_samples, break; case SYNC_STATE_WAIT_FOR_BUFFER: - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); /* Check the buffer state, as the worker may have consumed one * since we last queried the status */ @@ -428,21 +425,21 @@ int sync_tx(struct bladerf *dev, void *samples, unsigned int num_samples, __FUNCTION__, b->prod_i); } - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); break; case SYNC_STATE_BUFFER_READY: - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); b->status[b->prod_i] = SYNC_BUFFER_PARTIAL; b->partial_off = 0; - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); s->state= SYNC_STATE_USING_BUFFER; break; case SYNC_STATE_USING_BUFFER: - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); buf_dest = (uint8_t*)b->buffers[b->prod_i]; samples_to_copy = uint_min(num_samples - samples_written, @@ -466,7 +463,7 @@ int sync_tx(struct bladerf *dev, void *samples, unsigned int num_samples, __FUNCTION__, b->prod_i); b->status[b->prod_i] = SYNC_BUFFER_IN_FLIGHT; - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); /* This call may block and it results in a per-stream lock * being held, so the buffer lock must be dropped. @@ -475,12 +472,12 @@ int sync_tx(struct bladerf *dev, void *samples, unsigned int num_samples, * not touch the status for this this buffer, or the * producer index. */ - status = bladerf_submit_stream_buffer( + status = async_submit_stream_buffer( s->worker->stream, buf_dest, s->stream_config.timeout_ms); - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); if (status == 0) { b->prod_i = (b->prod_i + 1) % b->num_buffers; @@ -497,7 +494,7 @@ int sync_tx(struct bladerf *dev, void *samples, unsigned int num_samples, } } - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); break; } } diff --git a/host/libraries/libbladeRF/src/sync.h b/host/libraries/libbladeRF/src/sync.h index f01612dd3..17c84dd1f 100644 --- a/host/libraries/libbladeRF/src/sync.h +++ b/host/libraries/libbladeRF/src/sync.h @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#if !defined(BLADERF_SYNC_H_) && defined(ENABLE_LIBBLADERF_SYNC) +#ifndef BLADERF_SYNC_H_ #define BLADERF_SYNC_H_ #include @@ -63,7 +63,7 @@ struct buffer_mgmt { unsigned int resubmit_count; - pthread_mutex_t lock; + MUTEX lock; pthread_cond_t buf_ready; /**< Buffer produced by RX callback, or * buffer emptied by TX callback */ }; diff --git a/host/libraries/libbladeRF/src/sync_worker.c b/host/libraries/libbladeRF/src/sync_worker.c index 38cdd0091..b55a73247 100644 --- a/host/libraries/libbladeRF/src/sync_worker.c +++ b/host/libraries/libbladeRF/src/sync_worker.c @@ -15,10 +15,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef ENABLE_LIBBLADERF_SYNC -#error "Build configuration bug: this file should not be included in the build." -#endif - #include #include #include @@ -35,6 +31,7 @@ #include "rel_assert.h" #include "bladerf_priv.h" +#include "async.h" #include "sync.h" #include "sync_worker.h" #include "conversions.h" @@ -60,9 +57,9 @@ static void *rx_callback(struct bladerf *dev, /* Check if the caller has requested us to shut down. We'll keep the * SHUTDOWN bit set through our transition into the IDLE state so we * can act on it there. */ - pthread_mutex_lock(&w->request_lock); + MUTEX_LOCK(&w->request_lock); requests = w->requests; - pthread_mutex_unlock(&w->request_lock); + MUTEX_UNLOCK(&w->request_lock); if (requests & SYNC_WORKER_STOP) { log_verbose("%s worker: Got STOP request upon entering callback. " @@ -70,7 +67,7 @@ static void *rx_callback(struct bladerf *dev, return NULL; } - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); /* Get the index of the buffer that was just filled */ samples_idx = sync_buf2idx(b, samples); @@ -110,7 +107,7 @@ static void *rx_callback(struct bladerf *dev, } - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); return next_buf; } @@ -131,9 +128,9 @@ static void *tx_callback(struct bladerf *dev, /* Check if the caller has requested us to shut down. We'll keep the * SHUTDOWN bit set through our transition into the IDLE state so we * can act on it there. */ - pthread_mutex_lock(&w->request_lock); + MUTEX_LOCK(&w->request_lock); requests = w->requests; - pthread_mutex_unlock(&w->request_lock); + MUTEX_UNLOCK(&w->request_lock); if (requests & SYNC_WORKER_STOP) { log_verbose("%s worker: Got STOP request upon entering callback. " @@ -146,14 +143,14 @@ static void *tx_callback(struct bladerf *dev, * callbacks we get have samples=NULL */ if (samples != NULL) { - pthread_mutex_lock(&b->lock); + MUTEX_LOCK(&b->lock); completed_idx = sync_buf2idx(b, samples); assert(b->status[completed_idx] == SYNC_BUFFER_IN_FLIGHT); b->status[completed_idx] = SYNC_BUFFER_EMPTY; pthread_cond_signal(&b->buf_ready); - pthread_mutex_unlock(&b->lock); + MUTEX_UNLOCK(&b->lock); log_verbose("%s worker: Buffer %u emptied.\r\n", MODULE_STR(s), completed_idx); @@ -178,15 +175,15 @@ int sync_worker_init(struct bladerf_sync *s) s->worker->cb = s->stream_config.module == BLADERF_MODULE_RX ? rx_callback : tx_callback; - status = bladerf_init_stream(&s->worker->stream, - s->dev, - s->worker->cb, - &s->buf_mgmt.buffers, - s->buf_mgmt.num_buffers, - s->stream_config.format, - s->stream_config.samples_per_buffer, - s->stream_config.num_xfers, - s); + status = async_init_stream(&s->worker->stream, + s->dev, + s->worker->cb, + &s->buf_mgmt.buffers, + s->buf_mgmt.num_buffers, + s->stream_config.format, + s->stream_config.samples_per_buffer, + s->stream_config.num_xfers, + s); if (status != 0) { log_debug("%s worker: Failed to init stream: %s\n", MODULE_STR(s), @@ -195,11 +192,8 @@ int sync_worker_init(struct bladerf_sync *s) } - status = pthread_mutex_init(&s->worker->state_lock, NULL); - if (status != 0) { - status = BLADERF_ERR_UNEXPECTED; - goto worker_init_out; - } + MUTEX_INIT(&s->worker->state_lock); + MUTEX_INIT(&s->worker->request_lock); status = pthread_cond_init(&s->worker->state_changed, NULL); if (status != 0) { @@ -207,12 +201,6 @@ int sync_worker_init(struct bladerf_sync *s) goto worker_init_out; } - status = pthread_mutex_init(&s->worker->request_lock, NULL); - if (status != 0) { - status = BLADERF_ERR_UNEXPECTED; - goto worker_init_out; - } - status = pthread_cond_init(&s->worker->requests_pending, NULL); if (status != 0) { status = BLADERF_ERR_UNEXPECTED; @@ -256,9 +244,9 @@ void sync_worker_deinit(struct sync_worker *w, sync_worker_submit_request(w, SYNC_WORKER_STOP); if (lock != NULL && cond != NULL) { - pthread_mutex_lock(lock); + MUTEX_LOCK(lock); pthread_cond_signal(cond); - pthread_mutex_unlock(lock); + MUTEX_UNLOCK(lock); } status = sync_worker_wait_for_state(w, SYNC_WORKER_STATE_STOPPED, 3000); @@ -271,17 +259,17 @@ void sync_worker_deinit(struct sync_worker *w, pthread_join(w->thread, NULL); log_verbose("%s: Worker joined.\n", __FUNCTION__); - bladerf_deinit_stream(w->stream); + async_deinit_stream(w->stream); free(w); } void sync_worker_submit_request(struct sync_worker *w, unsigned int request) { - pthread_mutex_lock(&w->request_lock); + MUTEX_LOCK(&w->request_lock); w->requests |= request; pthread_cond_signal(&w->requests_pending); - pthread_mutex_unlock(&w->request_lock); + MUTEX_UNLOCK(&w->request_lock); } int sync_worker_wait_for_state(struct sync_worker *w, sync_worker_state state, @@ -307,23 +295,23 @@ int sync_worker_wait_for_state(struct sync_worker *w, sync_worker_state state, timeout_abs.tv_nsec %= nsec_per_sec; } - pthread_mutex_lock(&w->state_lock); + MUTEX_LOCK(&w->state_lock); status = 0; while (w->state != state && status == 0) { status = pthread_cond_timedwait(&w->state_changed, &w->state_lock, &timeout_abs); } - pthread_mutex_unlock(&w->state_lock); + MUTEX_UNLOCK(&w->state_lock); } else { - pthread_mutex_lock(&w->state_lock); + MUTEX_LOCK(&w->state_lock); while (w->state != state) { log_verbose(": Waiting for state change, current = %d\n", w->state); status = pthread_cond_wait(&w->state_changed, &w->state_lock); } - pthread_mutex_unlock(&w->state_lock); + MUTEX_UNLOCK(&w->state_lock); } if (status != 0) { @@ -345,23 +333,23 @@ sync_worker_state sync_worker_get_state(struct sync_worker *w, { sync_worker_state ret; - pthread_mutex_lock(&w->state_lock); + MUTEX_LOCK(&w->state_lock); ret = w->state; if (err_code) { *err_code = w->err_code; w->err_code = 0; } - pthread_mutex_unlock(&w->state_lock); + MUTEX_UNLOCK(&w->state_lock); return ret; } static void set_state(struct sync_worker *w, sync_worker_state state) { - pthread_mutex_lock(&w->state_lock); + MUTEX_LOCK(&w->state_lock); w->state = state; pthread_cond_signal(&w->state_changed); - pthread_mutex_unlock(&w->state_lock); + MUTEX_UNLOCK(&w->state_lock); } @@ -371,7 +359,7 @@ static sync_worker_state exec_idle_state(struct bladerf_sync *s) unsigned int requests; unsigned int i; - pthread_mutex_lock(&s->worker->request_lock); + MUTEX_LOCK(&s->worker->request_lock); while (s->worker->requests == 0) { log_verbose("%s worker: Waiting for pending requests\n", MODULE_STR(s)); @@ -382,7 +370,7 @@ static sync_worker_state exec_idle_state(struct bladerf_sync *s) requests = s->worker->requests; s->worker->requests = 0; - pthread_mutex_unlock(&s->worker->request_lock); + MUTEX_UNLOCK(&s->worker->request_lock); if (requests & SYNC_WORKER_STOP) { log_verbose("%s worker: Got request to stop\n", @@ -393,7 +381,7 @@ static sync_worker_state exec_idle_state(struct bladerf_sync *s) } else if (requests & SYNC_WORKER_START) { log_verbose("%s worker: Got request to start\n", module2str(s->stream_config.module)); - pthread_mutex_lock(&s->buf_mgmt.lock); + MUTEX_LOCK(&s->buf_mgmt.lock); if (s->stream_config.module == BLADERF_MODULE_TX) { /* If we've previously timed out on a stream, we'll likely have some @@ -418,7 +406,7 @@ static sync_worker_state exec_idle_state(struct bladerf_sync *s) } } - pthread_mutex_unlock(&s->buf_mgmt.lock); + MUTEX_UNLOCK(&s->buf_mgmt.lock); next_state = SYNC_WORKER_STATE_RUNNING; } else { @@ -433,23 +421,23 @@ static void exec_running_state(struct bladerf_sync *s) { int status; - status = bladerf_stream(s->worker->stream, s->stream_config.module); + status = async_run_stream(s->worker->stream, s->stream_config.module); log_verbose("%s worker: stream ended with: %s\n", MODULE_STR(s), bladerf_strerror(status)); /* Save off the result of running the stream so we can report what * happened to the API caller */ - pthread_mutex_lock(&s->worker->state_lock); + MUTEX_LOCK(&s->worker->state_lock); s->worker->err_code = status; - pthread_mutex_unlock(&s->worker->state_lock); + MUTEX_UNLOCK(&s->worker->state_lock); /* Wake the API-side if an error occurred, so that it can propagate * the stream error code back to the API caller */ if (status != 0) { - pthread_mutex_lock(&s->buf_mgmt.lock); + MUTEX_LOCK(&s->buf_mgmt.lock); pthread_cond_signal(&s->buf_mgmt.buf_ready); - pthread_mutex_unlock(&s->buf_mgmt.lock); + MUTEX_UNLOCK(&s->buf_mgmt.lock); } } diff --git a/host/libraries/libbladeRF/src/sync_worker.h b/host/libraries/libbladeRF/src/sync_worker.h index 325a4fa66..dca4a15aa 100644 --- a/host/libraries/libbladeRF/src/sync_worker.h +++ b/host/libraries/libbladeRF/src/sync_worker.h @@ -15,7 +15,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#if !defined(BLADERF_SYNC_WORKER_H_) && defined(ENABLE_LIBBLADERF_SYNC) +#ifndef BLADERF_SYNC_WORKER_H_ #define BLADERF_SYNC_WORKER_H_ #include "host_config.h" @@ -56,7 +56,7 @@ struct sync_worker { /* These items should be accessed while holding state_lock */ sync_worker_state state; int err_code; - pthread_mutex_t state_lock; + MUTEX state_lock; pthread_cond_t state_changed; /* Worker thread uses this to inform a * waiting main thread about a state * change */ @@ -66,7 +66,7 @@ struct sync_worker { */ unsigned int requests; pthread_cond_t requests_pending; - pthread_mutex_t request_lock; + MUTEX request_lock; }; /** diff --git a/host/libraries/libbladeRF/src/xb.c b/host/libraries/libbladeRF/src/xb.c index 52ed3e0e5..332c3fa91 100644 --- a/host/libraries/libbladeRF/src/xb.c +++ b/host/libraries/libbladeRF/src/xb.c @@ -22,13 +22,17 @@ #include #include #include -#include "rel_assert.h" -#include "log.h" -#include "version_compat.h" #include "libbladeRF.h" /* Public API */ #include "bladerf_priv.h" /* Implementation-specific items ("private") */ +#include "si5338.h" +#include "xb.h" +#include "lms.h" +#include "rel_assert.h" +#include "log.h" +#include "version_compat.h" + #define BLADERF_CONFIG_RX_SWAP_IQ 0x20000000 #define BLADERF_CONFIG_TX_SWAP_IQ 0x10000000 @@ -70,59 +74,59 @@ static int xb200_attach(struct bladerf *dev) { log_debug(" Attaching transverter board\n"); - if ((status = bladerf_si5338_write(dev, 39, 2))) + if ((status = SI5338_WRITE(dev, 39, 2))) return status; - if ((status = bladerf_si5338_write(dev, 34, 0x22))) + if ((status = SI5338_WRITE(dev, 34, 0x22))) return status; - if ((status = bladerf_config_gpio_read(dev, &val))) + if ((status = CONFIG_GPIO_READ(dev, &val))) return status; val |= 0x80000000; - if ((status = bladerf_config_gpio_write(dev, val))) + if ((status = CONFIG_GPIO_WRITE(dev, val))) return status; - if ((status = bladerf_expansion_gpio_read(dev, &val))) + if ((status = XB_GPIO_READ(dev, &val))) return status; - if ((status = bladerf_expansion_gpio_dir_write(dev, 0x3C003836))) + if ((status = XB_GPIO_DIR_WRITE(dev, 0x3C003836))) return status; - if ((status = bladerf_expansion_gpio_write(dev, 0x800))) + if ((status = XB_GPIO_WRITE(dev, 0x800))) return status; // Load ADF4351 registers via SPI // Refer to ADF4351 reference manual for register set // The LO is set to a Int-N 1248MHz +3dBm tone // Registers are written in order from 5 downto 0 - if ((status = bladerf_xb_spi_write(dev, 0x580005))) + if ((status = XB_SPI_WRITE(dev, 0x580005))) return status; - if ((status = bladerf_xb_spi_write(dev, 0x99A16C))) + if ((status = XB_SPI_WRITE(dev, 0x99A16C))) return status; - if ((status = bladerf_xb_spi_write(dev, 0xC004B3))) + if ((status = XB_SPI_WRITE(dev, 0xC004B3))) return status; log_debug(" MUXOUT: %s\n", mux_lut[muxout]); - if ((status = bladerf_xb_spi_write(dev, 0x60008E42 | (1<<8) | (muxout << 26)))) + if ((status = XB_SPI_WRITE(dev, 0x60008E42 | (1<<8) | (muxout << 26)))) return status; - if ((status = bladerf_xb_spi_write(dev, 0x08008011))) + if ((status = XB_SPI_WRITE(dev, 0x08008011))) return status; - if ((status = bladerf_xb_spi_write(dev, 0x00410000))) + if ((status = XB_SPI_WRITE(dev, 0x00410000))) return status; - status = bladerf_expansion_gpio_read(dev, &val); + status = XB_GPIO_READ(dev, &val); if (!status && (val & 0x1)) log_debug(" MUXOUT Bit set: OK\n"); else { log_debug(" MUXOUT Bit not set: FAIL\n"); } - status = bladerf_expansion_gpio_write(dev, 0x3C000800); + status = XB_GPIO_WRITE(dev, 0x3C000800); return status; } -int bladerf_expansion_attach(struct bladerf *dev, bladerf_xb xb) { +int xb_attach(struct bladerf *dev, bladerf_xb xb) { bladerf_xb attached; int status; - status = bladerf_expansion_get_attached(dev, &attached); + status = xb_get_attached(dev, &attached); if (status) return status; @@ -139,11 +143,11 @@ int bladerf_expansion_attach(struct bladerf *dev, bladerf_xb xb) { return 0; } -int bladerf_expansion_get_attached(struct bladerf *dev, bladerf_xb *xb) { +int xb_get_attached(struct bladerf *dev, bladerf_xb *xb) { int status; uint32_t val; - status = bladerf_config_gpio_read(dev, &val); + status = CONFIG_GPIO_READ(dev, &val); if (status) return status; @@ -151,11 +155,11 @@ int bladerf_expansion_get_attached(struct bladerf *dev, bladerf_xb *xb) { return 0; } -int bladerf_xb200_enable(struct bladerf *dev, bool enable) { +int xb200_enable(struct bladerf *dev, bool enable) { int status; uint32_t val, orig; - status = bladerf_expansion_gpio_read(dev, &orig); + status = XB_GPIO_READ(dev, &orig); if (status) return status; @@ -168,14 +172,14 @@ int bladerf_xb200_enable(struct bladerf *dev, bool enable) { if (status || (val == orig)) return status; - return bladerf_expansion_gpio_write(dev, val); + return XB_GPIO_WRITE(dev, val); } -int bladerf_xb200_get_filterbank(struct bladerf *dev, bladerf_module module, bladerf_xb200_filter *filter) { +int xb200_get_filterbank(struct bladerf *dev, bladerf_module module, bladerf_xb200_filter *filter) { int status; uint32_t val; - status = bladerf_expansion_gpio_read(dev, &val); + status = XB_GPIO_READ(dev, &val); if (status) return status; @@ -183,7 +187,7 @@ int bladerf_xb200_get_filterbank(struct bladerf *dev, bladerf_module module, bla return 0; } -int bladerf_xb200_set_filterbank(struct bladerf *dev, bladerf_module module, bladerf_xb200_filter filter) { +int xb200_set_filterbank(struct bladerf *dev, bladerf_module module, bladerf_xb200_filter filter) { int status; uint32_t orig, val, bits; @@ -197,16 +201,16 @@ int bladerf_xb200_set_filterbank(struct bladerf *dev, bladerf_module module, bla } } - status = bladerf_expansion_gpio_read(dev, &orig); + status = XB_GPIO_READ(dev, &orig); val = orig & ~bits; val |= filter << ((module == BLADERF_MODULE_RX) ? BLADERF_XB_RX_SHIFT : BLADERF_XB_TX_SHIFT); if (status || (orig == val)) return status; - return bladerf_expansion_gpio_write(dev, val); + return XB_GPIO_WRITE(dev, val); } -int bladerf_xb200_auto_filter_selection(struct bladerf *dev, bladerf_module mod, unsigned int frequency) { +int xb200_auto_filter_selection(struct bladerf *dev, bladerf_module mod, unsigned int frequency) { int status; bladerf_xb200_filter filter; @@ -227,7 +231,7 @@ int bladerf_xb200_auto_filter_selection(struct bladerf *dev, bladerf_module mod, } else { filter = BLADERF_XB200_CUSTOM; } - status = bladerf_xb200_set_filterbank(dev, mod, filter); + status = xb200_set_filterbank(dev, mod, filter); } if ((mod == BLADERF_MODULE_RX && dev->rx_filter == BLADERF_XB200_AUTO_3DB) || @@ -241,13 +245,13 @@ int bladerf_xb200_auto_filter_selection(struct bladerf *dev, bladerf_module mod, } else { filter = BLADERF_XB200_CUSTOM; } - status = bladerf_xb200_set_filterbank(dev, mod, filter); + status = xb200_set_filterbank(dev, mod, filter); } return status; } -int bladerf_xb200_set_path(struct bladerf *dev, bladerf_module module, bladerf_xb200_path path) { +int xb200_set_path(struct bladerf *dev, bladerf_module module, bladerf_xb200_path path) { int status; uint32_t val; bool enable; @@ -256,7 +260,7 @@ int bladerf_xb200_set_path(struct bladerf *dev, bladerf_module module, bladerf_x enable = (path == BLADERF_XB200_MIX); - status = bladerf_lms_read( dev, 0x5A, &lorig ); + status = LMS_READ( dev, 0x5A, &lorig ); if (status) return status; lval = lorig; @@ -272,16 +276,16 @@ int bladerf_xb200_set_path(struct bladerf *dev, bladerf_module module, bladerf_x if (status || (lorig == lval)) return status; - status = bladerf_lms_write(dev, 0x5A, lval); + status = LMS_WRITE(dev, 0x5A, lval); if (status) return status; - status = bladerf_expansion_gpio_read(dev, &val); + status = XB_GPIO_READ(dev, &val); if (status) return status; if (enable) { - status = bladerf_expansion_gpio_read(dev, &val); + status = XB_GPIO_READ(dev, &val); if (status) return status; if (!(val & BLADERF_XB_RF_ON)) { @@ -300,14 +304,14 @@ int bladerf_xb200_set_path(struct bladerf *dev, bladerf_module module, bladerf_x else val |= enable ? (BLADERF_XB_TX_ENABLE | BLADERF_XB_CONFIG_TX_BYPASS) : BLADERF_XB_CONFIG_TX_BYPASS_N; - return bladerf_expansion_gpio_write(dev, val); + return XB_GPIO_WRITE(dev, val); } -int bladerf_xb200_get_path(struct bladerf *dev, bladerf_module module, bladerf_xb200_path *path) { +int xb200_get_path(struct bladerf *dev, bladerf_module module, bladerf_xb200_path *path) { int status; uint32_t val; - status = bladerf_expansion_gpio_read(dev, &val); + status = XB_GPIO_READ(dev, &val); if (status) return status; if (module == BLADERF_MODULE_RX) diff --git a/host/libraries/libbladeRF/src/xb.h b/host/libraries/libbladeRF/src/xb.h index 72badb86c..d72ebe60f 100644 --- a/host/libraries/libbladeRF/src/xb.h +++ b/host/libraries/libbladeRF/src/xb.h @@ -26,9 +26,49 @@ #define XB_H_ #include +#include "bladerf_priv.h" + +#define XB_SPI_WRITE(dev, val) dev->fn->xb_spi(dev, val) +#define XB_GPIO_READ(dev, val) dev->fn->expansion_gpio_read(dev, val) +#define XB_GPIO_WRITE(dev, val) dev->fn->expansion_gpio_write(dev, val) +#define XB_GPIO_DIR_READ(dev, val) dev->fn->expansion_gpio_dir_read(dev, val) +#define XB_GPIO_DIR_WRITE(dev, val) dev->fn->expansion_gpio_dir_write(dev, val) + +/** + * Attach and enable an expansion board's features + * + * @param dev Device handle + * @param xb Expansion board + * + * @return 0 on success, BLADERF_ERR_* on failure + */ +int xb_attach(struct bladerf *dev, bladerf_xb xb); + +/** + * Determine which expansion board is attached + * + * @param dev Device handle + * @param xb Expansion board + * + * @return 0 on success, BLADERF_ERR_* on failure + */ +int xb_get_attached(struct bladerf *dev, bladerf_xb *xb); + +/** + * Select an XB-200 filterbank + * + * @param dev Device handle + * @param mod Module + * @param filter XB200 filterbank + * + * @return 0 on success, BLADERF_ERR_* on failure + */ +int xb200_set_filterbank(struct bladerf *dev, + bladerf_module mod, + bladerf_xb200_filter filter); /** - * Filterbank autoselection helper function + * Select an appropriate filterbank, based upon the specified frequency * * @param[in] dev Device handle * @param[in] mod Module to change @@ -36,6 +76,46 @@ * * @return 0 on success, BLADERF_ERR_* value on failure */ -int bladerf_xb200_auto_filter_selection(struct bladerf *dev, bladerf_module mod, unsigned int frequency); +int xb200_auto_filter_selection(struct bladerf *dev, bladerf_module mod, + unsigned int frequency); + +/** + * Get the current selected XB-200 filterbank + * + * @param[in] dev Device handle + * @param[in] module Module to query + * @param[out] filter Pointer to filterbank, only updated if return + * value is 0. + * + * @return 0 on success, BLADERF_ERR_* on failure + */ +int xb200_get_filterbank(struct bladerf *dev, + bladerf_module module, + bladerf_xb200_filter *filter); +/** + * Configure the XB-200 signal path + * + * @param dev Device handle + * @param module Module to configure + * @param path Desired XB-200 signal path + * + * @return 0 on success, BLADERF_ERR_* on failure + */ +int xb200_set_path(struct bladerf *dev, + bladerf_module module, + bladerf_xb200_path path); + +/** + * Get the current XB-200 signal path + * + * @param dev Device handle + * @param module Module to query + * @param path Pointer to XB200 signal path + * + * @return 0 on success, value from \ref RETCODES list on failure + */ +int xb200_get_path(struct bladerf *dev, + bladerf_module module, + bladerf_xb200_path *path); #endif /* XB_H_ */