Skip to content

Instantly share code, notes, and snippets.

@bit-hack
Created December 1, 2019 23:59
Show Gist options
  • Save bit-hack/ecd42385a4044b6f4bb86d55985eac4d to your computer and use it in GitHub Desktop.
Save bit-hack/ecd42385a4044b6f4bb86d55985eac4d to your computer and use it in GitHub Desktop.
Simple win32 binary serial library
/* .__ .__
* ______ ___________|__|____ | |
* / ___// __ \_ __ \ \__ \ | |
* \___ \\ ___/| | \/ |/ __ \| |__
* /____ >\___ >__| |__(____ /____/
* \/ \/ \/
*/
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "serial.h"
struct serial_t {
HANDLE handle;
};
static BOOL set_timeouts(
HANDLE handle)
{
COMMTIMEOUTS com_timeout;
ZeroMemory(&com_timeout, sizeof(com_timeout));
com_timeout.ReadIntervalTimeout = 3;
com_timeout.ReadTotalTimeoutMultiplier = 3;
com_timeout.ReadTotalTimeoutConstant = 2;
com_timeout.WriteTotalTimeoutMultiplier = 3;
com_timeout.WriteTotalTimeoutConstant = 2;
return SetCommTimeouts(handle, &com_timeout);
}
serial_t *serial_open(
uint32_t port,
uint32_t baud_rate)
{
// construct com port device name
char dev_name[32];
snprintf(dev_name, sizeof(dev_name), "\\\\.\\COM%d", (int)port);
// open handle to serial device
HANDLE handle = CreateFileA(
dev_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
goto on_error;
}
// query serial device control block
DCB dbc;
ZeroMemory(&dbc, sizeof(dbc));
dbc.DCBlength = sizeof(dbc);
if (GetCommState(handle, &dbc) == FALSE) {
goto on_error;
}
// change baud rate
if (dbc.BaudRate != baud_rate) {
dbc.BaudRate = baud_rate;
}
dbc.fBinary = TRUE;
dbc.fParity = FALSE;
dbc.fOutxCtsFlow = FALSE;
dbc.fDtrControl = FALSE;
dbc.ByteSize = 8;
dbc.fOutX = FALSE;
dbc.fInX = FALSE;
dbc.fNull = FALSE;
dbc.fRtsControl = RTS_CONTROL_DISABLE;
dbc.Parity = NOPARITY;
dbc.StopBits = ONESTOPBIT;
dbc.EofChar = 0;
dbc.ErrorChar = 0;
dbc.EvtChar = 0;
dbc.XonChar = 0;
dbc.XoffChar = 0;
if (SetCommState(handle, &dbc) == FALSE) {
goto on_error;
}
// set com timeouts
if (set_timeouts(handle) == FALSE) {
goto on_error;
}
// wrap in serial object
serial_t *serial = malloc(sizeof(serial_t));
if (serial == NULL) {
goto on_error;
}
serial->handle = handle;
// success
return serial;
// error handler
on_error:
if (handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
return NULL;
}
void serial_close(
serial_t *serial)
{
assert(serial);
if (serial->handle != INVALID_HANDLE_VALUE) {
CloseHandle(serial->handle);
}
free(serial);
}
uint32_t serial_send(
serial_t *serial,
const void *data,
size_t nbytes)
{
assert(serial && data && nbytes);
DWORD nb_written = 0;
if (WriteFile(
serial->handle,
data,
nbytes,
&nb_written,
NULL) == FALSE) {
return 0;
}
return nb_written;
}
uint32_t serial_read(
serial_t *serial,
void *dst,
size_t nbytes)
{
assert(serial && dst && nbytes);
DWORD nb_read = 0;
if (ReadFile(
serial->handle,
dst, nbytes,
&nb_read,
NULL) == FALSE) {
return 0;
}
return nb_read;
}
void serial_flush(
serial_t *serial) {
FlushFileBuffers(serial->handle);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment