示例#1
0
void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size)
{
	if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first
			|| GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped
		struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer);
		struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer);

		if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
			int i;
			for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
				struct libusb_iso_packet_descriptor *lib_desc = &ltransfer->iso_packet_desc[i];

				switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
				case STATUS_SUCCESS:
				case STATUS_CANCELLED:
				case STATUS_REQUEST_CANCELED:
					lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
					break;
				default:
					lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
					break;
				}

				lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
			}
		}

		*io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred;
		*io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus);
	}
	else {
		*io_result = GetLastError();
	}
}
示例#2
0
int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
{
	unsigned i;
	int _index, object_index, triggered;
	HANDLE *handles_to_wait_on;
	int *handle_to_index;
	DWORD nb_handles_to_wait_on = 0;
	DWORD ret;

	CHECK_INIT_POLLING;

	triggered = 0;
	handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE));	
	handle_to_index = (int*) calloc(nfds, sizeof(int));
	if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
		errno = ENOMEM;
		triggered = -1;
		goto poll_exit;
	}

	for (i = 0; i < nfds; ++i) {
		fds[i].revents = 0;

		
		if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
			fds[i].revents |= POLLERR;
			errno = EACCES;
			usbi_warn(NULL, "unsupported set of events");
			triggered = -1;
			goto poll_exit;
		}

		_index = _fd_to_index_and_lock(fds[i].fd);
		poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events);

		if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
		  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
			fds[i].revents |= POLLNVAL | POLLERR;
			errno = EBADF;
			if (_index >= 0) {
				LeaveCriticalSection(&_poll_fd[_index].mutex);
			}
			usbi_warn(NULL, "invalid fd");
			triggered = -1;
			goto poll_exit;
		}

		
		if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
			fds[i].revents |= POLLNVAL | POLLERR;
			errno = EBADF;
			usbi_warn(NULL, "attempted POLLIN on fd without READ access");
			LeaveCriticalSection(&_poll_fd[_index].mutex);
			triggered = -1;
			goto poll_exit;
		}

		if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
			fds[i].revents |= POLLNVAL | POLLERR;
			errno = EBADF;
			usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
			LeaveCriticalSection(&_poll_fd[_index].mutex);
			triggered = -1;
			goto poll_exit;
		}

		
		if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
		  || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
			poll_dbg("  completed");
			
			fds[i].revents = fds[i].events;
			triggered++;
		} else {
			handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
			handle_to_index[nb_handles_to_wait_on] = i;
			nb_handles_to_wait_on++;
		}
		LeaveCriticalSection(&_poll_fd[_index].mutex);
	}

	
	if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
		if (timeout < 0) {
			poll_dbg("starting infinite wait for %d handles...", (int)nb_handles_to_wait_on);
		} else {
			poll_dbg("starting %d ms wait for %d handles...", timeout, (int)nb_handles_to_wait_on);
		}
		ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on,
			FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
		object_index = ret-WAIT_OBJECT_0;
		if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) {
			poll_dbg("  completed after wait");
			i = handle_to_index[object_index];
			_index = _fd_to_index_and_lock(fds[i].fd);
			fds[i].revents = fds[i].events;
			triggered++;
			if (_index >= 0) {
				LeaveCriticalSection(&_poll_fd[_index].mutex);
			}
		} else if (ret == WAIT_TIMEOUT) {
			poll_dbg("  timed out");
			triggered = 0;	
		} else {
			errno = EIO;
			triggered = -1;	
		}
	}

poll_exit:
	if (handles_to_wait_on != NULL) {
		free(handles_to_wait_on);
	}
	if (handle_to_index != NULL) {
		free(handle_to_index);
	}
	return triggered;
}
示例#3
0
/* Get a list of HANDLE
*/
void API_EXPORTED libusb_get_handles_to_wait_on(struct libusb_context *ctx, HANDLE **handles_to_wait_on_ret, int *nb_handles_to_wait_on)
{
        int _index;
        HANDLE *handles_to_wait_on = 0;
        struct usbi_pollfd *ipollfd;
        POLL_NFDS_TYPE nfds = 0;

        CHECK_INIT_POLLING;

        *nb_handles_to_wait_on = 0;

        usbi_mutex_lock(&ctx->pollfds_lock);
        list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd)
	        nfds++;

	if (nfds != 0) {
                handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE));	// +1 for fd_update
                if (handles_to_wait_on == NULL) {
	                errno = ENOMEM;
                        goto libusb_get_handles_to_wait_on_exit;
	        }

        }
	else {
                goto libusb_get_handles_to_wait_on_exit;
	}

	list_for_each_entry(ipollfd, &ctx->pollfds, list, struct usbi_pollfd) {
		struct libusb_pollfd *pollfd_current = &ipollfd->pollfd;

		// Only one of POLLIN or POLLOUT can be selected with this version of poll (not both)
		if ((pollfd_current->events & ~POLLIN) && (!(pollfd_current->events & POLLOUT))) {
			errno = EACCES;
			usbi_warn(NULL, "unsupported set of events");
                        *nb_handles_to_wait_on = -1;
			goto libusb_get_handles_to_wait_on_exit;
		}

		_index = _fd_to_index_and_lock(pollfd_current->fd);
		poll_dbg("fd=%d: (overlapped=%p) got events %04X", poll_fd[_index].fd, poll_fd[_index].overlapped, pollfd_current->events);

		if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
		  || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) {
			errno = EBADF;
			if (_index >= 0) {
                          LeaveCriticalSection(&_poll_fd[_index].mutex);
			}
			usbi_warn(NULL, "invalid fd");
                        *nb_handles_to_wait_on = -1;
			goto libusb_get_handles_to_wait_on_exit;
		}

		// IN or OUT must match our fd direction
		if ((pollfd_current->events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
			errno = EBADF;
			usbi_warn(NULL, "attempted POLLIN on fd without READ access");
			LeaveCriticalSection(&_poll_fd[_index].mutex);
                        *nb_handles_to_wait_on = -1;
			goto libusb_get_handles_to_wait_on_exit;
		}

		if ((pollfd_current->events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) {
			errno = EBADF;
			usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access");
			LeaveCriticalSection(&_poll_fd[_index].mutex);
                        *nb_handles_to_wait_on = -1;
			goto libusb_get_handles_to_wait_on_exit;
		}

		// The following macro only works if overlapped I/O was reported pending
		if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
		  || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
			poll_dbg("  completed");
			// checks above should ensure this works:
		} else {
                        handles_to_wait_on[*nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent;
			(*nb_handles_to_wait_on)++;
		}
		LeaveCriticalSection(&_poll_fd[_index].mutex);
	}


libusb_get_handles_to_wait_on_exit:
     usbi_mutex_unlock(&ctx->pollfds_lock);
     *handles_to_wait_on_ret = handles_to_wait_on;
}