Ejemplo n.º 1
0
int libusb_submit_transfer(struct libusb_transfer* transfer)
{
	transfer_wrapper* wrapper = GetWrapper(transfer);
	void*& context = wrapper->usb;
	if (NULL == context)
	{
		int ret (LIBUSB_ERROR_OTHER);
		switch(transfer->type)
		{
		case LIBUSB_TRANSFER_TYPE_CONTROL :
			fprintf(stderr, "ERROR: libusb_submit_transfer() with LIBUSB_TRANSFER_TYPE_CONTROL; use libusb_control_transfer() instead.\n");
			return(LIBUSB_ERROR_INVALID_PARAM);
		case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS :
			ret = usb_isochronous_setup_async(translate(transfer->dev_handle), &context, transfer->endpoint, transfer->iso_packet_desc[0].length);
			break;
		case LIBUSB_TRANSFER_TYPE_BULK :
			ret = usb_bulk_setup_async(translate(transfer->dev_handle), &context, transfer->endpoint);
			break;
		case LIBUSB_TRANSFER_TYPE_INTERRUPT :
			ret = usb_interrupt_setup_async(translate(transfer->dev_handle), &context, transfer->endpoint);
			break;
		default :
			return(LIBUSB_ERROR_INVALID_PARAM);
		}
		if (ret < 0)
		{
			// TODO: better error handling...
			// what do the functions usb_***_setup_async() actually return on error?
			return(ret);
		}

		TMapIsocTransfers::iterator it = mIsocTransfers.find(transfer->endpoint);
		if (it == mIsocTransfers.end())
			mIsocTransfers.insert(std::make_pair(transfer->endpoint, new TListTransfers()));
	}

	mIsocTransfers[transfer->endpoint]->Append(wrapper);
	transfer->status = LIBUSB_TRANSFER_COMPLETED;
	int ret = usb_submit_async(context, (char*)transfer->buffer, transfer->length);
	if (ret < 0)
	{
		// TODO: better error handling...
		// what does usb_submit_async() actually returns on error?
		// LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
		// LIBUSB_ERROR_BUSY if the transfer has already been submitted.
		// another LIBUSB_ERROR code on other failure
		return(ret);
	}
	// 0 on success
	return(0);
}
Ejemplo n.º 2
0
int TransferAsync(struct BENCHMARK_TRANSFER_PARAM* transferParam, struct BENCHMARK_TRANSFER_HANDLE** handleRef)
{
	int ret;
	struct BENCHMARK_TRANSFER_HANDLE* handle;

	*handleRef = NULL;

	// Submit transfers until the maximum number of outstanding transfer(s) is reached.
	while (transferParam->OutstandingTransferCount < transferParam->Test->BufferCount)
	{
		// Get the next available benchmark transfer handle.
		*handleRef = handle = &transferParam->TransferHandles[transferParam->TransferHandleNextIndex];

		// If a libusb-win32 transfer context hasn't been setup for this benchmark transfer
		// handle, do it now.
		//
		if (!handle->Context)
		{
			// Data buffer(s) are located at the end of the transfer param.
			handle->Data = transferParam->Buffer + (transferParam->TransferHandleNextIndex * transferParam->Test->BufferSize);
			handle->DataMaxLength = transferParam->Test->BufferSize;

			
			switch (ENDPOINT_TYPE(transferParam))
			{
			case USB_ENDPOINT_TYPE_ISOCHRONOUS:
				ret = usb_isochronous_setup_async(transferParam->Test->DeviceHandle, 
					&handle->Context,
					transferParam->Ep.bEndpointAddress,
					transferParam->IsoPacketSize ? transferParam->IsoPacketSize : transferParam->Ep.wMaxPacketSize);
				break;
			case USB_ENDPOINT_TYPE_BULK:
				ret = usb_bulk_setup_async(transferParam->Test->DeviceHandle,
					&handle->Context,
					transferParam->Ep.bEndpointAddress);
				break;
			case USB_ENDPOINT_TYPE_INTERRUPT:
				ret = usb_interrupt_setup_async(transferParam->Test->DeviceHandle,
					&handle->Context,
					transferParam->Ep.bEndpointAddress);
				break;
			default:
				ret = -1;
				break;
			}

			if (ret < 0) 
			{
				CONERR("failed creating transfer context ret=%d\n",ret);
				goto Done;
			}
		}


		// Submit this transfer now.
		handle->ReturnCode = ret = usb_submit_async(handle->Context, handle->Data, handle->DataMaxLength);
		if (ret < 0) goto Done;

		// Mark this handle has InUse.
		handle->InUse = TRUE;

		// When transfers ir successfully submitted, OutstandingTransferCount goes up; when
		// they are completed it goes down.
		//
		transferParam->OutstandingTransferCount++;

		// Move TransferHandleNextIndex to the next available transfer.
		INC_ROLL(transferParam->TransferHandleNextIndex, transferParam->Test->BufferCount);

	}

	// If the number of outstanding transfers has reached the limit, wait for the 
	// oldest outstanding transfer to complete.
	//
	if (transferParam->OutstandingTransferCount == transferParam->Test->BufferCount)
	{
		// TransferHandleWaitIndex is the index of the oldest outstanding transfer.
		*handleRef = handle = &transferParam->TransferHandles[transferParam->TransferHandleWaitIndex];

		// Only wait, cancelling & freeing is handled by the caller.
		handle->ReturnCode = ret = usb_reap_async_nocancel(handle->Context, transferParam->Test->Timeout);

		if (ret < 0) goto Done;

		// Mark this handle has no longer InUse.
		handle->InUse = FALSE;

		// When transfers ir successfully submitted, OutstandingTransferCount goes up; when
		// they are completed it goes down.
		//
		transferParam->OutstandingTransferCount--;

		// Move TransferHandleWaitIndex to the oldest outstanding transfer.
		INC_ROLL(transferParam->TransferHandleWaitIndex, transferParam->Test->BufferCount);
	}

Done:
	return ret;
}