int sync_init(struct bladerf *dev, bladerf_module module, bladerf_format format, unsigned int num_buffers, unsigned int buffer_size, unsigned int num_transfers, unsigned int stream_timeout) { struct bladerf_sync *sync; int status = 0; size_t i, bytes_per_sample; if (num_transfers >= num_buffers) { return BLADERF_ERR_INVAL; } switch (format) { case BLADERF_FORMAT_SC16_Q11: case BLADERF_FORMAT_SC16_Q11_META: bytes_per_sample = 4; break; default: log_debug("Invalid format value: %d\n", format); return BLADERF_ERR_INVAL; } /* bladeRF GPIF DMA requirement */ if ((bytes_per_sample * buffer_size) % 4096 != 0) { return BLADERF_ERR_INVAL; } /* Deallocate any existing sync handle for this module */ switch (module) { case BLADERF_MODULE_TX: case BLADERF_MODULE_RX: sync_deinit(dev->sync[module]); sync = dev->sync[module] = (struct bladerf_sync *) calloc(1, sizeof(struct bladerf_sync)); if (dev->sync[module] == NULL) { status = BLADERF_ERR_MEM; } break; default: log_debug("Invalid bladerf_module value encountered: %d", module); status = BLADERF_ERR_INVAL; } if (status != 0) { return status; } sync->dev = dev; sync->state = SYNC_STATE_CHECK_WORKER; sync->buf_mgmt.num_buffers = num_buffers; sync->buf_mgmt.resubmit_count = 0; sync->stream_config.module = module; sync->stream_config.format = format; sync->stream_config.samples_per_buffer = buffer_size; sync->stream_config.num_xfers = num_transfers; sync->stream_config.timeout_ms = stream_timeout; sync->stream_config.bytes_per_sample = bytes_per_sample; sync->meta.state = SYNC_META_STATE_HEADER; sync->meta.msg_per_buf = msg_per_buf(dev, buffer_size, bytes_per_sample); sync->meta.samples_per_msg = samples_per_msg(dev, bytes_per_sample); log_verbose("%s: Buffer size: %u\n", __FUNCTION__, buffer_size); log_verbose("%s: Msg per buffer: %u\n", __FUNCTION__, sync->meta.msg_per_buf); log_verbose("%s: Samples per msg: %u\n", __FUNCTION__, sync->meta.samples_per_msg); MUTEX_INIT(&sync->buf_mgmt.lock); pthread_cond_init(&sync->buf_mgmt.buf_ready, NULL); sync->buf_mgmt.status = (sync_buffer_status*) malloc(num_buffers * sizeof(sync_buffer_status)); if (sync->buf_mgmt.status == NULL) { status = BLADERF_ERR_MEM; } else { switch (module) { case BLADERF_MODULE_RX: /* When starting up an RX stream, the first 'num_transfers' * transfers will be submitted to the USB layer to grab data */ sync->buf_mgmt.prod_i = num_transfers; sync->buf_mgmt.cons_i = 0; sync->buf_mgmt.partial_off = 0; for (i = 0; i < num_buffers; i++) { if (i < num_transfers) { sync->buf_mgmt.status[i] = SYNC_BUFFER_IN_FLIGHT; } else { sync->buf_mgmt.status[i] = SYNC_BUFFER_EMPTY; } } sync->meta.msg_timestamp = 0; sync->meta.msg_flags = 0; break; case BLADERF_MODULE_TX: sync->buf_mgmt.prod_i = 0; sync->buf_mgmt.cons_i = 0; sync->buf_mgmt.partial_off = 0; for (i = 0; i < num_buffers; i++) { sync->buf_mgmt.status[i] = SYNC_BUFFER_EMPTY; } sync->meta.in_burst = false; sync->meta.now = false; break; } status = sync_worker_init(sync); } if (status != 0) { sync_deinit(dev->sync[module]); dev->sync[module] = NULL; } return status; }
int sync_init(struct bladerf_sync *sync, struct bladerf *dev, bladerf_channel_layout layout, bladerf_format format, unsigned int num_buffers, size_t buffer_size, size_t msg_size, unsigned int num_transfers, unsigned int stream_timeout) { int status = 0; size_t i, bytes_per_sample; if (num_transfers >= num_buffers) { return BLADERF_ERR_INVAL; } switch (format) { case BLADERF_FORMAT_SC16_Q11: case BLADERF_FORMAT_SC16_Q11_META: bytes_per_sample = 4; break; default: log_debug("Invalid format value: %d\n", format); return BLADERF_ERR_INVAL; } /* bladeRF GPIF DMA requirement */ if ((bytes_per_sample * buffer_size) % 4096 != 0) { return BLADERF_ERR_INVAL; } /* Deinitialize sync handle if it's initialized */ sync_deinit(sync); MUTEX_INIT(&sync->lock); switch (layout & BLADERF_DIRECTION_MASK) { case BLADERF_TX: sync->buf_mgmt.submitter = SYNC_TX_SUBMITTER_FN; break; case BLADERF_RX: sync->buf_mgmt.submitter = SYNC_TX_SUBMITTER_INVALID; break; } sync->dev = dev; sync->state = SYNC_STATE_CHECK_WORKER; sync->buf_mgmt.num_buffers = num_buffers; sync->buf_mgmt.resubmit_count = 0; sync->stream_config.layout = layout; sync->stream_config.format = format; sync->stream_config.samples_per_buffer = (unsigned int)buffer_size; sync->stream_config.num_xfers = num_transfers; sync->stream_config.timeout_ms = stream_timeout; sync->stream_config.bytes_per_sample = bytes_per_sample; sync->meta.state = SYNC_META_STATE_HEADER; sync->meta.msg_size = msg_size; sync->meta.msg_per_buf = msg_per_buf(msg_size, buffer_size, bytes_per_sample); sync->meta.samples_per_msg = samples_per_msg(msg_size, bytes_per_sample); log_verbose("%s: Buffer size: %u\n", __FUNCTION__, buffer_size); log_verbose("%s: Msg per buffer: %u\n", __FUNCTION__, sync->meta.msg_per_buf); log_verbose("%s: Samples per msg: %u\n", __FUNCTION__, sync->meta.samples_per_msg); MUTEX_INIT(&sync->buf_mgmt.lock); pthread_cond_init(&sync->buf_mgmt.buf_ready, NULL); sync->buf_mgmt.status = (sync_buffer_status*) malloc(num_buffers * sizeof(sync_buffer_status)); if (sync->buf_mgmt.status == NULL) { status = BLADERF_ERR_MEM; goto error; } switch (layout & BLADERF_DIRECTION_MASK) { case BLADERF_RX: /* When starting up an RX stream, the first 'num_transfers' * transfers will be submitted to the USB layer to grab data */ sync->buf_mgmt.prod_i = num_transfers; sync->buf_mgmt.cons_i = 0; sync->buf_mgmt.partial_off = 0; for (i = 0; i < num_buffers; i++) { if (i < num_transfers) { sync->buf_mgmt.status[i] = SYNC_BUFFER_IN_FLIGHT; } else { sync->buf_mgmt.status[i] = SYNC_BUFFER_EMPTY; } } sync->meta.msg_timestamp = 0; sync->meta.msg_flags = 0; break; case BLADERF_TX: sync->buf_mgmt.prod_i = 0; sync->buf_mgmt.cons_i = BUFFER_MGMT_INVALID_INDEX; sync->buf_mgmt.partial_off = 0; for (i = 0; i < num_buffers; i++) { sync->buf_mgmt.status[i] = SYNC_BUFFER_EMPTY; } sync->meta.in_burst = false; sync->meta.now = false; break; } status = sync_worker_init(sync); if (status < 0) { goto error; } sync->initialized = true; return 0; error: sync_deinit(sync); return status; }