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; }
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; }
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; } }
void IsoTransferPool::fillTransfer(libusb_transfer* transfer) { transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; transfer->num_iso_packets = num_packets_; libusb_set_iso_packet_lengths(transfer, packet_size_); }
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); }
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); }
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; }
/* 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; }