Beispiel #1
0
void INT_USB_FUNC(void)
{
    /* some bits in GINTSTS can be set even though we didn't enable the interrupt source
     * so AND it with the actual mask */
    unsigned long sts = GINTSTS & GINTMSK;
    logf("usb-drv: INT 0x%lx", sts);

    if(sts & GINTMSK_usbreset)
    {
        DCFG &= ~bitm(DCFG, devadr); /* Address 0 */
        reset_endpoints();
        usb_core_bus_reset();
    }

    if(sts & GINTMSK_enumdone)  /* enumeration done, we now know the speed */
    {
        /* Set up the maximum packet sizes accordingly */
        uint32_t maxpacket = (usb_drv_port_speed() ? 512 : 64) << DEPCTL_mps_bitp;
        for (int dir = 0; dir < 2; dir++)
        {
            bool out = dir == DIR_OUT;
            for (unsigned i = 1; i < num_eps(out); i++)
            {
                int ep = (out ? out_ep_list : in_ep_list)[i];
                DEPCTL(ep, out) &= ~(DEPCTL_mps_bits << DEPCTL_mps_bitp);
                DEPCTL(ep, out) |= maxpacket;
            }
        }
    }

    if(sts & (GINTMSK_outepintr | GINTMSK_inepintr))
    {
        unsigned long daint = DAINT;

        for (int i = 0; i < USB_NUM_ENDPOINTS; i++)
        {
            if (daint & DAINT_IN_EP(i))
                handle_ep_int(i, false);
            if (daint & DAINT_OUT_EP(i))
                handle_ep_int(i, true);
        }

        DAINT = daint;
    }

    if(sts & GINTMSK_disconnect)
        cancel_all_transfers(true);

    GINTSTS = sts;
}
Beispiel #2
0
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));

    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++;
        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" );
        }

       /* Call user callback requesting more data to transmit */
        next_buffer = stream->cb(
                        stream->dev,
                        stream,
                        &metadata,
                        transfer->buffer,
                        bytes_to_sc16q11(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 == stream_data->num_transfers) {
            stream->state = STREAM_DONE;
        } else {
            cancel_all_transfers(stream);
        }
    }

    MUTEX_UNLOCK(&stream->lock);
}
Beispiel #3
0
static int lusb_stream(void *driver, struct bladerf_stream *stream,
                       bladerf_module module)
{
    size_t i;
    int status = 0;
    void *buffer;
    struct bladerf_metadata metadata;
    struct bladerf *dev = stream->dev;
    struct bladerf_lusb *lusb = (struct bladerf_lusb *) driver;
    struct lusb_stream_data *stream_data = stream->backend_data;
    struct timeval tv = { 0, LIBUSB_HANDLE_EVENTS_TIMEOUT_NSEC };

    /* Currently unused, so zero it out for a sanity check when debugging */
    memset(&metadata, 0, sizeof(metadata));

    MUTEX_LOCK(&stream->lock);

    /* Set up initial set of buffers */
    for (i = 0; i < stream_data->num_transfers; i++) {
        if (module == BLADERF_MODULE_TX) {
            buffer = stream->cb(dev,
                                stream,
                                &metadata,
                                NULL,
                                stream->samples_per_buffer,
                                stream->user_data);

            if (buffer == BLADERF_STREAM_SHUTDOWN) {
                /* If we have transfers in flight and the user prematurely
                 * cancels the stream, we'll start shutting down */
                if (stream_data->num_avail != stream_data->num_transfers) {
                    stream->state = STREAM_SHUTTING_DOWN;
                } else {
                    /* No transfers have been shipped out yet so we can
                     * simply enter our "done" state */
                    stream->state = STREAM_DONE;
                }

                /* In either of the above we don't want to attempt to
                 * get any more buffers from the user */
                break;
            }
        } else {
            buffer = stream->buffers[i];
        }

        if (buffer != BLADERF_STREAM_NO_DATA) {
            status = submit_transfer(stream, buffer);

            /* If we failed to submit any transfers, cancel everything in
             * flight.  We'll leave the stream in the running state so we can
             * have libusb fire off callbacks with the cancelled status*/
            if (status < 0) {
                stream->error_code = status;
                cancel_all_transfers(stream);
            }
        }
    }
    MUTEX_UNLOCK(&stream->lock);

    /* This loop is required so libusb can do callbacks and whatnot */
    while (stream->state != STREAM_DONE) {
        status = libusb_handle_events_timeout(lusb->context, &tv);

        if (status < 0 && status != LIBUSB_ERROR_INTERRUPTED) {
            log_warning("unexpected value from events processing: "
                        "%d: %s\n", status, libusb_error_name(status));
            status = error_conv(status);
        }
    }

    return status;
}
Beispiel #4
0
void usb_drv_cancel_all_transfers()
{
    cancel_all_transfers(false);
}