Exemple #1
0
int fnusb_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, int ep, int xfers, int pkts, int len)
{
	int ret, i;

	strm->parent = dev;
	strm->cb = cb;
	strm->num_xfers = xfers;
	strm->pkts = pkts;
	strm->len = len;
	strm->buffer = malloc(xfers * pkts * len);
	strm->xfers = malloc(sizeof(struct libusb_transfer*) * xfers);

	uint8_t *bufp = strm->buffer;

	for (i=0; i<xfers; i++) {
		printf("Creating EP %02x transfer #%d\n", ep, i);
		strm->xfers[i] = libusb_alloc_transfer(pkts);

		libusb_fill_iso_transfer(strm->xfers[i], dev->dev, ep, bufp, pkts * len, pkts, iso_callback, strm, 0);

		libusb_set_iso_packet_lengths(strm->xfers[i], len);

		ret = libusb_submit_transfer(strm->xfers[i]);
		if (ret < 0)
			printf("Failed to submit xfer %d: %d\n", i, ret);

		bufp += pkts*len;
	}

	return 0;

}
Exemple #2
0
int fnusb_start_iso(fnusb_dev *dev, fnusb_isoc_stream *strm, fnusb_iso_cb cb, int ep, int xfers, int pkts, int len)
{
	freenect_context *ctx = dev->parent->parent;
	int ret, i;

	strm->parent = dev;
	strm->cb = cb;
	strm->num_xfers = xfers;
	strm->pkts = pkts;
	strm->len = len;
	strm->buffer = (uint8_t*)malloc(xfers * pkts * len);
	strm->xfers = (struct libusb_transfer**)malloc(sizeof(struct libusb_transfer*) * xfers);
	strm->dead = 0;
	strm->dead_xfers = 0;

	uint8_t *bufp = strm->buffer;

	for (i=0; i<xfers; i++) {
		FN_SPEW("Creating EP %02x transfer #%d\n", ep, i);
		strm->xfers[i] = libusb_alloc_transfer(pkts);

		libusb_fill_iso_transfer(strm->xfers[i], dev->dev, ep, bufp, pkts * len, pkts, iso_callback, strm, 0);

		libusb_set_iso_packet_lengths(strm->xfers[i], len);

		ret = libusb_submit_transfer(strm->xfers[i]);
		if (ret < 0)
			FN_WARNING("Failed to submit isochronous transfer %d: %d\n", i, ret);

		bufp += pkts*len;
	}

	return 0;

}
/* Once setup has succeded, this is called once to start transfers. */
int usb_start_transfers(int fd) {
    if (!is_setup) {
        LOGD("Must call setup before starting.\n");
        return -1;
    }
	static uint8_t buf[PACKET_SIZE * NUM_PACKETS];
	static struct libusb_transfer *xfr[NUM_TRANSFERS];
	int num_iso_pack = NUM_PACKETS;
    int i;

    outfd = fd;
    if (outfd < 3) {
        LOGD("Set outfd to %d. Are you sure?\n", outfd);
    }

    for (i=0; i<NUM_TRANSFERS; i++) {
        xfr[i] = libusb_alloc_transfer(num_iso_pack);
        if (!xfr[i]) {
            LOGD("libusb_alloc_transfer failed.\n");
            return -ENOMEM;
        }

        libusb_fill_iso_transfer(xfr[i], devh, EP_ISO_IN, buf,
                sizeof(buf), num_iso_pack, transfer_cb, NULL, 1000);
        libusb_set_iso_packet_lengths(xfr[i], sizeof(buf)/num_iso_pack);

        libusb_submit_transfer(xfr[i]);
    }
    return 0;
}
Exemple #4
0
int main() {
	int i;
	for (i=0;i<2000;i++) {
		sinbuffer[i] = sin(i*567*2*M_PI/2000.);
	}

	file = fopen("20k.bin","r");
	assert(file);

	struct libusb_transfer *xfrs[NUMTRANSFERS];

	libusb_init(NULL);
	libusb_device_handle *dev = libusb_open_device_with_vid_pid(NULL,0x03eb,0x204f);
	assert(dev);

	for (i=0;i<NUMTRANSFERS;i++) {
		xfrs[i] = libusb_alloc_transfer(50);
		char *buf = malloc(PACKETS*PACKETSIZE);
		libusb_fill_iso_transfer(xfrs[i],dev,0x01,buf,PACKETS*PACKETSIZE,PACKETS,callback,NULL,0);
		libusb_set_iso_packet_lengths(xfrs[i],PACKETSIZE);
		transfer(xfrs[i]);
	}
	t = dtime();
	while (1) libusb_handle_events(NULL);
}
bool LibusbSoundplaneDriver::processThreadScheduleTransfer(Transfer &transfer)
{
	if (processThreadShouldStopTransfers())
	{
		return false;
	}

	libusb_fill_iso_transfer(
		transfer.transfer,
		transfer.device,
		transfer.endpointAddress,
		reinterpret_cast<unsigned char *>(transfer.packets),
		sizeof(transfer.packets),
		transfer.numPackets(),
		processThreadTransferCallbackStatic,
		&transfer,
		1000);
	libusb_set_iso_packet_lengths(
		transfer.transfer,
		sizeof(transfer.packets) / transfer.numPackets());

	const auto result = libusb_submit_transfer(transfer.transfer);
	if (result < 0)
	{
		fprintf(stderr, "Failed to submit USB transfer: %s\n", libusb_error_name(result));
		return false;
	}
	else
	{
		mOutstandingTransfers++;
		return true;
	}
}
static int usb_send_sco_packet(uint8_t *packet, int size){
#ifdef HAVE_SCO
    int r;

    if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;

    // log_info("usb_send_acl_packet enter, size %u", size);
    
    // prepare transfer
    int completed = 0;
    libusb_fill_iso_transfer(sco_out_transfer, handle, sco_out_addr, packet, size, 1,
        async_callback, &completed, 0);
    libusb_set_iso_packet_lengths(sco_out_transfer, size);
    sco_out_transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
    sco_out_transfer->iso_packet_desc[0].length = size;

    // update state before submitting transfer
    usb_sco_out_active = 1;

    r = libusb_submit_transfer(sco_out_transfer);
    if (r < 0) {
        usb_sco_out_active = 0;
        log_error("Error submitting sco transfer, %d", r);
        return -1;
    }
#endif
    return 0;
}
/**
 * \brief Create an isochronous segment.
 *
 * \param _endpoint
 * \param packets
 * \param _isotransfer
 * \param dev_handle
 * \param timeout
 */
