int in_read;
};
-struct altos_file *
+PUBLIC struct altos_file *
altos_open(struct altos_device *device)
{
struct altos_file *file = calloc (sizeof (struct altos_file), 1);
return file;
}
-void
+PUBLIC void
altos_close(struct altos_file *file)
{
if (file->fd != -1) {
}
}
-void
+PUBLIC void
altos_free(struct altos_file *file)
{
altos_close(file);
free(file);
}
-int
+PUBLIC int
altos_flush(struct altos_file *file)
{
+ if (file->out_used && 0) {
+ printf ("flush \"");
+ fwrite(file->out_data, 1, file->out_used, stdout);
+ printf ("\"\n");
+ }
while (file->out_used) {
int ret;
return 0;
}
-int
+PUBLIC int
altos_putchar(struct altos_file *file, char c)
{
int ret;
#include <poll.h>
#endif
-int
+static int
altos_fill(struct altos_file *file, int timeout)
{
int ret;
return LIBALTOS_ERROR;
#ifdef USE_POLL
fd[0].fd = file->fd;
- fd[0].events = POLLIN;
+ fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
fd[1].fd = file->pipe[0];
fd[1].events = POLLIN;
ret = poll(fd, 2, timeout);
}
if (ret == 0)
return LIBALTOS_TIMEOUT;
+
+ if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+ return LIBALTOS_ERROR;
if (fd[0].revents & POLLIN)
#endif
{
#endif
}
}
+ if (file->in_used && 0) {
+ printf ("fill \"");
+ fwrite(file->in_data, 1, file->in_used, stdout);
+ printf ("\"\n");
+ }
return 0;
}
-int
+PUBLIC int
altos_getchar(struct altos_file *file, int timeout)
{
int ret;
unsigned char in_data[USB_BUF_SIZE];
int in_used;
int in_read;
+ OVERLAPPED ov_read;
+ BOOL pend_read;
+ OVERLAPPED ov_write;
};
PUBLIC struct altos_list *
}
static int
-altos_fill(struct altos_file *file, int timeout)
+altos_queue_read(struct altos_file *file)
{
- DWORD result;
DWORD got;
- COMMTIMEOUTS timeouts;
-
- if (file->in_read < file->in_used)
+ if (file->pend_read)
return LIBALTOS_SUCCESS;
- file->in_read = file->in_used = 0;
- if (timeout)
- timeouts.ReadTotalTimeoutConstant = timeout;
- else
- timeouts.ReadTotalTimeoutConstant = 1000;
+ if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
+ if (GetLastError() != ERROR_IO_PENDING)
+ return LIBALTOS_ERROR;
+ file->pend_read = TRUE;
+ } else {
+ file->pend_read = FALSE;
+ file->in_read = 0;
+ file->in_used = got;
+ }
+ return LIBALTOS_SUCCESS;
+}
- timeouts.ReadIntervalTimeout = MAXDWORD;
- timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
- timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 0;
+static int
+altos_wait_read(struct altos_file *file, int timeout)
+{
+ DWORD ret;
+ DWORD got;
- if (!SetCommTimeouts(file->handle, &timeouts))
- printf("SetCommTimeouts failed %d\n", GetLastError());
+ if (!file->pend_read)
+ return LIBALTOS_SUCCESS;
- for (;;) {
- if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, NULL)) {
- result = GetLastError();
+ if (!timeout)
+ timeout = INFINITE;
+
+ ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE))
return LIBALTOS_ERROR;
- got = 0;
- }
+ file->pend_read = FALSE;
file->in_read = 0;
file->in_used = got;
- if (got)
- return LIBALTOS_SUCCESS;
- if (timeout)
- return LIBALTOS_TIMEOUT;
+ break;
+ case WAIT_TIMEOUT:
+ return LIBALTOS_TIMEOUT;
+ break;
+ default:
+ return LIBALTOS_ERROR;
}
+ return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_fill(struct altos_file *file, int timeout)
+{
+ int ret;
+
+ if (file->in_read < file->in_used)
+ return LIBALTOS_SUCCESS;
+
+ file->in_read = file->in_used = 0;
+
+ ret = altos_queue_read(file);
+ if (ret)
+ return ret;
+ ret = altos_wait_read(file, timeout);
+ if (ret)
+ return ret;
+
+ return LIBALTOS_SUCCESS;
}
PUBLIC int
DWORD put;
char *data = file->out_data;
char used = file->out_used;
- DWORD result;
+ DWORD ret;
while (used) {
- if (!WriteFile(file->handle, data, used, &put, NULL)) {
- result = GetLastError();
- return LIBALTOS_ERROR;
+ if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
+ if (GetLastError() != ERROR_IO_PENDING)
+ return LIBALTOS_ERROR;
+ ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE))
+ return LIBALTOS_ERROR;
+ break;
+ default:
+ return LIBALTOS_ERROR;
+ }
}
data += put;
used -= put;
struct altos_file *file = calloc (1, sizeof (struct altos_file));
char full_name[64];
DCB dcbSerialParams = {0};
+ COMMTIMEOUTS timeouts;
if (!file)
return NULL;
strcat(full_name, device->path);
file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
+ FILE_FLAG_OVERLAPPED, NULL);
if (file->handle == INVALID_HANDLE_VALUE) {
free(file);
return NULL;
}
+ file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ timeouts.WriteTotalTimeoutConstant = 0;
+ SetCommTimeouts(file->handle, &timeouts);
+
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(file->handle, &dcbSerialParams)) {
CloseHandle(file->handle);