libbladeRF: Asynchronous API

| libbladeRF 2.2.1-git Nuand bladeRF library

Typedefs | Macros | Functions
Asynchronous API
Streaming

## Description

This interface gives the API user full control over the stream and buffer management, at the cost of added complexity.

Note
  New users are recommended to first evaluate the Synchronous API interface, and to only use this interface if the former is found to not yield suitable performance.

These functions are either thread-safe or may be used in a thread-safe manner (per the details noted in the function description).

## Typedefs
typedef void *(* | bladerf_stream_cb) (struct bladerf *dev, struct bladerf_stream *stream, struct bladerf_metadata *meta, void *samples, size_t num_samples, void *user_data)

## Macros
#define | BLADERF_STREAM_SHUTDOWN (NULL)
#define | BLADERF_STREAM_NO_DATA ((void *)(-1))

## Functions
API_EXPORT int CALL_CONV | bladerf_init_stream (struct bladerf_stream **stream, struct bladerf *dev, bladerf_stream_cb callback, void ***buffers, size_t num_buffers, bladerf_format format, size_t samples_per_buffer, size_t num_transfers, void *user_data)
API_EXPORT int CALL_CONV | bladerf_stream (struct bladerf_stream *stream, bladerf_channel_layout layout)
API_EXPORT int CALL_CONV | bladerf_submit_stream_buffer (struct bladerf_stream *stream, void *buffer, unsigned int timeout_ms)
API_EXPORT int CALL_CONV | bladerf_submit_stream_buffer_nb (struct bladerf_stream *stream, void *buffer)
API_EXPORT void CALL_CONV | bladerf_deinit_stream (struct bladerf_stream *stream)
API_EXPORT int CALL_CONV | bladerf_set_stream_timeout (struct bladerf *dev, bladerf_direction dir, unsigned int timeout)
API_EXPORT int CALL_CONV | bladerf_get_stream_timeout (struct bladerf *dev, bladerf_direction dir, unsigned int *timeout)

## Typedef Documentation

## ◆ bladerf_stream_cb

typedef void*(* bladerf_stream_cb) (struct bladerf *dev, struct bladerf_stream *stream, struct bladerf_metadata *meta, void *samples, size_t num_samples, void *user_data)

This typedef represents a callback function that is executed in response to this interface's asynchronous events.

Stream callbacks must not block or perform long-running operations. Otherwise, timeouts may occur. If this cannot be guaranteed, consider returning BLADERF_STREAM_NO_DATA in callbacks and later submit a buffer using bladerf_submit_stream_buffer(). However, callbacks should always take a single approach of returning buffers or returning BLADERF_STREAM_NO_DATA and submitting buffers later – but not both.

When running in a full-duplex mode of operation with simultaneous TX and RX stream threads, be aware that one stream's callback may occur in the context of another stream's thread. The API user is responsible for ensuring their callbacks are thread safe. For example, when managing access to sample buffers, the caller must ensure that if one thread is processing samples in a buffer, that this buffer is not returned via the callback's return value.

As of libbladeRF v0.15.0, is guaranteed that only one callback from a stream will occur at a time. (i.e., a second TX callback will not fire while one is currently being handled.) To achieve this, while a callback is executing, a per-stream lock is held. It is important to consider this when thinking about the order of lock acquisitions both in the callbacks, and the code surrounding bladerf_submit_stream_buffer().

Note
  Do not call bladerf_submit_stream_buffer() from a callback.

For both RX and TX, the stream callback receives:

- dev: Device structure
- stream: The associated stream
- metadata: For future support - do not attempt to read/write this in the current library implementation.
- user_data: User data provided when initializing stream

For TX callbacks:

- samples: Pointer to buffer of samples that was sent
- num_samples: Number of sent in last transfer and to send in next transfer
- Return value: The user specifies the address of the next buffer to send, BLADERF_STREAM_SHUTDOWN, or BLADERF_STREAM_NO_DATA.

For RX callbacks:

