Beispiel #1
0
static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer)
{
	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
	struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
	struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
	struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
	BOOL direction_in, ret;
	struct winfd wfd;
	DWORD flags;
	HANDLE eventHandle;
	PUKW_CONTROL_HEADER setup = NULL;
	const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL;

	transfer_priv->pollable_fd = INVALID_WINFD;
	if (control_transfer) {
		setup = (PUKW_CONTROL_HEADER) transfer->buffer;
		direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN;
	} else {
		direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN;
	}
	flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER;
	flags |= UKW_TF_SHORT_TRANSFER_OK;

	eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (eventHandle == NULL) {
		usbi_err(ctx, "Failed to create event for async transfer");
		return LIBUSB_ERROR_NO_MEM;
	}

	wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer);
	if (wfd.fd < 0) {
		CloseHandle(eventHandle);
		return LIBUSB_ERROR_NO_MEM;
	}

	transfer_priv->pollable_fd = wfd;
	if (control_transfer) {
		// Split out control setup header and data buffer
		DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER);
		PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)];

		ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped);
	} else {
		ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer, 
			transfer->length, &transfer->actual_length, wfd.overlapped);
	}
	if (!ret) {
		int libusbErr = translate_driver_error(GetLastError());
		usbi_err(ctx, "UkwIssue%sTransfer failed: error %d",
			control_transfer ? "Control" : "Bulk", GetLastError());
		wince_clear_transfer_priv(itransfer);
		return libusbErr;
	}
	usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT);
	itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;

	return LIBUSB_SUCCESS;
}
Beispiel #2
0
static int wince_reset_device(
	struct libusb_device_handle *handle)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	if (!UkwResetDevice(priv->dev)) {
		return translate_driver_error(GetLastError());
	}
	return LIBUSB_SUCCESS;
}
Beispiel #3
0
static int wince_set_interface_altsetting(
	struct libusb_device_handle *handle,
	int interface_number, int altsetting)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting)) {
		return translate_driver_error(GetLastError());
	}
	return LIBUSB_SUCCESS;
}
Beispiel #4
0
static int wince_claim_interface(
	struct libusb_device_handle *handle,
	int interface_number)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	if (!UkwClaimInterface(priv->dev, interface_number)) {
		return translate_driver_error(GetLastError());
	}
	return LIBUSB_SUCCESS;
}
Beispiel #5
0
static int wince_get_device_descriptor(
   struct libusb_device *device,
   unsigned char *buffer, int *host_endian)
{
	struct wince_device_priv *priv = _device_priv(device);

	*host_endian = 1;
	memcpy(buffer, &priv->desc, DEVICE_DESC_LENGTH);
	return LIBUSB_SUCCESS;
}
Beispiel #6
0
static int wince_attach_kernel_driver(
	struct libusb_device_handle *handle,
	int interface_number)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	if (!UkwAttachKernelDriver(priv->dev, interface_number)) {
		return translate_driver_error(GetLastError());
	}	
	return LIBUSB_SUCCESS;
}
Beispiel #7
0
static int wince_kernel_driver_active(
	struct libusb_device_handle *handle,
	int interface_number)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	BOOL result = FALSE;
	if (!UkwKernelDriverActive(priv->dev, interface_number, &result)) {
		return translate_driver_error(GetLastError());
	}
	return result ? 1 : 0;
}
Beispiel #8
0
static int wince_cancel_transfer(struct usbi_transfer *itransfer)
{
	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
	struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
	struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);

	if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT))
		return translate_driver_error(GetLastError());

	return LIBUSB_SUCCESS;
}
Beispiel #9
0
static int wince_get_configuration(
   struct libusb_device_handle *handle,
   int *config)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	UCHAR cv = 0;
	if (!UkwGetConfig(priv->dev, &cv)) {
		return translate_driver_error(GetLastError());
	}
	(*config) = cv;
	return LIBUSB_SUCCESS;
}
Beispiel #10
0
static int wince_get_active_config_descriptor(
	struct libusb_device *device,
	unsigned char *buffer, size_t len, int *host_endian)
{
	struct wince_device_priv *priv = _device_priv(device);
	DWORD actualSize = len;
	*host_endian = 0;
	if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize)) {
		return translate_driver_error(GetLastError());
	}
	return actualSize;
}
Beispiel #11
0
static int wince_clear_halt(
	struct libusb_device_handle *handle,
	unsigned char endpoint)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	if (!UkwClearHaltHost(priv->dev, endpoint)) {
		return translate_driver_error(GetLastError());
	}
	if (!UkwClearHaltDevice(priv->dev, endpoint)) {
		return translate_driver_error(GetLastError());
	}
	return LIBUSB_SUCCESS;
}
Beispiel #12
0
static int wince_release_interface(
	struct libusb_device_handle *handle,
	int interface_number)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0)) {
		return translate_driver_error(GetLastError());
	}
	if (!UkwReleaseInterface(priv->dev, interface_number)) {
		return translate_driver_error(GetLastError());
	}
	return LIBUSB_SUCCESS;
}
Beispiel #13
0
static int wince_set_configuration(
	struct libusb_device_handle *handle,
	int config)
{
	struct wince_device_priv *priv = _device_priv(handle->dev);
	// Setting configuration 0 places the device in Address state.
	// This should correspond to the "unconfigured state" required by
	// libusb when the specified configuration is -1.
	UCHAR cv = (config < 0) ? 0 : config;
	if (!UkwSetConfig(priv->dev, cv)) {
		return translate_driver_error(GetLastError());
	}
	return LIBUSB_SUCCESS;
}
Beispiel #14
0
static int wince_get_config_descriptor(
	struct libusb_device *device,
	uint8_t config_index,
	unsigned char *buffer, size_t len, int *host_endian)
{
	struct wince_device_priv *priv = _device_priv(device);
	DWORD actualSize = len;

	*host_endian = 0;
	if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize))
		return translate_driver_error(GetLastError());

	return actualSize;
}
Beispiel #15
0
static int init_device(struct libusb_device *dev, UKW_DEVICE drv_dev,
					   unsigned char bus_addr, unsigned char dev_addr)
{
	struct wince_device_priv *priv = _device_priv(dev);
	int r = LIBUSB_SUCCESS;

	dev->bus_number = bus_addr;
	dev->device_address = dev_addr;
	priv->dev = drv_dev;

	if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc))) {
		r = translate_driver_error(GetLastError());
	}
	return r;
}
Beispiel #16
0
static void wince_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
{
	struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
	struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer);
	struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev);
	int status;

	usbi_dbg("handling I/O completion with errcode %d", io_result);

	if (io_result == ERROR_NOT_SUPPORTED && 
		transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) {
		/* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper 
		 * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the 
		 * endpoint isn't actually stalled.
		 *
		 * One example of this is that some devices will occasionally fail to reply to an IN
		 * token. The WinCE USB layer carries on with the transaction until it is completed
		 * (or cancelled) but then completes it with USB_ERROR_STALL.
		 *
		 * This code therefore needs to confirm that there really is a stall error, by both
		 * checking the pipe status and requesting the endpoint status from the device.
		 */
		BOOL halted = FALSE;
		usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall");
		if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) {
			/* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS
			 * control request to the device. This is done synchronously, which is a bit 
			 * naughty, but this is a special corner case.
			 */
			WORD wStatus = 0;
			DWORD written = 0;
			UKW_CONTROL_HEADER ctrlHeader;
			ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD |
				LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT;
			ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS;
			ctrlHeader.wValue = 0;
			ctrlHeader.wIndex = transfer->endpoint;
			ctrlHeader.wLength = sizeof(wStatus);
			if (UkwIssueControlTransfer(priv->dev,
					UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT,
					&ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) {
				if (written == sizeof(wStatus) &&
						(wStatus & STATUS_HALT_FLAG) == 0) {
					if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) {
						usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success");
						io_result = ERROR_SUCCESS;
					} else {
						usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error");
						io_result = ERROR_IO_DEVICE;
					}
				}
			}
		}
	}

	switch(io_result) {
	case ERROR_SUCCESS:
		itransfer->transferred += io_size;
		status = LIBUSB_TRANSFER_COMPLETED;
		break;
	case ERROR_CANCELLED:
		usbi_dbg("detected transfer cancel");
		status = LIBUSB_TRANSFER_CANCELLED;
		break;
	case ERROR_NOT_SUPPORTED:
	case ERROR_GEN_FAILURE:
		usbi_dbg("detected endpoint stall");
		status = LIBUSB_TRANSFER_STALL;
		break;
	case ERROR_SEM_TIMEOUT:
		usbi_dbg("detected semaphore timeout");
		status = LIBUSB_TRANSFER_TIMED_OUT;
		break;
	case ERROR_OPERATION_ABORTED:
		if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) {
			usbi_dbg("detected timeout");
			status = LIBUSB_TRANSFER_TIMED_OUT;
		} else {
			usbi_dbg("detected operation aborted");
			status = LIBUSB_TRANSFER_CANCELLED;
		}
		break;
	default:
		usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result));
		status = LIBUSB_TRANSFER_ERROR;
		break;
	}
	wince_clear_transfer_priv(itransfer);
	if (status == LIBUSB_TRANSFER_CANCELLED) {
		usbi_handle_transfer_cancellation(itransfer);
	} else {
		usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
	}
}
Beispiel #17
0
static void wince_destroy_device(
	struct libusb_device *dev)
{
	struct wince_device_priv *priv = _device_priv(dev);
	UkwReleaseDeviceList(driver_handle, &priv->dev, 1);
}