Exemplo n.º 1
0
/* Enter a new state and submit the corresponding request to the device.
 */
static int submit_request(const struct sr_dev_inst *sdi,
			  enum protocol_state state)
{
	struct dev_context *devc;
	struct acquisition_state *acq;
	int ret;

	devc = sdi->priv;
	acq  = devc->acquisition;

	devc->state = state;

	acq->xfer_out->length = 0;
	acq->reg_seq_pos = 0;
	acq->reg_seq_len = 0;

	/* Perform the model-specific action for the new state. */
	ret = (*devc->model->prepare_request)(sdi);

	if (ret != SR_OK) {
		devc->transfer_error = TRUE;
		return ret;
	}

	if (acq->reg_seq_pos < acq->reg_seq_len) {
		if ((state & STATE_EXPECT_RESPONSE) != 0)
			next_reg_read(acq);
		else
			next_reg_write(acq);
	}

	return submit_transfer(devc, acq->xfer_out);
}
Exemplo n.º 2
0
int usb_send_interrupt_out(int usb_number, unsigned char* buffer, unsigned char length)
{
  struct usb_state* state = usb_states+usb_number;

  if(!state->devh)
  {
    fprintf(stderr, "no usb device opened for index %d\n", usb_number);
    return -1;
  }

  unsigned char* buf = calloc(length, sizeof(unsigned char));
  if(!buf)
  {
    fprintf(stderr, "calloc failed\n");
    return -1;
  }

  memcpy(buf, buffer, length);

  if(state->type == C_TYPE_XONE_PAD && length > 2)
  {
    buf[2] = state->counter++;
  }

  struct libusb_transfer* transfer = libusb_alloc_transfer(0);

  transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;

  libusb_fill_interrupt_transfer(transfer, state->devh, controller[state->type].endpoints.out.address, buf, length, (libusb_transfer_cb_fn)usb_callback, usb_state_indexes+usb_number, 1000);

  return submit_transfer(transfer);
}
Exemplo n.º 3
0
/* USB input transfer completion callback.
 */