IsoSegment::IsoSegment(EndpointDescriptorPtr _endpoint, int packets,
	IsoTransfer *_isotransfer, libusb_device_handle *dev_handle,
	int timeout)
	throw(USBError) : endpoint(_endpoint), isotransfer(_isotransfer) {
	// compute the packet size for the packets that we need
	int	packetsize = endpoint->maxPacketSize()
			* endpoint->transactionOpportunities();

	// allocate the transfer
	transfer = libusb_alloc_transfer(packets);
	if (NULL == transfer) {
		debug(LOG_ERR, DEBUG_LOG, 0, "cannot allocate transfer");
	}
	transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
	transfer->num_iso_packets = packets;

	// create a buffer for the data
	size_t	buffersize = packets * packetsize;
	unsigned char	*buffer = (unsigned char *)calloc(1, buffersize);
	transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER;

	// fill the transfer request structure
	libusb_fill_iso_transfer(transfer, dev_handle,
		endpoint->bEndpointAddress(), buffer, buffersize,
		packets, isotransfer_callback, isotransfer, timeout);

	// set the packet sizes, all have the same size
	libusb_set_iso_packet_lengths(transfer, packetsize);

	// log completion of the segment creation
	debug(LOG_DEBUG, DEBUG_LOG, 0, "created IsoSegment with %d packets",
		packets);
}
Exemple #8
0
void perform_transfer(urb_t *urb) {
	int direction = urb->direction == IN ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT;

	/* Take a care about timings */
	if(urb->timing) {
		int time = urb->timing*pow(10,6);
		usleep(time);
	}

	/* Trigger libusb to perform the transfer */
	int r, bytes_transferred = 0;
	struct libusb_transfer transfer;
	switch(urb->type) {
		case CTRL:
			r = libusb_control_transfer(dev_handle, 
					urb->bmRequestType | direction,
					urb->bRequest,
					urb->wValue,
					urb->wIndex,
					urb->data,
					urb->data_size,
					0);
			ASSERT2(r >= 0, TRANSFER_FAILED_MESSAGE, libusb_error_name(r));
			break;
		case BULK:
			r = libusb_bulk_transfer(dev_handle,
					urb->endpoint | direction,
					urb->data,
					urb->data_size,
					&bytes_transferred,
					0);
			ASSERT2(r == 0, TRANSFER_FAILED_MESSAGE, libusb_error_name(r));
			break;
		case INTR:
			r = libusb_interrupt_transfer(dev_handle,
					urb->endpoint | direction,
					urb->data,
					urb->data_size,
					&bytes_transferred,
					0);
			ASSERT2(r == 0, TRANSFER_FAILED_MESSAGE, libusb_error_name(r));
			break;
		case ISOC:
			libusb_fill_iso_transfer(&transfer,
					dev_handle,
					urb->endpoint | direction,
					urb->data,
					urb->data_size,
					1,
					continue_transfer_cb,
					NULL,
					0);
			libusb_submit_transfer(&transfer);
			ASSERT2(r == 0, TRANSFER_FAILED_MESSAGE, libusb_error_name(r));
			break;
	}
}
Exemple #9
0
unsigned char unixUsbDriver::usbIsoInit(void){
    int error;

    for(int n=0;n<NUM_FUTURE_CTX;n++){
        for (unsigned char k=0;k<NUM_ISO_ENDPOINTS;k++){
            isoCtx[k][n] = libusb_alloc_transfer(ISO_PACKETS_PER_CTX);
            transferCompleted[k][n].number = (k * ISO_PACKETS_PER_CTX) + n;
            transferCompleted[k][n].completed = false;
            libusb_fill_iso_transfer(isoCtx[k][n], handle, pipeID[k], dataBuffer[k][n], ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX, ISO_PACKETS_PER_CTX, isoCallback, (void*)&transferCompleted[k][n], 4000);
            libusb_set_iso_packet_lengths(isoCtx[k][n], ISO_PACKET_SIZE);
        }
    }

    for(int n=0;n<NUM_FUTURE_CTX;n++){
        for (unsigned char k=0;k<NUM_ISO_ENDPOINTS;k++){
            error = libusb_submit_transfer(isoCtx[k][n]);
            if(error){
                qDebug() << "libusb_submit_transfer FAILED";
                qDebug() << "ERROR" << libusb_error_name(error);
            } else {
                if(n == 0){
                    qint64 t0;
                    qint64 t = QDateTime::currentMSecsSinceEpoch();
                    if(k==0){
                        t0 = t;
                    }
                    midBufferOffsets[k] = t0 - t;
                    qDebug() << "isoCtx submitted successfully!";
                    qDebug() << "[n, k] = " << n << k;
                    qDebug() << "t = " << t;
                    qDebug() << "Delay = " << 0;//midBufferOffsets[k];
                }
            }
        }
    }

    isoTimer = new QTimer();
    isoTimer->setTimerType(Qt::PreciseTimer);
    isoTimer->start(ISO_TIMER_PERIOD);
    connect(isoTimer, SIGNAL(timeout()), this, SLOT(isoTimerTick()));

    qDebug() << "Setup successful!";

    isoHandler = new worker();
    workerThread = new QThread();

    isoHandler->ctx = ctx;
    isoHandler->moveToThread(workerThread);
    connect(workerThread, SIGNAL(started()), isoHandler, SLOT(handle()));

    workerThread->start();

    qDebug() << "MAIN THREAD ID" << QThread::currentThreadId();
    //QThread::sleep(1);
    qDebug() << "Iso Stack initialised!";
    return 1;
}
static int usb_send_sco_packet(uint8_t *packet, int size){
#ifdef HAVE_SCO
    int r;

    if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;

    // log_info("usb_send_acl_packet enter, size %u", size);

    // store packet in free slot
    int tranfer_index = sco_ring_write;
    uint8_t * data = &sco_ring_buffer[tranfer_index * SCO_PACKET_SIZE];
    memcpy(data, packet, size);

    // setup transfer
    struct libusb_transfer * sco_transfer = sco_ring_transfers[tranfer_index];
    libusb_fill_iso_transfer(sco_transfer, handle, sco_out_addr, data, size, NUM_ISO_PACKETS, async_callback, NULL, 0);
    libusb_set_iso_packet_lengths(sco_transfer, ISO_PACKET_SIZE);
    r = libusb_submit_transfer(sco_transfer);
    if (r < 0) {
        log_error("Error submitting sco transfer, %d", r);
        return -1;
    }

    // mark slot as full
    sco_ring_write++;
    if (sco_ring_write == SCO_RING_BUFFER_COUNT){
        sco_ring_write = 0;
    }
    sco_ring_transfers_active++;

    // log_info("H2: queued packet at index %u, num active %u", tranfer_index, sco_ring_transfers_active);

    // notify upper stack that packet processed and that it might be possible to send again
    if (sco_ring_have_space()){
        uint8_t event[] = { DAEMON_EVENT_HCI_PACKET_SENT, 0};
        packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
    } 
#endif
    return 0;
}
Exemple #11
0
/* Setup the ISOC transfer by allocating the packets for transfer and
 * the buffer for audio data. */
