예제 #1
0
static void *rx_callback(struct bladerf *dev,
                         struct bladerf_stream *stream,
                         struct bladerf_metadata *meta,
                         void *samples,
                         size_t num_samples,
                         void *user_data)
{
    unsigned int requests;      /* Pending requests */
    unsigned int next_idx;
    unsigned int samples_idx;
    void *next_buf = NULL;      /* Next buffer to submit for reception */

    struct bladerf_sync *s = (struct bladerf_sync *)user_data;
    struct sync_worker  *w = s->worker;
    struct buffer_mgmt  *b = &s->buf_mgmt;

    /* Check if the caller has requested us to shut down. We'll keep the
     * SHUTDOWN bit set through our transition into the IDLE state so we
     * can act on it there. */
    pthread_mutex_lock(&w->request_lock);
    requests = w->requests;
    pthread_mutex_unlock(&w->request_lock);

    if (requests & SYNC_WORKER_STOP) {
        log_verbose("%s worker: Got STOP request upon entering callback. "
                    "Ending stream.\n", MODULE_STR(s));
        return NULL;
    }

    pthread_mutex_lock(&b->lock);

    /* Get the index of the buffer we've been notified about having been
     * completed */
    samples_idx = sync_buf2idx(b, samples);

    if (b->status[b->prod_i] == SYNC_BUFFER_EMPTY) {
        next_idx = b->prod_i;
        b->prod_i = (next_idx + 1) % b->num_buffers;

        b->status[samples_idx] = SYNC_BUFFER_FULL;
        b->status[next_idx] = SYNC_BUFFER_IN_FLIGHT;
        pthread_cond_signal(&b->buf_ready);
    } else {

        /* TODO propgate back the RX Overrun to the sync_rx() caller */
        log_debug("RX overrun @ buffer %u\r\n", samples_idx);

        next_idx = samples_idx;
        b->status[samples_idx] = SYNC_BUFFER_IN_FLIGHT;
    }

    next_buf = b->buffers[next_idx];

    log_verbose("%s worker: buf[%u] = full, buf[%u] = in_flight\n",
                MODULE_STR(s), samples_idx, next_idx);

    pthread_mutex_unlock(&b->lock);
    return next_buf;
}
예제 #2
0
static void *tx_callback(struct bladerf *dev,
                         struct bladerf_stream *stream,
                         struct bladerf_metadata *meta,
                         void *samples,
                         size_t num_samples,
                         void *user_data)
{
    unsigned int requests;      /* Pending requests */
    unsigned int completed_idx; /* Index of completed buffer */

    struct bladerf_sync *s = (struct bladerf_sync *)user_data;
    struct sync_worker  *w = s->worker;
    struct buffer_mgmt  *b = &s->buf_mgmt;

    /* Check if the caller has requested us to shut down. We'll keep the
     * SHUTDOWN bit set through our transition into the IDLE state so we
     * can act on it there. */
    pthread_mutex_lock(&w->request_lock);
    requests = w->requests;
    pthread_mutex_unlock(&w->request_lock);

    if (requests & SYNC_WORKER_STOP) {
        log_verbose("%s worker: Got STOP request upon entering callback. "
                    "Ending stream.\r\n", MODULE_STR(s));
        return NULL;
    }


    /* Mark the last transfer as being completed. Note that the first
     * callbacks we get have samples=NULL */
    if (samples != NULL) {

        pthread_mutex_lock(&b->lock);

        completed_idx = sync_buf2idx(b, samples);
        assert(b->status[completed_idx] == SYNC_BUFFER_IN_FLIGHT);
        b->status[completed_idx] = SYNC_BUFFER_EMPTY;

        pthread_cond_signal(&b->buf_ready);
        pthread_mutex_unlock(&b->lock);

        log_verbose("%s worker: Buffer %u emptied.\r\n",
                    MODULE_STR(s), completed_idx);
    }

    return BLADERF_STREAM_NO_DATA;
}
예제 #3
0
static void *rx_callback(struct bladerf *dev,
                         struct bladerf_stream *stream,
                         struct bladerf_metadata *meta,
                         void *samples,
                         size_t num_samples,
                         void *user_data)
{
    unsigned int requests;      /* Pending requests */
    unsigned int next_idx;
    unsigned int samples_idx;
    void *next_buf = NULL;      /* Next buffer to submit for reception */

    struct bladerf_sync *s = (struct bladerf_sync *)user_data;
    struct sync_worker  *w = s->worker;
    struct buffer_mgmt  *b = &s->buf_mgmt;

    /* Check if the caller has requested us to shut down. We'll keep the
     * SHUTDOWN bit set through our transition into the IDLE state so we
     * can act on it there. */
    pthread_mutex_lock(&w->request_lock);
    requests = w->requests;
    pthread_mutex_unlock(&w->request_lock);

    if (requests & SYNC_WORKER_STOP) {
        log_verbose("%s worker: Got STOP request upon entering callback. "
                    "Ending stream.\n", MODULE_STR(s));
        return NULL;
    }

    pthread_mutex_lock(&b->lock);

    /* Get the index of the buffer that was just filled */
    samples_idx = sync_buf2idx(b, samples);

    if (b->resubmit_count == 0) {
        if (b->status[b->prod_i] == SYNC_BUFFER_EMPTY) {

            /* This buffer is now ready for the consumer */
            b->status[samples_idx] = SYNC_BUFFER_FULL;
            pthread_cond_signal(&b->buf_ready);

            /* Update the state of the buffer being submitted next */
            next_idx = b->prod_i;
            b->status[next_idx] = SYNC_BUFFER_IN_FLIGHT;
            next_buf = b->buffers[next_idx];

            /* Advance to the next buffer for the next callback */
            b->prod_i = (next_idx + 1) % b->num_buffers;

            log_verbose("%s worker: buf[%u] = full, buf[%u] = in_flight\n",
                        MODULE_STR(s), samples_idx, next_idx);

        } else {
            /* TODO propgate back the RX Overrun to the sync_rx() caller */
            log_debug("RX overrun @ buffer %u\r\n", samples_idx);

            next_buf = samples;
            b->resubmit_count = s->stream_config.num_xfers - 1;
        }
    } else {
        /* We're still recovering from an overrun at this point. Just
         * turn around and resubmit this buffer */
        next_buf = samples;
        b->resubmit_count--;
        log_verbose("Resubmitting buffer %u (%u resubmissions left)\r\n",
                    samples_idx, b->resubmit_count);
    }


    pthread_mutex_unlock(&b->lock);
    return next_buf;
}