/* * This file is part of the bladeRF project: * http://www.github.com/nuand/bladeRF * * Copyright (c) 2017-2018 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. */ #include "conversions.h" int str2version(const char *str, struct bladerf_version *version) { unsigned long tmp; const char *start = str; char *end; /* Major version */ errno = 0; tmp = strtoul(start, &end, 10); if (errno != 0 || tmp > UINT16_MAX || end == start || *end != '.') { return -1; } version->major = (uint16_t)tmp; /* Minor version */ if (end[0] == '\0' || end[1] == '\0') { return -1; } errno = 0; start = &end[1]; tmp = strtoul(start, &end, 10); if (errno != 0 || tmp > UINT16_MAX || end == start || *end != '.') { return -1; } version->minor = (uint16_t)tmp; /* Patch version */ if (end[0] == '\0' || end[1] == '\0') { return -1; } errno = 0; start = &end[1]; tmp = strtoul(start, &end, 10); if (errno != 0 || tmp > UINT16_MAX || end == start || (*end != '-' && *end != '\0')) { return -1; } version->patch = (uint16_t)tmp; version->describe = str; return 0; } const char *devspeed2str(bladerf_dev_speed speed) { switch (speed) { case BLADERF_DEVICE_SPEED_HIGH: /* Yeah, the USB IF actually spelled it "Hi" instead of "High". * I know. It hurts me too. */ return "Hi-Speed"; case BLADERF_DEVICE_SPEED_SUPER: /* ...and no hyphen :( */ return "SuperSpeed"; default: return "Unknown"; } } bladerf_log_level str2loglevel(const char *str, bool *ok) { bladerf_log_level level = BLADERF_LOG_LEVEL_ERROR; bool valid = true; if (!strcasecmp(str, "critical")) { level = BLADERF_LOG_LEVEL_CRITICAL; } else if (!strcasecmp(str, "error")) { level = BLADERF_LOG_LEVEL_ERROR; } else if (!strcasecmp(str, "warning")) { level = BLADERF_LOG_LEVEL_WARNING; } else if (!strcasecmp(str, "info")) { level = BLADERF_LOG_LEVEL_INFO; } else if (!strcasecmp(str, "debug")) { level = BLADERF_LOG_LEVEL_DEBUG; } else if (!strcasecmp(str, "verbose")) { level = BLADERF_LOG_LEVEL_VERBOSE; } else { valid = false; } *ok = valid; return level; } const char *module2str(bladerf_module m) { switch (m) { case BLADERF_MODULE_RX: return "RX"; case BLADERF_MODULE_TX: return "TX"; default: return "Unknown"; } } bladerf_module str2module(const char *str) { if (!strcasecmp(str, "RX")) { return BLADERF_MODULE_RX; } else if (!strcasecmp(str, "TX")) { return BLADERF_MODULE_TX; } else { return BLADERF_MODULE_INVALID; } } const char *channel2str(bladerf_channel ch) { switch (ch) { case BLADERF_CHANNEL_RX(0): return "RX1"; case BLADERF_CHANNEL_TX(0): return "TX1"; case BLADERF_CHANNEL_RX(1): return "RX2"; case BLADERF_CHANNEL_TX(1): return "TX2"; default: return "Unknown"; } } bladerf_channel str2channel(char const *str) { bladerf_channel rv; if (strcasecmp(str, "rx") == 0 || strcasecmp(str, "rx1") == 0) { rv = BLADERF_CHANNEL_RX(0); } else if (strcasecmp(str, "rx2") == 0) { rv = BLADERF_CHANNEL_RX(1); } else if (strcasecmp(str, "tx") == 0 || strcasecmp(str, "tx1") == 0) { rv = BLADERF_CHANNEL_TX(0); } else if (strcasecmp(str, "tx2") == 0) { rv = BLADERF_CHANNEL_TX(1); } else { rv = BLADERF_CHANNEL_INVALID; } return rv; } bladerf_direction channel2direction (bladerf_channel ch) { if (ch == BLADERF_CHANNEL_RX(0) || ch == BLADERF_CHANNEL_RX(1)) { return BLADERF_RX; } else { return BLADERF_TX; } } const char *direction2str(bladerf_direction dir) { switch (dir) { case BLADERF_RX: return "RX"; case BLADERF_TX: return "TX"; default: return "Unknown"; } } const char *trigger2str(bladerf_trigger_signal trigger) { switch (trigger) { case BLADERF_TRIGGER_J71_4: return "J71-4"; case BLADERF_TRIGGER_J51_1: return "J51-1"; case BLADERF_TRIGGER_MINI_EXP_1: return "MiniExp-1"; case BLADERF_TRIGGER_USER_0: return "User-0"; case BLADERF_TRIGGER_USER_1: return "User-1"; case BLADERF_TRIGGER_USER_2: return "User-2"; case BLADERF_TRIGGER_USER_3: return "User-3"; case BLADERF_TRIGGER_USER_4: return "User-4"; case BLADERF_TRIGGER_USER_5: return "User-5"; case BLADERF_TRIGGER_USER_6: return "User-6"; case BLADERF_TRIGGER_USER_7: return "User-7"; default: return "Unknown"; } } bladerf_trigger_signal str2trigger(const char *str) { if (!strcasecmp("J71-4", str)) { return BLADERF_TRIGGER_J71_4; } else if (!strcasecmp("J51-1", str)) { return BLADERF_TRIGGER_J51_1; } else if (!strcasecmp("Miniexp-1", str)) { return BLADERF_TRIGGER_MINI_EXP_1; } else if (!strcasecmp("User-0", str)) { return BLADERF_TRIGGER_USER_0; } else if (!strcasecmp("User-1", str)) { return BLADERF_TRIGGER_USER_1; } else if (!strcasecmp("User-2", str)) { return BLADERF_TRIGGER_USER_2; } else if (!strcasecmp("User-3", str)) { return BLADERF_TRIGGER_USER_3; } else if (!strcasecmp("User-4", str)) { return BLADERF_TRIGGER_USER_4; } else if (!strcasecmp("User-5", str)) { return BLADERF_TRIGGER_USER_5; } else if (!strcasecmp("User-6", str)) { return BLADERF_TRIGGER_USER_6; } else if (!strcasecmp("User-7", str)) { return BLADERF_TRIGGER_USER_7; } else { return BLADERF_TRIGGER_INVALID; } } const char *triggerrole2str(bladerf_trigger_role role) { switch (role) { case BLADERF_TRIGGER_ROLE_MASTER: return "Master"; case BLADERF_TRIGGER_ROLE_SLAVE: return "Slave"; case BLADERF_TRIGGER_ROLE_DISABLED: return "Disabled"; default: return "Unknown"; } } bladerf_trigger_role str2triggerrole(const char *str) { if (!strcasecmp("Master", str)) { return BLADERF_TRIGGER_ROLE_MASTER; } else if (!strcasecmp("Slave", str)) { return BLADERF_TRIGGER_ROLE_SLAVE; } else if (!strcasecmp("Disabled", str) || !strcasecmp("Off", str)) { return BLADERF_TRIGGER_ROLE_DISABLED; } else { return BLADERF_TRIGGER_ROLE_INVALID; } } int str2loopback(const char *str, bladerf_loopback *loopback) { int status = 0; if (!strcasecmp("firmware", str)) { *loopback = BLADERF_LB_FIRMWARE; } else if (!strcasecmp("bb_txlpf_rxvga2", str)) { *loopback = BLADERF_LB_BB_TXLPF_RXVGA2; } else if (!strcasecmp("bb_txlpf_rxlpf", str)) { *loopback = BLADERF_LB_BB_TXLPF_RXLPF; } else if (!strcasecmp("bb_txvga1_rxvga2", str)) { *loopback = BLADERF_LB_BB_TXVGA1_RXVGA2; } else if (!strcasecmp("bb_txvga1_rxlpf", str)) { *loopback = BLADERF_LB_BB_TXVGA1_RXLPF; } else if (!strcasecmp("rf_lna1", str)) { *loopback = BLADERF_LB_RF_LNA1; } else if (!strcasecmp("rf_lna2", str)) { *loopback = BLADERF_LB_RF_LNA2; } else if (!strcasecmp("rf_lna3", str)) { *loopback = BLADERF_LB_RF_LNA3; } else if (!strcasecmp("rfic_bist", str)) { *loopback = BLADERF_LB_RFIC_BIST; } else if (!strcasecmp("none", str)) { *loopback = BLADERF_LB_NONE; } else { status = -1; } return status; } char const *loopback2str(bladerf_loopback loopback) { switch (loopback) { case BLADERF_LB_BB_TXLPF_RXVGA2: return "bb_txlpf_rxvga2"; case BLADERF_LB_BB_TXLPF_RXLPF: return "bb_txlpf_rxlpf"; case BLADERF_LB_BB_TXVGA1_RXVGA2: return "bb_txvga1_rxvga2"; case BLADERF_LB_BB_TXVGA1_RXLPF: return "bb_txvga1_rxlpf"; case BLADERF_LB_RF_LNA1: return "rf_lna1"; case BLADERF_LB_RF_LNA2: return "rf_lna2"; case BLADERF_LB_RF_LNA3: return "rf_lna3"; case BLADERF_LB_FIRMWARE: return "firmware"; case BLADERF_LB_NONE: return "none"; case BLADERF_LB_RFIC_BIST: return "rfic_bist"; default: return "unknown"; } } int str2lnagain(const char *str, bladerf_lna_gain *gain) { *gain = BLADERF_LNA_GAIN_MAX; if (!strcasecmp("max", str) || !strcasecmp("BLADERF_LNA_GAIN_MAX", str)) { *gain = BLADERF_LNA_GAIN_MAX; return 0; } else if (!strcasecmp("mid", str) || !strcasecmp("BLADERF_LNA_GAIN_MID", str)) { *gain = BLADERF_LNA_GAIN_MID; return 0; } else if (!strcasecmp("bypass", str) || !strcasecmp("BLADERF_LNA_GAIN_BYPASS", str)) { *gain = BLADERF_LNA_GAIN_BYPASS; return 0; } else { *gain = BLADERF_LNA_GAIN_UNKNOWN; return -1; } } char const *tuningmode2str(bladerf_tuning_mode mode) { switch (mode) { case BLADERF_TUNING_MODE_HOST: return "Host"; case BLADERF_TUNING_MODE_FPGA: return "FPGA"; default: return "Unknown"; } } const char *backend_description(bladerf_backend b) { switch (b) { case BLADERF_BACKEND_ANY: return "Any"; case BLADERF_BACKEND_LINUX: return "Linux kernel driver"; case BLADERF_BACKEND_LIBUSB: return "libusb"; case BLADERF_BACKEND_CYPRESS: return "Cypress driver"; case BLADERF_BACKEND_DUMMY: return "Dummy"; default: return "Unknown"; } } void sc16q11_to_float(const int16_t *in, float *out, unsigned int n) { unsigned int i; for (i = 0; i < (2 * n); i += 2) { out[i] = (float)in[i] * (1.0f / 2048.0f); out[i + 1] = (float)in[i + 1] * (1.0f / 2048.0f); } } void float_to_sc16q11(const float *in, int16_t *out, unsigned int n) { unsigned int i; for (i = 0; i < (2 * n); i += 2) { out[i] = (int16_t)(in[i] * 2048.0f); out[i + 1] = (int16_t)(in[i + 1] * 2048.0f); } } bladerf_cal_module str_to_bladerf_cal_module(const char *str) { bladerf_cal_module module = BLADERF_DC_CAL_INVALID; if (!strcasecmp(str, "lpf_tuning") || !strcasecmp(str, "lpftuning") || !strcasecmp(str, "tuning")) { module = BLADERF_DC_CAL_LPF_TUNING; } else if (!strcasecmp(str, "tx_lpf") || !strcasecmp(str, "txlpf")) { module = BLADERF_DC_CAL_TX_LPF; } else if (!strcasecmp(str, "rx_lpf") || !strcasecmp(str, "rxlpf")) { module = BLADERF_DC_CAL_RX_LPF; } else if (!strcasecmp(str, "rx_vga2") || !strcasecmp(str, "rxvga2")) { module = BLADERF_DC_CAL_RXVGA2; } return module; } const char *smb_mode_to_str(bladerf_smb_mode mode) { switch (mode) { case BLADERF_SMB_MODE_DISABLED: return "Disabled"; case BLADERF_SMB_MODE_OUTPUT: return "Output"; case BLADERF_SMB_MODE_INPUT: return "Input"; case BLADERF_SMB_MODE_UNAVAILBLE: return "Unavailable"; default: return "Unknown"; } }; bladerf_smb_mode str_to_smb_mode(const char *str) { if (!strcasecmp(str, "disabled") || !strcasecmp(str, "off")) { return BLADERF_SMB_MODE_DISABLED; } else if (!strcasecmp(str, "output")) { return BLADERF_SMB_MODE_OUTPUT; } else if (!strcasecmp(str, "input")) { return BLADERF_SMB_MODE_INPUT; } else if (!strcasecmp(str, "unavailable")) { return BLADERF_SMB_MODE_UNAVAILBLE; } else { return BLADERF_SMB_MODE_INVALID; } } bladerf_tuning_mode str_to_tuning_mode(const char *str) { if (!strcasecmp(str, "fpga")) { return BLADERF_TUNING_MODE_FPGA; } else if (!strcasecmp(str, "host")) { return BLADERF_TUNING_MODE_HOST; } else { return BLADERF_TUNING_MODE_INVALID; } } unsigned int str2uint(const char *str, unsigned int min, unsigned int max, bool *ok) { unsigned int ret; char *optr; errno = 0; ret = strtoul(str, &optr, 0); if (errno == ERANGE || (errno != 0 && ret == 0)) { *ok = false; return 0; } if (str == optr) { *ok = false; return 0; } if (ret >= min && ret <= max) { *ok = true; return (unsigned int)ret; } *ok = false; return 0; } int str2int(const char *str, int min, int max, bool *ok) { long int ret; char *optr; errno = 0; ret = strtol(str, &optr, 0); if ((errno == ERANGE && (ret == LONG_MAX || ret == LONG_MIN)) || (errno != 0 && ret == 0)) { *ok = false; return 0; } if (str == optr) { *ok = false; return 0; } if (ret >= min && ret <= max) { *ok = true; return (int)ret; } *ok = false; return 0; } uint64_t str2uint64(const char *str, uint64_t min, uint64_t max, bool *ok) { uint64_t ret; char *optr; errno = 0; ret = (uint64_t)strtod(str, &optr); if ((errno == ERANGE && ret == ULONG_MAX) || (errno != 0 && ret == 0)) { *ok = false; return 0; } if (str == optr) { *ok = false; return 0; } if (ret >= min && ret <= max) { *ok = true; return ret; } *ok = false; return 0; } double str2double(const char *str, double min, double max, bool *ok) { double ret; char *optr; errno = 0; ret = strtod(str, &optr); if (errno == ERANGE || (errno != 0 && ret == 0)) { *ok = false; return NAN; } if (str == optr) { *ok = false; return NAN; } if (ret >= min && ret <= max) { *ok = true; return ret; } *ok = false; return NAN; } static uint64_t suffix_multiplier(const char *str, const struct numeric_suffix *suffixes, const size_t num_suff, bool *ok) { unsigned i; *ok = true; if (!strlen(str)) return 1; for (i = 0; i < num_suff; i++) { if (!strcasecmp(suffixes[i].suffix, str)) { return suffixes[i].multiplier; } } *ok = false; return 0; } unsigned int str2uint_suffix(const char *str, unsigned int min, unsigned int max, const struct numeric_suffix *suffixes, const size_t num_suff, bool *ok) { uint64_t mult; unsigned int rv; double val; char *optr; errno = 0; val = strtod(str, &optr); if (errno == ERANGE || (errno != 0 && val == 0)) { *ok = false; return 0; } if (str == optr) { *ok = false; return 0; } mult = suffix_multiplier(optr, suffixes, num_suff, ok); if (!*ok) return false; rv = (unsigned int)(val * mult); if (rv >= min && rv <= max) { return rv; } *ok = false; return 0; } uint64_t str2uint64_suffix(const char *str, uint64_t min, uint64_t max, const struct numeric_suffix *suffixes, const size_t num_suff, bool *ok) { uint64_t mult, rv; long double val; char *optr; errno = 0; val = strtold(str, &optr); if (errno == ERANGE && (errno != 0 && val == 0)) { *ok = false; return 0; } if (str == optr) { *ok = false; return 0; } mult = suffix_multiplier(optr, suffixes, num_suff, ok); if (!*ok) return false; rv = (uint64_t)(val * mult); if (rv >= min && rv <= max) { return rv; } *ok = false; return 0; } int str2bool(const char *str, bool *val) { unsigned int i; char *str_true[] = { "true", "t", "one", "1", "enable", "en", "on" }; char *str_false[] = { "false", "f", "zero", "0", "disable", "dis", "off" }; for (i = 0; i < ARRAY_SIZE(str_true); i++) { if (!strcasecmp(str_true[i], str)) { *val = true; return 0; } } for (i = 0; i < ARRAY_SIZE(str_false); i++) { if (!strcasecmp(str_false[i], str)) { *val = false; return 0; } } return BLADERF_ERR_INVAL; }