int cmd_load(struct cli_state *state, int argc, char **argv) { /* Valid commands: load fpga <filename> load fx3 <filename> */ int rv = CMD_RET_OK ; if (!cli_device_is_opened(state)) { return CMD_RET_NODEV; } else if (cli_device_is_streaming(state)) { return CMD_RET_BUSY; } if ( argc == 3 ) { if( strcasecmp( argv[1], "fpga" ) == 0 ) { rv = load_fpga(state, argv[2]); } else if( strcasecmp( argv[1], "fx3" ) == 0 ) { rv = load_fx3(state, argv[2]); } else { cli_err(state, argv[0], "\"%s\" is not a valid programming target\n", argv[1]) ; rv = CMD_RET_INVPARAM; } } else { rv = CMD_RET_NARGS; } return rv; }
int rxtx_cmd_stop(struct cli_state *s, struct rxtx_data *rxtx) { int status; if (!cli_device_is_opened(s)) { status = CMD_RET_NODEV; } else if (rxtx_get_state(rxtx) != RXTX_STATE_RUNNING) { status = CMD_RET_STATE; } else { rxtx_submit_request(rxtx, RXTX_TASK_REQ_STOP); status = 0; } return status; }
int flash_check_state(struct cli_state *s, const char *cmd_name) { if (!cli_device_is_opened(s)) { return CLI_RET_NODEV; } if (cli_device_is_streaming(s)) { cli_err(s, cmd_name, "Flash operations require that the device is not " "actively streaming."); /* Technically not the error, but we want to suppress the more generic * error message... */ return CLI_RET_INVPARAM; } return 0; }
int rxtx_cmd_start_check(struct cli_state *s, struct rxtx_data *rxtx, const char *argv0) { int status = CMD_RET_UNKNOWN; int fpga_status; bool have_file; if (!cli_device_is_opened(s)) { return CMD_RET_NODEV; } else if (rxtx_get_state(rxtx) != RXTX_STATE_IDLE) { return CMD_RET_STATE; } else { fpga_status = bladerf_is_fpga_configured(s->dev); if (fpga_status < 0) { s->last_lib_error = fpga_status; status = CMD_RET_LIBBLADERF; } else if (fpga_status != 1) { status = CMD_RET_NOFPGA; } else { pthread_mutex_lock(&rxtx->file_mgmt.file_meta_lock); have_file = (rxtx->file_mgmt.path != NULL); pthread_mutex_unlock(&rxtx->file_mgmt.file_meta_lock); if (!have_file) { cli_err(s, argv0, "File not configured"); status = CMD_RET_INVPARAM; } else { status = validate_stream_params(s, rxtx, argv0); } if (status == 0) { check_samplerate(s, rxtx); } } } return status; }
int cmd_erase(struct cli_state *state, int argc, char **argv) { int status; int page_offset, n_bytes; bool ok; if (!cli_device_is_opened(state)) { return CMD_RET_NODEV; } if (argc != 3) { return CMD_RET_NARGS; } page_offset = str2uint(argv[1], 0, INT_MAX, &ok); if(!ok) { cli_err(state, argv[0], "Invalid value for \"page_offset\" (%s)", argv[1]); return CMD_RET_INVPARAM; } n_bytes = str2uint(argv[2], 0, INT_MAX, &ok); if(!ok) { cli_err(state, argv[0], "Invalid value for \"n_bytes\" (%s)", argv[2]); return CMD_RET_INVPARAM; } status = bladerf_erase_flash(state->dev, page_offset, n_bytes); if (status >= 0) { printf("Erased %d pages at %d\n", status, page_offset); return CMD_RET_OK; } else { state->last_lib_error = status; return CMD_RET_LIBBLADERF; } }
int cmd_poke(struct cli_state *state, int argc, char **argv) { /* Valid commands: poke dac <address> <value> poke lms <address> <value> poke si <address> <value> */ int rv = CLI_RET_OK; int status; bool ok; int (*f)(struct bladerf *, uint8_t, uint8_t); unsigned int address, value; if (!cli_device_is_opened(state)) { return CLI_RET_NODEV; } if( argc == 4 ) { /* Parse the value */ value = str2uint( argv[3], 0, MAX_VALUE, &ok ); if( !ok ) { cli_err(state, argv[0], "Invalid value provided (%s)", argv[3]); return CLI_RET_INVPARAM; } /* Are we reading from the DAC? */ if( strcasecmp( argv[1], "dac" ) == 0 ) { /* Parse address */ address = str2uint( argv[2], 0, DAC_MAX_ADDRESS, &ok ); if( !ok ) { invalid_address(state, argv[0], argv[2]); rv = CLI_RET_INVPARAM; } else { /* TODO: Point function pointer */ /* f = vctcxo_dac_write */ f = NULL; } } /* Are we reading from the LMS6002D */ else if( strcasecmp( argv[1], "lms" ) == 0 ) { /* Parse address */ address = str2uint( argv[2], 0, LMS_MAX_ADDRESS, &ok ); if( !ok ) { invalid_address(state, argv[0], argv[2]); rv = CLI_RET_INVPARAM; } else { f = bladerf_lms_write; } } /* Are we reading from the Si5338? */ else if( strcasecmp( argv[1], "si" ) == 0 ) { /* Parse address */ address = str2uint( argv[2], 0, SI_MAX_ADDRESS, &ok ); if( !ok ) { invalid_address(state, argv[0], argv[2]); rv = CLI_RET_INVPARAM; } else { f = bladerf_si5338_write; } } /* I guess we aren't reading from anything :( */ else { cli_err(state, argv[0], "%s is not a pokeable device\n", argv[1] ); rv = CLI_RET_INVPARAM; } /* Write the value to the address */ if( rv == CLI_RET_OK && f ) { status = f( state->dev, (uint8_t)address, (uint8_t)value ); if (status < 0) { state->last_lib_error = status; rv = CLI_RET_LIBBLADERF; } else { printf( " 0x%2.2x: 0x%2.2x\n", address, value ); if (f == bladerf_lms_write) { uint8_t readback; int status = bladerf_lms_read(state->dev, (uint8_t)address, &readback); if (status == 0) { lms_reg_info(address, readback); putchar('\n'); /* To be consistent with peek output */ } } } } } else { cli_err(state, argv[0], "Invalid number of arguments (%d)\n", argc); rv = CLI_RET_INVPARAM; } return rv; }
int cmd_rxtx(struct cli_state *s, int argc, char **argv) { int ret = CMD_RET_OK; int fpga_loaded; enum rxtx_cmd cmd; struct common_cfg *common; bool is_tx; int (*start_init)(struct cli_state *s); int (*stop_cleanup)(struct cli_state *s); if (!strcasecmp("tx", argv[0])) { is_tx = true; common = &s->rxtx_data->tx.common; start_init = tx_start_init; stop_cleanup = tx_stop_cleanup; } else if (!strcasecmp("rx", argv[0])) { is_tx = false; common = &s->rxtx_data->rx.common; start_init = rx_start_init; stop_cleanup = rx_stop_cleanup; } else { /* Bug */ assert(0); return CMD_RET_UNKNOWN; } /* Just <rx|tx> is supported shorthand for <rx|tx> config */ if (argc == 1) { cmd = RXTX_CMD_CFG; } else { cmd = get_cmd(argv[1]); } switch (cmd) { case RXTX_CMD_START: if (!cli_device_is_opened(s)) { ret = CMD_RET_NODEV; } else if (get_state(common) == RXTX_STATE_RUNNING) { ret = CMD_RET_STATE; } else { fpga_loaded = bladerf_is_fpga_configured(s->dev); if (fpga_loaded < 0) { s->last_lib_error = fpga_loaded; ret = CMD_RET_LIBBLADERF; } else if (!fpga_loaded) { cli_err(s, argv[0], "FPGA is not configured"); ret = CMD_RET_INVPARAM; } else { ret = validate_config(s, argv[0], s->rxtx_data, is_tx); if (!ret) { ret = open_samples_file(common, NULL, is_tx ? "r" : "w"); if (!ret) { ret = start_init(s); } } } } break; case RXTX_CMD_STOP: if (!cli_device_is_opened(s)) { ret = CMD_RET_NODEV; } else if (get_state(common) != RXTX_STATE_RUNNING) { ret = CMD_RET_STATE; } else { ret = stop_cleanup(s); } break; case RXTX_CMD_CFG: if (argc > 2) { if (get_state(common) != RXTX_STATE_RUNNING) { ret = handle_params(s, argc, argv, is_tx); } else { ret = CMD_RET_STATE; } } else { print_config(s->rxtx_data, is_tx); } break; default: cli_err(s, argv[0], "Invalid command (%s)", argv[1]); ret = CMD_RET_INVPARAM; } return ret; }
int cmd_info(struct cli_state *state, int argc, char **argv) { int status; bladerf_fpga_size fpga_size; uint16_t dac_trim; bool fpga_loaded; struct bladerf_devinfo info; bladerf_dev_speed usb_speed; if (!cli_device_is_opened(state)) { return CLI_RET_NODEV; } status = bladerf_get_devinfo(state->dev, &info); if (status < 0) { state->last_lib_error = status; return CLI_RET_LIBBLADERF; } status = bladerf_is_fpga_configured(state->dev); if (status < 0) { state->last_lib_error = status; return CLI_RET_LIBBLADERF; } fpga_loaded = status != 0; status = bladerf_get_fpga_size(state->dev, &fpga_size); if (status < 0) { state->last_lib_error = status; return CLI_RET_LIBBLADERF; } status = bladerf_get_vctcxo_trim(state->dev, &dac_trim); if (status < 0) { state->last_lib_error = status; return CLI_RET_LIBBLADERF; } usb_speed = bladerf_device_speed(state->dev); printf("\n"); printf(" Serial #: %s\n", info.serial); printf(" VCTCXO DAC calibration: 0x%.4x\n", dac_trim); if (fpga_size != 0) { printf(" FPGA size: %d KLE\n", fpga_size); } else { printf(" FPGA size: Unknown\n"); } printf(" FPGA loaded: %s\n", fpga_loaded ? "yes" : "no"); printf(" USB bus: %d\n", info.usb_bus); printf(" USB address: %d\n", info.usb_addr); printf(" USB speed: %s\n", devspeed2str(usb_speed)); switch(info.backend) { case BLADERF_BACKEND_LIBUSB: printf(" Backend: libusb\n"); break; case BLADERF_BACKEND_LINUX: printf(" Backend: Linux driver\n"); break; default: printf(" Backend: Unknown\n"); } printf(" Instance: %d\n", info.instance); printf("\n"); return 0; }
bool cli_device_in_use(struct cli_state *s) { return cli_device_is_opened(s) && (rxtx_tx_task_running(s) || rxtx_rx_task_running(s)); }
bool cli_device_is_streaming(struct cli_state *s) { return cli_device_is_opened(s) && (rxtx_task_running(s->rx) || rxtx_task_running(s->tx)); }
int cmd_flash_init_cal(struct cli_state *state, int argc, char **argv) { int rv; bool ok; uint16_t dac; bladerf_fpga_size fpga_size; struct bladerf_image *image = NULL; if(argc != 3 && argc != 4) { return CMD_RET_NARGS; } rv = str2fpga(argv[1], &fpga_size); if (rv != 0) { cli_err(state, argv[0], "Invalid FPGA provided."); return rv; } dac = str2uint(argv[2], 0, 0xffff, &ok); if(!ok) { cli_err(state, argv[0], "Invalid VCTCXO trim value provided."); return CMD_RET_INVPARAM; } image = bladerf_alloc_cal_image(fpga_size, dac); if (!image) { return CMD_RET_MEM; } if (argc == 3) { if (!cli_device_is_opened(state)) { rv = CMD_RET_NODEV; goto cmd_flash_init_cal_out; } rv = bladerf_program_flash_unaligned(state->dev, image->address, image->data, image->length); if(rv < 0) { cli_err(state, argv[0], "Failed to write calibration data.\n" "\n" "This may have resulted in a corrupted flash. If the device fails to\n" "boot at the next power cycle, re-flash the firmware.\n" "\n" "See the following page for more information:\n" " https://github.com/Nuand/bladeRF/wiki/Upgrading-bladeRF-firmware\n" ); state->last_lib_error = rv; rv = CMD_RET_LIBBLADERF; } else { rv = 0; } } else { assert(argc == 4); rv = bladerf_image_write(image, argv[3]); } cmd_flash_init_cal_out: bladerf_free_image(image); return rv; }