Exemple #1
0
void rxtx_print_state(struct rxtx_data *rxtx,
                      const char *prefix, const char *suffix)
{
    enum rxtx_state state = rxtx_get_state(rxtx);

    switch (state) {
        case RXTX_STATE_IDLE:
            printf("%sIdle%s", prefix, suffix);
            break;

        case RXTX_STATE_START:
            printf("%sStarting%s", prefix, suffix);
            break;

        case RXTX_STATE_RUNNING:
            printf("%sRunning%s", prefix, suffix);
            break;

        case RXTX_STATE_STOP:
            printf("%sStopping%s", prefix, suffix);
            break;

        case RXTX_STATE_SHUTDOWN:
            printf("%sShutting down%s", prefix, suffix);
            break;

        case RXTX_STATE_FAIL:
            printf("%sFailed Initialization%s", prefix, suffix);
            break;

        default:
            printf("%sInvalid/Unknown (BUG)%s", prefix, suffix);
    }
}
Exemple #2
0
int rxtx_cmd_start_check(struct cli_state *s, struct rxtx_data *rxtx,
                         const char *argv0)
{
    int status = CLI_RET_UNKNOWN;
    bool have_file;

    if (rxtx_get_state(rxtx) != RXTX_STATE_IDLE) {
        return CLI_RET_STATE;
    } else {
        MUTEX_LOCK(&rxtx->file_mgmt.file_meta_lock);
        have_file = (rxtx->file_mgmt.path != NULL);
        MUTEX_UNLOCK(&rxtx->file_mgmt.file_meta_lock);

        if (!have_file) {
            cli_err(s, argv0, "File not configured\n");
            status = CLI_RET_INVPARAM;
        } else {
            status = validate_stream_params(s, rxtx, argv0);
        }

        if (status == 0) {
            check_samplerate(s, rxtx);
        }
    }

    return status;
}
Exemple #3
0
void rxtx_shutdown(struct rxtx_data *rxtx)
{
    if (rxtx_get_state(rxtx) != RXTX_STATE_FAIL) {
        rxtx_submit_request(rxtx, RXTX_TASK_REQ_SHUTDOWN);
        pthread_join(rxtx->task_mgmt.thread, NULL);
    }

    free(rxtx->file_mgmt.path);
}
Exemple #4
0
int rxtx_cmd_stop(struct cli_state *s, struct rxtx_data *rxtx)
{
    int status;

    if (rxtx_get_state(rxtx) != RXTX_STATE_RUNNING) {
        status = CLI_RET_STATE;
    } else {
        rxtx_submit_request(rxtx, RXTX_TASK_REQ_STOP);
        status = 0;
    }

    return status;
}
Exemple #5
0
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;
}
Exemple #6
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;
}
Exemple #7
0
void *rx_task(void *cli_state_arg)
{
    int status = 0;
    unsigned char requests;
    enum rxtx_state task_state;
    struct cli_state *cli_state = (struct cli_state *) cli_state_arg;
    struct rxtx_data *rx = cli_state->rx;
    struct rx_params *rx_params = rx->params;
    struct rx_callback_data cb_data;

    task_state = rxtx_get_state(rx);
    assert(task_state == RXTX_STATE_INIT);

    set_last_error(&rx->last_error, ETYPE_BLADERF, 0);
    requests = 0;

    while (task_state != RXTX_STATE_SHUTDOWN) {
        switch (task_state) {
            case RXTX_STATE_INIT:
                rxtx_set_state(rx, RXTX_STATE_IDLE);
                break;

            case RXTX_STATE_IDLE:
                rxtx_task_exec_idle(rx, &requests);
                break;

            case RXTX_STATE_START:
            {
                /* This should be set to an appropriate value upon
                 * encountering an error condition */
                enum error_type err_type = ETYPE_BUG;

                /* Clear the last error */
                set_last_error(&rx->last_error, ETYPE_ERRNO, 0);

                /* Set up count of samples to receive */
                pthread_mutex_lock(&rx->param_lock);
                cb_data.samples_left = rx_params->n_samples;
                pthread_mutex_unlock(&rx->param_lock);

                cb_data.rx = rx;
                cb_data.inf = cb_data.samples_left == 0;

                /* Choose the callback appropriate for the desired file type */
                pthread_mutex_lock(&rx->file_mgmt.file_meta_lock);

                switch (rx->file_mgmt.format) {
                    case RXTX_FMT_CSV_SC16Q12:
                        cb_data.write_samples = rx_write_csv_sc16q12;
                        break;

                    case RXTX_FMT_BIN_SC16Q12:
                        cb_data.write_samples = rx_write_bin_sc16q12;
                        break;

                    default:
                        status = CMD_RET_INVPARAM;
                        set_last_error(&rx->last_error, ETYPE_CLI, status);
                        rxtx_set_state(rx, RXTX_STATE_IDLE);
                }

                /* Open the specified file */
                if (status == 0) {
                    assert(rx->file_mgmt.path);
                }

                pthread_mutex_unlock(&rx->file_mgmt.file_meta_lock);

                /* Set up the reception stream and buffer information */
                if (status == 0) {
                    pthread_mutex_lock(&rx->data_mgmt.lock);

                    rx->data_mgmt.next_idx = 0;

                    status = bladerf_init_stream(&rx->data_mgmt.stream,
                                cli_state->dev,
                                rx_callback,
                                &rx->data_mgmt.buffers,
                                rx->data_mgmt.num_buffers,
                                BLADERF_FORMAT_SC16_Q12,
                                rx->data_mgmt.samples_per_buffer,
                                rx->data_mgmt.num_transfers,
                                &cb_data);

                    if (status < 0) {
                        err_type = ETYPE_BLADERF;
                    }

                    pthread_mutex_unlock(&rx->data_mgmt.lock);
                }

                if (status == 0) {
                    rxtx_set_state(rx, RXTX_STATE_RUNNING);
                } else {
                    bladerf_deinit_stream(rx->data_mgmt.stream);
                    rx->data_mgmt.stream = NULL;
                    set_last_error(&rx->last_error, err_type, status);
                    rxtx_set_state(rx, RXTX_STATE_IDLE);
                }
            }
            break;

            case RXTX_STATE_RUNNING:
                rxtx_task_exec_running(rx, cli_state);
                break;

            case RXTX_STATE_STOP:
                rxtx_task_exec_stop(rx, &requests);
                break;

            case RXTX_STATE_SHUTDOWN:
                break;

            default:
                /* Bug - can only get here with a corrupted value */
                assert(0);
        }

        task_state = rxtx_get_state(rx);
    }

    return NULL;
}
Exemple #8
0
int rxtx_handle_wait(struct cli_state *s, struct rxtx_data *rxtx,
                     int argc, char **argv)
{
    int status;
    bool ok;
    unsigned int timeout_ms = 0;
    struct timespec timeout_abs;
    enum rxtx_state state;

    static const struct numeric_suffix times[] = {
        { "ms", 1 },
        { "s", 1000 },
        { "m", 60 * 1000 },
        { "h", 60 * 60 * 1000 },
    };

    if (argc < 2 || argc > 3) {
        return CMD_RET_NARGS;
    }

    /* The start cmd should have waited until we entered the RUNNING state */
    state = rxtx_get_state(rxtx);
    if (state != RXTX_STATE_RUNNING) {
        return 0;
    }

    if (argc == 3) {
        timeout_ms = str2uint_suffix(argv[2], 0, UINT_MAX, times,
                                     sizeof(times)/sizeof(times[0]), &ok);

        if (!ok) {
            cli_err(s, argv[0], "Invalid wait timeout: \"%s\"\n", argv[2]);
            return CMD_RET_INVPARAM;
        }
    }

    if (timeout_ms != 0) {
        const unsigned int timeout_sec = timeout_ms / 1000;

        status = clock_gettime(CLOCK_REALTIME, &timeout_abs);
        if (status != 0) {
            return CMD_RET_UNKNOWN;
        }

        timeout_abs.tv_sec += timeout_sec;
        timeout_abs.tv_nsec += (timeout_ms % 1000) * 1000 * 1000;

        if (timeout_abs.tv_nsec >= NSEC_PER_SEC) {
            timeout_abs.tv_sec += timeout_abs.tv_nsec / NSEC_PER_SEC;
            timeout_abs.tv_nsec %= NSEC_PER_SEC;
        }

        pthread_mutex_lock(&rxtx->task_mgmt.lock);
        rxtx->task_mgmt.main_task_waiting = true;
        while (rxtx->task_mgmt.main_task_waiting) {
            status = pthread_cond_timedwait(&rxtx->task_mgmt.signal_done,
                                            &rxtx->task_mgmt.lock,
                                            &timeout_abs);

            if (status == ETIMEDOUT) {
                rxtx->task_mgmt.main_task_waiting = false;
            }
        }
        pthread_mutex_unlock(&rxtx->task_mgmt.lock);

        /* Expected and OK condition */
        if (status == ETIMEDOUT) {
            status = 0;
        }

    } else {
        pthread_mutex_lock(&rxtx->task_mgmt.lock);
        rxtx->task_mgmt.main_task_waiting = true;
        while (rxtx->task_mgmt.main_task_waiting) {
            status = pthread_cond_wait(&rxtx->task_mgmt.signal_done,
                                       &rxtx->task_mgmt.lock);
        }
        pthread_mutex_unlock(&rxtx->task_mgmt.lock);
    }

    if (status != 0) {
        status = CMD_RET_UNKNOWN;
    }

    return status;
}
Exemple #9
0
bool rxtx_task_running(struct rxtx_data *rxtx)
{
    return rxtx_get_state(rxtx) == RXTX_STATE_RUNNING;
}
Exemple #10
0
int rxtx_handle_wait(struct cli_state *s, struct rxtx_data *rxtx,
                     int argc, char **argv)
{
    int status = CLI_RET_UNKNOWN;
    bool ok;
    unsigned int timeout_ms = 0;
    struct timespec timeout_abs;
    enum rxtx_state state;

    static const struct numeric_suffix times[] = {
        { "ms", 1 },
        { "s", 1000 },
        { "m", 60 * 1000 },
        { "h", 60 * 60 * 1000 },
    };

    if (argc < 2 || argc > 3) {
        return CLI_RET_NARGS;
    }

    /* The start cmd should have waited until we entered the RUNNING state */
    state = rxtx_get_state(rxtx);
    if (state != RXTX_STATE_RUNNING) {
        return 0;
    }

    if (argc == 3) {
        timeout_ms = str2uint_suffix(argv[2], 0, UINT_MAX, times,
                                     sizeof(times)/sizeof(times[0]), &ok);

        if (!ok) {
            cli_err(s, argv[0], "Invalid wait timeout: \"%s\"\n", argv[2]);
            return CLI_RET_INVPARAM;
        }
    }

    /* Release the device lock (acquired in cmd_handle()) while we wait
     * because we won't be doing device-control operations during this time.
     * This ensures that when the associated rx/tx task completes, it will be
     * able to acquire the device control lock to release this wait. */
    MUTEX_UNLOCK(&s->dev_lock);

    if (timeout_ms != 0) {
        const unsigned int timeout_sec = timeout_ms / 1000;

        status = clock_gettime(CLOCK_REALTIME, &timeout_abs);
        if (status != 0) {
            goto out;
        }

        timeout_abs.tv_sec += timeout_sec;
        timeout_abs.tv_nsec += (timeout_ms % 1000) * 1000 * 1000;

        if (timeout_abs.tv_nsec >= NSEC_PER_SEC) {
            timeout_abs.tv_sec += timeout_abs.tv_nsec / NSEC_PER_SEC;
            timeout_abs.tv_nsec %= NSEC_PER_SEC;
        }

        MUTEX_LOCK(&rxtx->task_mgmt.lock);
        rxtx->task_mgmt.main_task_waiting = true;
        while (rxtx->task_mgmt.main_task_waiting) {
            status = pthread_cond_timedwait(&rxtx->task_mgmt.signal_done,
                                            &rxtx->task_mgmt.lock,
                                            &timeout_abs);

            if (status == ETIMEDOUT) {
                rxtx->task_mgmt.main_task_waiting = false;
            }
        }
        MUTEX_UNLOCK(&rxtx->task_mgmt.lock);

    } else {
        MUTEX_LOCK(&rxtx->task_mgmt.lock);
        rxtx->task_mgmt.main_task_waiting = true;
        while (rxtx->task_mgmt.main_task_waiting) {
            status = pthread_cond_wait(&rxtx->task_mgmt.signal_done,
                                       &rxtx->task_mgmt.lock);
        }
        MUTEX_UNLOCK(&rxtx->task_mgmt.lock);
    }

out:
    /* Re-acquire the device control lock, as the top-level command handler
     * will be unlocking this when it's done */
    MUTEX_LOCK(&s->dev_lock);

    /* Expected and OK condition */
    if (status == ETIMEDOUT) {
        status = 0;
    }

    if (status != 0) {
        status = CLI_RET_UNKNOWN;
    }

    return status;
}
Exemple #11
0
void *tx_task(void *cli_state_arg)
{
    int status = 0;
    int disable_status;
    unsigned char requests;
    enum rxtx_state task_state;
    struct cli_state *cli_state = (struct cli_state *) cli_state_arg;
    struct rxtx_data *tx = cli_state->tx;
    MUTEX *dev_lock = &cli_state->dev_lock;

    /* We expect to be in the IDLE state when this is kicked off. We could
     * also get into the shutdown state if the program exits before we
     * finish up initialization */
    task_state = rxtx_get_state(tx);
    assert(task_state == RXTX_STATE_INIT);

    set_last_error(&tx->last_error, ETYPE_BLADERF, 0);
    requests = 0;

    while (task_state != RXTX_STATE_SHUTDOWN) {
        task_state = rxtx_get_state(tx);
        switch (task_state) {
            case RXTX_STATE_INIT:
                rxtx_set_state(tx, RXTX_STATE_IDLE);
                break;

            case RXTX_STATE_IDLE:
                rxtx_task_exec_idle(tx, &requests);
                break;

            case RXTX_STATE_START:
            {
                enum error_type err_type = ETYPE_BUG;

                /* Clear out the last error */
                set_last_error(&tx->last_error, ETYPE_ERRNO, 0);

                /* Bug catcher */
                MUTEX_LOCK(&tx->file_mgmt.file_meta_lock);
                assert(tx->file_mgmt.file != NULL);
                MUTEX_UNLOCK(&tx->file_mgmt.file_meta_lock);

                /* Initialize the TX synchronous data configuration */
                status = bladerf_sync_config(cli_state->dev,
                                             BLADERF_MODULE_TX,
                                             BLADERF_FORMAT_SC16_Q11,
                                             tx->data_mgmt.num_buffers,
                                             tx->data_mgmt.samples_per_buffer,
                                             tx->data_mgmt.num_transfers,
                                             tx->data_mgmt.timeout_ms);

                if (status < 0) {
                    err_type = ETYPE_BLADERF;
                }

                if (status == 0) {
                    rxtx_set_state(tx, RXTX_STATE_RUNNING);
                } else {
                    set_last_error(&tx->last_error, err_type, status);
                    rxtx_set_state(tx, RXTX_STATE_IDLE);
                }
            }
            break;

            case RXTX_STATE_RUNNING:
                MUTEX_LOCK(dev_lock);
                status = bladerf_enable_module(cli_state->dev,
                                               tx->module, true);
                MUTEX_UNLOCK(dev_lock);

                if (status < 0) {
                    set_last_error(&tx->last_error, ETYPE_BLADERF, status);
                } else {
                    status = tx_task_exec_running(tx, cli_state);

                    if (status < 0) {
                        set_last_error(&tx->last_error, ETYPE_BLADERF, status);
                    }

                    MUTEX_LOCK(dev_lock);
                    disable_status = bladerf_enable_module(cli_state->dev,
                                                           tx->module, false);
                    MUTEX_UNLOCK(dev_lock);

                    if (status == 0 && disable_status < 0) {
                        set_last_error(
                                &tx->last_error,
                                ETYPE_BLADERF,
                                disable_status);
                    }
                }
                rxtx_set_state(tx, RXTX_STATE_STOP);
                break;

            case RXTX_STATE_STOP:
                rxtx_task_exec_stop(tx, &requests);
                break;

            case RXTX_STATE_SHUTDOWN:
                break;

            default:
                /* Bug */
                assert(0);
                rxtx_set_state(tx, RXTX_STATE_IDLE);
        }
    }

    return NULL;
}
Exemple #12
0
void *tx_task(void *cli_state_arg)
{
    int status = 0;
    unsigned char requests;
    enum rxtx_state task_state;
    struct cli_state *cli_state = (struct cli_state *) cli_state_arg;
    struct rxtx_data *tx = cli_state->tx;
    struct tx_params *tx_params = tx->params;
    struct tx_callback_data cb_data;

    /* We expect to be in the IDLE state when this is kicked off. We could
     * also get into the shutdown state if the program exits before we
     * finish up initialization */
    task_state = rxtx_get_state(tx);
    assert(task_state == RXTX_STATE_INIT);

    set_last_error(&tx->last_error, ETYPE_BLADERF, 0);
    requests = 0;

    while (task_state != RXTX_STATE_SHUTDOWN) {
        task_state = rxtx_get_state(tx);
        switch (task_state) {
            case RXTX_STATE_INIT:
                rxtx_set_state(tx, RXTX_STATE_IDLE);
                break;

            case RXTX_STATE_IDLE:
                rxtx_task_exec_idle(tx, &requests);
                break;

            case RXTX_STATE_START:
            {
                enum error_type err_type = ETYPE_BUG;

                /* Clear out the last error */
                set_last_error(&tx->last_error, ETYPE_ERRNO, 0);

                /* Set up repeat and delay parameters for this run */
                cb_data.tx = tx;
                cb_data.delay = 0;
                cb_data.done = false;

                pthread_mutex_lock(&tx->param_lock);
                cb_data.repeats_left = tx_params->repeat;
                pthread_mutex_unlock(&tx->param_lock);

                if (cb_data.repeats_left == 0) {
                    cb_data.repeat_inf = true;
                } else {
                    cb_data.repeat_inf = false;
                }

                /* Bug catcher */
                pthread_mutex_lock(&tx->file_mgmt.file_meta_lock);
                assert(tx->file_mgmt.file != NULL);
                pthread_mutex_unlock(&tx->file_mgmt.file_meta_lock);

                /* Initialize the stream */
                status = bladerf_init_stream(&tx->data_mgmt.stream,
                                             cli_state->dev,
                                             tx_callback,
                                             &tx->data_mgmt.buffers,
                                             tx->data_mgmt.num_buffers,
                                             BLADERF_FORMAT_SC16_Q11,
                                             tx->data_mgmt.samples_per_buffer,
                                             tx->data_mgmt.num_transfers,
                                             &cb_data);

                if (status < 0) {
                    err_type = ETYPE_BLADERF;
                }

                if (status == 0) {
                    rxtx_set_state(tx, RXTX_STATE_RUNNING);
                } else {
                    bladerf_deinit_stream(tx->data_mgmt.stream);
                    tx->data_mgmt.stream = NULL;
                    set_last_error(&tx->last_error, err_type, status);
                    rxtx_set_state(tx, RXTX_STATE_IDLE);
                }
            }
            break;

            case RXTX_STATE_RUNNING:
                rxtx_task_exec_running(tx, cli_state);
                break;

            case RXTX_STATE_STOP:
                rxtx_task_exec_stop(tx, &requests);
                break;

            case RXTX_STATE_SHUTDOWN:
                break;

            default:
                /* Bug */
                assert(0);
                rxtx_set_state(tx, RXTX_STATE_IDLE);
        }
    }

    return NULL;
}