static void LIBUSB_CALL transfer_in_completed(struct libusb_transfer *transfer)
{
	const struct sr_dev_inst *sdi;
	struct dev_context *devc;
	struct acquisition_state *acq;

	sdi  = transfer->user_data;
	devc = sdi->priv;
	acq  = devc->acquisition;

	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
		sr_err("Transfer from device failed (state %d): %s.",
		       devc->state, libusb_error_name(transfer->status));
		devc->transfer_error = TRUE;
		return;
	}
	if ((devc->state & STATE_EXPECT_RESPONSE) == 0) {
		sr_err("Unexpected completion of input transfer (state %d).",
		       devc->state);
		devc->transfer_error = TRUE;
		return;
	}

	if (acq->reg_seq_pos < acq->reg_seq_len && !devc->cancel_requested) {
		/* Complete register read sequence. */
		if (read_reg_response(acq) != SR_OK) {
			devc->transfer_error = TRUE;
			return;
		}
		/* Repeat until all queued registers have been read. */
		if (++acq->reg_seq_pos < acq->reg_seq_len) {
			next_reg_read(acq);
			submit_transfer(devc, acq->xfer_out);
			return;
		}
	}

	switch (devc->state) {
	case STATE_STATUS_REQUEST:
		if (devc->cancel_requested)
			submit_request(sdi, STATE_STOP_CAPTURE);
		else
			handle_status_response(sdi);
		break;
	case STATE_LENGTH_REQUEST:
		if (devc->cancel_requested)
			submit_request(sdi, STATE_READ_FINISH);
		else
			handle_length_response(sdi);
		break;
	case STATE_READ_REQUEST:
		handle_read_response(sdi);
		break;
	default:
		sr_err("Unexpected device state %d.", devc->state);
		devc->transfer_error = TRUE;
		break;
	}
}
Exemplo n.º 4
0
/* The top-level code will have aquired the stream->lock for us */
int lusb_submit_stream_buffer(void *driver, struct bladerf_stream *stream,
                              void *buffer, unsigned int timeout_ms,
                              bool nonblock)
{
    int status = 0;
    struct lusb_stream_data *stream_data = stream->backend_data;
    struct timespec timeout_abs;

    if (buffer == BLADERF_STREAM_SHUTDOWN) {
        if (stream_data->num_avail == stream_data->num_transfers) {
            stream->state = STREAM_DONE;
        } else {
            stream->state = STREAM_SHUTTING_DOWN;
        }

        return 0;
    }

    if (stream_data->num_avail == 0) {
        if (nonblock) {
            log_debug("Non-blocking buffer submission requested, but no "
                      "transfers are currently available.");

            return BLADERF_ERR_WOULD_BLOCK;
        }

        if (timeout_ms != 0) {
            status = populate_abs_timeout(&timeout_abs, timeout_ms);
            if (status != 0) {
                return BLADERF_ERR_UNEXPECTED;
            }

            while (stream_data->num_avail == 0 && status == 0) {
                status = pthread_cond_timedwait(&stream->can_submit_buffer,
                        &stream->lock,
                        &timeout_abs);
            }
        } else {
            while (stream_data->num_avail == 0 && status == 0) {
                status = pthread_cond_wait(&stream->can_submit_buffer,
                        &stream->lock);
            }
        }
    }

    if (status == ETIMEDOUT) {
        log_debug("%s: Timed out waiting for a transfer to become available.\n",
                  __FUNCTION__);
        return BLADERF_ERR_TIMEOUT;
    } else if (status != 0) {
        return BLADERF_ERR_UNEXPECTED;
    } else {
        return submit_transfer(stream, buffer);
    }
}
Exemplo n.º 5
0
static int usb_poll_interrupt(int usb_number)
{
  struct usb_state* state = usb_states+usb_number;
  struct libusb_transfer* transfer = libusb_alloc_transfer(0);
  transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER ;
  unsigned int size = controller[state->type].endpoints.in.size;
  unsigned char* buf = calloc(size, sizeof(char));
  libusb_fill_interrupt_transfer(transfer, state->devh, controller[state->type].endpoints.in.address, buf, size, (libusb_transfer_cb_fn)usb_callback, usb_state_indexes+usb_number, 1000);
  int ret = submit_transfer(transfer);
  if(ret != -1)
  {
    state->ack = 0;
  }
  return ret;
}
Exemplo n.º 6
0
int usb_send_control(int usb_number, unsigned char* buffer, unsigned char length)
{
  struct usb_state* state = usb_states+usb_number;

  if(!state->devh)
  {
    fprintf(stderr, "no usb device opened for index %d\n", usb_number);
    return -1;
  }

  struct libusb_control_setup* control_setup = (struct libusb_control_setup*)buffer;
  if(control_setup->wLength > BUFFER_SIZE-LIBUSB_CONTROL_SETUP_SIZE)
  {
    fprintf(stderr, "wLength (%hu) is higher than %hu\n", control_setup->wLength, BUFFER_SIZE-LIBUSB_CONTROL_SETUP_SIZE);
    return -1;
  }

  unsigned int size = length;

  if(control_setup->bmRequestType & LIBUSB_ENDPOINT_IN)
  {
    size += control_setup->wLength;
  }

  unsigned char* buf = calloc(size, sizeof(char));
  if(!buf)
  {
    fprintf(stderr, "calloc failed\n");
    return -1;
  }

  memcpy(buf, buffer, length);

  struct libusb_transfer* transfer = libusb_alloc_transfer(0);

  transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;

  libusb_fill_control_transfer(transfer, state->devh, buf, (libusb_transfer_cb_fn)usb_callback, usb_state_indexes+usb_number, 1000);

  return submit_transfer(transfer);
}
Exemplo n.º 7
0
/* The top-level code will have aquired the stream->lock for us */
int lusb_submit_stream_buffer(void *driver, struct bladerf_stream *stream,
                              void *buffer, unsigned int timeout_ms)
{
    int status;
    struct lusb_stream_data *stream_data = stream->backend_data;
    struct timespec timeout_abs;

    if (buffer == BLADERF_STREAM_SHUTDOWN) {
        if (stream_data->num_avail_transfers == stream_data->num_transfers) {
            stream->state = STREAM_DONE;
        } else {
            stream->state = STREAM_SHUTTING_DOWN;
        }

        return 0;
    }

    status = populate_abs_timeout(&timeout_abs, timeout_ms);
    if (status != 0) {
        return BLADERF_ERR_UNEXPECTED;
    }

    while (stream_data->num_avail_transfers == 0 && status == 0) {
        status = pthread_cond_timedwait(&stream->can_submit_buffer,
                                        &stream->lock,
                                        &timeout_abs);
    }

    if (status == ETIMEDOUT) {
        return BLADERF_ERR_TIMEOUT;
    } else if (status != 0) {
        return BLADERF_ERR_UNEXPECTED;
    } else {
        return submit_transfer(stream, buffer);
    }
}
Exemplo n.º 8
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);
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
static int cyapi_stream(void *driver, struct bladerf_stream *stream,
                       bladerf_module module)
{
    int status;
    int idx = 0;
    long len;
    void *next_buffer;
    ULONG timeout_ms;
    bool success, done;
    struct stream_data *data = get_stream_data(stream);
    struct bladerf_cyapi *cyapi = get_backend_data(driver);
    struct bladerf_metadata meta;

    assert(stream->dev->transfer_timeout[stream->module] <= ULONG_MAX);
    if (stream->dev->transfer_timeout[stream->module] == 0) {
        timeout_ms = INFINITE;
    } else {
        timeout_ms = stream->dev->transfer_timeout[stream->module];
    }

    switch (module) {
        case BLADERF_MODULE_RX:
            data->ep = get_ep(cyapi->dev, SAMPLE_EP_IN);
            break;

        case BLADERF_MODULE_TX:
            data->ep = get_ep(cyapi->dev, SAMPLE_EP_OUT);
            break;

        default:
            assert(!"Invalid module");
            return BLADERF_ERR_UNEXPECTED;
    }

    if (data->ep == NULL) {
        log_debug("Failed to get EP handle.\n");
        return BLADERF_ERR_UNEXPECTED;
    }

    data->ep->XferMode = XMODE_DIRECT;
    data->ep->Abort();
    data->ep->Reset();

    log_verbose("Starting stream...\n");
    status = 0;
    done = false;
    memset(&meta, 0, sizeof(meta));

    MUTEX_LOCK(&stream->lock);

    for (unsigned int i = 0; i < data->num_transfers && status == 0; i++) {
        if (module == BLADERF_MODULE_TX) {
            next_buffer = stream->cb(stream->dev, stream, &meta, NULL,
                                     stream->samples_per_buffer,
                                     stream->user_data);

            if (next_buffer == BLADERF_STREAM_SHUTDOWN) {
                done = true;
                break;
            } else if (next_buffer == BLADERF_STREAM_NO_DATA) {
                continue;
            }
        } else {
            next_buffer = stream->buffers[i];
        }

        status = submit_transfer(stream, next_buffer);
    }

    MUTEX_UNLOCK(&stream->lock);
    if (status != 0) {
        goto out;
    }

    while (!done) {
        struct transfer *xfer;
        size_t i;

        i = data->inflight_i;
        xfer = &data->transfers[i];
        success = data->ep->WaitForXfer(&xfer->event, timeout_ms);

        if (!success) {
            status = BLADERF_ERR_TIMEOUT;
            log_debug("Steam timed out.\n");
            break;
        }

        len = 0;
        next_buffer = NULL;

        log_verbose("Got transfer complete in slot %u (buffer %p)\n",
                    i, data->transfers[i].buffer);

        MUTEX_LOCK(&stream->lock);
        success = data->ep->FinishDataXfer(data->transfers[i].buffer, len,
                                           &data->transfers[i].event,
                                           xfer->handle);

        if (success) {
            next_buffer = stream->cb(stream->dev, stream, &meta,
                                     data->transfers[i].buffer,
                                     bytes_to_samples(stream->format, len),
                                     stream->user_data);

        } else {
            done = true;
            status = BLADERF_ERR_IO;
            log_debug("Failed to finish transfer %u, buf=%p.\n",
                      (unsigned int)i, &data->transfers[i].buffer);
        }

        data->transfers[i].buffer = NULL;
        data->transfers[i].handle = NULL;
        data->num_avail++;
        pthread_cond_signal(&stream->can_submit_buffer);

        if (next_buffer == BLADERF_STREAM_SHUTDOWN) {
            done = true;
        } else if (next_buffer != BLADERF_STREAM_NO_DATA) {
            status = submit_transfer(stream, next_buffer);
            done = (status != 0);
        }

        data->inflight_i = next_idx(data, data->inflight_i);
        MUTEX_UNLOCK(&stream->lock);
    }

out:

    MUTEX_LOCK(&stream->lock);
    stream->error_code = status;
    stream->state = STREAM_SHUTTING_DOWN;

    data->ep->Abort();
    data->ep->Reset();


    for (unsigned int i = 0; i < data->num_transfers; i++) {
        LONG len = 0;
        if (data->transfers[i].handle != NULL) {
            data->ep->FinishDataXfer(data->transfers[i].buffer, len,
                                     &data->transfers[i].event,
                                     data->transfers[i].handle);


            data->transfers[i].buffer = NULL;
            data->transfers[i].handle = NULL;
            data->num_avail++;
        }
    }

    assert(data->num_avail == data->num_transfers);

    stream->state = STREAM_DONE;
    log_verbose("Stream done (error_code = %d)\n", stream->error_code);
    MUTEX_UNLOCK(&stream->lock);

    return 0;
}
Exemplo n.º 11
0
/* USB output transfer completion callback.
 */
