--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <windows.h>
+#include <conio.h>
+
+#include "log.h"
+#include "serial.h"
+
+struct serial_port {
+ HANDLE handle;
+};
+
+port_t * serial_open(const char *name, int speed)
+{
+ port_t *pt = NULL;
+ HANDLE port = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (port == INVALID_HANDLE_VALUE) return NULL;
+
+ DCB settings;
+ memset(&settings, 0, sizeof(settings));
+ settings.DCBlength = sizeof(settings);
+
+ char seta[120];
+ snprintf(seta, sizeof(seta), "baud=%d data=8 parity=N stop=1 dtr=off rts=off", speed);
+ if (!BuildCommDCBA(seta, &settings)) {
+ loge("Invalid serial port settings");
+ CloseHandle(port);
+ return NULL;
+ }
+
+ if (!SetCommState(port, &settings)) {
+ loge("Unable to configure serial port");
+ CloseHandle(port);
+ return NULL;
+ }
+
+ COMMTIMEOUTS tout;
+ tout.ReadIntervalTimeout = MAXDWORD;
+ tout.ReadTotalTimeoutMultiplier = MAXDWORD;
+ tout.ReadTotalTimeoutConstant = 30000;
+ tout.WriteTotalTimeoutMultiplier = 0;
+ tout.WriteTotalTimeoutConstant = 0;
+
+ if (!SetCommTimeouts(port, &tout)) {
+ loge("Unable to set serial timeouts");
+ CloseHandle(port);
+ return NULL;
+ }
+
+ pt = malloc(sizeof(port_t));
+ pt->handle = port;
+
+ return pt;
+
+}
+
+void serial_close(port_t * pt)
+{
+ if (pt == NULL) return;
+ if (pt->handle == INVALID_HANDLE_VALUE) return;
+
+ CloseHandle(pt->handle);
+ pt->handle = INVALID_HANDLE_VALUE;
+
+ return;
+}
+
+int serial_read(port_t * pt, unsigned char * buff, size_t len)
+{
+ if (pt == NULL || pt->handle == INVALID_HANDLE_VALUE) return -1;
+ int count = 0;
+ unsigned char * p = buff;
+ int done = 0;
+
+ /* read will block if no chars, will return whats there otherwise,
+ * and will timeout after 30 seconds */
+ while (done < len) {
+ if (!ReadFile(pt->handle, p, len-done, (LPDWORD)&count, NULL))
+ return -1;
+ p += count;
+ done += count;
+ }
+
+ return count;
+}
+
+int serial_write(port_t * pt, unsigned char * buff, size_t len)
+{
+ if (pt == NULL || pt->handle == INVALID_HANDLE_VALUE) return -1;
+
+ int n;
+
+ if (WriteFile(pt->handle, buff, len, (LPDWORD)&n, NULL))
+ return n;
+
+ return 0;
+}
+
+int serial_break(port_t * pt, int set)
+{
+ if (pt == NULL || pt->handle == INVALID_HANDLE_VALUE) return -1;
+
+ if (set) {
+ SetCommBreak(pt->handle);
+ } else {
+ ClearCommBreak(pt->handle);
+ }
+
+ return 0;
+}
+