- samples: Buffer filled with received data
- num_samples: Number of samples received and size of next buffers
- Return value: The user specifies the next buffer to fill with RX data, which should be `num_samples` in size, BLADERF_STREAM_SHUTDOWN, or BLADERF_STREAM_NO_DATA.

Definition at line 2724 of file libbladeRF.h.

## Macro Definition Documentation

## ◆ BLADERF_STREAM_NO_DATA

#define BLADERF_STREAM_NO_DATA ((void *)(-1))

Use this value in a stream callback to indicate that no buffer is being provided. In this case, buffers are expected to be provided via bladerf_submit_stream_buffer().

Definition at line 2672 of file libbladeRF.h.

## ◆ BLADERF_STREAM_SHUTDOWN

#define BLADERF_STREAM_SHUTDOWN (NULL)

Use this as a return value in callbacks or as the buffer parameter to bladerf_submit_stream_buffer() to shutdown a stream.

Definition at line 2665 of file libbladeRF.h.

## Function Documentation

## ◆ bladerf_deinit_stream()

API_EXPORT void CALL_CONV bladerf_deinit_stream | ( | struct bladerf_stream * | stream | ) |

Deinitialize and deallocate stream resources.

Precondition
  Stream is no longer being used (via bladerf_submit_stream_buffer() or bladerf_stream() calls.)

Postcondition
  Stream is deallocated and may no longer be used.

Parameters

  stream | Stream to deinitialize. This function does nothing if stream is `NULL`.

## ◆ bladerf_get_stream_timeout()

API_EXPORT int CALL_CONV bladerf_get_stream_timeout | ( | struct bladerf * | dev,
|  | bladerf_direction | dir,
|  | unsigned int * | timeout
| ) |  |

Get transfer timeout in milliseconds

Parameters

  | dev | Device handle
  [in] | dir | Stream direction
  [out] | timeout | On success, updated with current transfer timeout value. Undefined on failure.

Returns
  0 on success, value from Error codes list on failure

## ◆ bladerf_init_stream()

API_EXPORT int CALL_CONV bladerf_init_stream | ( | struct bladerf_stream ** | stream,
|  | struct bladerf * | dev,
|  | bladerf_stream_cb | callback,
|  | void *** | buffers,
|  | size_t | num_buffers,
|  | bladerf_format | format,
|  | size_t | samples_per_buffer,
|  | size_t | num_transfers,
|  | void * | user_data
| ) |  |

Initialize a stream for use with asynchronous routines.

This function will internally allocate data buffers, which will be provided to the API user in callback functions.

The `buffers` output parameter populates a pointer to the list of allocated buffers. This allows the API user to implement a buffer management scheme to best suit his or her specific use case.

Generally, one will want to set the `buffers` parameter to a value larger than the `num_transfers` parameter, and keep track of which buffers are currently "in-flight", versus those available for use.

For example, for a transmit stream, modulated data can be actively written into free buffers while transfers of other buffers are occurring. Once a buffer has been filled with data, it can be marked 'in-flight' and be returned in a successive callback to transmit.

The choice of values for the `num_transfers` and `buffer_size` should be made based upon the desired samplerate, and the stream timeout value specified via bladerf_set_stream_timeout(), which defaults to 1 second.

For a given sample rate, the below relationship must be upheld to transmit or receive data without timeouts or dropped data.

