static void *usb_pump_events(void *user_data) { IGNORE(user_data); for (;;) { // NOTE: This is a blocking call so // no need for sleep() libusb_handle_events_completed(NULL, NULL); } }
int64_t FX3Stream::send(int64_t words, uint32_t *data, unsigned timeout) { if( error ) { cerr << "Blocked" << endl; return 0; } totalBytes = words*4; extBuf = (unsigned char*)data; transferredBytes = 0; submittedBytes = 0; shortPackets = 0; //Start transfer for( unsigned i = 0; i < transfers.size() && transferredBytes+submittedBytes < totalBytes; ++i ) { int64_t remainingBytes = totalBytes-(transferredBytes+submittedBytes); if( remainingBytes > FX3_TRANSFER_SIZE ) { libusb_fill_bulk_transfer( transfers[i], devhandle, FX3_OUT_EP, &extBuf[transferredBytes+submittedBytes], FX3_TRANSFER_SIZE, FX3Stream::sendCallback, this, timeout ); submittedBytes += FX3_TRANSFER_SIZE; } else if( remainingBytes > 0 ) { libusb_fill_bulk_transfer( transfers[i], devhandle, FX3_OUT_EP, &extBuf[transferredBytes+submittedBytes], remainingBytes, FX3Stream::sendCallback, this, timeout ); submittedBytes += remainingBytes; } error = libusb_submit_transfer( transfers[i] ); if( error ) { cerr << "Error submitting transfer: " << libusb_error_name(error) << endl; break; } } //Wait for transfer while( submittedBytes ) { int r = libusb_handle_events_completed(0,0); if( r ) { cerr << "Error handling events: " << libusb_error_name(r) << endl; error = r; break; } } if( shortPackets ) { cerr << "Error: Short packet(s) in outgoing transfers." << endl; shortPackets = 0; } if( error < 0 ) { cerr << "Error sending data: " << libusb_error_name(error) << endl; } if( error == LIBUSB_ERROR_TIMEOUT ) { error = 0; } return transferredBytes/4; }
int USBRequest::request(libusb_context* ctx, USBDevice *device, unsigned char endpoint, size_t request_bytes) { std::cout << "Request start" << std::endl; bytes = request_bytes; mDevice = device; err = 0; done = 0; ep = endpoint; addBuffers(); while(!done) { libusb_handle_events_completed(ctx, &done); } std::cout << "Remaining: " << bytes << std::endl; if(err != 0) { std::cout << "Erreur" << std::endl; } return err; }
static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) { int r, *completed = transfer->user_data; struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle); while (!*completed) { r = libusb_handle_events_completed(ctx, completed); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying", libusb_error_name(r)); libusb_cancel_transfer(transfer); continue; } } }
int Context::handleEvents(State & state, Context_wrapper * wrapper){ Stack * stack = state.stack; int result = 0; timeval tv; bool timeValSet = fillTimeval(state, tv, 1); int completed; if (stack->is<LUA_TBOOLEAN>(2)){ completed = (stack->to<bool>(2)) ? 1 : 0; } else{ completed = -1; } if (timeValSet){ if (completed >= 0){ result = libusb_handle_events_timeout_completed(wrapper->context, &tv, &completed); } else{ result = libusb_handle_events_timeout(wrapper->context, &tv); } } else{ if (completed >= 0){ result = libusb_handle_events_completed(wrapper->context, &completed); } else{ result = libusb_handle_events(wrapper->context); } } if (result == LIBUSB_SUCCESS){ stack->push<bool>(true); return 1; } else{ stack->push<bool>(false); stack->push<int>(result); return 2; } }
static void *read_thread(void *param) { hid_device *dev = param; unsigned char *buf; const size_t length = dev->input_ep_max_packet_size; /* Set up the transfer object. */ buf = malloc(length); dev->transfer = libusb_alloc_transfer(0); libusb_fill_interrupt_transfer(dev->transfer, dev->device_handle, dev->input_endpoint, buf, length, read_callback, dev, 5000/*timeout*/); /* Make the first submission. Further submissions are made from inside read_callback() */ libusb_submit_transfer(dev->transfer); /* Notify the main thread that the read thread is up and running. */ pthread_barrier_wait(&dev->barrier); /* Handle all the events. */ while (!dev->shutdown_thread) { int res; res = libusb_handle_events(usb_context); if (res < 0) { /* There was an error. */ LOG("read_thread(): libusb reports error # %d\n", res); /* Break out of this loop only on fatal error.*/ if (res != LIBUSB_ERROR_BUSY && res != LIBUSB_ERROR_TIMEOUT && res != LIBUSB_ERROR_OVERFLOW && res != LIBUSB_ERROR_INTERRUPTED) { break; } } } /* Cancel any transfer that may be pending. This call will fail if no transfers are pending, but that's OK. */ libusb_cancel_transfer(dev->transfer); while (!dev->cancelled) libusb_handle_events_completed(usb_context, &dev->cancelled); /* Now that the read thread is stopping, Wake any threads which are waiting on data (in hid_read_timeout()). Do this under a mutex to make sure that a thread which is about to go to sleep waiting on the condition acutally will go to sleep before the condition is signaled. */ pthread_mutex_lock(&dev->mutex); pthread_cond_broadcast(&dev->condition); pthread_mutex_unlock(&dev->mutex); /* The dev->transfer->buffer and dev->transfer objects are cleaned up in hid_close(). They are not cleaned up here because this thread could end either due to a disconnect or due to a user call to hid_close(). In both cases the objects can be safely cleaned up after the call to pthread_join() (in hid_close()), but since hid_close() calls libusb_cancel_transfer(), on these objects, they can not be cleaned up here. */ return NULL; }
//We adopted for async method here because there are 2 thread polling same fd // i.e both read and write are polling same fd when one event triggers and other one is //not completed then another thread will wait for more than 60sec. CY_RETURN_STATUS CySpiRead ( CY_HANDLE handle, CY_DATA_BUFFER *readBuffer, UINT32 ioTimeout ) { struct libusb_transfer *readTransfer; CY_DEVICE *device; libusb_device_handle *devHandle; int readCompleted = 0; struct timeval time; int r; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; readBuffer->transferCount = 0; readTransfer = libusb_alloc_transfer(0); if (readTransfer == NULL){ CY_DEBUG_PRINT_ERROR("CY:Error in allocating transfers \n"); return CY_ERROR_ALLOCATION_FAILED; } libusb_fill_bulk_transfer(readTransfer, devHandle, device->inEndpoint, readBuffer->buffer, readBuffer->length, spi_read_cb, &readCompleted, ioTimeout); libusb_submit_transfer (readTransfer); time.tv_sec = (ioTimeout / 1000); time.tv_usec = ((ioTimeout % 1000) * 1000);//polling timeout. while (readCompleted == 0){ r = libusb_handle_events_timeout_completed(glContext, &time, &readCompleted); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(readTransfer); while (!readCompleted) if (libusb_handle_events_completed(glContext, &readCompleted) < 0) break; readBuffer->transferCount = readTransfer->actual_length; libusb_free_transfer(readTransfer); return r; } } if (readTransfer->status == LIBUSB_TRANSFER_COMPLETED){ readBuffer->transferCount = readTransfer->actual_length; libusb_free_transfer (readTransfer); return CY_SUCCESS; } else{ if (readTransfer->status == LIBUSB_TRANSFER_TIMED_OUT){ //We should not be hitting this case.. As the time out is infinite!! CY_DEBUG_PRINT_ERROR ("CY:Timeout error in doing SPI read/write .... %d Libusb errors %d\n", readTransfer->actual_length,readTransfer->status); readBuffer->transferCount = readTransfer->actual_length; CySpiReset (handle); libusb_free_transfer (readTransfer); return CY_ERROR_IO_TIMEOUT; } if (readTransfer->status == LIBUSB_TRANSFER_OVERFLOW){ //Need to handle this properly! CY_DEBUG_PRINT_ERROR ("CY:OverFlow error in doing SPI read/write .... Libusb errors %d %d \n", readTransfer->status, readTransfer->actual_length); readBuffer->transferCount = readTransfer->actual_length; CySpiReset (handle); libusb_free_transfer (readTransfer); return CY_ERROR_BUFFER_OVERFLOW; } if (readTransfer->status != LIBUSB_TRANSFER_COMPLETED){ CY_DEBUG_PRINT_ERROR ("CY:Error in doing SPI read/write .... Libusb errors are %d %d\n", readTransfer->status, readTransfer->actual_length); readBuffer->transferCount = readTransfer->actual_length; CySpiReset (handle); libusb_free_transfer (readTransfer); //If timer is not completed then it implies we have timeout error return CY_ERROR_REQUEST_FAILED; } } return CY_ERROR_REQUEST_FAILED; }
/** \ingroup syncio * Perform a USB control transfer. * * The direction of the transfer is inferred from the bmRequestType field of * the setup packet. * * The wValue, wIndex and wLength fields values should be given in host-endian * byte order. * * \param dev_handle a handle for the device to communicate with * \param bmRequestType the request type field for the setup packet * \param bRequest the request field for the setup packet * \param wValue the value field for the setup packet * \param wIndex the index field for the setup packet * \param data a suitably-sized data buffer for either input or output * (depending on direction bits within bmRequestType) * \param wLength the length field for the setup packet. The data buffer should * be at least this size. * \param timeout timeout (in millseconds) that this function should wait * before giving up due to no response being received. For an unlimited * timeout, use value 0. * \returns on success, the number of bytes actually transferred * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the * device * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failures */ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) { struct libusb_transfer *transfer = libusb_alloc_transfer(0); unsigned char *buffer; int completed = 0; int r; if (!transfer) return LIBUSB_ERROR_NO_MEM; buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); if (!buffer) { libusb_free_transfer(transfer); return LIBUSB_ERROR_NO_MEM; } libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength); if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); libusb_fill_control_transfer(transfer, dev_handle, buffer, ctrl_transfer_cb, &completed, timeout); transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; r = libusb_submit_transfer(transfer); if (r < 0) { libusb_free_transfer(transfer); return r; } while (!completed) { r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0) break; libusb_free_transfer(transfer); return r; } } if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) memcpy(data, libusb_control_transfer_get_data(transfer), transfer->actual_length); switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = transfer->actual_length; break; case LIBUSB_TRANSFER_TIMED_OUT: r = LIBUSB_ERROR_TIMEOUT; break; case LIBUSB_TRANSFER_STALL: r = LIBUSB_ERROR_PIPE; break; case LIBUSB_TRANSFER_NO_DEVICE: r = LIBUSB_ERROR_NO_DEVICE; break; case LIBUSB_TRANSFER_OVERFLOW: r = LIBUSB_ERROR_OVERFLOW; break; default: usbi_warn(HANDLE_CTX(dev_handle), "unrecognised status code %d", transfer->status); r = LIBUSB_ERROR_OTHER; } libusb_free_transfer(transfer); return r; }
static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, int *transferred, unsigned int timeout, unsigned char type) { struct libusb_transfer *transfer = libusb_alloc_transfer(0); int completed = 0; int r; if (!transfer) return LIBUSB_ERROR_NO_MEM; libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, bulk_transfer_cb, &completed, timeout); transfer->type = type; r = libusb_submit_transfer(transfer); if (r < 0) { libusb_free_transfer(transfer); return r; } while (!completed) { r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0) break; libusb_free_transfer(transfer); return r; } } *transferred = transfer->actual_length; switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = 0; break; case LIBUSB_TRANSFER_TIMED_OUT: r = LIBUSB_ERROR_TIMEOUT; break; case LIBUSB_TRANSFER_STALL: r = LIBUSB_ERROR_PIPE; break; case LIBUSB_TRANSFER_OVERFLOW: r = LIBUSB_ERROR_OVERFLOW; break; case LIBUSB_TRANSFER_NO_DEVICE: r = LIBUSB_ERROR_NO_DEVICE; break; default: usbi_warn(HANDLE_CTX(dev_handle), "unrecognised status code %d", transfer->status); r = LIBUSB_ERROR_OTHER; } libusb_free_transfer(transfer); return r; }
int64_t FX3Stream::receive(int64_t maxWords, uint32_t *data, unsigned timeout, bool shortOK) { if( error ) { cerr << "Blocked" << endl; return 0; } totalBytes = maxWords*4; extBuf = (unsigned char*)data; transferredBytes = 0; submittedBytes = 0; shortPackets = 0; while( transferredBytes < totalBytes ) { //Retrieve from internal buffer while( consumedBytes < storedBytes && transferredBytes < totalBytes ) { extBuf[transferredBytes] = intBuf[consumedBytes]; transferredBytes += 1; consumedBytes += 1; } if( transferredBytes && shortOK ) { break; } //Request remaining data if( transferredBytes < totalBytes ) { storedBytes = 0; consumedBytes = 0; for( unsigned i = 0; i < transfers.size() && transferredBytes+submittedBytes < totalBytes; ++i ) { int64_t remainingBytes = totalBytes-(transferredBytes+submittedBytes); uint32_t size = FX3_TRANSFER_SIZE; if( remainingBytes < FX3_TRANSFER_SIZE ) { //request full packets size = ((remainingBytes+inPktSize-1)/inPktSize)*inPktSize; } libusb_fill_bulk_transfer( transfers[i], devhandle, FX3_IN_EP, recvBufs[i], size, FX3Stream::receiveCallback, this, timeout ); error = libusb_submit_transfer( transfers[i] ); if( error ) { cerr << "Error submitting transfer: " << libusb_error_name(error) << endl; break; } submittedBytes += size; } //Wait for data while( submittedBytes ) { int r = libusb_handle_events_completed(0,0); if( r ) { cerr << "Error handling events: " << libusb_error_name(r) << endl; error = r; break; } } if( shortPackets ) { if( FX3_DEBUG ) cerr << "Warning: " << shortPackets << " short packets in middle of incoming transfers." << endl; shortPackets = 0; } if( error < 0 && error != LIBUSB_ERROR_TIMEOUT ) { cerr << "Error receiving data: " << libusb_error_name(error) << endl; break; } else if( error == LIBUSB_ERROR_TIMEOUT ) { error = 0; break; } } } if( FX3_DEBUG ) { cerr << "R: " << transferredBytes << " bytes, " << shortPackets << " short packets" << endl; if( FX3_PRINT_DATA ) { for( int i = 0; i < transferredBytes-3; i += 4 ) { cerr << hex << setw(2) << setfill('0') << (unsigned)extBuf[i+3]; cerr << hex << setw(2) << setfill('0') << (unsigned)extBuf[i+2]; cerr << hex << setw(2) << setfill('0') << (unsigned)extBuf[i+1]; cerr << hex << setw(2) << setfill('0') << (unsigned)extBuf[i+0] << dec << ' '; } cerr << endl; } } return transferredBytes/4; }