From 1cd0d8735f1a30540a1ffd5b2ee8ce992bcc93c4 Mon Sep 17 00:00:00 2001 From: Edouard Griffiths Date: Wed, 23 Mar 2016 16:49:58 +0100 Subject: [PATCH] Windows build: Compilable libbladerf library --- libbladerf/include/backend/backend_config.h | 86 ++++ libbladerf/include/host_config.h | 240 +++++++++ libbladerf/include/version.h | 10 + libbladerf/libbladerf.pro | 96 ++++ libbladerf/src/file_ops.c | 523 ++++++++++++++++++++ sdrangel.windows.pro | 1 + windows.install.bat | 1 + 7 files changed, 957 insertions(+) create mode 100644 libbladerf/include/backend/backend_config.h create mode 100644 libbladerf/include/host_config.h create mode 100644 libbladerf/include/version.h create mode 100644 libbladerf/libbladerf.pro create mode 100644 libbladerf/src/file_ops.c diff --git a/libbladerf/include/backend/backend_config.h b/libbladerf/include/backend/backend_config.h new file mode 100644 index 000000000..5cf57a0b1 --- /dev/null +++ b/libbladerf/include/backend/backend_config.h @@ -0,0 +1,86 @@ +/** + * @file backend_config.h + * + * @brief Compile-time backend selection + * + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2013 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_BACKEND_CONFIG_H__ +#define BLADERF_BACKEND_CONFIG_H__ + +#define ENABLE_BACKEND_USB +#define ENABLE_BACKEND_LIBUSB +/* #undef ENABLE_BACKEND_CYAPI */ +/* #undef ENABLE_BACKEND_DUMMY */ +/* #undef ENABLE_BACKEND_LINUX_DRIVER */ + +#include "backend/backend.h" +#include "backend/usb/usb.h" + +#ifdef ENABLE_BACKEND_DUMMY + extern const struct backend_fns backend_fns_dummy; +# define BACKEND_DUMMY &backend_fns_dummy, +#else +# define BACKEND_DUMMY +#endif + +#ifdef ENABLE_BACKEND_USB + extern const struct backend_fns backend_fns_usb; +# define BACKEND_USB &backend_fns_usb, + +# ifdef ENABLE_BACKEND_LIBUSB + extern const struct usb_driver usb_driver_libusb; +# define BACKEND_USB_LIBUSB &usb_driver_libusb, +# else +# define BACKEND_USB_LIBUSB +# endif + +# ifdef ENABLE_BACKEND_CYAPI + extern const struct usb_driver usb_driver_cypress; +# define BACKEND_USB_CYAPI &usb_driver_cypress, +# else +# define BACKEND_USB_CYAPI +# endif + + +# define BLADERF_USB_BACKEND_LIST { \ + BACKEND_USB_LIBUSB \ + BACKEND_USB_CYAPI \ + } + +# if !defined(ENABLE_BACKEND_LIBUSB) && !defined(ENABLE_BACKEND_CYAPI) +# error "No USB backends are enabled. One or more must be enabled." +# endif +#else +# define BACKEND_USB +#endif + +#if !defined(ENABLE_BACKEND_USB) && \ + !defined(ENABLE_BACKEND_DUMMY) + #error "No backends are enabled. One more more must be enabled." +#endif + +/* This list should be ordered by preference (highest first) */ +#define BLADERF_BACKEND_LIST { \ + BACKEND_USB \ + BACKEND_DUMMY \ +} + +#endif diff --git a/libbladerf/include/host_config.h b/libbladerf/include/host_config.h new file mode 100644 index 000000000..cde9cf819 --- /dev/null +++ b/libbladerf/include/host_config.h @@ -0,0 +1,240 @@ +/** + * @file host_config.h.in + * + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (c) 2013 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 HOST_CONFIG_H__ +#define HOST_CONFIG_H__ + +#define BLADERF_OS_LINUX 0 +#define BLADERF_OS_FREEBSD 0 +#define BLADERF_OS_OSX 0 +#define BLADERF_OS_WINDOWS 1 +#define BLADERF_BIG_ENDIAN 0 + +#if !(BLADERF_OS_LINUX || BLADERF_OS_OSX || BLADERF_OS_WINDOWS || BLADERF_OS_FREEBSD) +# error "Build not configured for any supported operating systems" +#endif + +#if 1 < (BLADERF_OS_LINUX + BLADERF_OS_OSX + BLADERF_OS_WINDOWS + BLADERF_OS_FREEBSD) +#error "Build configured for multiple operating systems" +#endif + + +/******************************************************************************* + * Endianness conversions + * + * HOST_TO_LE16 16-bit host endianness to little endian conversion + * LE16_TO_HOST 16-bit little endian to host endianness conversion + * HOST_TO_BE16 16-bit host endianness to big endian conversion + * BE16_TO_HOST 16-bit big endian to host endianness conversion + * HOST_TO_LE32 32-bit host endianness to little endian conversion + * LE32_TO_HOST 32-bit little endian to host endianness conversion + * HOST_TO_BE32 32-bit host endianness to big endian conversion + * BE32_TO_HOST 32-bit big endian to host endianness conversion + * HOST_TO_BE64 64-bit host endianness to big endian conversion + * BE64_TO_HOST 64-bit big endian to host endianness conversion + ******************************************************************************/ + +/*----------------------- + * Linux + *---------------------*/ +#if BLADERF_OS_LINUX +#include + +#define HOST_TO_LE16(val) htole16(val) +#define LE16_TO_HOST(val) le16toh(val) +#define HOST_TO_BE16(val) htobe16(val) +#define BE16_TO_HOST(val) be16toh(val) + +#define HOST_TO_LE32(val) htole32(val) +#define LE32_TO_HOST(val) le32toh(val) +#define HOST_TO_BE32(val) htobe32(val) +#define BE32_TO_HOST(val) be32toh(val) + +#define HOST_TO_LE64(val) htole64(val) +#define LE64_TO_HOST(val) le64toh(val) +#define HOST_TO_BE64(val) be64toh(val) +#define BE64_TO_HOST(val) be64toh(val) + +/*----------------------- + * FREEBSD + *---------------------*/ +#elif BLADERF_OS_FREEBSD +#include + +#define HOST_TO_LE16(val) htole16(val) +#define LE16_TO_HOST(val) le16toh(val) +#define HOST_TO_BE16(val) htobe16(val) +#define BE16_TO_HOST(val) be16toh(val) + +#define HOST_TO_LE32(val) htole32(val) +#define LE32_TO_HOST(val) le32toh(val) +#define HOST_TO_BE32(val) htobe32(val) +#define BE32_TO_HOST(val) be32toh(val) + +#define HOST_TO_LE64(val) htole64(val) +#define LE64_TO_HOST(val) le64toh(val) +#define HOST_TO_BE64(val) be64toh(val) +#define BE64_TO_HOST(val) be64toh(val) + +/*----------------------- + * Apple OSX + *---------------------*/ +#elif BLADERF_OS_OSX +#include + +#define HOST_TO_LE16(val) OSSwapHostToLittleInt16(val) +#define LE16_TO_HOST(val) OSSwapLittleToHostInt16(val) +#define HOST_TO_BE16(val) OSSwapHostToBigInt16(val) +#define BE16_TO_HOST(val) OSSwapBigToHostInt16(val) + +#define HOST_TO_LE32(val) OSSwapHostToLittleInt32(val) +#define LE32_TO_HOST(val) OSSwapLittleToHostInt32(val) +#define HOST_TO_BE32(val) OSSwapHostToBigInt32(val) +#define BE32_TO_HOST(val) OSSwapBigToHostInt32(val) + +#define HOST_TO_LE64(val) OSSwapHostToLittleInt64(val) +#define LE64_TO_HOST(val) OSSwapLittleToHostInt64(val) +#define HOST_TO_BE64(val) OSSwapHostToBigInt64(val) +#define BE64_TO_HOST(val) OSSwapBigToHostInt64(val) + +/*----------------------- + * Windows + *---------------------*/ +#elif BLADERF_OS_WINDOWS +#include + +/* We'll assume little endian for Windows platforms: + * http://blogs.msdn.com/b/larryosterman/archive/2005/06/07/426334.aspx + */ +#define HOST_TO_LE16(val) (val) +#define LE16_TO_HOST(val) (val) +#define HOST_TO_BE16(val) _byteswap_ushort(val) +#define BE16_TO_HOST(val) _byteswap_ushort(val) + +#define HOST_TO_LE32(val) (val) +#define LE32_TO_HOST(val) (val) +#define HOST_TO_BE32(val) _byteswap_ulong(val) +#define BE32_TO_HOST(val) _byteswap_ulong(val) + + +#define HOST_TO_LE64(val) (val) +#define LE64_TO_HOST(val) (val) +#define HOST_TO_BE64(val) _byteswap_uint64(val) +#define BE64_TO_HOST(val) _byteswap_uint64(val) + +/*----------------------- + * Unsupported or bug + *---------------------*/ +#else +#error "Encountered an OS that we do not have endian wrappers for?" +#endif + +/******************************************************************************* + * Miscellaneous Linux fixups + ******************************************************************************/ +#if BLADERF_OS_LINUX + +/* Added here just to keep this out of the other source files. We'll have + * a few Windows replacements for unistd.h items. */ +#include +#include + +/******************************************************************************* + * Miscellaneous FREEBSD fixups + ******************************************************************************/ +#elif BLADERF_OS_FREEBSD + +#include +#include +#include + +/******************************************************************************* + * Miscellaneous OSX fixups + ******************************************************************************/ +#elif BLADERF_OS_OSX + +#include +#include + +/******************************************************************************* + * Miscellaneous Windows fixups + ******************************************************************************/ +#elif BLADERF_OS_WINDOWS + +/* Rename a few functions and types */ +#include +#include +#define usleep(x) Sleep((x+999)/1000) + +/* Changes specific to Microsoft Visual Studio and its C89-compliant ways */ +#if _MSC_VER +# define strtok_r strtok_s +# define strtoull _strtoui64 +# define snprintf _snprintf +# define vsnprintf _vsnprintf +# define strcasecmp _stricmp +# define strncasecmp _strnicmp +# define fileno _fileno +# define strdup _strdup +# define access _access + +/* ssize_t lives elsewhere */ +# include +# define ssize_t SSIZE_T + +/* With msvc, inline is only available for C++. Otherwise we need to use __inline: + * http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx */ +# if !defined(__cplusplus) +# define inline __inline +# endif + +#endif // _MSC_VER + +#endif + +/* Windows (msvc) does not support C99 designated initializers. + * + * Therefore, the following macro should be used. However, note that you'll + * need to be sure to keep your elements in order to avoid breaking Windows + * portability! + * + * http://stackoverflow.com/questions/5440611/how-to-rewrite-c-struct-designated-initializers-to-c89-resp-msvc-c-compiler + * + * Here's a sample regexep you could use in vim to clean these up in your code: + * @\(\s\+\)\(\.[a-zA-Z0-9_]\+\)\s*=\s*\([a-zA-Z0-9_]\+\)\(,\)\?@\1FIELD_INIT(\2,\3)\4@gc + */ +#if _MSC_VER +# define FIELD_INIT(field, ...) __VA_ARGS__ +#else +# define FIELD_INIT(field, ...) field = __VA_ARGS__ +#endif // _MSC_VER + +/******************************************************************************* + * Miscellaneous utility macros + ******************************************************************************/ +#define ARRAY_SIZE(n) (sizeof(n) / sizeof(n[0])) + +#endif diff --git a/libbladerf/include/version.h b/libbladerf/include/version.h new file mode 100644 index 000000000..8547cf98f --- /dev/null +++ b/libbladerf/include/version.h @@ -0,0 +1,10 @@ +#ifndef VERSION_H__ +#define VERSION_H__ + +#define LIBBLADERF_VERSION "1.5.1-git-unknown" + +#define LIBBLADERF_VERSION_MAJOR 1 +#define LIBBLADERF_VERSION_MINOR 5 +#define LIBBLADERF_VERSION_PATCH 1 + +#endif diff --git a/libbladerf/libbladerf.pro b/libbladerf/libbladerf.pro new file mode 100644 index 000000000..f1d1c5ca9 --- /dev/null +++ b/libbladerf/libbladerf.pro @@ -0,0 +1,96 @@ +#-------------------------------------------------------- +# +# Pro file for Android and Windows builds with Qt Creator +# +#-------------------------------------------------------- + +QT += core + +TEMPLATE = lib +TARGET = libbladerf + +CONFIG(MINGW32):LIBBLADERFSRC = "D:\softs\bladeRF" +CONFIG(MINGW32):LIBBLADERFCOMMONSRC = "D:\softs\bladeRF\host\common" +CONFIG(MINGW32):LIBBLADERFLIBSRC = "D:\softs\bladeRF\host\libraries\libbladeRF" +INCLUDEPATH += $$LIBBLADERFLIBSRC/include +INCLUDEPATH += $$LIBBLADERFLIBSRC/src +INCLUDEPATH += $$LIBBLADERFSRC/firmware_common +INCLUDEPATH += $$LIBBLADERFSRC/fpga_common/include +INCLUDEPATH += $$LIBBLADERFCOMMONSRC/include +INCLUDEPATH += $$LIBBLADERFCOMMONSRC/include/windows +INCLUDEPATH += $$PWD/include + +CONFIG(MINGW32):INCLUDEPATH += "D:\libusb-1.0.19\include\libusb-1.0" + +SOURCES = $$LIBBLADERFLIBSRC/src/async.c\ + $$LIBBLADERFLIBSRC/src/bladerf_priv.c\ + $$LIBBLADERFLIBSRC/src/config.c\ + $$LIBBLADERFLIBSRC/src/device_identifier.c\ + $$PWD/src/file_ops.c\ + $$LIBBLADERFLIBSRC/src/flash_fields.c\ + $$LIBBLADERFLIBSRC/src/fx3_fw.c\ + $$LIBBLADERFLIBSRC/src/gain.c\ + $$LIBBLADERFLIBSRC/src/init_fini.c\ + $$LIBBLADERFLIBSRC/src/sync.c\ + $$LIBBLADERFLIBSRC/src/tuning.c\ + $$LIBBLADERFLIBSRC/src/xb.c\ + $$LIBBLADERFLIBSRC/src/bladerf.c\ + $$LIBBLADERFLIBSRC/src/capabilities.c\ + $$LIBBLADERFLIBSRC/src/dc_cal_table.c\ + $$LIBBLADERFLIBSRC/src/devinfo.c\ + $$LIBBLADERFLIBSRC/src/flash.c\ + $$LIBBLADERFLIBSRC/src/fpga.c\ + $$LIBBLADERFLIBSRC/src/fx3_fw_log.c\ + $$LIBBLADERFLIBSRC/src/image.c\ + $$LIBBLADERFLIBSRC/src/si5338.c\ + $$LIBBLADERFLIBSRC/src/sync_worker.c\ + $$LIBBLADERFLIBSRC/src/version_compat.c\ + $$LIBBLADERFLIBSRC/src/backend/backend.c\ + $$LIBBLADERFLIBSRC/src/backend/dummy.c\ + $$LIBBLADERFLIBSRC/src/backend/usb/libusb.c\ + $$LIBBLADERFLIBSRC/src/backend/usb/usb.c\ + $$LIBBLADERFLIBSRC/src/backend/usb/nios_access.c\ + $$LIBBLADERFLIBSRC/src/backend/usb/nios_legacy_access.c\ + $$LIBBLADERFSRC/fpga_common/src/band_select.c\ + $$LIBBLADERFSRC/fpga_common/src/lms.c\ + $$LIBBLADERFCOMMONSRC/src/conversions.c\ + $$LIBBLADERFCOMMONSRC/src/devcfg.c\ + $$LIBBLADERFCOMMONSRC/src/sha256.c + +HEADERS = $$LIBBLADERFLIBSRC/src/async.h\ + $$LIBBLADERFLIBSRC/src/capabilities.h\ + $$LIBBLADERFLIBSRC/src/dc_cal_table.h\ + $$LIBBLADERFLIBSRC/src/devinfo.h\ + $$LIBBLADERFLIBSRC/src/flash.h\ + $$LIBBLADERFLIBSRC/src/fpga.h\ + $$LIBBLADERFLIBSRC/src/fx3_fw_log.h\ + $$LIBBLADERFLIBSRC/src/metadata.h\ + $$LIBBLADERFLIBSRC/src/sync.h\ + $$LIBBLADERFLIBSRC/src/tuning.h\ + $$LIBBLADERFLIBSRC/src/xb.h\ + $$LIBBLADERFLIBSRC/src/bladerf_priv.h\ + $$LIBBLADERFLIBSRC/src/config.h\ + $$LIBBLADERFLIBSRC/src/device_identifier.h\ + $$LIBBLADERFLIBSRC/src/file_ops.h\ + $$LIBBLADERFLIBSRC/src/flash_fields.h\ + $$LIBBLADERFLIBSRC/src/fx3_fw.h\ + $$LIBBLADERFLIBSRC/src/gain.h\ + $$LIBBLADERFLIBSRC/src/si5338.h\ + $$LIBBLADERFLIBSRC/src/sync_worker.h\ + $$LIBBLADERFLIBSRC/src/version_compat.h\ + $$LIBBLADERFLIBSRC/src/backend/backend.h\ + $$LIBBLADERFLIBSRC/src/backend/dummy.h\ + $$LIBBLADERFLIBSRC/src/backend/usb/usb.h\ + $$LIBBLADERFLIBSRC/src/backend/usb/nios_access.h\ + $$LIBBLADERFLIBSRC/src/backend/usb/nios_legacy_access.h\ + $$LIBBLADERFSRC/fpga_common/include/band_select.h\ + $$LIBBLADERFSRC/fpga_common/include/lms.h\ + $$LIBBLADERFCOMMONSRC/include/sha256.h\ + $$PWD/include/host_config.h\ + $$PWD/include/backend/backend_config.h\ + $$PWD/include/version.h + +CONFIG(MINGW32):LIBS += -LD:\libusb-1.0.19\MinGW32\dll -llibusb-1.0 + +CONFIG(ANDROID):CONFIG += mobility +CONFIG(ANDROID):MOBILITY = diff --git a/libbladerf/src/file_ops.c b/libbladerf/src/file_ops.c new file mode 100644 index 000000000..c710a90bf --- /dev/null +++ b/libbladerf/src/file_ops.c @@ -0,0 +1,523 @@ +/* + * This file is part of the bladeRF project: + * http://www.github.com/nuand/bladeRF + * + * Copyright (C) 2013-2014 Nuand LLC + * Copyright (C) 2013 Daniel Gröber + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "host_config.h" +#include "file_ops.h" +#include "minmax.h" +#include "log.h" +#include "rel_assert.h" + +#define LOCAL_BLADERF_OS_LINUX 1 + +/* Paths to search for bladeRF files */ +struct search_path_entries { + bool prepend_home; + const char *path; +}; + +int file_write(FILE *f, uint8_t *buf, size_t len) +{ + size_t rv; + + rv = fwrite(buf, 1, len, f); + if(rv < len) { + log_debug("File write failed: %s\n", strerror(errno)); + return BLADERF_ERR_IO; + } + + return 0; +} + +int file_read(FILE *f, char *buf, size_t len) +{ + size_t rv; + + rv = fread(buf, 1, len, f); + if(rv < len) { + if(feof(f)) + log_debug("Unexpected end of file: %s\n", strerror(errno)); + else + log_debug("Error reading file: %s\n", strerror(errno)); + + return BLADERF_ERR_IO; + } + + return 0; +} + +ssize_t file_size(FILE *f) +{ + ssize_t rv = BLADERF_ERR_IO; + long int fpos = ftell(f); + long len; + + if(fpos < 0) { + log_verbose("ftell failed: %s\n", strerror(errno)); + goto out; + } + + if(fseek(f, 0, SEEK_END)) { + log_verbose("fseek failed: %s\n", strerror(errno)); + goto out; + } + + len = ftell(f); + if(len < 0) { + log_verbose("ftell failed: %s\n", strerror(errno)); + goto out; + } else if (len == LONG_MAX) { + log_debug("ftell called with a directory?\n"); + goto out; + } + + if(fseek(f, fpos, SEEK_SET)) { + log_debug("fseek failed: %s\n", strerror(errno)); + goto out; + } + + rv = (ssize_t) len; + assert(rv == len); + +out: + return rv; +} + +int file_read_buffer(const char *filename, uint8_t **buf_ret, size_t *size_ret) +{ + int status = BLADERF_ERR_UNEXPECTED; + FILE *f; + uint8_t *buf = NULL; + ssize_t len; + + f = fopen(filename, "rb"); + if (!f) { + switch (errno) { + case ENOENT: + return BLADERF_ERR_NO_FILE; + + case EACCES: + return BLADERF_ERR_PERMISSION; + + default: + return BLADERF_ERR_IO; + } + } + + len = file_size(f); + if(len < 0) { + status = BLADERF_ERR_IO; + goto out; + } + + buf = (uint8_t*) malloc(len); + if (!buf) { + status = BLADERF_ERR_MEM; + goto out; + } + + status = file_read(f, (char*)buf, len); + if (status < 0) { + goto out; + } + + *buf_ret = buf; + *size_ret = len; + fclose(f); + return 0; + +out: + free(buf); + if (f) { + fclose(f); + } + + return status; +} + +/* Remove the last entry in a path. This is used to strip the executable name +* from a path to get the directory that the executable resides in. */ +static size_t strip_last_path_entry(char *buf, char dir_delim) +{ + size_t len = strlen(buf); + + while (len > 0 && buf[len - 1] != dir_delim) { + buf[len - 1] = '\0'; + len--; + } + + return len; +} + +#if LOCAL_BLADERF_OS_LINUX || LOCAL_BLADERF_OS_OSX || LOCAL_BLADERF_OS_FREEBSD +#define ACCESS_FILE_EXISTS F_OK +#define DIR_DELIMETER '/' + +static const struct search_path_entries search_paths[] = { + { false, "" }, + { true, "/.config/Nuand/bladeRF/" }, + { true, "/.Nuand/bladeRF/" }, + + /* LIBBLADERF_SEARCH_PATH_PREFIX is defined in the libbladeRF + * CMakeLists.txt file. It defaults to ${CMAKE_INSTALL_PREFIX}, but + * can be overridden via -DLIBBLADERF_SEARCH_PATH_OVERRIDE + */ + // { false, LIBBLADERF_SEARCH_PREFIX "/etc/Nuand/bladeRF/" }, + // { false, LIBBLADERF_SEARCH_PREFIX "/share/Nuand/bladeRF/" }, + + /* These two entries are here for reverse compatibility. + * + * We failed to prefix ${CMAKE_INSTALL_PREFIX} on these from the beginning, + * forcing package maintainers to hard-code one of these locations, + * despite having a different ${CMAKE_INSTALL_PREFIX}. + * + * We'll keep these around for some time as fall-backs, as not to break + * existing packaging scripts. + */ + { false, "/etc/Nuand/bladeRF/" }, + { false, "/usr/share/Nuand/bladeRF/" }, +}; + +static inline size_t get_home_dir(char *buf, size_t max_len) +{ + // const char *home; + // + // home = getenv("HOME"); + // if (home != NULL && strlen(home) > 0 && strlen(home) < max_len) { + // strncat(buf, home, max_len); + // } else { + // const struct passwd *passwd; + // const uid_t uid = getuid(); + // passwd = getpwuid(uid); + // strncat(buf, passwd->pw_dir, max_len); + // } + strcpy(buf, "/"); + + return strlen(buf); +} + +static inline size_t get_install_dir(char *buf, size_t max_len) +{ + return 0; +} + +#if LOCAL_BLADERF_OS_LINUX +static inline size_t get_binary_dir(char *buf, size_t max_len) +{ + return 0; + + // ssize_t result = readlink("/proc/self/exe", buf, max_len); + // + // if (result > 0) { + // return strip_last_path_entry(buf, DIR_DELIMETER); + // } else { + // return 0; + // } +} +#elif LOCAL_BLADERF_OS_FREEBSD +static inline size_t get_binary_dir(char *buf, size_t max_len) +{ + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + ssize_t result = sysctl(mib, 4, buf, &max_len, NULL, 0); + + if (result > 0) { + return strip_last_path_entry(buf, DIR_DELIMETER); + } else { + return 0; + } +} +#elif LOCAL_BLADERF_OS_OSX +#include +static inline size_t get_binary_dir(char *buf, size_t max_len) +{ + uint32_t buf_size = max_len; + int status = _NSGetExecutablePath(buf, &buf_size); + + if (status == 0) { + return strip_last_path_entry(buf, DIR_DELIMETER); + } else { + return 0; + } + +} +#endif + +#elif LOCAL_BLADERF_OS_WINDOWS +#define ACCESS_FILE_EXISTS 0 +#define DIR_DELIMETER '\\' +#include + +static const struct search_path_entries search_paths[] = { + { false, "" }, + { true, "/Nuand/bladeRF/" }, +}; + +static inline size_t get_home_dir(char *buf, size_t max_len) +{ + /* Explicitly link to a runtime DLL to get SHGetKnownFolderPath. + * This deals with the case where we might not be able to staticly + * link it at build time, e.g. mingw32. + * + * http://msdn.microsoft.com/en-us/library/784bt7z7.aspx + */ + typedef HRESULT (CALLBACK* LPFNSHGKFP_T)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR*); + HINSTANCE hDLL; // Handle to DLL + LPFNSHGKFP_T lpfnSHGetKnownFolderPath; // Function pointer + + const KNOWNFOLDERID folder_id = FOLDERID_RoamingAppData; + PWSTR path; + HRESULT status; + + assert(max_len < INT_MAX); + + hDLL = LoadLibrary("Shell32"); + if (hDLL == NULL) { + // DLL couldn't be loaded, bail out. + return 0; + } + + lpfnSHGetKnownFolderPath = (LPFNSHGKFP_T)GetProcAddress(hDLL, "SHGetKnownFolderPath"); + + if (!lpfnSHGetKnownFolderPath) { + // Can't find the procedure we want. Free and bail. + FreeLibrary(hDLL); + return 0; + } + + status = lpfnSHGetKnownFolderPath(&folder_id, 0, NULL, &path); + if (status == S_OK) { + WideCharToMultiByte(CP_ACP, 0, path, -1, buf, (int)max_len, NULL, NULL); + CoTaskMemFree(path); + } + + FreeLibrary(hDLL); + + return strlen(buf); +} + +static inline size_t get_binary_dir(char *buf, size_t max_len) +{ + DWORD status; + + assert(max_len <= MAXDWORD); + status = GetModuleFileName(NULL, buf, (DWORD) max_len); + + if (status > 0) { + return strip_last_path_entry(buf, DIR_DELIMETER); + } else { + return 0; + } +} + +static inline size_t get_install_dir(char *buf, size_t max_len) +{ + typedef LONG (CALLBACK* LPFNREGOPEN_T)(HKEY, LPCTSTR, DWORD, REGSAM, PHKEY); + typedef LONG (CALLBACK* LPFNREGQUERY_T)(HKEY, LPCTSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD); + typedef LONG (CALLBACK* LPFNREGCLOSE_T)(HKEY); + + HINSTANCE hDLL; // Handle to DLL + LPFNREGOPEN_T lpfnRegOpenKeyEx; // Function pointer + LPFNREGQUERY_T lpfnRegQueryValueEx; // Function pointer + LPFNREGCLOSE_T lpfnRegCloseKey; // Function pointer + HKEY hk; + DWORD len; + + assert(max_len < INT_MAX); + + memset(buf, 0, max_len); + hDLL = LoadLibrary("Advapi32"); + if (hDLL == NULL) { + // DLL couldn't be loaded, bail out. + return 0; + } + + lpfnRegOpenKeyEx = (LPFNREGOPEN_T)GetProcAddress(hDLL, "RegOpenKeyExA"); + if (!lpfnRegOpenKeyEx) { + // Can't find the procedure we want. Free and bail. + FreeLibrary(hDLL); + return 0; + } + + lpfnRegQueryValueEx = (LPFNREGQUERY_T)GetProcAddress(hDLL, "RegQueryValueExA"); + if (!lpfnRegQueryValueEx) { + // Can't find the procedure we want. Free and bail. + FreeLibrary(hDLL); + return 0; + } + + lpfnRegCloseKey = (LPFNREGCLOSE_T)GetProcAddress(hDLL, "RegCloseKey"); + if (!lpfnRegCloseKey) { + // Can't find the procedure we want. Free and bail. + FreeLibrary(hDLL); + return 0; + } + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Nuand LLC", 0, KEY_READ, &hk)) { + FreeLibrary(hDLL); + return 0; + } + + len = (DWORD)max_len; + if (RegQueryValueEx(hk, "Path", 0, NULL, (LPBYTE) buf, &len) == ERROR_SUCCESS) { + if (len > 0 && len < max_len && buf[len - 1] != '\\') + strcat(buf, "\\"); + } else + len = 0; + + if (len) { + lpfnRegCloseKey(hk); + } + + FreeLibrary(hDLL); + + return len; +} + +#else +#error "Unknown OS or missing BLADERF_OS_* definition" +#endif + +/* We're not using functions that use the *nix PATH_MAX (which is known to be + * problematic), or the WIN32 MAX_PATH. Therefore, we'll just use this + * arbitrary, but "sufficiently" large max buffer size for paths */ +#define PATH_MAX_LEN 4096 + +char *file_find(const char *filename) +{ + size_t i, max_len; + char *full_path = (char*) calloc(PATH_MAX_LEN + 1, 1); + const char *env_var = getenv("BLADERF_SEARCH_DIR"); + + /* Check directory specified by environment variable */ + if (env_var != NULL) { + strncat(full_path, env_var, PATH_MAX_LEN - 1); + full_path[strlen(full_path)] = DIR_DELIMETER; + + max_len = PATH_MAX_LEN - strlen(full_path); + + if (max_len >= strlen(filename)) { + strncat(full_path, filename, max_len); + if (access(full_path, ACCESS_FILE_EXISTS) != -1) { + return full_path; + } + } + } + + /* Check the directory containing the currently running binary */ + memset(full_path, 0, PATH_MAX_LEN); + max_len = PATH_MAX_LEN - 1; + + if (get_binary_dir(full_path, max_len) != 0) { + max_len -= strlen(full_path); + + if (max_len >= strlen(filename)) { + strncat(full_path, filename, max_len); + if (access(full_path, ACCESS_FILE_EXISTS) != -1) { + return full_path; + } + } else { + log_debug("Skipping search for %s in %s. " + "Path would be truncated.\n", + filename, full_path); + } + } + + + /* Search our list of pre-determined paths */ + for (i = 0; i < ARRAY_SIZE(search_paths); i++) { + memset(full_path, 0, PATH_MAX_LEN); + max_len = PATH_MAX_LEN; + + if (search_paths[i].prepend_home) { + const size_t len = get_home_dir(full_path, max_len); + + if (len != 0) { + max_len -= len; + } else { + continue; + } + + } + + strncat(full_path, search_paths[i].path, max_len); + max_len = PATH_MAX_LEN - strlen(full_path); + + if (max_len >= strlen(filename)) { + strncat(full_path, filename, max_len); + + if (access(full_path, ACCESS_FILE_EXISTS) != -1) { + return full_path; + } + } else { + log_debug("Skipping search for %s in %s. " + "Path would be truncated.\n", + filename, full_path); + } + } + + /* Search the installation directory, if applicable */ + if (get_install_dir(full_path, PATH_MAX_LEN)) { + max_len = PATH_MAX_LEN - strlen(full_path); + + if (max_len >= strlen(filename)) { + strncat(full_path, filename, max_len); + if (access(full_path, ACCESS_FILE_EXISTS) != -1) { + return full_path; + } + } else { + log_debug("Skipping search for %s in %s. " + "Path would be truncated.\n", + filename, full_path); + } + } + + free(full_path); + return NULL; +} + +int file_find_and_read(const char *filename, uint8_t **buf, size_t *size) +{ + int status; + char *full_path = file_find(filename); + *buf = NULL; + *size = 0; + + if (full_path != NULL) { + status = file_read_buffer(full_path, buf, size); + free(full_path); + return status; + } else { + return BLADERF_ERR_NO_FILE; + } +} + +#undef LOCAL_BLADERF_OS_LINUX diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro index 631b3708f..b04537f98 100644 --- a/sdrangel.windows.pro +++ b/sdrangel.windows.pro @@ -10,6 +10,7 @@ SUBDIRS += lz4 SUBDIRS += librtlsdr SUBDIRS += libhackrf SUBDIRS += libairspy +SUBDIRS += libbladerf SUBDIRS += plugins/samplesource/filesource SUBDIRS += plugins/samplesource/sdrdaemon SUBDIRS += plugins/samplesource/rtlsdr diff --git a/windows.install.bat b/windows.install.bat index d795461a2..2bb7a4f26 100644 --- a/windows.install.bat +++ b/windows.install.bat @@ -6,6 +6,7 @@ copy lz4\%1\lz4.dll %2 copy libhackrf\%1\libhackrf.dll %2 copy librtlsdr\%1\librtlsdr.dll %2 copy libairspy\%1\libairspy.dll %2 +copy libbladerf\%1\libbladerf.dll %2 copy %libusbdir%\dll\libusb-1.0.dll %2 mkdir %2\plugins mkdir %2\plugins\channel