From b15ca8c24d97e2d9c5ec07dbf5fba4194e4b702f Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sun, 18 Aug 2024 01:54:22 +0100 Subject: [PATCH] Reformat spacing/comments in src/ser_win32.c --- src/ser_win32.c | 1102 ++++++++++++++++++++++------------------------- 1 file changed, 513 insertions(+), 589 deletions(-) diff --git a/src/ser_win32.c b/src/ser_win32.c index f37f4bb5..9af426de 100644 --- a/src/ser_win32.c +++ b/src/ser_win32.c @@ -17,27 +17,24 @@ * along with this program. If not, see . */ -/* - * Native Win32 serial interface for avrdude. - */ +// Native Win32 serial interface for avrdude #include #if defined(WIN32) - #define WIN32_LEAN_AND_MEAN #include #include #include #include -#include /* for isprint */ -#include /* ENOTTY */ +#include // For isprint +#include // ENOTTY #include "avrdude.h" #include "libavrdude.h" -long serial_recv_timeout = 5000; /* ms */ -long serial_drain_timeout = 250; /* ms */ +long serial_recv_timeout = 5000; // ms +long serial_drain_timeout = 250; // ms #define W32SERBUFSIZE 1024 @@ -46,25 +43,25 @@ struct baud_mapping { DWORD speed; }; -/* HANDLE hComPort=INVALID_HANDLE_VALUE; */ +// HANDLE hComPort=INVALID_HANDLE_VALUE; -static const struct baud_mapping baud_lookup_table [] = { - { 300, CBR_300 }, - { 600, CBR_600 }, - { 1200, CBR_1200 }, - { 2400, CBR_2400 }, - { 4800, CBR_4800 }, - { 9600, CBR_9600 }, - { 19200, CBR_19200 }, - { 38400, CBR_38400 }, - { 57600, CBR_57600 }, - { 115200, CBR_115200 }, - { 0, 0 } /* Terminator. */ +static const struct baud_mapping baud_lookup_table[] = { + {300, CBR_300}, + {600, CBR_600}, + {1200, CBR_1200}, + {2400, CBR_2400}, + {4800, CBR_4800}, + {9600, CBR_9600}, + {19200, CBR_19200}, + {38400, CBR_38400}, + {57600, CBR_57600}, + {115200, CBR_115200}, + {0, 0} // Terminator }; static DWORD serial_baud_lookup(long baud) { for(const struct baud_mapping *map = baud_lookup_table; map->baud; map++) - if (map->baud == baud) + if(map->baud == baud) return map->speed; // Return the raw rate when asked for non-standard baud rate @@ -73,580 +70,508 @@ static DWORD serial_baud_lookup(long baud) { return baud; } +static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) { // ms + COMMTIMEOUTS ctmo; -static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms -{ - COMMTIMEOUTS ctmo; - ZeroMemory (&ctmo, sizeof(COMMTIMEOUTS)); - ctmo.ReadIntervalTimeout = 0; - ctmo.ReadTotalTimeoutMultiplier = 0; - ctmo.ReadTotalTimeoutConstant = timeout; + ZeroMemory(&ctmo, sizeof(COMMTIMEOUTS)); + ctmo.ReadIntervalTimeout = 0; + ctmo.ReadTotalTimeoutMultiplier = 0; + ctmo.ReadTotalTimeoutConstant = timeout; - return SetCommTimeouts(hComPort, &ctmo); + return SetCommTimeouts(hComPort, &ctmo); } static int ser_setparams(const union filedescriptor *fd, long baud, unsigned long cflags) { - if(cx->ser_serial_over_ethernet) - return -ENOTTY; + if(cx->ser_serial_over_ethernet) + return -ENOTTY; + + DCB dcb; + HANDLE hComPort = (HANDLE) fd->pfd; + + ZeroMemory(&dcb, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = serial_baud_lookup(baud); + dcb.fBinary = 1; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + switch ((cflags & (SERIAL_CS5 | SERIAL_CS6 | SERIAL_CS7 | SERIAL_CS8))) { + case SERIAL_CS5: + dcb.ByteSize = 5; + break; + case SERIAL_CS6: + dcb.ByteSize = 6; + break; + case SERIAL_CS7: + dcb.ByteSize = 7; + break; + case SERIAL_CS8: + dcb.ByteSize = 8; + break; + } + switch ((cflags & (SERIAL_NO_PARITY | SERIAL_PARENB | SERIAL_PARODD))) { + case SERIAL_NO_PARITY: + dcb.Parity = NOPARITY; + break; + case SERIAL_PARENB: + dcb.Parity = EVENPARITY; + break; + case SERIAL_PARODD: + dcb.Parity = ODDPARITY; + break; + } + switch ((cflags & (SERIAL_NO_CSTOPB | SERIAL_CSTOPB))) { + case SERIAL_NO_CSTOPB: + dcb.StopBits = ONESTOPBIT; + break; + case SERIAL_CSTOPB: + dcb.StopBits = TWOSTOPBITS; + break; + } + if(!SetCommState(hComPort, &dcb)) + return -1; - DCB dcb; - HANDLE hComPort = (HANDLE)fd->pfd; - - ZeroMemory (&dcb, sizeof(DCB)); - dcb.DCBlength = sizeof(DCB); - dcb.BaudRate = serial_baud_lookup (baud); - dcb.fBinary = 1; - dcb.fDtrControl = DTR_CONTROL_DISABLE; - dcb.fRtsControl = RTS_CONTROL_DISABLE; - switch ((cflags & (SERIAL_CS5 | SERIAL_CS6 | SERIAL_CS7 | SERIAL_CS8))) { - case SERIAL_CS5: - dcb.ByteSize = 5; - break; - case SERIAL_CS6: - dcb.ByteSize = 6; - break; - case SERIAL_CS7: - dcb.ByteSize = 7; - break; - case SERIAL_CS8: - dcb.ByteSize = 8; - break; - } - switch ((cflags & (SERIAL_NO_PARITY | SERIAL_PARENB | SERIAL_PARODD))) { - case SERIAL_NO_PARITY: - dcb.Parity = NOPARITY; - break; - case SERIAL_PARENB: - dcb.Parity = EVENPARITY; - break; - case SERIAL_PARODD: - dcb.Parity = ODDPARITY; - break; - } - switch ((cflags & (SERIAL_NO_CSTOPB | SERIAL_CSTOPB))) { - case SERIAL_NO_CSTOPB: - dcb.StopBits = ONESTOPBIT; - break; - case SERIAL_CSTOPB: - dcb.StopBits = TWOSTOPBITS; - break; - } - if (!SetCommState(hComPort, &dcb)) - return -1; - - return 0; -} - -static int net_open(const char *port, union filedescriptor *fdp) { - WSADATA wsaData; - LPVOID lpMsgBuf; - - char *hstr, *pstr, *end; - unsigned int pnum; - int fd; - struct sockaddr_in sockaddr; - struct hostent *hp; - - if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { - pmsg_error("WSAStartup() failed\n"); - return -1; - } - - hstr = mmt_strdup(port); - if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) { - pmsg_error("mangled host:port string %s\n", hstr); - mmt_free(hstr); - return -1; - } - - /* - * Terminate the host section of the description. - */ - *pstr++ = '\0'; - - pnum = strtoul(pstr, &end, 10); - - if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) { - pmsg_error("bad port number %s\n", pstr); - mmt_free(hstr); - return -1; - } - - if ((hp = gethostbyname(hstr)) == NULL) { - pmsg_error("unknown host %s\n", hstr); - mmt_free(hstr); - return -1; - } - - mmt_free(hstr); - - if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - WSAGetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - pmsg_error("cannot open socket: %s\n", (char *) lpMsgBuf); - LocalFree(lpMsgBuf); - return -1; - } - - memset(&sockaddr, 0, sizeof(struct sockaddr_in)); - sockaddr.sin_family = AF_INET; - sockaddr.sin_port = htons(pnum); - memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr)); - - if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - WSAGetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - pmsg_error("connect failed: %s\n", (char *) lpMsgBuf); - LocalFree(lpMsgBuf); - return -1; - } - - fdp->ifd = fd; - - cx->ser_serial_over_ethernet = 1; - return 0; -} - - -static int ser_open(const char *port, union pinfo pinfo, union filedescriptor *fdp) { - LPVOID lpMsgBuf; - HANDLE hComPort=INVALID_HANDLE_VALUE; - char *newname = 0; - - /* - * If the port is of the form "net::", then - * handle it as a TCP connection to a terminal server. - */ - if (str_starts(port, "net:")) { - return net_open(port + strlen("net:"), fdp); - } - - if (str_casestarts(port, "com")) { - - // prepend "\\\\.\\" to name, required for port # >= 10 - newname = mmt_malloc(strlen("\\\\.\\") + strlen(port) + 1); - strcpy(newname, "\\\\.\\"); - strcat(newname, port); - - port = newname; - } - - hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (hComPort == INVALID_HANDLE_VALUE) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL); - pmsg_error("cannot open port %s: %s\n", port, (char*) lpMsgBuf); - LocalFree( lpMsgBuf ); - return -1; - } - - if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE)) - { - CloseHandle(hComPort); - pmsg_error("cannot set buffers for %s\n", port); - return -1; - } - - fdp->pfd = (void *)hComPort; - if (ser_setparams(fdp, pinfo.serialinfo.baud, pinfo.serialinfo.cflags) != 0) - { - CloseHandle(hComPort); - pmsg_error("cannot set com-state for %s\n", port); - return -1; - } - - if (!serial_w32SetTimeOut(hComPort,0)) - { - CloseHandle(hComPort); - pmsg_error("cannot set initial timeout for %s\n", port); - return -1; - } - - if (newname != 0) { - mmt_free(newname); - } - return 0; -} - - -static void ser_close(union filedescriptor *fd) { - if (cx->ser_serial_over_ethernet) { - closesocket(fd->ifd); - WSACleanup(); - } else { - HANDLE hComPort=(HANDLE)fd->pfd; - if (hComPort != INVALID_HANDLE_VALUE) - CloseHandle (hComPort); - - hComPort = INVALID_HANDLE_VALUE; - } -} - -static int ser_set_dtr_rts(const union filedescriptor *fd, int is_on) { - if(cx->ser_serial_over_ethernet) - return 0; - - HANDLE hComPort=(HANDLE)fd->pfd; - - EscapeCommFunction(hComPort, is_on? SETDTR: CLRDTR); - EscapeCommFunction(hComPort, is_on? SETRTS: CLRRTS); - - return 0; -} - -static int net_send(const union filedescriptor *fd, const unsigned char *buf, size_t len) { - LPVOID lpMsgBuf; - int rc; - - if (fd->ifd < 0) { - pmsg_notice("%s(): connection not open\n", __func__); - return -1; - } - - if (!len) - return 0; - - if (verbose >= MSG_TRACE) - trace_buffer(__func__, buf, len); - - while (len) { - rc = send(fd->ifd, (const char *) buf, len > 1024? 1024: len, 0); - if (rc < 0) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - WSAGetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - pmsg_error("unable to send: %s\n", (char *) lpMsgBuf); - LocalFree(lpMsgBuf); - return -1; - } - buf += rc; - len -= rc; - } - - return 0; -} - - -static int ser_send(const union filedescriptor *fd, const unsigned char *buf, size_t len) { - if(cx->ser_serial_over_ethernet) - return net_send(fd, buf, len); - - DWORD written; - - HANDLE hComPort=(HANDLE)fd->pfd; - - if (hComPort == INVALID_HANDLE_VALUE) { - pmsg_error("port not open\n"); - return -1; - } - - if (!len) - return 0; - - if (verbose >= MSG_TRACE) - trace_buffer(__func__, buf, len); - - serial_w32SetTimeOut(hComPort,500); - - if (!WriteFile (hComPort, buf, len, &written, NULL)) { - pmsg_error("unable to write: %s\n", "sorry no info avail"); // TODO - return -1; - } - - if (written != len) { - pmsg_error("size/send mismatch\n"); - return -1; - } - - return 0; -} - - -static int net_recv(const union filedescriptor *fd, unsigned char *buf, size_t buflen) { - LPVOID lpMsgBuf; - struct timeval timeout, to2; - fd_set rfds; - int nfds; - int rc; - unsigned char *p = buf; - size_t len = 0; - - if (fd->ifd < 0) { - pmsg_error("connection not open\n"); - return -1; - } - - timeout.tv_sec = serial_recv_timeout / 1000L; - timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000; - to2 = timeout; - - while (len < buflen) { -reselect: - FD_ZERO(&rfds); - FD_SET(fd->ifd, &rfds); - - nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2); - if (nfds == 0) { - pmsg_notice2("%s(): programmer is not responding\n", __func__); - return -1; - } else if (nfds == -1) { - if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) { - pmsg_notice("%s(): programmer is not responding, reselecting\n", __func__); - goto reselect; - } else { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - WSAGetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - pmsg_error("%s(): %s\n", __func__, (char *) lpMsgBuf); - LocalFree(lpMsgBuf); - return -1; - } - } - - rc = recv(fd->ifd, (char *) p, (buflen - len > 1024)? 1024: buflen - len, 0); - if (rc < 0) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - WSAGetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - pmsg_error("unable to read: %s\n", (char *) lpMsgBuf); - LocalFree(lpMsgBuf); - return -1; - } - p += rc; - len += rc; - } - - if (verbose >= MSG_TRACE) - trace_buffer(__func__, buf, len); - - return 0; -} - -static int ser_recv(const union filedescriptor *fd, unsigned char *buf, size_t buflen) { - if(cx->ser_serial_over_ethernet) - return net_recv(fd, buf, buflen); - - DWORD read; - - HANDLE hComPort=(HANDLE)fd->pfd; - - if (hComPort == INVALID_HANDLE_VALUE) { - pmsg_error("port not open\n"); - return -1; - } - - serial_w32SetTimeOut(hComPort, serial_recv_timeout); - - if (!ReadFile(hComPort, buf, buflen, &read, NULL)) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL); - pmsg_error("unable to read: %s\n", (char*) lpMsgBuf); - LocalFree(lpMsgBuf); - return -1; - } - - /* time out detected */ - if (read < buflen) { - pmsg_notice2("%s(): programmer is not responding\n", __func__); - return -1; - } - - if (verbose >= MSG_TRACE) - trace_buffer(__func__, buf, read); - - return 0; -} - -static int net_drain(const union filedescriptor *fd, int display) { - LPVOID lpMsgBuf; - struct timeval timeout; - fd_set rfds; - int nfds; - unsigned char buf; - int rc; - - if (fd->ifd < 0) { - pmsg_error("connection not open\n"); - return -1; - } - - if (display) { - msg_info("drain>"); - } - - timeout.tv_sec = 0; - timeout.tv_usec = serial_drain_timeout*1000L; - - while (1) { - FD_ZERO(&rfds); - FD_SET(fd->ifd, &rfds); - - reselect: - nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout); - if (nfds == 0) { - if (display) { - msg_info("ifd, (char *) &buf, 1, 0); - if (rc < 0) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - WSAGetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - pmsg_error("unable to read: %s\n", (char *) lpMsgBuf); - LocalFree(lpMsgBuf); - return -1; - } - - if (display) { - msg_info("%02x ", buf); - } - } - - return 0; -} - -static int ser_drain(const union filedescriptor *fd, int display) { - if(cx->ser_serial_over_ethernet) - return net_drain(fd, display); - - // int rc; - unsigned char buf[10]; - BOOL readres; - DWORD read; - - HANDLE hComPort=(HANDLE)fd->pfd; - - if (hComPort == INVALID_HANDLE_VALUE) { - pmsg_error("port not open\n"); - return -1; - } - - serial_w32SetTimeOut(hComPort, serial_drain_timeout); - - if (display) { - msg_info("drain>"); - } - - while (1) { - readres=ReadFile(hComPort, buf, 1, &read, NULL); - if (!readres) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL ); - pmsg_error("unable to read: %s\n", (char*) lpMsgBuf); - LocalFree( lpMsgBuf ); - return -1; - } - - if (read) { // data avail - if (display) - msg_info("%02x ", buf[0]); - } - else { // no more data - if (display) - msg_info(" 65535)) { + pmsg_error("bad port number %s\n", pstr); + mmt_free(hstr); + return -1; + } + + if((hp = gethostbyname(hstr)) == NULL) { + pmsg_error("unknown host %s\n", hstr); + mmt_free(hstr); + return -1; + } + + mmt_free(hstr); + + if((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("cannot open socket: %s\n", (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + + memset(&sockaddr, 0, sizeof(struct sockaddr_in)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(pnum); + memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr)); + + if(connect(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("connect failed: %s\n", (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + + fdp->ifd = fd; + + cx->ser_serial_over_ethernet = 1; + return 0; +} + +static int ser_open(const char *port, union pinfo pinfo, union filedescriptor *fdp) { + LPVOID lpMsgBuf; + HANDLE hComPort = INVALID_HANDLE_VALUE; + char *newname = 0; + + /* + * If the port is of the form "net::", then handle it as a TCP + * connection to a terminal server. + */ + if(str_starts(port, "net:")) { + return net_open(port + strlen("net:"), fdp); + } + + if(str_casestarts(port, "com")) { + + // Prepend "\\\\.\\" to name, required for port # >= 10 + newname = mmt_malloc(strlen("\\\\.\\") + strlen(port) + 1); + strcpy(newname, "\\\\.\\"); + strcat(newname, port); + + port = newname; + } + + hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if(hComPort == INVALID_HANDLE_VALUE) { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("cannot open port %s: %s\n", port, (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + + if(!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE)) { + CloseHandle(hComPort); + pmsg_error("cannot set buffers for %s\n", port); + return -1; + } + + fdp->pfd = (void *) hComPort; + if(ser_setparams(fdp, pinfo.serialinfo.baud, pinfo.serialinfo.cflags) != 0) { + CloseHandle(hComPort); + pmsg_error("cannot set com-state for %s\n", port); + return -1; + } + + if(!serial_w32SetTimeOut(hComPort, 0)) { + CloseHandle(hComPort); + pmsg_error("cannot set initial timeout for %s\n", port); + return -1; + } + + if(newname != 0) { + mmt_free(newname); + } + return 0; +} + +static void ser_close(union filedescriptor *fd) { + if(cx->ser_serial_over_ethernet) { + closesocket(fd->ifd); + WSACleanup(); + } else { + HANDLE hComPort = (HANDLE) fd->pfd; + + if(hComPort != INVALID_HANDLE_VALUE) + CloseHandle(hComPort); + + hComPort = INVALID_HANDLE_VALUE; + } +} + +static int ser_set_dtr_rts(const union filedescriptor *fd, int is_on) { + if(cx->ser_serial_over_ethernet) + return 0; + + HANDLE hComPort = (HANDLE) fd->pfd; + + EscapeCommFunction(hComPort, is_on? SETDTR: CLRDTR); + EscapeCommFunction(hComPort, is_on? SETRTS: CLRRTS); + + return 0; +} + +static int net_send(const union filedescriptor *fd, const unsigned char *buf, size_t len) { + LPVOID lpMsgBuf; + int rc; + + if(fd->ifd < 0) { + pmsg_notice("%s(): connection not open\n", __func__); + return -1; + } + + if(!len) + return 0; + + if(verbose >= MSG_TRACE) + trace_buffer(__func__, buf, len); + + while(len) { + rc = send(fd->ifd, (const char *) buf, len > 1024? 1024: len, 0); + if(rc < 0) { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("unable to send: %s\n", (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + buf += rc; + len -= rc; + } + + return 0; +} + +static int ser_send(const union filedescriptor *fd, const unsigned char *buf, size_t len) { + if(cx->ser_serial_over_ethernet) + return net_send(fd, buf, len); + + DWORD written; + + HANDLE hComPort = (HANDLE) fd->pfd; + + if(hComPort == INVALID_HANDLE_VALUE) { + pmsg_error("port not open\n"); + return -1; + } + + if(!len) + return 0; + + if(verbose >= MSG_TRACE) + trace_buffer(__func__, buf, len); + + serial_w32SetTimeOut(hComPort, 500); + + if(!WriteFile(hComPort, buf, len, &written, NULL)) { + pmsg_error("unable to write: %s\n", "sorry no info avail"); // TODO + return -1; + } + + if(written != len) { + pmsg_error("size/send mismatch\n"); + return -1; + } + + return 0; +} + +static int net_recv(const union filedescriptor *fd, unsigned char *buf, size_t buflen) { + LPVOID lpMsgBuf; + struct timeval timeout, to2; + fd_set rfds; + int nfds; + int rc; + unsigned char *p = buf; + size_t len = 0; + + if(fd->ifd < 0) { + pmsg_error("connection not open\n"); + return -1; + } + + timeout.tv_sec = serial_recv_timeout/1000L; + timeout.tv_usec = (serial_recv_timeout%1000L)*1000; + to2 = timeout; + + while(len < buflen) { + reselect: + FD_ZERO(&rfds); + FD_SET(fd->ifd, &rfds); + + nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2); + if(nfds == 0) { + pmsg_notice2("%s(): programmer is not responding\n", __func__); + return -1; + } else if(nfds == -1) { + if(WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) { + pmsg_notice("%s(): programmer is not responding, reselecting\n", __func__); + goto reselect; + } else { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("%s(): %s\n", __func__, (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + } + + rc = recv(fd->ifd, (char *) p, (buflen - len > 1024)? 1024: buflen - len, 0); + if(rc < 0) { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("unable to read: %s\n", (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + p += rc; + len += rc; + } + + if(verbose >= MSG_TRACE) + trace_buffer(__func__, buf, len); + + return 0; +} + +static int ser_recv(const union filedescriptor *fd, unsigned char *buf, size_t buflen) { + if(cx->ser_serial_over_ethernet) + return net_recv(fd, buf, buflen); + + DWORD read; + + HANDLE hComPort = (HANDLE) fd->pfd; + + if(hComPort == INVALID_HANDLE_VALUE) { + pmsg_error("port not open\n"); + return -1; + } + + serial_w32SetTimeOut(hComPort, serial_recv_timeout); + + if(!ReadFile(hComPort, buf, buflen, &read, NULL)) { + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("unable to read: %s\n", (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + + // Time out detected + if(read < buflen) { + pmsg_notice2("%s(): programmer is not responding\n", __func__); + return -1; + } + + if(verbose >= MSG_TRACE) + trace_buffer(__func__, buf, read); + + return 0; +} + +static int net_drain(const union filedescriptor *fd, int display) { + LPVOID lpMsgBuf; + struct timeval timeout; + fd_set rfds; + int nfds; + unsigned char buf; + int rc; + + if(fd->ifd < 0) { + pmsg_error("connection not open\n"); + return -1; + } + + if(display) { + msg_info("drain>"); + } + + timeout.tv_sec = 0; + timeout.tv_usec = serial_drain_timeout*1000L; + + while(1) { + FD_ZERO(&rfds); + FD_SET(fd->ifd, &rfds); + + reselect: + nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout); + if(nfds == 0) { + if(display) { + msg_info("ifd, (char *) &buf, 1, 0); + if(rc < 0) { + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("unable to read: %s\n", (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + + if(display) { + msg_info("%02x ", buf); + } + } + + return 0; +} + +static int ser_drain(const union filedescriptor *fd, int display) { + if(cx->ser_serial_over_ethernet) + return net_drain(fd, display); + + unsigned char buf[10]; + BOOL readres; + DWORD read; + + HANDLE hComPort = (HANDLE) fd->pfd; + + if(hComPort == INVALID_HANDLE_VALUE) { + pmsg_error("port not open\n"); + return -1; + } + + serial_w32SetTimeOut(hComPort, serial_drain_timeout); + + if(display) { + msg_info("drain>"); + } + + while(1) { + readres = ReadFile(hComPort, buf, 1, &read, NULL); + if(!readres) { + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) & lpMsgBuf, 0, NULL); + pmsg_error("unable to read: %s\n", (char *) lpMsgBuf); + LocalFree(lpMsgBuf); + return -1; + } + + if(read) { // Data avail + if(display) + msg_info("%02x ", buf[0]); + } else { // No more data + if(display) + msg_info("