#define RETURN_OK() RETURN_CODE(SP_OK);
#define RETURN_ERROR(err, msg) do { DEBUG_ERROR(err, msg); return err; } while (0)
#define RETURN_FAIL(msg) do { DEBUG_FAIL(msg); return SP_ERR_FAIL; } while (0)
-#define RETURN_VALUE(fmt, x) do { DEBUG("%s returning " fmt, __func__, x); return x; } while (0)
+#define RETURN_VALUE(fmt, x) do { \
+ typeof(x) _x = x; \
+ DEBUG("%s returning " fmt, __func__, _x); \
+ return _x; \
+} while (0)
#define SET_ERROR(val, err, msg) do { DEBUG_ERROR(err, msg); val = err; } while (0)
#define SET_FAIL(val, msg) do { DEBUG_FAIL(msg); val = SP_ERR_FAIL; } while (0)
#define TRACE(fmt, ...) DEBUG("%s(" fmt ") called", __func__, ##__VA_ARGS__)
*list_ptr = list;
RETURN_OK();
case SP_ERR_SUPP:
- DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform.");
+ DEBUG_ERROR(SP_ERR_SUPP, "Enumeration not supported on this platform");
default:
if (list)
sp_free_port_list(list);
DEBUG("Opening port %s", port->name);
#ifdef _WIN32
- DWORD desired_access = 0, flags_and_attributes = 0;
+ DWORD desired_access = 0, flags_and_attributes = 0, errors;
char *escaped_port_name;
+ COMSTAT status;
/* Prefix port name with '\\.\' to work with ports above COM9. */
if (!(escaped_port_name = malloc(strlen(port->name + 5))))
data.term.c_cflag |= (CLOCAL | CREAD | HUPCL);
#endif
+#ifdef _WIN32
+ if (ClearCommError(port->hdl, &errors, &status) == 0)
+ RETURN_FAIL("ClearCommError() failed");
+#endif
+
ret = set_config(port, &data, &config);
if (ret < 0) {
/* Start asynchronous write. */
if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
if (GetLastError() == ERROR_IO_PENDING) {
- DEBUG("Asynchronous write started");
- port->writing = 1;
- RETURN_VALUE("%d", ++written);
+ if (HasOverlappedIoCompleted(&port->write_ovl)) {
+ DEBUG("Asynchronous write completed immediately");
+ port->writing = 0;
+ written++;
+ continue;
+ } else {
+ DEBUG("Asynchronous write running");
+ port->writing = 1;
+ RETURN_VALUE("%d", ++written);
+ }
} else {
/* Actual failure of some kind. */
RETURN_FAIL("WriteFile() failed");
}
} else {
- DEBUG("Single byte written immediately.");
+ DEBUG("Single byte written immediately");
written++;
}
}
- DEBUG("All bytes written immediately.");
+ DEBUG("All bytes written immediately");
RETURN_VALUE("%d", written);
#else
RETURN_FAIL("ReadFile() failed");
/* Get number of bytes read. */
- GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE);
+ if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
+ RETURN_FAIL("GetOverlappedResult() failed");
RETURN_VALUE("%d", bytes_read);
#else
COMSTAT comstat;
if (ClearCommError(port->hdl, &errors, &comstat) == 0)
- RETURN_FAIL("ClearComError() failed");
+ RETURN_FAIL("ClearCommError() failed");
RETURN_VALUE("%d", comstat.cbInQue);
#else
int bytes_waiting;
COMSTAT comstat;
if (ClearCommError(port->hdl, &errors, &comstat) == 0)
- RETURN_FAIL("ClearComError() failed");
+ RETURN_FAIL("ClearCommError() failed");
RETURN_VALUE("%d", comstat.cbOutQue);
#else
int bytes_waiting;
if (config->parity >= 0) {
switch (config->parity) {
- /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
case SP_PARITY_NONE:
data->dcb.Parity = NOPARITY;
break;