static void LIBUSB_CALL transfer_out_completed(struct libusb_transfer *transfer)
{
	const struct sr_dev_inst *sdi;
	struct dev_context *devc;
	struct acquisition_state *acq;

	sdi  = transfer->user_data;
	devc = sdi->priv;
	acq  = devc->acquisition;

	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
		sr_err("Transfer to device failed (state %d): %s.",
		       devc->state, libusb_error_name(transfer->status));
		devc->transfer_error = TRUE;
		return;
	}

	/* If this was a read request, wait for the response. */
	if ((devc->state & STATE_EXPECT_RESPONSE) != 0) {
		submit_transfer(devc, acq->xfer_in);
		return;
	}
	if (acq->reg_seq_pos < acq->reg_seq_len)
		acq->reg_seq_pos++; /* register write completed */

	/* Repeat until all queued registers have been written. */
	if (acq->reg_seq_pos < acq->reg_seq_len && !devc->cancel_requested) {
		next_reg_write(acq);
		submit_transfer(devc, acq->xfer_out);
		return;
	}

	switch (devc->state) {
	case STATE_START_CAPTURE:
		sr_info("Acquisition started.");

		if (!devc->cancel_requested)
			devc->state = STATE_STATUS_WAIT;
		else
			submit_request(sdi, STATE_STOP_CAPTURE);
		break;
	case STATE_STOP_CAPTURE:
		if (!devc->cancel_requested)
			submit_request(sdi, STATE_LENGTH_REQUEST);
		else
			devc->state = STATE_IDLE;
		break;
	case STATE_READ_PREPARE:
		if (acq->mem_addr_next < acq->mem_addr_stop && !devc->cancel_requested)
			submit_request(sdi, STATE_READ_REQUEST);
		else
			submit_request(sdi, STATE_READ_FINISH);
		break;
	case STATE_READ_FINISH:
		devc->state = STATE_IDLE;
		break;
	default:
		sr_err("Unexpected device state %d.", devc->state);
		devc->transfer_error = TRUE;
		break;
	}
}