static int setup_isoc_transfer()
{
	uintptr_t i;
	static unsigned int packet_size;

	if (packet_size != aud_cfg.format[aud_cfg.fmt_idx].pkt_size) {
		packet_size = aud_cfg.format[aud_cfg.fmt_idx].pkt_size;
	}
	/* We allocate one more 'audio_duration_ms' transfer than necessary on purpose */
	/* It will be use later to handle audio wrapping */
	if(abuf == NULL)
		abuf = malloc(packets_per_transfer*packet_size*num_transfers
				+ audio_duration_ms*packet_size);

	if(aud_cfg.xfers == NULL)
		aud_cfg.xfers = calloc(num_transfers, sizeof(struct libusb_transfer*));

	for (i=0; i<num_transfers; i++) {
		aud_cfg.xfers[i] = libusb_alloc_transfer(packets_per_transfer);
		CHECK_ERROR(abuf == NULL || aud_cfg.xfers[i] == NULL,
			-1, "Unable to allocate ISOC libusb transfer");

		libusb_fill_iso_transfer(aud_cfg.xfers[i],
				audio_hdl,
				aud_cfg.format[aud_cfg.fmt_idx].ep,
				abuf + i*(packets_per_transfer * packet_size),
				packets_per_transfer * packet_size,
				packets_per_transfer,
				(libusb_transfer_cb_fn) aud_cap_callback,
				(void*)i,
				USB_TIMEOUT);

		libusb_set_iso_packet_lengths(aud_cfg.xfers[i], packet_size);
	}

	return 0;
}
static int usb_open(void *transport_config){
    int r;

    sco_state_machine_init();
    sco_ring_init();
    handle_packet = NULL;

    // default endpoint addresses
    event_in_addr = 0x81; // EP1, IN interrupt
    acl_in_addr =   0x82; // EP2, IN bulk
    acl_out_addr =  0x02; // EP2, OUT bulk
    sco_in_addr  =  0x83; // EP3, IN isochronous
    sco_out_addr =  0x03; // EP3, OUT isochronous    

    // USB init
    r = libusb_init(NULL);
    if (r < 0) return -1;

    libusb_state = LIB_USB_OPENED;

    // configure debug level
    libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING);
    
#ifdef HAVE_USB_VENDOR_ID_AND_PRODUCT_ID

    // Use a specified device
    log_info("Want vend: %04x, prod: %04x", USB_VENDOR_ID, USB_PRODUCT_ID);
    handle = libusb_open_device_with_vid_pid(NULL, USB_VENDOR_ID, USB_PRODUCT_ID);

    if (!handle){
        log_error("libusb_open_device_with_vid_pid failed!");
        usb_close(handle);
        return -1;
    }
    log_info("libusb open %d, handle %p", r, handle);

    r = prepare_device(handle);
    if (r < 0){
        usb_close(handle);
        return -1;
    }

#else
    // Scan system for an appropriate devices
    libusb_device **devs;
    ssize_t cnt;

    log_info("Scanning for USB Bluetooth device");
    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0) {
        usb_close(handle);
        return -1;
    }

    int startIndex = 0;
    dev = NULL;

    while (1){
        int deviceIndex = scan_for_bt_device(devs, startIndex);
        if (deviceIndex < 0){
            break;
        }
        startIndex = deviceIndex+1;

        log_info("USB Bluetooth device found, index %u", deviceIndex);
        
        handle = NULL;
        r = libusb_open(devs[deviceIndex], &handle);

        if (r < 0) {
            log_error("libusb_open failed!");
            handle = NULL;
            continue;
        }
    
        log_info("libusb open %d, handle %p", r, handle);

        // reset device
        libusb_reset_device(handle);
        if (r < 0) {
            log_error("libusb_reset_device failed!");
            libusb_close(handle);
            handle = NULL;
            continue;
        }

        // device found
        r = prepare_device(handle);
        
        if (r < 0){
            continue;
        }

        libusb_state = LIB_USB_INTERFACE_CLAIMED;

        break;
    }

    libusb_free_device_list(devs, 1);

    if (handle == 0){
        log_error("No USB Bluetooth device found");
        return -1;
    }

    scan_for_bt_endpoints();

#endif
    
    // allocate transfer handlers
    int c;
    for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
        event_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers Events
        acl_in_transfer[c]  =  libusb_alloc_transfer(0); // 0 isochronous transfers ACL in
        if ( !event_in_transfer[c] || !acl_in_transfer[c]) {
            usb_close(handle);
            return LIBUSB_ERROR_NO_MEM;
        }
    }

    command_out_transfer = libusb_alloc_transfer(0);
    acl_out_transfer     = libusb_alloc_transfer(0);

    // TODO check for error

    libusb_state = LIB_USB_TRANSFERS_ALLOCATED;

#ifdef HAVE_SCO

    // incoming
    for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
        sco_in_transfer[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // isochronous transfers SCO in
        log_info("Alloc iso transfer");
        if (!sco_in_transfer[c]) {
            usb_close(handle);
            return LIBUSB_ERROR_NO_MEM;
        }
        // configure sco_in handlers
        libusb_fill_iso_transfer(sco_in_transfer[c], handle, sco_in_addr, 
            hci_sco_in_buffer[c], SCO_PACKET_SIZE, NUM_ISO_PACKETS, async_callback, NULL, 0);
        libusb_set_iso_packet_lengths(sco_in_transfer[c], ISO_PACKET_SIZE);
        r = libusb_submit_transfer(sco_in_transfer[c]);
        log_info("Submit iso transfer res = %d", r);
        if (r) {
            log_error("Error submitting isochronous in transfer %d", r);
            usb_close(handle);
            return r;
        }
    }

    // outgoing
    for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){
        sco_ring_transfers[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // 1 isochronous transfers SCO out - up to 3 parts
    }
#endif

    for (c = 0 ; c < ASYNC_BUFFERS ; c++) {
        // configure event_in handlers
        libusb_fill_interrupt_transfer(event_in_transfer[c], handle, event_in_addr, 
                hci_event_in_buffer[c], HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
        r = libusb_submit_transfer(event_in_transfer[c]);
        if (r) {
            log_error("Error submitting interrupt transfer %d", r);
            usb_close(handle);
            return r;
        }
 
        // configure acl_in handlers
        libusb_fill_bulk_transfer(acl_in_transfer[c], handle, acl_in_addr, 
                hci_acl_in_buffer[c] + HCI_INCOMING_PRE_BUFFER_SIZE, HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
        r = libusb_submit_transfer(acl_in_transfer[c]);
        if (r) {
            log_error("Error submitting bulk in transfer %d", r);
            usb_close(handle);
            return r;
        }
 
     }

    // Check for pollfds functionality
    doing_pollfds = libusb_pollfds_handle_timeouts(NULL);
    
    // NOTE: using pollfds doesn't work on Linux, so it is disable until further investigation here
    doing_pollfds = 0;

    if (doing_pollfds) {
        log_info("Async using pollfds:");

        const struct libusb_pollfd ** pollfd = libusb_get_pollfds(NULL);
        for (num_pollfds = 0 ; pollfd[num_pollfds] ; num_pollfds++);
        pollfd_data_sources = malloc(sizeof(data_source_t) * num_pollfds);
        if (!pollfd_data_sources){
            log_error("Cannot allocate data sources for pollfds");
            usb_close(handle);
            return 1;            
        }
        for (r = 0 ; r < num_pollfds ; r++) {
            data_source_t *ds = &pollfd_data_sources[r];
            ds->fd = pollfd[r]->fd;
            ds->process = usb_process_ds;
            run_loop_add_data_source(ds);
            log_info("%u: %p fd: %u, events %x", r, pollfd[r], pollfd[r]->fd, pollfd[r]->events);
        }
        free(pollfd);
    } else {
        log_info("Async using timers:");

        usb_timer.process = usb_process_ts;
        run_loop_set_timer(&usb_timer, AYSNC_POLLING_INTERVAL_MS);
        run_loop_add_timer(&usb_timer);
        usb_timer_active = 1;
    }

    return 0;
}