static int linux_rx(struct bladerf *dev, bladerf_format format, void *samples, int n, struct bladerf_metadata *metadata) { ssize_t i, ret = 0; size_t bytes_read = 0; const size_t bytes_total = c16_samples_to_bytes(n); struct bladerf_linux *backend = (struct bladerf_linux *)dev->backend; int8_t *samples8 = (int8_t *)samples; while (bytes_read < bytes_total) { i = read(backend->fd, samples8 + bytes_read, bytes_total - bytes_read); if (i < 0 && errno != EINTR) { int errno_val = errno; bladerf_set_error(&dev->error, ETYPE_ERRNO, errno_val); ret = BLADERF_ERR_IO; log_error("Read failed with errno=%d: %s\n", errno_val, strerror(errno_val)); break; } else if (i > 0) { bytes_read += i; } } if (ret < 0) { return ret; } else { return bytes_to_c16_samples(bytes_read); } }
static void LIBUSB_CALL lusb_stream_cb(struct libusb_transfer *transfer) { struct bladerf_stream *stream = transfer->user_data; void *next_buffer = NULL; struct bladerf_metadata metadata; struct lusb_stream_data *stream_data = stream->backend_data; size_t transfer_i; /* Currently unused - zero out for out own debugging sanity... */ memset(&metadata, 0, sizeof(metadata)); pthread_mutex_lock(&stream->lock); transfer_i = transfer_idx(stream_data, transfer); assert(stream_data->transfer_status[transfer_i] == TRANSFER_IN_FLIGHT || stream_data->transfer_status[transfer_i] == TRANSFER_CANCEL_PENDING); if (transfer_i >= stream_data->num_transfers) { log_error("Unable to find transfer"); stream->state = STREAM_SHUTTING_DOWN; } else { stream_data->transfer_status[transfer_i] = TRANSFER_AVAIL; stream_data->num_avail_transfers++; pthread_cond_signal(&stream->can_submit_buffer); } /* Check to see if the transfer has been cancelled or errored */ if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { /* Errored out for some reason .. */ stream->state = STREAM_SHUTTING_DOWN; switch(transfer->status) { case LIBUSB_TRANSFER_CANCELLED: /* We expect this case when we begin tearing down the stream */ break; case LIBUSB_TRANSFER_STALL: log_error("Hit stall for buffer %p\n", transfer->buffer); stream->error_code = BLADERF_ERR_IO; break; case LIBUSB_TRANSFER_ERROR: log_error("Got transfer error for buffer %p\n", transfer->buffer); stream->error_code = BLADERF_ERR_IO; break; case LIBUSB_TRANSFER_OVERFLOW : log_error("Got transfer over for buffer %p, " "transfer \"actual_length\" = %d\n", transfer->buffer, transfer->actual_length); stream->error_code = BLADERF_ERR_IO; break; case LIBUSB_TRANSFER_TIMED_OUT: stream->error_code = BLADERF_ERR_TIMEOUT; break; case LIBUSB_TRANSFER_NO_DEVICE: stream->error_code = BLADERF_ERR_NODEV; break; default: log_error( "Unexpected transfer status: %d\n", transfer->status ); break; } } if (stream->state == STREAM_RUNNING) { /* Sanity check for debugging purposes */ if (transfer->length != transfer->actual_length) { log_warning( "Received short transfer\n" ); /* For the SC16Q11 format, we're 4 bytes per samples... */ if ((transfer->actual_length & 3) != 0) { log_warning( "Fractional samples received - stream likely corrupt\n" ); } } /* Call user callback requesting more data to transmit */ next_buffer = stream->cb( stream->dev, stream, &metadata, transfer->buffer, bytes_to_c16_samples(transfer->actual_length), stream->user_data); if (next_buffer == BLADERF_STREAM_SHUTDOWN) { stream->state = STREAM_SHUTTING_DOWN; } else if (next_buffer != BLADERF_STREAM_NO_DATA) { int status = submit_transfer(stream, next_buffer); if (status != 0) { /* If this fails, we probably have a serious problem...so just * shut it down. */ stream->state = STREAM_SHUTTING_DOWN; } } } /* Check to see if all the transfers have been cancelled, * and if so, clean up the stream */ if (stream->state == STREAM_SHUTTING_DOWN) { /* We know we're done when all of our transfers have returned to their * "available" states */ if (stream_data->num_avail_transfers == stream_data->num_transfers) { stream->state = STREAM_DONE; } else { cancel_all_transfers(stream); } } pthread_mutex_unlock(&stream->lock); }