Windows nonblocking write: 1 byte at a time to know when buffer fills.
This commit is contained in:
parent
a3cb91f5e1
commit
0765af5644
49
serialport.c
49
serialport.c
|
@ -64,7 +64,7 @@ struct sp_port {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE hdl;
|
HANDLE hdl;
|
||||||
OVERLAPPED write_ovl;
|
OVERLAPPED write_ovl;
|
||||||
BYTE *write_buf;
|
BYTE pending_byte;
|
||||||
BOOL writing;
|
BOOL writing;
|
||||||
#else
|
#else
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -627,7 +627,6 @@ enum sp_return sp_open(struct sp_port *port, enum sp_mode flags)
|
||||||
sp_close(port);
|
sp_close(port);
|
||||||
RETURN_FAIL("CreateEvent() failed");
|
RETURN_FAIL("CreateEvent() failed");
|
||||||
}
|
}
|
||||||
port->write_buf = NULL;
|
|
||||||
port->writing = FALSE;
|
port->writing = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,9 +697,6 @@ enum sp_return sp_close(struct sp_port *port)
|
||||||
RETURN_FAIL("CloseHandle() failed");
|
RETURN_FAIL("CloseHandle() failed");
|
||||||
port->hdl = INVALID_HANDLE_VALUE;
|
port->hdl = INVALID_HANDLE_VALUE;
|
||||||
if (port->nonblocking) {
|
if (port->nonblocking) {
|
||||||
if (port->writing)
|
|
||||||
/* Write should have been stopped by closing the port, so safe to free buffer. */
|
|
||||||
free(port->write_buf);
|
|
||||||
/* Close event handle created for overlapped writes. */
|
/* Close event handle created for overlapped writes. */
|
||||||
if (CloseHandle(port->write_ovl.hEvent) == 0)
|
if (CloseHandle(port->write_ovl.hEvent) == 0)
|
||||||
RETURN_FAIL("CloseHandle() failed");
|
RETURN_FAIL("CloseHandle() failed");
|
||||||
|
@ -791,6 +787,7 @@ enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DWORD written = 0;
|
DWORD written = 0;
|
||||||
|
BYTE *ptr = (BYTE *) buf;
|
||||||
|
|
||||||
if (port->nonblocking) {
|
if (port->nonblocking) {
|
||||||
/* Non-blocking write. */
|
/* Non-blocking write. */
|
||||||
|
@ -800,8 +797,6 @@ enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
|
||||||
if (HasOverlappedIoCompleted(&port->write_ovl)) {
|
if (HasOverlappedIoCompleted(&port->write_ovl)) {
|
||||||
DEBUG("Previous write completed");
|
DEBUG("Previous write completed");
|
||||||
port->writing = 0;
|
port->writing = 0;
|
||||||
free(port->write_buf);
|
|
||||||
port->write_buf = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG("Previous write not complete");
|
DEBUG("Previous write not complete");
|
||||||
/* Can't take a new write until the previous one finishes. */
|
/* Can't take a new write until the previous one finishes. */
|
||||||
|
@ -809,29 +804,31 @@ enum sp_return sp_write(struct sp_port *port, const void *buf, size_t count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy user buffer. */
|
/* Keep writing data until the OS has to actually start an async IO for it.
|
||||||
if (!(port->write_buf = malloc(count)))
|
* At that point we know the buffer is full. */
|
||||||
RETURN_ERROR(SP_ERR_MEM, "buffer copy malloc failed");
|
while (written < count)
|
||||||
memcpy(port->write_buf, buf, count);
|
{
|
||||||
|
/* Copy first byte of user buffer. */
|
||||||
|
port->pending_byte = *ptr++;
|
||||||
|
|
||||||
/* Start asynchronous write. */
|
/* Start asynchronous write. */
|
||||||
if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
|
if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
|
||||||
if (GetLastError() == ERROR_IO_PENDING) {
|
if (GetLastError() == ERROR_IO_PENDING) {
|
||||||
DEBUG("Asynchronous write started");
|
DEBUG("Asynchronous write started");
|
||||||
port->writing = 1;
|
port->writing = 1;
|
||||||
RETURN_VALUE("%d", count);
|
RETURN_VALUE("%d", ++written);
|
||||||
|
} else {
|
||||||
|
/* Actual failure of some kind. */
|
||||||
|
RETURN_FAIL("WriteFile() failed");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
free(port->write_buf);
|
DEBUG("Single byte written immediately.");
|
||||||
port->write_buf = NULL;
|
written++;
|
||||||
/* Actual failure of some kind. */
|
|
||||||
RETURN_FAIL("WriteFile() failed");
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
DEBUG("Write completed immediately");
|
|
||||||
free(port->write_buf);
|
|
||||||
port->write_buf = NULL;
|
|
||||||
RETURN_VALUE("%d", count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG("All bytes written immediately.");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Blocking write. */
|
/* Blocking write. */
|
||||||
if (WriteFile(port->hdl, buf, count, &written, NULL) == 0) {
|
if (WriteFile(port->hdl, buf, count, &written, NULL) == 0) {
|
||||||
|
|
Loading…
Reference in New Issue