Source file: /~heha/hsn/bl/stm32flash.zip/src/serial_w32.cpp

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <ctype.h>

#include "port.h"

PortSerial::PortSerial(const port_options&ops)
:Port("serial_w32",F_BYTE|F_GVR_ETX|F_CMD_INIT|F_RETRY) {
	/* timeout in ms */
 COMMTIMEOUTS timeouts = {MAXDWORD, MAXDWORD, 500, 0, 500};
 char*devName;
	/* Fix the device name if required */
 if (strlen(ops.device) > 4 && ops.device[0] != '\\') {
  devName = new char[strlen(ops.device)+5];
  sprintf(devName, "\\\\.\\%s", ops.device);
 }else{
  devName = const_cast<char*>(ops.device);
 }
	/* Create file handle for port */
 fd = CreateFileA(devName, GENERIC_READ|GENERIC_WRITE,
			   0,		/* Exclusive access */
			   NULL,	/* No security */
			   OPEN_EXISTING,
			   0,		/* No overlap */
			   NULL);
 if (devName!=ops.device) delete[] devName;
 if (fd == INVALID_HANDLE_VALUE) {
  if (GetLastError() == ERROR_FILE_NOT_FOUND)
  fprintf(stderr, "File not found: %s\n", ops.device);
  fd=0;
 }
 SetupComm(fd, 4096, 4096);	// Set input and output buffer size
 SetCommTimeouts(fd, &timeouts);
 SetCommMask(fd, EV_ERR);	// Notify us of error events
	// DCBlength must be initialized before calling GetCommState
 oldtio.DCBlength = sizeof oldtio;
 GetCommState(fd, &oldtio);	// Retrieve port parameters
 newtio=oldtio;			// copy entire structure
 newtio.BaudRate = ops.baudRate;
 switch (ops.mode[0]) {
  case '5': newtio.ByteSize = 5; break;
  case '6': newtio.ByteSize = 6; break;
  case '7': newtio.ByteSize = 7; break;
  case '8': newtio.ByteSize = 8; break;
 }
 switch (ops.mode[1]) {
  case 'N':case 'n': newtio.Parity = NOPARITY;   break;
  case 'E':case 'e': newtio.Parity = EVENPARITY; break;
  case 'O':case 'o': newtio.Parity = ODDPARITY;  break;
 }
 switch (ops.mode[2]) {
  case '1': newtio.StopBits = ONESTOPBIT; break;
  case '2': newtio.StopBits = TWOSTOPBITS; break;
 }
	// reset all other settings
 newtio.fOutxCtsFlow = FALSE;
 newtio.fOutxDsrFlow = FALSE;
 newtio.fDtrControl = DTR_CONTROL_DISABLE;
 newtio.fDsrSensitivity = FALSE;
 newtio.fTXContinueOnXoff = FALSE;
 newtio.fOutX = FALSE;
 newtio.fInX = FALSE;
 newtio.fErrorChar = FALSE;
 newtio.fNull = FALSE;
 newtio.fRtsControl = RTS_CONTROL_DISABLE;
 newtio.fAbortOnError = FALSE;
 flush();
 if (!SetCommState(fd, &newtio)) return;
 _snprintf(setup_str, sizeof setup_str, "%s %u %s",ops.device,ops.baudRate,ops.mode);
}

PortSerial::~PortSerial() {
 flush();
 SetCommState(fd, &oldtio);
 CloseHandle(fd);
}


Port::err_t PortSerial::read(void *buf, size_t nbyte) const{
 DWORD r;
 uint8_t*pos = reinterpret_cast<uint8_t*>(buf);
 while (nbyte) {
  ReadFile(fd, pos, DWORD(nbyte), &r, NULL);
  if (!r) return ERR_TIMEDOUT;
  nbyte -= r;
  pos += r;
 }
 return OK;
}

Port::err_t PortSerial::write(const void *buf, size_t nbyte) const{
 DWORD r;
 const uint8_t *pos = reinterpret_cast<const uint8_t*>(buf);
 while (nbyte) {
  if (!WriteFile(fd, pos, DWORD(nbyte), &r, NULL)) return ERR_UNKNOWN;
  if (r < 1) return ERR_UNKNOWN;
  nbyte -= r;
  pos += r;
 }
 return OK;
}

Port::err_t PortSerial::gpio(serial_gpio_t n, bool level) const{
 int bit;
 switch (n) {
  case GPIO_RTS: bit = level ? SETRTS : CLRRTS; break;
  case GPIO_DTR: bit = level ? SETDTR : CLRDTR; break;
  case GPIO_BRK: if (!level) return OK;
  if (!EscapeCommFunction(fd, SETBREAK)) return ERR_UNKNOWN;
  Sleep(500);
  if (!EscapeCommFunction(fd, CLRBREAK)) return ERR_UNKNOWN;
  return OK;
  default: return ERR_UNKNOWN;
 }
 return EscapeCommFunction(fd, bit) ? OK : ERR_UNKNOWN;	// handle RTS/DTR
}

Port*port_open(const port_options&ops) {
 Port*p=new PortSerial(ops);
 if (*p) return p;
 delete p;
#ifdef __linux__
 p=new PortI2c(ops);
 if (*p) return p;
 delete p;
#endif
 return 0;
}

#ifdef _WIN32
#include <setupapi.h>
#include <devguid.h>

static bool openable(const char*n) {
 char buf[16];
 _snprintf(buf,sizeof buf,"\\\\.\\%s",n);
 HANDLE h=CreateFileA(buf,0,0,0,OPEN_EXISTING,0,0);
 if (h!=INVALID_HANDLE_VALUE) CloseHandle(h);
 return h!=INVALID_HANDLE_VALUE;
}

const char*Port::find_com(int n) {
 ++n;
 HANDLE devs=SetupDiGetClassDevs((LPGUID)&GUID_DEVCLASS_PORTS,0,0,DIGCF_PRESENT);
 if (devs==INVALID_HANDLE_VALUE) return 0;
 SP_DEVINFO_DATA devInfo;
 devInfo.cbSize=sizeof devInfo;
 char*s=new char[16];
 for (DWORD i=0; SetupDiEnumDeviceInfo(devs,i,&devInfo); i++) {
  HKEY hKey;	// No idea how to skip directly over deactivated COM ports
  if ((hKey=SetupDiOpenDevRegKey(devs,&devInfo,DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ))
     ==INVALID_HANDLE_VALUE) continue;
  DWORD len=16;
  *s=0;
  RegQueryValueExA(hKey,"PortName",0,0,(LPBYTE)s,&len);
  RegCloseKey(hKey);
  if (*s=='C' && openable(s) && !--n) break;	// Fehlschläge und LPTx ausfiltern
  *s=0;
 }
 SetupDiDestroyDeviceInfoList(devs);
 if (!*s) {delete s; return 0;}
 return s;
}

#endif
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded