Ejemplo n.º 1
0
int usbi_close(int fd)
{
	int _index;
	int r = -1;

	CHECK_INIT_POLLING;

	_index = _fd_to_index_and_lock(fd);

	if (_index < 0) {
		errno = EBADF;
	} else {
		if (poll_fd[_index].overlapped != NULL) {
			
			CloseHandle(poll_fd[_index].overlapped->hEvent);
			free(poll_fd[_index].overlapped);
		}
		r = _close(poll_fd[_index].fd);
		if (r != 0) {
			errno = EIO;
		}
		poll_fd[_index] = INVALID_WINFD;
		LeaveCriticalSection(&_poll_fd[_index].mutex);
	}
	return r;
}
Ejemplo n.º 2
0
ssize_t usbi_write(int fd, const void *buf, size_t count)
{
	int _index;

	CHECK_INIT_POLLING;

	if (count != sizeof(unsigned char)) {
		usbi_err(NULL, "this function should only used for signaling");
		return -1;
	}

	_index = _fd_to_index_and_lock(fd);

	if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
		errno = EBADF;
		if (_index >= 0) {
			LeaveCriticalSection(&_poll_fd[_index].mutex);
		}
		return -1;
	}

	poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
	SetEvent(poll_fd[_index].overlapped->hEvent);
	poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
	
	
	poll_fd[_index].overlapped->InternalHigh++;

	LeaveCriticalSection(&_poll_fd[_index].mutex);
	return sizeof(unsigned char);
}
Ejemplo n.º 3
0
/*
 * synchronous write for fake "pipe" signaling
 */
ssize_t usbi_write(int fd, const void *buf, size_t count)
{
	int _index;
	UNUSED(buf);

	CHECK_INIT_POLLING;

	if (count != sizeof(unsigned char)) {
		usbi_err(NULL, "this function should only used for signaling");
		return -1;
	}

	_index = _fd_to_index_and_lock(fd);

	if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
		errno = EBADF;
		if (_index >= 0) {
			LeaveCriticalSection(&_poll_fd[_index].mutex);
		}
		return -1;
	}

	poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId());
	SetEvent(poll_fd[_index].overlapped->hEvent);
	poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
	// If two threads write on the pipe at the same time, we need to
	// process two separate reads => use the overlapped as a counter
	poll_fd[_index].overlapped->InternalHigh++;

	LeaveCriticalSection(&_poll_fd[_index].mutex);
	return sizeof(unsigned char);
}
Ejemplo n.º 4
0
void usbi_free_fd(int fd)
{
	int _index;

	CHECK_INIT_POLLING;

	_index = _fd_to_index_and_lock(fd);
	if (_index < 0) {
		return;
	}
	_free_index(_index);
	LeaveCriticalSection(&_poll_fd[_index].mutex);
}
Ejemplo n.º 5
0
/*
 * Release a pollable file descriptor.
 *
 * Note that the associated Windows handle is not closed by this call
 */
void usbi_free_fd(struct winfd *wfd)
{
	int _index;

	CHECK_INIT_POLLING;

	_index = _fd_to_index_and_lock(wfd->fd);
	if (_index < 0) {
		return;
	}
	_free_index(_index);
	*wfd = INVALID_WINFD;
	LeaveCriticalSection(&_poll_fd[_index].mutex);
}
Ejemplo n.º 6
0
/*
 * close a fake pipe fd
 */
int usbi_close(int fd)
{
	int _index;
	int r = -1;

	CHECK_INIT_POLLING;

	_index = _fd_to_index_and_lock(fd);

	if (_index < 0) {
		errno = EBADF;
	} else {
		free_overlapped(poll_fd[_index].overlapped);
		poll_fd[_index] = INVALID_WINFD;
		LeaveCriticalSection(&_poll_fd[_index].mutex);
	}
	return r;
}
Ejemplo n.º 7
0
/*
 * synchronous read for fake "pipe" signaling
 */
