Convert operating system errors.

Errors reported by system calls are now converted to the corresponding
libdivecomputer status code. This results in a more descriptive and
meaningfull return value.
This commit is contained in:
Jef Driesen 2016-01-08 21:20:11 +01:00
parent 4fd0118d4e
commit f8417037c6
3 changed files with 246 additions and 130 deletions

View File

@ -45,15 +45,25 @@
#ifdef _WIN32
typedef int s_ssize_t;
typedef DWORD s_errcode_t;
#define S_ERRNO WSAGetLastError ()
#define S_EAGAIN WSAEWOULDBLOCK
#define S_ENOMEM WSA_NOT_ENOUGH_MEMORY
#define S_EINVAL WSAEINVAL
#define S_EACCES WSAEACCES
#define S_EAFNOSUPPORT WSAEAFNOSUPPORT
#define S_INVALID INVALID_SOCKET
#define S_IOCTL ioctlsocket
#define S_CLOSE closesocket
#else
typedef ssize_t s_ssize_t;
typedef int s_errcode_t;
#define S_ERRNO errno
#define S_EAGAIN EAGAIN
#define S_ENOMEM ENOMEM
#define S_EINVAL EINVAL
#define S_EACCES EACCES
#define S_EAFNOSUPPORT EAFNOSUPPORT
#define S_INVALID -1
#define S_IOCTL ioctl
#define S_CLOSE close
@ -73,6 +83,23 @@ struct dc_irda_t {
int timeout;
};
static dc_status_t
syserror(s_errcode_t errcode)
{
switch (errcode) {
case S_EINVAL:
return DC_STATUS_INVALIDARGS;
case S_ENOMEM:
return DC_STATUS_NOMEMORY;
case S_EACCES:
return DC_STATUS_NOACCESS;
case S_EAFNOSUPPORT:
return DC_STATUS_UNSUPPORTED;
default:
return DC_STATUS_IO;
}
}
dc_status_t
dc_irda_open (dc_irda_t **out, dc_context_t *context)
{
@ -85,11 +112,7 @@ dc_irda_open (dc_irda_t **out, dc_context_t *context)
// Allocate memory.
device = (dc_irda_t *) malloc (sizeof (dc_irda_t));
if (device == NULL) {
#ifdef _WIN32
SYSERROR (context, ERROR_OUTOFMEMORY);
#else
SYSERROR (context, ENOMEM);
#endif
SYSERROR (context, S_ENOMEM);
return DC_STATUS_NOMEMORY;
}
@ -124,8 +147,9 @@ dc_irda_open (dc_irda_t **out, dc_context_t *context)
// Open the socket.
device->fd = socket (AF_IRDA, SOCK_STREAM, 0);
if (device->fd == S_INVALID) {
SYSERROR (context, S_ERRNO);
status = DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
SYSERROR (context, errcode);
status = syserror(errcode);
goto error_wsacleanup;
}
@ -155,15 +179,17 @@ dc_irda_close (dc_irda_t *device)
// Close the socket.
if (S_CLOSE (device->fd) != 0) {
SYSERROR (device->context, S_ERRNO);
dc_status_set_error(&status, DC_STATUS_IO);
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
dc_status_set_error(&status, syserror(errcode));
}
#ifdef _WIN32
// Terminate the winsock dll.
if (WSACleanup () != 0) {
SYSERROR (device->context, S_ERRNO);
dc_status_set_error(&status, DC_STATUS_IO);
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
dc_status_set_error(&status, syserror(errcode));
}
#endif
@ -227,9 +253,10 @@ dc_irda_discover (dc_irda_t *device, dc_irda_callback_t callback, void *userdata
// discovered, while on Windows it succeeds and sets the number
// of devices to zero. Both situations are handled the same here.
if (rc != 0) {
if (S_ERRNO != S_EAGAIN) {
SYSERROR (device->context, S_ERRNO);
return DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
if (errcode != S_EAGAIN) {
SYSERROR (device->context, errcode);
return syserror(errcode);
}
}
@ -305,8 +332,9 @@ dc_irda_connect_name (dc_irda_t *device, unsigned int address, const char *name)
#endif
if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) {
SYSERROR (device->context, S_ERRNO);
return DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
return syserror(errcode);
}
return DC_STATUS_SUCCESS;
@ -337,8 +365,9 @@ dc_irda_connect_lsap (dc_irda_t *device, unsigned int address, unsigned int lsap
#endif
if (connect (device->fd, (struct sockaddr *) &peer, sizeof (peer)) != 0) {
SYSERROR (device->context, S_ERRNO);
return DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
return syserror(errcode);
}
return DC_STATUS_SUCCESS;
@ -357,8 +386,9 @@ dc_irda_get_available (dc_irda_t *device, size_t *value)
#endif
if (S_IOCTL (device->fd, FIONREAD, &bytes) != 0) {
SYSERROR (device->context, S_ERRNO);
return DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
return syserror(errcode);
}
if (value)
@ -391,8 +421,9 @@ dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual)
while (nbytes < size) {
int rc = select (device->fd + 1, &fds, NULL, NULL, (device->timeout >= 0 ? &tv : NULL));
if (rc < 0) {
SYSERROR (device->context, S_ERRNO);
status = DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
status = syserror(errcode);
goto out;
} else if (rc == 0) {
break; // Timeout.
@ -400,8 +431,9 @@ dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual)
s_ssize_t n = recv (device->fd, (char*) data + nbytes, size - nbytes, 0);
if (n < 0) {
SYSERROR (device->context, S_ERRNO);
status = DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
status = syserror(errcode);
goto out;
} else if (n == 0) {
break; // EOF reached.
@ -437,8 +469,9 @@ dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual)
while (nbytes < size) {
s_ssize_t n = send (device->fd, (char*) data + nbytes, size - nbytes, 0);
if (n < 0) {
SYSERROR (device->context, S_ERRNO);
status = DC_STATUS_IO;
s_errcode_t errcode = S_ERRNO;
SYSERROR (device->context, errcode);
status = syserror(errcode);
goto out;
}

View File

@ -77,6 +77,23 @@ struct dc_serial_t {
unsigned int nbits;
};
static dc_status_t
syserror(int errcode)
{
switch (errcode) {
case EINVAL:
return DC_STATUS_INVALIDARGS;
case ENOMEM:
return DC_STATUS_NOMEMORY;
case ENOENT:
return DC_STATUS_NODEVICE;
case EACCES:
case EBUSY:
return DC_STATUS_NOACCESS;
default:
return DC_STATUS_IO;
}
}
dc_status_t
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
@ -154,16 +171,18 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
// without waiting for the modem connection to complete.
device->fd = open (name, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (device->fd == -1) {
SYSERROR (context, errno);
status = DC_STATUS_IO;
int errcode = errno;
SYSERROR (context, errcode);
status = syserror (errcode);
goto error_free;
}
#ifndef ENABLE_PTY
// Enable exclusive access mode.
if (ioctl (device->fd, TIOCEXCL, NULL) != 0) {
SYSERROR (context, errno);
status = DC_STATUS_IO;
int errcode = errno;
SYSERROR (context, errcode);
status = syserror (errcode);
goto error_close;
}
#endif
@ -173,8 +192,9 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
// It is also used to check if the obtained
// file descriptor represents a terminal device.
if (tcgetattr (device->fd, &device->tty) != 0) {
SYSERROR (context, errno);
status = DC_STATUS_IO;
int errcode = errno;
SYSERROR (context, errcode);
status = syserror (errcode);
goto error_close;
}
@ -199,8 +219,9 @@ dc_serial_close (dc_serial_t *device)
// Restore the initial terminal attributes.
if (tcsetattr (device->fd, TCSANOW, &device->tty) != 0) {
SYSERROR (device->context, errno);
dc_status_set_error(&status, DC_STATUS_IO);
int errcode = errno;
SYSERROR (device->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
#ifndef ENABLE_PTY
@ -210,8 +231,9 @@ dc_serial_close (dc_serial_t *device)
// Close the device.
if (close (device->fd) != 0) {
SYSERROR (device->context, errno);
dc_status_set_error(&status, DC_STATUS_IO);
int errcode = errno;
SYSERROR (device->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
// Free memory.
@ -233,8 +255,9 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
struct termios tty;
memset (&tty, 0, sizeof (tty));
if (tcgetattr (device->fd, &tty) != 0) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
// Setup raw input/output mode without echo.
@ -329,8 +352,9 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
}
if (cfsetispeed (&tty, baud) != 0 ||
cfsetospeed (&tty, baud) != 0) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
// Set the character size.
@ -425,8 +449,9 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Apply the new settings.
if (tcsetattr (device->fd, TCSANOW, &tty) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
// Configure a custom baudrate if necessary.
@ -435,8 +460,9 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Get the current settings.
struct serial_struct ss;
if (ioctl (device->fd, TIOCGSERIAL, &ss) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
// Set the custom divisor.
@ -446,14 +472,16 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Apply the new settings.
if (ioctl (device->fd, TIOCSSERIAL, &ss) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
#elif defined(IOSSIOSPEED)
speed_t speed = baudrate;
if (ioctl (device->fd, IOSSIOSPEED, &speed) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
#else
// Custom baudrates are not supported.
@ -501,8 +529,9 @@ dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
// Get the current settings.
struct serial_struct ss;
if (ioctl (device->fd, TIOCGSERIAL, &ss) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
// Set or clear the low latency flag.
@ -514,8 +543,9 @@ dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
// Apply the new settings.
if (ioctl (device->fd, TIOCSSERIAL, &ss) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
#elif defined(IOSSDATALAT)
// Set the receive latency in microseconds. Serial drivers use this
@ -523,8 +553,9 @@ dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds)
// the hardware. A value of zero restores the default value.
unsigned long usec = (milliseconds == 0 ? 1 : milliseconds * 1000);
if (ioctl (device->fd, IOSSDATALAT, &usec) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
#endif
@ -558,8 +589,9 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
if (timeout > 0) {
struct timeval now;
if (gettimeofday (&now, NULL) != 0) {
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
@ -583,10 +615,11 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
int rc = select (device->fd + 1, &fds, NULL, NULL, timeout >= 0 ? &tvt : NULL);
if (rc < 0) {
if (errno == EINTR)
int errcode = errno;
if (errcode == EINTR)
continue; // Retry.
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
} else if (rc == 0) {
break; // Timeout.
@ -594,10 +627,11 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
ssize_t n = read (device->fd, (char *) data + nbytes, size - nbytes);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
int errcode = errno;
if (errcode == EINTR || errcode == EAGAIN)
continue; // Retry.
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
} else if (n == 0) {
break; // EOF.
@ -634,8 +668,9 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
if (device->halfduplex) {
// Get the current time.
if (gettimeofday (&tvb, NULL) != 0) {
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
}
@ -647,10 +682,11 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
int rc = select (device->fd + 1, NULL, &fds, NULL, NULL);
if (rc < 0) {
if (errno == EINTR)
int errcode = errno;
if (errcode == EINTR)
continue; // Retry.
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
} else if (rc == 0) {
break; // Timeout.
@ -658,10 +694,11 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
ssize_t n = write (device->fd, (const char *) data + nbytes, size - nbytes);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
int errcode = errno;
if (errcode == EINTR || errcode == EAGAIN)
continue; // Retry.
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
} else if (n == 0) {
break; // EOF.
@ -677,9 +714,10 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
#else
while (tcdrain (device->fd) != 0) {
#endif
if (errno != EINTR ) {
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
int errcode = errno;
if (errcode != EINTR ) {
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
}
@ -687,8 +725,9 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
if (device->halfduplex) {
// Get the current time.
if (gettimeofday (&tve, NULL) != 0) {
SYSERROR (device->context, errno);
status = DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
@ -746,8 +785,9 @@ dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
}
if (tcflush (device->fd, flags) != 0) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -775,8 +815,9 @@ dc_serial_set_break (dc_serial_t *device, unsigned int level)
unsigned long action = (level ? TIOCSBRK : TIOCCBRK);
if (ioctl (device->fd, action, NULL) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -794,8 +835,9 @@ dc_serial_set_dtr (dc_serial_t *device, unsigned int level)
int value = TIOCM_DTR;
if (ioctl (device->fd, action, &value) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -813,8 +855,9 @@ dc_serial_set_rts (dc_serial_t *device, unsigned int level)
int value = TIOCM_RTS;
if (ioctl (device->fd, action, &value) != 0 && NOPTY) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -828,8 +871,9 @@ dc_serial_get_available (dc_serial_t *device, size_t *value)
int bytes = 0;
if (ioctl (device->fd, TIOCINQ, &bytes) != 0) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
if (value)
@ -848,8 +892,9 @@ dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
int status = 0;
if (ioctl (device->fd, TIOCMGET, &status) != 0) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
SYSERROR (device->context, errcode);
return syserror (errcode);
}
if (status & TIOCM_CAR)
@ -880,9 +925,10 @@ dc_serial_sleep (dc_serial_t *device, unsigned int timeout)
ts.tv_nsec = (timeout % 1000) * 1000000;
while (nanosleep (&ts, &ts) != 0) {
if (errno != EINTR ) {
SYSERROR (device->context, errno);
return DC_STATUS_IO;
int errcode = errno;
if (errcode != EINTR ) {
SYSERROR (device->context, errcode);
return syserror (errcode);
}
}

View File

@ -48,6 +48,23 @@ struct dc_serial_t {
unsigned int nbits;
};
static dc_status_t
syserror(DWORD errcode)
{
switch (errcode) {
case ERROR_INVALID_PARAMETER:
return DC_STATUS_INVALIDARGS;
case ERROR_OUTOFMEMORY:
return DC_STATUS_NOMEMORY;
case ERROR_FILE_NOT_FOUND:
return DC_STATUS_NODEVICE;
case ERROR_ACCESS_DENIED:
return DC_STATUS_NOACCESS;
default:
return DC_STATUS_IO;
}
}
dc_status_t
dc_serial_enumerate (dc_serial_callback_t callback, void *userdata)
{
@ -148,8 +165,9 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
0, // Non-overlapped I/O.
NULL);
if (device->hFile == INVALID_HANDLE_VALUE) {
SYSERROR (context, GetLastError ());
status = DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (context, errcode);
status = syserror (errcode);
goto error_free;
}
@ -159,8 +177,9 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
// represents a serial device.
if (!GetCommState (device->hFile, &device->dcb) ||
!GetCommTimeouts (device->hFile, &device->timeouts)) {
SYSERROR (context, GetLastError ());
status = DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (context, errcode);
status = syserror (errcode);
goto error_close;
}
@ -186,14 +205,16 @@ dc_serial_close (dc_serial_t *device)
// Restore the initial communication settings and timeouts.
if (!SetCommState (device->hFile, &device->dcb) ||
!SetCommTimeouts (device->hFile, &device->timeouts)) {
SYSERROR (device->context, GetLastError ());
dc_status_set_error(&status, DC_STATUS_IO);
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
// Close the device.
if (!CloseHandle (device->hFile)) {
SYSERROR (device->context, GetLastError ());
dc_status_set_error(&status, DC_STATUS_IO);
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
dc_status_set_error(&status, syserror (errcode));
}
// Free memory.
@ -214,8 +235,9 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Retrieve the current settings.
DCB dcb;
if (!GetCommState (device->hFile, &dcb)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
dcb.fBinary = TRUE; // Enable Binary Transmission
@ -303,8 +325,9 @@ dc_serial_configure (dc_serial_t *device, unsigned int baudrate, unsigned int da
// Apply the new settings.
if (!SetCommState (device->hFile, &dcb)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
device->baudrate = baudrate;
@ -324,8 +347,9 @@ dc_serial_set_timeout (dc_serial_t *device, int timeout)
// Retrieve the current timeouts.
COMMTIMEOUTS timeouts;
if (!GetCommTimeouts (device->hFile, &timeouts)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
// Update the settings.
@ -354,8 +378,9 @@ dc_serial_set_timeout (dc_serial_t *device, int timeout)
// Activate the new timeouts.
if (!SetCommTimeouts (device->hFile, &timeouts)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -393,8 +418,9 @@ dc_serial_read (dc_serial_t *device, void *data, size_t size, size_t *actual)
}
if (!ReadFile (device->hFile, data, size, &dwRead, NULL)) {
SYSERROR (device->context, GetLastError ());
status = DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
@ -427,23 +453,26 @@ dc_serial_write (dc_serial_t *device, const void *data, size_t size, size_t *act
// Get the current time.
if (!QueryPerformanceFrequency(&freq) ||
!QueryPerformanceCounter(&begin)) {
SYSERROR (device->context, GetLastError ());
status = DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
}
if (!WriteFile (device->hFile, data, size, &dwWritten, NULL)) {
SYSERROR (device->context, GetLastError ());
status = DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
if (device->halfduplex) {
// Get the current time.
if (!QueryPerformanceCounter(&end)) {
SYSERROR (device->context, GetLastError ());
status = DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
status = syserror (errcode);
goto out;
}
@ -503,8 +532,9 @@ dc_serial_purge (dc_serial_t *device, dc_direction_t direction)
}
if (!PurgeComm (device->hFile, flags)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -519,8 +549,9 @@ dc_serial_flush (dc_serial_t *device)
INFO (device->context, "Flush: none");
if (!FlushFileBuffers (device->hFile)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -536,13 +567,15 @@ dc_serial_set_break (dc_serial_t *device, unsigned int level)
if (level) {
if (!SetCommBreak (device->hFile)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
} else {
if (!ClearCommBreak (device->hFile)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
}
@ -560,8 +593,9 @@ dc_serial_set_dtr (dc_serial_t *device, unsigned int level)
int status = (level ? SETDTR : CLRDTR);
if (!EscapeCommFunction (device->hFile, status)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -578,8 +612,9 @@ dc_serial_set_rts (dc_serial_t *device, unsigned int level)
int status = (level ? SETRTS : CLRRTS);
if (!EscapeCommFunction (device->hFile, status)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
return DC_STATUS_SUCCESS;
@ -594,8 +629,9 @@ dc_serial_get_available (dc_serial_t *device, size_t *value)
COMSTAT stats;
if (!ClearCommError (device->hFile, NULL, &stats)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
if (value)
@ -614,8 +650,9 @@ dc_serial_get_lines (dc_serial_t *device, unsigned int *value)
DWORD stats = 0;
if (!GetCommModemStatus (device->hFile, &stats)) {
SYSERROR (device->context, GetLastError ());
return DC_STATUS_IO;
DWORD errcode = GetLastError ();
SYSERROR (device->context, errcode);
return syserror (errcode);
}
if (stats & MS_RLSD_ON)