static const struct compat * find_fpga_match(const struct bladerf *dev) { size_t i; const struct compat *newest_fpga = &fpga_compat_tbl[0]; /* Device's FPGA is newer than what's in our table - complain */ if (version_less_than(&newest_fpga->ver, dev->fpga_version.major, dev->fpga_version.minor, dev->fpga_version.patch)) { log_info("FPGA version (v%u.%u.%u) is newer than entries in " "libbladeRF's compatibility table. Please update libbladeRF " "if problems arise.\n", dev->fpga_version.major, dev->fpga_version.minor, dev->fpga_version.patch); return newest_fpga; } for (i = 0; i < ARRAY_SIZE(fpga_compat_tbl); i++) { if (version_equal(&dev->fpga_version, &fpga_compat_tbl[i].ver)) { return &fpga_compat_tbl[i]; } } return NULL; }
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 * (1.7.0 could enable it, but 1.7.1 also allowed readback, * so we'll enforce 1.7.1 here. */ 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"); 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 * that the PAs will be disabled, and remain enabled across * frequency changes. */ status = lms_set_loopback_mode(dev, BLADERF_LB_RF_LNA3); if (status != 0) { goto out; } status = dev->fn->set_firmware_loopback(dev, true); } } else { /* If applicable, ensure FW loopback is disabled */ if (version_greater_or_equal(&dev->fw_version, 1, 7, 1)) { bool fw_lb_enabled = false; /* Query first, as the implementation of setting the mode * may interrupt running streams. The API don't guarantee that * switching loopback modes on the fly to work, but we can at least * try to avoid unnecessarily interrupting things...*/ status = dev->fn->get_firmware_loopback(dev, &fw_lb_enabled); if (status != 0) { goto out; } if (fw_lb_enabled) { status = dev->fn->set_firmware_loopback(dev, false); if (status != 0) { goto out; } } } status = lms_set_loopback_mode(dev, l); } out: MUTEX_UNLOCK(&dev->ctrl_lock); return status; }
int bladerf_set_loopback(struct bladerf *dev, bladerf_loopback l) { if (l == BLADERF_LB_FIRMWARE) { /* Firmware loopback was implemented in FW v1.7.0 */ if (version_less_than(&dev->fw_version, 1, 7, 0)) { log_warning("Firmware v1.7.0 or later is required " "for firmware loopback\n"); return BLADERF_ERR_UNSUPPORTED; } else { return dev->fn->set_firmware_loopback(dev, true); } } else { return lms_set_loopback_mode(dev, l); } }
int perform_format_config(struct bladerf *dev, bladerf_module module, bladerf_format format) { int status = 0; bool use_timestamps; bladerf_module other; bool other_using_timestamps; uint32_t gpio_val; status = requires_timestamps(format, &use_timestamps); if (status != 0) { log_debug("%s: Invalid format: %d\n", __FUNCTION__, format); return status; } if (use_timestamps && version_less_than(&dev->fpga_version, 0, 1, 0)) { log_warning("Timestamp support requires FPGA v0.1.0 or later.\n"); return BLADERF_ERR_UPDATE_FPGA; } switch (module) { case BLADERF_MODULE_RX: other = BLADERF_MODULE_TX; break; case BLADERF_MODULE_TX: other = BLADERF_MODULE_RX; break; default: log_debug("Invalid module: %d\n", module); return BLADERF_ERR_INVAL; } status = requires_timestamps(dev->module_format[other], &other_using_timestamps); if ((status == 0) && (other_using_timestamps != use_timestamps)) { log_debug("Format conflict detected: RX=%d, TX=%d\n"); return BLADERF_ERR_INVAL; } status = CONFIG_GPIO_READ(dev, &gpio_val); if (status != 0) { return status; } if (use_timestamps) { gpio_val |= (BLADERF_GPIO_TIMESTAMP | BLADERF_GPIO_TIMESTAMP_DIV2); } else { gpio_val &= ~(BLADERF_GPIO_TIMESTAMP | BLADERF_GPIO_TIMESTAMP_DIV2); } status = CONFIG_GPIO_WRITE(dev, gpio_val); if (status == 0) { dev->module_format[module] = format; } return status; }