ssize_t usbi_read(int fd, void *buf, size_t count)
{
	int _index;
	ssize_t r = -1;
	UNUSED(buf);

	CHECK_INIT_POLLING;

	if (count != sizeof(unsigned char)) {
		usbi_err(NULL, "this function should only used for signaling");
		return -1;
	}

	_index = _fd_to_index_and_lock(fd);

	if (_index < 0) {
		errno = EBADF;
		return -1;
	}

	if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
		usbi_warn(NULL, "waiting for event failed: %d", (int)GetLastError());
		errno = EIO;
		goto out;
	}

	poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());
	poll_fd[_index].overlapped->InternalHigh--;
	// Don't reset unless we don't have any more events to process
	if (poll_fd[_index].overlapped->InternalHigh <= 0) {
		ResetEvent(poll_fd[_index].overlapped->hEvent);
		poll_fd[_index].overlapped->Internal = STATUS_PENDING;
	}

	r = sizeof(unsigned char);

out:
	LeaveCriticalSection(&_poll_fd[_index].mutex);
	return r;
}
Ejemplo n.º 8
0
/*
 * synchronous write for fake "pipe" signaling
 */
ssize_t usbi_write(int fd, const void *buf, size_t count)
{
	int _index, i;
	struct pipe_data *item;
	const unsigned char * cbuf = (unsigned char*) buf;

	CHECK_INIT_POLLING;

	_index = _fd_to_index_and_lock(fd);

	if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
		errno = EBADF;
		if (_index >= 0) {
			LeaveCriticalSection(&_poll_fd[_index].mutex);
		}
		return -1;
	}

	item = calloc(1, sizeof(*item));
	item->data = calloc(sizeof(unsigned char), count+1);
	item->count = count;
	for(i = 0; i < count; i++) {
		item->data[i] = cbuf[i];
	}
	list_add(&item->list, &_poll_fd[_index].list);

	poll_dbg("set pipe event (fd = %d, thread = %08X)",
			 _index,
			 GetCurrentThreadId());
	SetEvent(poll_fd[_index].overlapped->hEvent);
	poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
	// If two threads write on the pipe at the same time, we need to
	// process two separate reads => use the overlapped as a counter
	poll_fd[_index].overlapped->InternalHigh++;

	LeaveCriticalSection(&_poll_fd[_index].mutex);
	return count;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
/*
 * synchronous read for fake "pipe" signaling
 */
ssize_t usbi_read(int fd, void *buf, size_t count)
{
	struct pipe_data * pdata;
	int _index;
	int res;
	ssize_t r = -1;

	CHECK_INIT_POLLING;

	_index = _fd_to_index_and_lock(fd);

	if (_index < 0) {
		errno = EBADF;
		return -1;
	}

	res = WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE);
	if (res != WAIT_OBJECT_0) {
		usbi_warn(NULL, "waiting for event failed: %d", (int)GetLastError());
		errno = EIO;
		goto out;
	}

	poll_fd[_index].overlapped->InternalHigh--;
	// Don't reset unless we don't have any more events to process
	if (poll_fd[_index].overlapped->InternalHigh <= 0) {
		ResetEvent(poll_fd[_index].overlapped->hEvent);
		poll_fd[_index].overlapped->Internal = STATUS_PENDING;
	}

	poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId());


	if (list_empty(&_poll_fd[_index].list)) {
		usbi_warn(NULL, "no data in the poll");
		r = 0;
	} else {
		int i;
		ssize_t t;
		unsigned char* cbuf = (unsigned char*) buf;
		pdata = list_entry(_poll_fd[_index].list.next, struct pipe_data, list);
		if (pdata == NULL) {
			usbi_err(NULL, "no pdata");
			r = 0;
			goto out;
		}

		if (pdata->data == NULL){
			usbi_err(NULL, "no data");
			r = 0;
			goto out;
		}

		t = MIN(pdata->count, count);

		for(i = 0; i < t; i++) {
			cbuf[i] = pdata->data[i];
		}

		free(pdata->data);
		list_del(&(pdata->list));
		free(pdata);
		r = t;
	}

out:
	LeaveCriticalSection(&_poll_fd[_index].mutex);
	return r;
}
Ejemplo n.º 11
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;
}