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; }
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; }
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; }