\[ Sample\ Rate > \frac{\#\ Transfers}{Timeout} \times Buffer\ Size \]

...where Sample Rate is in samples per second, and Timeout is in seconds.

To account for general system overhead, it is recommended to multiply the righthand side by 1.1 to 1.25.

While increasing the number of buffers available provides additional elasticity, be aware that it also increases latency.

Parameters

  [out] | stream | Upon success, this will be updated to contain a stream handle (i.e., address)
  | dev | Device to associate with the stream
  [in] | callback | Callback routine to handle asynchronous events
  [out] | buffers | This will be updated to point to a dynamically allocated array of buffer pointers.
  [in] | num_buffers | Number of buffers to allocate and return. This value must >= the `num_transfers` parameter.
  [in] | format | Sample data format
  [in] | samples_per_buffer | Size of allocated buffers, in units of samples Note that the physical size of the buffer is a function of this and the format parameter.
  [in] | num_transfers | Maximum number of transfers that may be in-flight simultaneously. This must be <= the `num_buffers` parameter.
  [in] | user_data | Caller-provided data that will be provided in stream callbacks

Note
  This call should be later followed by a call to bladerf_deinit_stream() to avoid memory leaks.

Returns
  0 on success, value from Error codes list on failure

## ◆ bladerf_set_stream_timeout()

API_EXPORT int CALL_CONV bladerf_set_stream_timeout | ( | struct bladerf * | dev,
|  | bladerf_direction | dir,
|  | unsigned int | timeout
| ) |  |

Set stream transfer timeout in milliseconds

Parameters

  | dev | Device handle
  [in] | dir | Stream direction
  [in] | timeout | Timeout in milliseconds

Returns
  0 on success, value from Error codes list on failure

## ◆ bladerf_stream()

API_EXPORT int CALL_CONV bladerf_stream | ( | struct bladerf_stream * | stream,
|  | bladerf_channel_layout | layout
| ) |  |

Begin running a stream. This call will block until the stream completes.

Only 1 RX stream and 1 TX stream may be running at a time. Attempting to call bladerf_stream() with more than one stream will yield unexpected (and most likely undesirable) results.

Note
  See the bladerf_stream_cb description for additional thread-safety caveats.

Precondition
  This function should be preceded by a call to bladerf_enable_module() to enable the associated RX or TX directions before attempting to use it to stream data.

Parameters

  | stream | A stream handle that has been successfully been initialized via bladerf_init_stream()
  [in] | layout | Stream direction and channel layout

Returns
  0 on success, value from Error codes list on failure

## ◆ bladerf_submit_stream_buffer()

API_EXPORT int CALL_CONV bladerf_submit_stream_buffer | ( | struct bladerf_stream * | stream,
|  | void * | buffer,
|  | unsigned int | timeout_ms
| ) |  |

Submit a buffer to a stream from outside of a stream callback function. Use this only when returning BLADERF_STREAM_NO_DATA from callbacks. Do not use this function if the associated callback functions will be returning buffers for submission.

This call may block if the device is not ready to submit a buffer for transfer. Use the `timeout_ms` to place an upper limit on the time this function can block.

To safely submit buffers from outside the stream callback flow, this function internally acquires a per-stream lock (the same one that is held during the execution of a stream callback). Therefore, it is important to be aware of locks that may be held while making this call, especially those acquired during execution of the associated stream callback function. (i.e., be wary of the order of lock acquisitions, including the internal per-stream lock.)

Parameters

  | stream | Stream to submit buffer to
  [in,out] | buffer | Buffer to fill (RX) or containing data (TX). This buffer is assumed to be the size specified in the associated bladerf_init_stream() call.
  [in] | timeout_ms | Milliseconds to timeout in, if this call blocks. 0 implies an "infinite" wait.

Returns
  0 on success, BLADERF_ERR_TIMEOUT upon a timeout, or a value from Error codes list on other failures

## ◆ bladerf_submit_stream_buffer_nb()

API_EXPORT int CALL_CONV bladerf_submit_stream_buffer_nb | ( | struct bladerf_stream * | stream,
|  | void * | buffer
| ) |  |

This is a non-blocking variant of bladerf_submit_stream_buffer(). All of the caveats and important notes from bladerf_submit_stream_buffer() apply.

In the event that this call would need to block in order to submit a buffer, it returns BLADERF_ERR_WOULD_BLOCK. In this case, the caller could either wait and try again or defer buffer submission to the asynchronous callback.

Parameters

  | stream | Stream to submit buffer to
  [in,out] | buffer | Buffer to fill (RX) or containing data (TX). This buffer is assumed to be the size specified in the associated bladerf_init_stream() call.

Returns
  0 on success, BLADERF_ERR_WOULD_BLOCK if the call would have to block to succeed, or another value from Error codes upon other failure