Beispiel #1
1
BOOL is_port_available(int nPort)
{
  TCHAR szPort[15];
  COMMCONFIG cc;
  DWORD dwCCSize;

  sprintf(szPort, "COM%d", nPort);

  // Check if this port is available
  dwCCSize = sizeof(cc);
  return GetDefaultCommConfig(szPort, &cc, &dwCCSize);
}
Beispiel #2
0
// This function searches through com ports 1 to 128 and determines if they
// exist or not. The list of existing ports is sent as a response.
std::vector<string> GetComPorts()
{
	vector<string> ports;
	int index = 1;
	// Go through each possible port (assuming no more than 64 ports on a system)
	for (int i = 1; i <= 64; ++i)    
    {
		char* buffer = new char[8];
		string port = "COM";
		port += itoa(i, buffer, 10);
		
		// First get the size
		DWORD dwSize = 0;
		LPCOMMCONFIG lpCC = (LPCOMMCONFIG) new BYTE[1];
		BOOL ret = GetDefaultCommConfig(port.c_str(), lpCC, &dwSize);
		delete [] lpCC;	

		// Now test the port
		lpCC = (LPCOMMCONFIG) new BYTE[dwSize];
		ret = GetDefaultCommConfig(port.c_str(), lpCC, &dwSize);
		
		// If the port exists, add to the vector
		if (ret != null)
		{
			string pusher = itoa(index++, buffer, 10);
			pusher += ". ";
			pusher += port;
			ports.push_back(pusher);
		}

		delete[] buffer;
		delete [] lpCC;
    }
	return ports;
}
Beispiel #3
0
BOOL CEnumerateSerial::UsingGetDefaultCommConfig(CSimpleArray<UINT>& ports)
#endif
{
  //Make sure we clear out any elements which may already be in the array
#if defined CENUMERATESERIAL_USE_STL
  ports.clear();
#else
  ports.RemoveAll();
#endif  

  //Up to 255 COM ports are supported so we iterate through all of them seeing
  //if we can get the default configuration
  for (UINT i=1; i<256; i++)
  {
    //Form the Raw device name
    CString sPort;
    sPort.Format(_T("COM%u"), i);

    COMMCONFIG cc;
    DWORD dwSize = sizeof(COMMCONFIG);
    if (GetDefaultCommConfig(sPort, &cc, &dwSize))
    {
    #if defined CENUMERATESERIAL_USE_STL
      ports.push_back(i);
    #else
      ports.Add(i);
    #endif  
    }
  }

  //Return the success indicator
  return TRUE;
}
PortNameList SerialEnumeratorWindows::listPorts()
{


	PortNameList retList;
    char comBufName[7];
    DWORD size;

	for (int i = 1; i < 256; i++)
	{

		// allocate and reset
	    COMMCONFIG CommConfig;
	    size = sizeof CommConfig;


		snprintf(comBufName, COMBUFSIZE, "COM%d", i);
		if (GetDefaultCommConfig( comBufName, &CommConfig, &size)
		           || size > sizeof CommConfig)
		{
			PortName nameStr(comBufName, COMBUFSIZE);
			retList.push_back(nameStr);
		}
	}
	return retList;

}
void CSerialPort::GetDefaultConfig(int nPort, COMMCONFIG& config)
{
  //Validate our parameters
  ASSERT(nPort>0 && nPort<=255);

  //Create the device name as a string
  CString sPort;
  sPort.Format(_T("COM%d"), nPort);

  DWORD dwSize = sizeof(COMMCONFIG);
  if (!GetDefaultCommConfig(sPort, &config, &dwSize))
  {
    TRACE(_T("Failed in call to GetDefaultCommConfig\n"));
    AfxThrowSerialException();
  }
}
Beispiel #6
0
bool setCommConfiguration(const char* device, RssconwindowsPortdata* pdata, DCB* port) {
	COMMCONFIG commConfig = {0};
	DWORD dwSize = sizeof(commConfig);
	commConfig.dwSize = dwSize;
	if (!GetDefaultCommConfig(device, &commConfig, &dwSize)) {
		fputs("Failed to get default port settings.\n", stderr);
		pdata->lastError = GetLastError();
		return false;
	}
	if (!SetCommConfig(pdata->portHandle, &commConfig, dwSize)) {
		fputs("Failed to set default port settings.\n", stderr);
		pdata->lastError = GetLastError();
		return false;
	}
	return true;
}
QVector<QString> SerialConnection::enumerate() {
    QVector<QString> ports;
#ifdef _WIN32
    COMMCONFIG cc;
    DWORD dwSize = sizeof(COMMCONFIG);
    for (size_t i=1; i<20; i++)
    {
        QString szPort = QString("COM%1").arg(QString::number(i));
        if (GetDefaultCommConfig(szPort.toStdWString().c_str(), &cc, &dwSize))
            ports.push_back(szPort);
    }
#else
    QDir dir("/dev");
    QStringList filters;
    filters << "ttyUSB*" << "ttyACM*" << "tty.usb*";// << "cu.usb*";
    dir.setFilter(QDir::Files|QDir::System);
    dir.setNameFilters(filters);

    QFileInfoList list = dir.entryInfoList();
    for (int i = 0; i < list.size(); ++i)
        ports.push_back(list.at(i).absoluteFilePath());
#endif
    return ports;
}
Beispiel #8
0
std::vector<std::string> GetSerialPorts(bool &bUseDirectPath)
{
	bUseDirectPath=false;

	std::vector<std::string> ret;
#if defined WIN32
	//windows

	std::vector<int> ports;
	std::vector<std::string> friendlyNames;
	char szPortName[40];

	EnumSerialFromWMI(ports, friendlyNames);

	bool bFoundPort = false;
	if (!ports.empty())
	{
		bFoundPort = true;
		std::vector<int>::const_iterator itt;
		for (itt = ports.begin(); itt != ports.end(); ++itt)
		{
			sprintf(szPortName, "COM%d", *itt);
			ret.push_back(szPortName);
		}
	}

	if (bFoundPort)
		return ret;

	//Scan old fashion way (SLOW!)
	COMMCONFIG cc;
	DWORD dwSize = sizeof(COMMCONFIG);
	for (int ii = 0; ii < 256; ii++)
	{
		sprintf(szPortName, "COM%d", ii);
		if (GetDefaultCommConfig(szPortName, &cc, &dwSize))
		{
			bFoundPort = true;
			sprintf(szPortName, "COM%d", ii);

			//Check if we did not already have it
			std::vector<std::string>::const_iterator itt;
			bool bFound = false;
			for (itt = ret.begin(); itt != ret.end(); ++itt)
			{
				if (*itt == szPortName)
				{
					bFound = true;
					break;
				}
			}
			if (!bFound)
				ret.push_back(szPortName); // add port
		}
	}
	// Method 2: CreateFile, slow
	// ---------
	if (!bFoundPort) {
		for (int ii = 0; ii < 256; ii++)
		{
			sprintf(szPortName, "\\\\.\\COM%d", ii);
			bool bSuccess = false;
			HANDLE hPort = ::CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
			if (hPort == INVALID_HANDLE_VALUE) {
				DWORD dwError = GetLastError();
				//Check to see if the error was because some other app had the port open
				if (dwError == ERROR_ACCESS_DENIED)
					bSuccess = TRUE;
			}
			else {
				//The port was opened successfully
				bSuccess = TRUE;
				//Don't forget to close the port, since we are going to do nothing with it anyway
				CloseHandle(hPort);
			}
			if (bSuccess) {
				bFoundPort = true;
				sprintf(szPortName, "COM%d", ii);
				ret.push_back(szPortName); // add port
			}
			// --------------            
		}
	}
	// Method 3: EnumSerialPortsWindows, often fails
	// ---------
	if (!bFoundPort) {
		std::vector<SerialPortInfo> serialports;
		EnumSerialPortsWindows(serialports);
		if (!serialports.empty())
		{
			std::vector<SerialPortInfo>::const_iterator itt;
			for (itt = serialports.begin(); itt != serialports.end(); ++itt)
			{
				ret.push_back(itt->szPortName); // add port
			}
		}
	}

#else
	//scan /dev for /dev/ttyUSB* or /dev/ttyS* or /dev/tty.usbserial* or /dev/ttyAMA*

	bool bHaveTtyAMAfree=false;
	std::string sLine = "";
	std::ifstream infile;

	infile.open("/boot/cmdline.txt");
	if (infile.is_open())
	{
		if (!infile.eof())
		{
			getline(infile, sLine);
			bHaveTtyAMAfree=(sLine.find("ttyAMA0")==std::string::npos);
		}
	}

	DIR *d=NULL;
	d=opendir("/dev");
	if (d != NULL)
	{
		struct dirent *de=NULL;
		// Loop while not NULL
		while ((de = readdir(d)))
		{
			std::string fname = de->d_name;
			if (fname.find("ttyUSB")!=std::string::npos)
			{
				ret.push_back("/dev/" + fname);
			}
			else if (fname.find("tty.usbserial")!=std::string::npos)
			{
				bUseDirectPath=true;
				ret.push_back("/dev/" + fname);
			}
			else if (fname.find("ttyACM")!=std::string::npos)
			{
				bUseDirectPath=true;
				ret.push_back("/dev/" + fname);
			}
#ifdef __FreeBSD__            
			else if (fname.find("ttyU")!=std::string::npos)
			{
				bUseDirectPath=true;
				ret.push_back("/dev/" + fname);
			}
#endif
#ifdef __APPLE__
			else if (fname.find("cu.")!=std::string::npos)
			{
				bUseDirectPath=true;
				ret.push_back("/dev/" + fname);
			}
#endif
			if (bHaveTtyAMAfree)
			{
				if (fname.find("ttyAMA0")!=std::string::npos)
				{
					ret.push_back("/dev/" + fname);
					bUseDirectPath=true;
				}
			}
		}
		closedir(d);
	}
	//also scan in /dev/usb
	d=opendir("/dev/usb");
	if (d != NULL)
	{
		struct dirent *de=NULL;
		// Loop while not NULL
		while ((de = readdir(d)))
		{
			std::string fname = de->d_name;
			if (fname.find("ttyUSB")!=std::string::npos)
			{
				bUseDirectPath=true;
				ret.push_back("/dev/usb/" + fname);
			}
		}
		closedir(d);
	}

#endif
	return ret;
}
Beispiel #9
0
// Open a port, by name.  Return 0 on success, non-zero for error
int Serial::Open(const wxString& name)
{
	Close();
#if defined(LINUX)
	struct serial_struct kernel_serial_settings;
	int bits;
	port_fd = open(name.mb_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (port_fd < 0) {
		if (errno == EACCES) {
		  error_msg = _("Unable to access ") + wxString(name,wxConvUTF8) + _(", insufficient permission");
			// TODO: we could look at the permission bits and owner
			// to make a better message here
		} else if (errno == EISDIR) {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", Object is a directory, not a serial port");
		} else if (errno == ENODEV || errno == ENXIO) {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", Serial port hardware not installed");
		} else if (errno == ENOENT) {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", Device name does not exist");
		} else {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", ") + wxString(strerror(errno),wxConvUTF8);
		}
		return -1;
	}
	if (ioctl(port_fd, TIOCMGET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to query serial port signals");
		return -1;
	}
	bits &= ~(TIOCM_DTR | TIOCM_RTS);
	if (ioctl(port_fd, TIOCMSET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to control serial port signals");
		return -1;
	}
	if (tcgetattr(port_fd, &settings_orig) != 0) {
		close(port_fd);
		error_msg = _("Unable to query serial port settings (perhaps not a serial port)");
		return -1;
	}
	memset(&settings, 0, sizeof(settings));
	settings.c_iflag = IGNBRK | IGNPAR;
	settings.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
	Set_baud(baud_rate);
	if (ioctl(port_fd, TIOCGSERIAL, &kernel_serial_settings) == 0) {
		kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
		ioctl(port_fd, TIOCSSERIAL, &kernel_serial_settings);
	}
	tcflush(port_fd, TCIFLUSH);
#elif defined(MACOSX)
	int bits;
	port_fd = open(name.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (port_fd < 0) {
	  error_msg = _("Unable to open ") + name + _(", ") + strerror(errno);
		return -1;
	}
	if (ioctl(port_fd, TIOCEXCL) == -1) {
		close(port_fd);
		error_msg = _("Unable to get exclussive access to port ") + name;
		return -1;
	}
	if (ioctl(port_fd, TIOCMGET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to query serial port signals on ") + name;
		return -1;
	}
	bits &= ~(TIOCM_DTR | TIOCM_RTS);
	if (ioctl(port_fd, TIOCMSET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to control serial port signals on ") + name;
		return -1;
	}
	if (tcgetattr(port_fd, &settings_orig) < 0) {
		close(port_fd);
		error_msg = _("Unable to access baud rate on port ") + name;
		return -1;
	}
	memset(&settings, 0, sizeof(settings));
	settings.c_cflag = CS8 | CLOCAL | CREAD | HUPCL;
	settings.c_iflag = IGNBRK | IGNPAR;
	Set_baud(baud_rate);
	tcflush(port_fd, TCIFLUSH);
#elif defined(WINDOWS)
	COMMCONFIG cfg;
	COMMTIMEOUTS timeouts;
	int got_default_cfg=0, port_num;
	char buf[1024], name_createfile[64], name_commconfig[64], *p;
	DWORD len;

	snprintf(buf, sizeof(buf), _("%s"), name.c_str());
	p = strstr(buf, _("COM"));
	if (p && sscanf(p + 3, _("%d"), &port_num) == 1) {
	  printf(_("port_num = %d\n"), port_num);
	  snprintf(name_createfile, sizeof(name_createfile), _("\\\\.\\COM%d"), port_num);
	  snprintf(name_commconfig, sizeof(name_commconfig), _("COM%d"), port_num);
	} else {
	  snprintf(name_createfile, sizeof(name_createfile), _("%s"), name.c_str());
	  snprintf(name_commconfig, sizeof(name_commconfig), _("%s"), name.c_str());
	}
	len = sizeof(COMMCONFIG);
	if (GetDefaultCommConfig(name_commconfig, &cfg, &len)) {
		// this prevents unintentionally raising DTR when opening
		// might only work on COM1 to COM9
		got_default_cfg = 1;
		memcpy(&port_cfg_orig, &cfg, sizeof(COMMCONFIG));
		cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
		cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
		SetDefaultCommConfig(name_commconfig, &cfg, sizeof(COMMCONFIG));
	} else {
	  printf(_("error with GetDefaultCommConfig\n"));
	}
	port_handle = CreateFile(name_createfile, GENERIC_READ | GENERIC_WRITE,
	   0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (port_handle == INVALID_HANDLE_VALUE) {
		win32_err(buf);
		error_msg =  _("Unable to open ") + name + _(", ") + buf;
		return -1;
	}
	len = sizeof(COMMCONFIG);
	if (!GetCommConfig(port_handle, &port_cfg, &len)) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to read communication config on ") + name + _(", ") + buf;
		return -1;
	}
	if (!got_default_cfg) {
		memcpy(&port_cfg_orig, &port_cfg, sizeof(COMMCONFIG));
	}
	// http://msdn2.microsoft.com/en-us/library/aa363188(VS.85).aspx
	port_cfg.dcb.BaudRate = baud_rate;
	port_cfg.dcb.fBinary = TRUE;
	port_cfg.dcb.fParity = FALSE;
	port_cfg.dcb.fOutxCtsFlow = FALSE;
	port_cfg.dcb.fOutxDsrFlow = FALSE;
	port_cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
	port_cfg.dcb.fDsrSensitivity = FALSE;
	port_cfg.dcb.fTXContinueOnXoff = TRUE;	// ???
	port_cfg.dcb.fOutX = FALSE;
	port_cfg.dcb.fInX = FALSE;
	port_cfg.dcb.fErrorChar = FALSE;
	port_cfg.dcb.fNull = FALSE;
	port_cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
	port_cfg.dcb.fAbortOnError = FALSE;
	port_cfg.dcb.ByteSize = 8;
	port_cfg.dcb.Parity = NOPARITY;
	port_cfg.dcb.StopBits = ONESTOPBIT;
	if (!SetCommConfig(port_handle, &port_cfg, sizeof(COMMCONFIG))) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to write communication config to ") + name + _(", ") + buf;
		return -1;
	}
	if (!EscapeCommFunction(port_handle, CLRDTR | CLRRTS)) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to control serial port signals on ") + name + _(", ") + buf;
		return -1;
	}
	// http://msdn2.microsoft.com/en-us/library/aa363190(VS.85).aspx
	// setting to all zeros means timeouts are not used
	//timeouts.ReadIntervalTimeout		= 0;
	timeouts.ReadIntervalTimeout		= MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier	= 0;
	timeouts.ReadTotalTimeoutConstant	= 0;
	timeouts.WriteTotalTimeoutMultiplier	= 0;
	timeouts.WriteTotalTimeoutConstant	= 0;
	if (!SetCommTimeouts(port_handle, &timeouts)) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to write timeout settings to ") + name + _(", ") + buf;
		return -1;
	}
#endif
	port_name = name;
	port_is_open = 1;
	return 0;
}
Beispiel #10
0
// Return a list of all serial ports
wxArrayString Serial::port_list()
{
	wxArrayString list;
#if defined(LINUX)
	// This is ugly guessing, but Linux doesn't seem to provide anything else.
	// If there really is an API to discover serial devices on Linux, please
	// email [email protected] with the info.  Please?
	// The really BAD aspect is all ports get DTR raised briefly, because linux
	// has no way to open the port without raising DTR, and there isn't any way
	// to tell if the device file really represents hardware without opening it.
	// maybe sysfs or udev provides a useful API??
	DIR *dir;
	struct dirent *f;
	struct stat st;
	unsigned int i, len[NUM_DEVNAMES];
	char s[512];
	int fd, bits;
	termios mytios;

	dir = opendir("/dev/");
	if (dir == NULL) return list;
	for (i=0; i<NUM_DEVNAMES; i++) len[i] = strlen(devnames[i]);
	// Read all the filenames from the /dev directory...
	while ((f = readdir(dir)) != NULL) {
		// ignore everything that doesn't begin with "tty"
		if (strncmp(f->d_name, "tty", 3)) continue;
		// ignore anything that's not a known serial device name
		for (i=0; i<NUM_DEVNAMES; i++) {
			if (!strncmp(f->d_name + 3, devnames[i], len[i])) break;
		}
		if (i >= NUM_DEVNAMES) continue;
		snprintf(s, sizeof(s), "/dev/%s", f->d_name);
		// check if it's a character type device (almost certainly is)
		if (stat(s, &st) != 0 || !(st.st_mode & S_IFCHR)) continue;
		// now see if we can open the file - if the device file is
		// populating /dev but doesn't actually represent a loaded
		// driver, this is where we will detect it.
		fd = open(s, O_RDONLY | O_NOCTTY | O_NONBLOCK);
		if (fd < 0) {
			// if permission denied, give benefit of the doubt
			// (otherwise the port will be invisible to the user
			// and we won't have a to alert them to the permssion
			// problem)
		  if (errno == EACCES) list.Add(wxString(s,wxConvUTF8));
			// any other error, assume it's not a real device
			continue;
		}
		// does it respond to termios requests? (probably will since
		// the name began with tty).  Some devices where a single
		// driver exports multiple names will open but this is where
		// we can really tell if they work with real hardare.
		if (tcgetattr(fd, &mytios) != 0) {
			close(fd);
			continue;
		}
		// does it respond to reading the control signals?  If it's
		// some sort of non-serial terminal (eg, pseudo terminals)
		// this is where we will detect it's not really a serial port
		if (ioctl(fd, TIOCMGET, &bits) < 0) {
			close(fd);
			continue;
		}
		// it passed all the tests, it's a serial port, or some sort
		// of "terminal" that looks exactly like a real serial port!
		close(fd);
		// unfortunately, Linux always raises DTR when open is called.
		// not nice!  Every serial port is going to get DTR raised
		// and then lowered.  I wish there were a way to prevent this,
		// but it seems impossible.
		list.Add(wxString(s,wxConvUTF8));
	}
	closedir(dir);
#elif defined(MACOSX)
	// adapted from SerialPortSample.c, by Apple
	// http://developer.apple.com/samplecode/SerialPortSample/listing2.html
	// and also testserial.c, by Keyspan
	// http://www.keyspan.com/downloads-files/developer/macosx/KesypanTestSerial.c
	// www.rxtx.org, src/SerialImp.c seems to be based on Keyspan's testserial.c
	// neither keyspan nor rxtx properly release memory allocated.
	// more documentation at:
	// http://developer.apple.com/documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/chapter_2_section_6.html
	mach_port_t masterPort;
	CFMutableDictionaryRef classesToMatch;
	io_iterator_t serialPortIterator;
	if (IOMasterPort(NULL, &masterPort) != KERN_SUCCESS) return list;
	// a usb-serial adaptor is usually considered a "modem",
	// especially when it implements the CDC class spec
	classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
	if (!classesToMatch) return list;
	CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey),
	   CFSTR(kIOSerialBSDModemType));
	if (IOServiceGetMatchingServices(masterPort, classesToMatch,
	   &serialPortIterator) != KERN_SUCCESS) return list;
	macos_ports(&serialPortIterator, list);
	IOObjectRelease(serialPortIterator);
	// but it might be considered a "rs232 port", so repeat this
	// search for rs232 ports
	classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
	if (!classesToMatch) return list;
	CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey),
	   CFSTR(kIOSerialBSDRS232Type));
	if (IOServiceGetMatchingServices(masterPort, classesToMatch,
	   &serialPortIterator) != KERN_SUCCESS) return list;
	macos_ports(&serialPortIterator, list);
	IOObjectRelease(serialPortIterator);
#elif defined(WINDOWS)
	// http://msdn.microsoft.com/en-us/library/aa365461(VS.85).aspx
	// page with 7 ways - not all of them work!
	// http://www.naughter.com/enumser.html
	// may be possible to just query the windows registary
	// http://it.gps678.com/2/ca9c8631868fdd65.html
	// search in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
	// Vista has some special new way, vista-only
	// http://msdn2.microsoft.com/en-us/library/aa814070(VS.85).aspx
	char *buffer, *p;
	//DWORD size = QUERYDOSDEVICE_BUFFER_SIZE;
	DWORD ret;

	buffer = (char *)malloc(QUERYDOSDEVICE_BUFFER_SIZE);
	if (buffer == NULL) return list;
	memset(buffer, 0, QUERYDOSDEVICE_BUFFER_SIZE);
	ret = QueryDosDeviceA(NULL, buffer, QUERYDOSDEVICE_BUFFER_SIZE);
	if (ret) {
		printf("Detect Serial using QueryDosDeviceA: ");
		for (p = buffer; *p; p += strlen(p) + 1) {
			printf(":  %s", p);
			if (strncmp(p, "COM", 3)) continue;
			list.Add(wxString(p) + ":");
		}
	} else {
		char buf[1024];
		win32_err(buf);
		printf("QueryDosDeviceA failed, error \"%s\"\n", buf);
		printf("Detect Serial using brute force GetDefaultCommConfig probing: ");
		for (int i=1; i<=32; i++) {
			printf("try  %s", buf);
			COMMCONFIG cfg;
			DWORD len;
			snprintf(buf, sizeof(buf), "COM%d", i);
			if (GetDefaultCommConfig(buf, &cfg, &len)) {
				wxString name;
				name.Printf("COM%d:", i);
				list.Add(name);
				printf(":  %s", buf);
			}
		}
	}
	free(buffer);
#endif
	list.Sort();
	return list;
}
wxArrayString *EnumerateSerialPorts(void)
{
      wxArrayString *preturn = new wxArrayString;

#ifdef __WXGTK__

      //    Looking for user privilege openable devices in /dev

      wxString sdev;

      for(int idev=0 ; idev < 8 ; idev++)
      {
            sdev.Printf(_T("/dev/ttyS%1d"), idev);

            int fd = open(sdev.mb_str(), O_RDWR|O_NDELAY|O_NOCTTY);
            if(fd > 0)
            {
                  /*  add to the output array  */
                  preturn->Add(wxString(sdev));
                  close(fd);
            }
      }

      for(int idev=0 ; idev < 8 ; idev++)
      {
            sdev.Printf(_T("/dev/ttyUSB%1d"), idev);

            int fd = open(sdev.mb_str(), O_RDWR|O_NDELAY|O_NOCTTY);
            if(fd > 0)
            {
                  /*  add to the output array  */
                  preturn->Add(wxString(sdev));
                  close(fd);
            }
      }

      //    Looking for BlueTooth GPS devices
      for(int idev=0 ; idev < 8 ; idev++)
      {
             sdev.Printf(_T("/dev/rfcomm%1d"), idev);

             int fd = open(sdev.mb_str(), O_RDWR|O_NDELAY|O_NOCTTY);
             if(fd > 0)
             {
                    /*  add to the output array  */
                    preturn->Add(wxString(sdev));
                    close(fd);
             }
      }



      //    A Fallback position, in case udev has failed or something.....
      if(preturn->IsEmpty())
      {
            preturn->Add( _T("/dev/ttyS0"));
            preturn->Add( _T("/dev/ttyS1"));
            preturn->Add( _T("/dev/ttyUSB0"));
            preturn->Add( _T("/dev/ttyUSB1"));
      }


#endif




#ifdef PROBE_PORTS__WITH_HELPER

/*
*     For modern Linux/(Posix??) systems, we may use
*     the system files /proc/tty/driver/serial
*     and /proc/tty/driver/usbserial to identify
*     available serial ports.
*     A complicating factor is that most (all??) linux
*     systems require root privileges to access these files.
*     We will use a helper program method here, despite implied vulnerability.
*/

char buf[256]; // enough to hold one line from serial devices list
char left_digit;
char right_digit;
int port_num;
FILE *f;

      pid_t pID = vfork();

      if (pID == 0)                // child
      {
//    Temporarily gain root privileges
            seteuid(file_user_id);

//  Execute the helper program
            execlp("ocpnhelper", "ocpnhelper", "-SB", NULL);

//  Return to user privileges
            seteuid(user_user_id);

            wxLogMessage(_T("Warning: ocpnhelper failed...."));
            _exit(0); // If exec fails then exit forked process.
       }


       wait(NULL);                  // for the child to quit

//    Read and parse the files

/*
      * see if we have any traditional ttySx ports available
*/
      f = fopen("/var/tmp/serial", "r");

      if (f != NULL)
      {
            wxLogMessage(_T("Parsing copy of /proc/tty/driver/serial..."));

            /* read in each line of the file */
            while(fgets(buf, sizeof(buf), f) != NULL)
            {
                  wxString sm(buf, wxConvUTF8);
                  sm.Prepend(_T("   "));
                  sm.Replace(_T("\n"), _T(" "));
                  wxLogMessage(sm);

                  /* if the line doesn't start with a number get the next line */
                  if (buf[0] < '0' || buf[0] > '9')
                        continue;

      /*
                  * convert digits to an int
      */
                  left_digit = buf[0];
                  right_digit = buf[1];
                  if (right_digit < '0' || right_digit > '9')
                        port_num = left_digit - '0';
                  else
                        port_num = (left_digit - '0') * 10 + right_digit - '0';

                  /* skip if "unknown" in the string */
                  if (strstr(buf, "unknown") != NULL)
                        continue;

                  /* upper limit of 15 */
                  if (port_num > 15)
                        continue;

                  /* create string from port_num  */

                  wxString s;
                  s.Printf(_T("/dev/ttyS%d"), port_num);

                  /*  add to the output array  */
                  preturn->Add(wxString(s));

            }

            fclose(f);
      }


/*
      * Same for USB ports
*/
      f = fopen("/var/tmp/usbserial", "r");

      if (f != NULL)
      {
            wxLogMessage(_T("Parsing copy of /proc/tty/driver/usbserial..."));

            /* read in each line of the file */
            while(fgets(buf, sizeof(buf), f) != NULL)
            {

                  wxString sm(buf, wxConvUTF8);
                  sm.Prepend(_T("   "));
                  sm.Replace(_T("\n"), _T(" "));
                  wxLogMessage(sm);

                  /* if the line doesn't start with a number get the next line */
                  if (buf[0] < '0' || buf[0] > '9')
                        continue;

      /*
                  * convert digits to an int
      */
                  left_digit = buf[0];
                  right_digit = buf[1];
                  if (right_digit < '0' || right_digit > '9')
                        port_num = left_digit - '0';
                  else
                        port_num = (left_digit - '0') * 10 + right_digit - '0';

                  /* skip if "unknown" in the string */
                  if (strstr(buf, "unknown") != NULL)
                        continue;

                  /* upper limit of 15 */
                  if (port_num > 15)
                        continue;

                  /* create string from port_num  */

                  wxString s;
                  s.Printf(_T("/dev/ttyUSB%d"), port_num);

                  /*  add to the output array  */
                  preturn->Add(wxString(s));

            }

            fclose(f);
      }


      //    As a fallback, in case seteuid doesn't work....
      //    provide some defaults
      //    This is currently the case for GTK+, which
      //    refuses to run suid.  sigh...

      if(preturn->IsEmpty())
      {
            preturn->Add( _T("/dev/ttyS0"));
            preturn->Add( _T("/dev/ttyS1"));
            preturn->Add( _T("/dev/ttyUSB0"));
            preturn->Add( _T("/dev/ttyUSB1"));
      }

//    Clean up the temporary files created by helper.
      pid_t cpID = vfork();

      if (cpID == 0)                // child
      {
//    Temporarily gain root privileges
            seteuid(file_user_id);

//  Execute the helper program
            execlp("ocpnhelper", "ocpnhelper", "-U", NULL);

//  Return to user privileges
            seteuid(user_user_id);
            _exit(0); // If exec fails then exit forked process.
      }

#endif      // __WXGTK__

#ifdef __WXOSX__
#include "macutils.h"
      char* paPortNames[MAX_SERIAL_PORTS] ;
      int iPortNameCount ;

      memset(paPortNames,0x00,sizeof(paPortNames)) ;
      iPortNameCount = FindSerialPortNames(&paPortNames[0],MAX_SERIAL_PORTS) ;
      for (int iPortIndex=0 ; iPortIndex<iPortNameCount ; iPortIndex++)
      {
            wxString sm(paPortNames[iPortIndex], wxConvUTF8);
            preturn->Add(sm);
            free(paPortNames[iPortIndex]) ;
      }
#endif      //__WXOSX__


#ifdef __WXMSW__
/*************************************************************************
 * Windows provides no system level enumeration of available serial ports
 * There are several ways of doing this.
 *
 *************************************************************************/

#include <windows.h>



      //    Method 1:  Use GetDefaultCommConfig()
      // Try first {g_nCOMPortCheck} possible COM ports, check for a default configuration
      for (int i=1; i<g_nCOMPortCheck; i++)
      {
            wxString s;
            s.Printf(_T("COM%d"), i);

            COMMCONFIG cc;
            DWORD dwSize = sizeof(COMMCONFIG);
            if (GetDefaultCommConfig(s.fn_str(), &cc, &dwSize))
                  preturn->Add(wxString(s));
      }


#if 0
      // Method 2:  Use FileOpen()
      // Try all 255 possible COM ports, check to see if it can be opened, or if
      // not, that an expected error is returned.

      BOOL bFound;
      for (int j=1; j<256; j++)
{
      char s[20];
      sprintf(s, "\\\\.\\COM%d", j);

          // Open the port tentatively
      BOOL bSuccess = FALSE;
      HANDLE hComm = ::CreateFile(s, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);

            //  Check for the error returns that indicate a port is there, but not currently useable
      if (hComm == INVALID_HANDLE_VALUE)
      {
            DWORD dwError = GetLastError();

            if (dwError == ERROR_ACCESS_DENIED ||
                dwError == ERROR_GEN_FAILURE ||
                dwError == ERROR_SHARING_VIOLATION ||
                dwError == ERROR_SEM_TIMEOUT)
                  bFound = TRUE;
      }
      else
      {
            bFound = TRUE;
            CloseHandle(hComm);
      }

      if (bFound)
            preturn->Add(wxString(s));
}
#endif

//    Search for Garmin device driver on Windows platforms

      HDEVINFO hdeviceinfo = INVALID_HANDLE_VALUE;


      hdeviceinfo = SetupDiGetClassDevs( (GUID *) &GARMIN_DETECT_GUID,
                                                      NULL, NULL,
                                                      DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);

      if (hdeviceinfo != INVALID_HANDLE_VALUE)
      {
            wxLogMessage(_T("EnumerateSerialPorts() Found Garmin USB Driver."));
            preturn->Add(_T("GARMIN"));         // Add generic Garmin selectable device
            g_bGarminPersistance = true;        // And record the existance
      }

#if 0
    SP_DEVICE_INTERFACE_DATA deviceinterface;
    deviceinterface.cbSize = sizeof(deviceinterface);

    if (SetupDiEnumDeviceInterfaces(hdeviceinfo,
                                                      NULL,
                                                      (GUID *) &GARMIN_DETECT_GUID,
                                                      0,
                                                      &deviceinterface))
      {
            wxLogMessage(_T("Found Garmin Device."));

            preturn->Add(_T("GARMIN"));         // Add generic Garmin selectable device
            g_bGarminPersistance = true;        // And record the existance

      }
#endif

#endif      //__WXMSW__

      return preturn;
}
int _init_uart(char* nm, char* speed)
{
	char fullNm[20];
	DCB dcb;
	DWORD dwErr;
	COMMTIMEOUTS tmo;
	COMSTAT comStat;
	COMMCONFIG ccfg;
	DWORD ccfgLen;
	int portNum = 0;
	char* scannm;
	char* shownm;
	char modemode;

	// skip COM if specified and scan number and mode (optional)
	scannm = strnicmp(nm, "COM", 3) ? nm : nm+3;
	sscanf(scannm, "%i%c%c", &portNum, &modemode, &serial_mode);

	if (modemode == '!')
		defaultyes = 1;	// omit Yes/No before programming
	
	// port number specified ?
	if(portNum)
	{
		sprintf(fullNm, "\\\\.\\COM%d", portNum);
		nm = fullNm;
	}

	// name to show in error messages
	shownm = nm;
	// do not show backslashes in error message
	if(!strncmp(shownm, "\\\\.\\", 4))
		shownm += 4;

	// try not to make pulse on DTR line during open
	ccfgLen = sizeof(ccfg);
	if(GetDefaultCommConfig(shownm, &ccfg, &ccfgLen))
	{
		ccfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
		if(!SetDefaultCommConfig(shownm, &ccfg, ccfgLen))
			fprintf(logfile,  "Warning: can not preset default comm config (%s)\n", shownm);
	}
	//else
		//fprintf(logfile,  "Warning: can not get default comm config (%s)\n", shownm);

	// open port
	port = CreateFile(nm, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
						 	    FILE_ATTRIBUTE_NORMAL, NULL);

	if(port == INVALID_HANDLE_VALUE) 
	{
		//fprintf(logfile,  "Can't open serial port %s\n", shownm);
		return -1;
	}

	// init queues
	PurgeComm(port, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

	// prepare DCB
	dcb.DCBlength = sizeof(dcb);		// sizeof(DCB) 
	dcb.BaudRate = CBR_9600;			// current baud rate 
	dcb.fBinary = TRUE;					// binary mode, no EOF check 
	dcb.fParity = FALSE;				// disable parity checking 
	dcb.fOutxCtsFlow = FALSE;			// CTS output flow control 
	dcb.fOutxDsrFlow = FALSE;			// DSR output flow control 
	dcb.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type 
	dcb.fDsrSensitivity = FALSE;		// DSR sensitivity 
	dcb.fTXContinueOnXoff = FALSE;		// XOFF continues Tx 
	dcb.fOutX = FALSE;					// XON/XOFF out flow control 
	dcb.fInX = FALSE;					// XON/XOFF in flow control 
	dcb.fErrorChar = FALSE;				// enable error replacement 
	dcb.fNull = FALSE;					// enable null stripping 
	dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control 
	dcb.fAbortOnError = FALSE;			// abort reads/writes on error 
	dcb.XonLim = 100;					// transmit XON threshold 
	dcb.XoffLim = 100;					// transmit XOFF threshold 
	dcb.ByteSize = 8;					// number of bits/, 4-8 
	dcb.Parity = NOPARITY;				// 0-4=no,odd,even,mark,space 
	dcb.StopBits = ONESTOPBIT;			// 0,1,2 = 1, 1.5, 2 
	dcb.XonChar = 17;					// Tx and Rx XON acter 
	dcb.XoffChar = 19;					// Tx and Rx XOFF acter 
	dcb.ErrorChar = 0;					// error replacement acter 
	dcb.EofChar = 0;					// end of input acter 
	dcb.EvtChar = 0;					// received event acter 

	// speed string specified ?
	if(speed)
	{
		if(sscanf(speed, "%lu", &dcb.BaudRate) != 1)
		{
			fprintf(logfile,  "Invalid speed specified (%s)\n", speed);
			return -1;
		}
	}

	if(!SetCommState(port, &dcb))
	{
		fprintf(logfile,  "Can't setup serial port (%s @ %s)\n", shownm, speed);
		return -1;
	}

	if(!SetupComm(port, 512, 512))
	{
		fprintf(logfile,  "Can't setup serial port queues.\n");
		return -1;
	}

	tmo.ReadIntervalTimeout = 100;		// between two characters
	tmo.ReadTotalTimeoutMultiplier = 1;
	tmo.ReadTotalTimeoutConstant = 500;
	tmo.WriteTotalTimeoutMultiplier = 1;
	tmo.WriteTotalTimeoutConstant = 1000;

	if(!SetCommTimeouts(port, &tmo))
	{
		fprintf(logfile,  "Can't set serial port timeouts (%s)\n", shownm);
		return -1;
	}
	if(!SetCommMask(port, EV_TXEMPTY))
	{
		fprintf(logfile,  "Can't set serial port waitmask (%s)\n", shownm);
		return -1;
	}

	// we are ready !
	EscapeCommFunction(port, CLRDTR);
	ClearCommError(port, &dwErr, &comStat);
	return 1;
}
Beispiel #13
0
std::vector<std::string> GetSerialPorts(bool &bUseDirectPath)
{
    bUseDirectPath=false;

    std::vector<std::string> ret;
#if defined WIN32
    //windows
    COMMCONFIG cc;
    DWORD dwSize = sizeof(COMMCONFIG);

    char szPortName[40];
    for (int ii=0; ii<256; ii++)
    {
        sprintf(szPortName,"COM%d",ii);
        if (GetDefaultCommConfig(szPortName, &cc, &dwSize))
        {
            sprintf(szPortName,"COM%d",ii);
            ret.push_back(szPortName);
        }
    }
#else
    //scan /dev for /dev/ttyUSB* or /dev/ttyS* or /dev/tty.usbserial* or /dev/ttyAMA*

    bool bHaveTtyAMAfree=false;
    std::string sLine = "";
    std::ifstream infile;

    infile.open("/boot/cmdline.txt");
    if (infile.is_open())
    {
        if (!infile.eof())
        {
            getline(infile, sLine);
            bHaveTtyAMAfree=(sLine.find("ttyAMA0")==std::string::npos);
        }
    }

    DIR *d=NULL;
    d=opendir("/dev");
    if (d != NULL)
    {
        struct dirent *de=NULL;
        // Loop while not NULL
        while ((de = readdir(d)))
        {
            std::string fname = de->d_name;
            if (fname.find("ttyUSB")!=std::string::npos)
            {
                ret.push_back("/dev/" + fname);
            }
            if (fname.find("tty.usbserial")!=std::string::npos)
            {
                bUseDirectPath=true;
                ret.push_back("/dev/" + fname);
            }
            if (bHaveTtyAMAfree)
            {
                if (fname.find("ttyAMA0")!=std::string::npos)
                {
                    ret.push_back("/dev/" + fname);
                    bUseDirectPath=true;
                }
            }
        }
        closedir(d);
    }
    //also scan in /dev/usb
    d=opendir("/dev/usb");
    if (d != NULL)
    {
        struct dirent *de=NULL;
        // Loop while not NULL
        while ((de = readdir(d)))
        {
            std::string fname = de->d_name;
            if (fname.find("ttyUSB")!=std::string::npos)
            {
                bUseDirectPath=true;
                ret.push_back("/dev/usb/" + fname);
            }
        }
        closedir(d);
    }

#endif
    return ret;
}
    int ArduinoSerial::openPort(const char *portName)
    {


        _portName = std::string(portName);
        _portOpened = false;
        triedToConfigureAgain = false;
        closeSerial();
        fd = 0;
        _numberOfChannels = 1;
#if defined(__APPLE__) || defined(__linux__)
        struct termios options;

        fd = open(portName, O_RDWR | O_NOCTTY | O_NDELAY);//O_SHLOCK
        sleep(2);
        int bits;
#endif
#ifdef __APPLE__
        std::stringstream sstm;

        if (fd < 0) {
            sstm << "Unable to open " << portName << ", " << strerror(errno);
            errorString = sstm.str();
            std::cout<<"Unable to open "<<portName<<", "<<strerror(errno)<<"\n";
            return -1;
        }
        if (ioctl(fd, TIOCEXCL) == -1) {
            close(fd);
            sstm << "Unable to get exclussive access to port " << portName;;
            errorString = sstm.str();
            std::cout<<"Unable to get exclussive access to port "<<portName<<"\n";
            return -1;
        }
        if (ioctl(fd, TIOCMGET, &bits) < 0) {
            close(fd);
            sstm <<"Unable to query serial port signals on " << portName;
            errorString = sstm.str();
            std::cout<<"Unable to query serial port signals on "<<portName<<"\n";
            return -1;
        }
        bits &= ~(TIOCM_DTR | TIOCM_RTS);
        if (ioctl(fd, TIOCMSET, &bits) < 0) {
            close(fd);
            sstm <<"Unable to control serial port signals on " << portName;
            errorString = sstm.str();
            std::cout<<"Unable to control serial port signals on "<<portName<<"\n";
            return -1;
        }
        struct termios settings_orig;
        if (tcgetattr(fd, &settings_orig) < 0) {
            close(fd);
            sstm <<"Unable to access baud rate on port " << portName;
            errorString = sstm.str();
            std::cout<<"Unable to access baud rate on port "<<portName<<"\n";
            return -1;
        }
#endif
#ifdef __linux__
 // struct serial_struct kernel_serial_settings;
    struct termios settings_orig;
    //struct termios settings;
    if (fd < 0)
    {
        if (errno == EACCES)
        {
            std::cout<<"Unable to access "<< portName<< ", insufficient permission";
            // TODO: we could look at the permission bits and owner
            // to make a better message here
        }
        else if (errno == EISDIR)
        {
            std::cout<< "Unable to open " << portName <<
                     ", Object is a directory, not a serial port";
        }
        else if (errno == ENODEV || errno == ENXIO)
        {
            std::cout<< "Unable to open " << portName <<
                     ", Serial port hardware not installed";
        }
        else if (errno == ENOENT)
        {
            std::cout<< "Unable to open " << portName <<
                     ", Device name does not exist";
        }
        else
        {
            std::cout<< "Unable to open " << portName; //<<

        }
        return -1;
    }
    if (ioctl(fd, TIOCMGET, &bits) < 0)
    {
        close(fd);
        std::cout<< "Unable to query serial port signals";
        return -1;
    }
    bits &= ~(TIOCM_DTR | TIOCM_RTS);
    if (ioctl(fd, TIOCMSET, &bits) < 0)
    {
        close(fd);
        std::cout<< "Unable to control serial port signals";
        return -1;
    }
    if (tcgetattr(fd, &settings_orig) != 0)
    {
        close(fd);
        std::cout<< "Unable to query serial port settings (perhaps not a serial port)";
        return -1;
    }
    /*memset(&settings, 0, sizeof(settings));
    settings.c_iflag = IGNBRK | IGNPAR;
    settings.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
    Set_baud(baud_rate);
    if (ioctl(port_fd, TIOCGSERIAL, &kernel_serial_settings) == 0) {
    	kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
    	ioctl(port_fd, TIOCSSERIAL, &kernel_serial_settings);
    }
    tcflush(port_fd, TCIFLUSH);*/
#endif
#if defined(__APPLE__) || defined(__linux__)
        if (fd == -1)
        {
            std::cout<<"Can't open serial port\n";
            return -1;
        }
        fcntl(fd, F_SETFL, 0);    // clear all flags on descriptor, enable direct I/O
        tcgetattr(fd, &options);   // read serial port options
        // enable receiver, set 8 bit data, ignore control lines
        options.c_cflag |= (CLOCAL | CREAD | CS8);
        // disable parity generation and 2 stop bits
        options.c_cflag &= ~(PARENB | CSTOPB);

        //cfsetispeed(&options, B9600);
        //cfsetospeed(&options, B9600);

        cfsetispeed(&options, B230400);
        cfsetospeed(&options, B230400);

        // set the new port options
        tcsetattr(fd, TCSANOW, &options);
#endif

#ifdef _WIN32

	COMMCONFIG cfg;
	COMMTIMEOUTS timeouts;
	int got_default_cfg=0, port_num;
	char buf[1024], name_createfile[64], name_commconfig[64], *p;
	DWORD len;

	snprintf(buf, sizeof(buf), "%s", _portName.c_str());
	p = strstr(buf, "COM");
	if (p && sscanf(p + 3, "%d", &port_num) == 1) {
		printf("port_num = %d\n", port_num);
		snprintf(name_createfile, sizeof(name_createfile), "\\\\.\\COM%d", port_num);
		snprintf(name_commconfig, sizeof(name_commconfig), "COM%d", port_num);
	} else {
		snprintf(name_createfile, sizeof(name_createfile), "%s", _portName.c_str());
		snprintf(name_commconfig, sizeof(name_commconfig), "%s", _portName.c_str());
	}
	len = sizeof(COMMCONFIG);
	if (GetDefaultCommConfig(name_commconfig, &cfg, &len)) {
		// this prevents unintentionally raising DTR when opening
		// might only work on COM1 to COM9
		got_default_cfg = 1;
		memcpy(&port_cfg_orig, &cfg, sizeof(COMMCONFIG));
		cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
		cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
		SetDefaultCommConfig(name_commconfig, &cfg, sizeof(COMMCONFIG));
	} else {
		printf("error with GetDefaultCommConfig\n");
	}
	port_handle = CreateFile(name_createfile, GENERIC_READ | GENERIC_WRITE,
	   0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (port_handle == INVALID_HANDLE_VALUE) {
		win32_err(buf);
		//error_msg =  "Unable to open " + _portName + ", " + buf;
		return -1;
	}
	len = sizeof(COMMCONFIG);
	if (!GetCommConfig(port_handle, &port_cfg, &len)) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to read communication config on " + _portName + ", " + buf;
		return -1;
	}
	if (!got_default_cfg) {
		memcpy(&port_cfg_orig, &port_cfg, sizeof(COMMCONFIG));
	}
	// http://msdn2.microsoft.com/en-us/library/aa363188(VS.85).aspx
	port_cfg.dcb.BaudRate = 230400;
	port_cfg.dcb.fBinary = TRUE;
	port_cfg.dcb.fParity = FALSE;
	port_cfg.dcb.fOutxCtsFlow = FALSE;
	port_cfg.dcb.fOutxDsrFlow = FALSE;
	port_cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
	port_cfg.dcb.fDsrSensitivity = FALSE;
	port_cfg.dcb.fTXContinueOnXoff = TRUE;	// ???
	port_cfg.dcb.fOutX = FALSE;
	port_cfg.dcb.fInX = FALSE;
	port_cfg.dcb.fErrorChar = FALSE;
	port_cfg.dcb.fNull = FALSE;
	port_cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
	port_cfg.dcb.fAbortOnError = FALSE;
	port_cfg.dcb.ByteSize = 8;
	port_cfg.dcb.Parity = NOPARITY;
	port_cfg.dcb.StopBits = ONESTOPBIT;
	if (!SetCommConfig(port_handle, &port_cfg, sizeof(COMMCONFIG))) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to write communication config to " + name + ", " + buf;
		return -1;
	}
	if (!EscapeCommFunction(port_handle, CLRDTR | CLRRTS)) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to control serial port signals on " + name + ", " + buf;
		return -1;
	}
	// http://msdn2.microsoft.com/en-us/library/aa363190(VS.85).aspx
	// setting to all zeros means timeouts are not used
	//timeouts.ReadIntervalTimeout		= 0;
	timeouts.ReadIntervalTimeout		= MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier	= 0;
	timeouts.ReadTotalTimeoutConstant	= 0;
	timeouts.WriteTotalTimeoutMultiplier	= 0;
	timeouts.WriteTotalTimeoutConstant	= 0;
	if (!SetCommTimeouts(port_handle, &timeouts)) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to write timeout settings to " + name + ", " + buf;
		return -1;
	}

#endif // _WIN32

        circularBuffer[0] = '\n';

        cBufHead = 0;
        cBufTail = 0;

        serialCounter = 0;

        _portOpened = true;


        setNumberOfChannelsAndSamplingRate(1, maxSamplingRate());


        return fd;
    }
void ModelViewController::DetectComPorts(bool init)
{
	bool bDirty = init;
	vector<std::string> currentComports;

#ifdef WIN32
	int highestCom = 0;
	for(int i = 1; i <=9 ; i++ )
	{
	        TCHAR strPort[32] = {0};
	        _stprintf(strPort, _T("COM%d"), i);

	        DWORD dwSize = 0;
	        LPCOMMCONFIG lpCC = (LPCOMMCONFIG) new BYTE[1];
	        GetDefaultCommConfig(strPort, lpCC, &dwSize);
		int r = GetLastError();
	        delete [] lpCC;

	        lpCC = (LPCOMMCONFIG) new BYTE[dwSize];
	        GetDefaultCommConfig(strPort, lpCC, &dwSize);
	        delete [] lpCC;

		if( r != 87 )
		{
			ToolkitLock guard;

			highestCom = i;
			if( this ) // oups extremely ugly, should move this code to a static method and a callback
			{
				const_cast<Fl_Menu_Item*>(gui->portInput->menu())[i-1].activate();
				const_cast<Fl_Menu_Item*>(gui->portInputSimple->menu())[i-1].activate();
			}
		}
		else
		{
			ToolkitLock guard;

			if( this ) // oups extremely ugly, should move this code to a static method and a callback
			{
				const_cast<Fl_Menu_Item*>(gui->portInput->menu())[i-1].deactivate();
				const_cast<Fl_Menu_Item*>(gui->portInputSimple->menu())[i-1].deactivate();
			}
		}
	}
	currentComports.push_back(string("COM"+highestCom));

#elif defined(__APPLE__)
	const char *ttyPattern[] = {"tty.", NULL};

#else // Linux
	const char *ttyPattern[] = {"ttyUSB", "ttyACM", NULL};
#endif

#ifndef WIN32
	DIR *d = opendir ("/dev");
	if (d) { // failed
		struct	dirent *e;
		while ((e = readdir (d))) {
			//fprintf (stderr, "name '%s'\n", e->d_name);
			for (const char **ttyPidx = ttyPattern; *ttyPidx != NULL; ++ttyPidx) {
               			if (strstr(e->d_name,*ttyPidx)) {
               				string device = string("/dev/") + e->d_name;
					currentComports.push_back(device);
				}
 			}
		}
		closedir(d);

		if ( currentComports.size() != this->comports.size() )
			bDirty = true;
	}

	if ( bDirty && gui) {
		ToolkitLock guard;

		static Fl_Menu_Item emptyList[] = {
			{0,0,0,0,0,0,0,0,0}
		};

		bool bWasEmpty = !comports.size();

		gui->portInputSimple->menu(emptyList);
		gui->portInput->menu(emptyList);
		comports.clear();

		for (size_t indx = 0; indx < currentComports.size(); ++indx) {
			string menuLabel = string(currentComports[indx]);
			gui->portInput->add(strdup(menuLabel.c_str()));
			gui->portInputSimple->add(strdup(menuLabel.c_str()));
			comports.push_back(currentComports[indx]);
		}

		// auto-select a new com-port
		if (bWasEmpty && comports.size()) {
			ProcessControl.m_sPortName = ValidateComPort(comports[0]);
			CopySettingsToGUI();
		}
	}
#endif
}
Beispiel #16
0
int fb_SerialOpen( FB_FILE *handle,
                   int iPort, FB_SERIAL_OPTIONS *options,
                   const char *pszDevice, void **ppvHandle )
{
    DWORD dwDefaultTxBufferSize = 16384;
    DWORD dwDefaultRxBufferSize = 16384;
    DWORD dwDesiredAccess = 0;
    DWORD dwShareMode = 0;
    char *pszDev, *p;
    HANDLE hDevice;
    int res;

    /* The IRQ stuff is not supported on Windows ... */
    if( options->IRQNumber!=0 )
        return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL );

    res = fb_ErrorSetNum( FB_RTERROR_OK );

    switch( handle->access ) {
    case FB_FILE_ACCESS_READ:
        dwDesiredAccess = GENERIC_READ;
        break;
    case FB_FILE_ACCESS_WRITE:
        dwDesiredAccess = GENERIC_WRITE;
        break;
    case FB_FILE_ACCESS_READWRITE:
    case FB_FILE_ACCESS_ANY:
        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
        break;
    }

    switch( handle->lock ) {
    case FB_FILE_LOCK_SHARED:
        dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
        break;
    case FB_FILE_LOCK_READ:
        dwShareMode = FILE_SHARE_WRITE;
        break;
    case FB_FILE_LOCK_WRITE:
        dwShareMode = FILE_SHARE_READ;
        break;
    case FB_FILE_LOCK_READWRITE:
        break;
    }

    /* Get device name without ":" */
    pszDev = calloc(strlen( pszDevice ) + 5, 1);
		if( iPort == 0 )
		{
			iPort = 1;
			strcpy( pszDev, "COM1:" );
		}
		else
		{
			if( iPort > 9 )
				strcpy(pszDev, "\\\\.\\");
			else
				*pszDev = '\0';

			strcat(pszDev, pszDevice);
			p = strchr( pszDev, ':');
			if( p )
				*p = '\0';
		}

#if 0
    /* FIXME: Use default COM properties by default */
    COMMCONFIG cc;
    if( !GetDefaultCommConfig( pszDev, &cc, &dwSizeCC ) ) {
    }
#endif

    /* Open device */
    hDevice =
        CreateFileA( pszDev,
                     dwDesiredAccess,
                     dwShareMode,
                     NULL,
                     OPEN_EXISTING,
                     0,
                     NULL );

    free( pszDev );

    if( hDevice==INVALID_HANDLE_VALUE )
        return fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND );

    /* Set rx/tx buffer sizes */
    if( res==FB_RTERROR_OK ) {
        COMMPROP prop;
        if( !GetCommProperties( hDevice, &prop ) ) {
            res = fb_ErrorSetNum( FB_RTERROR_NOPRIVILEDGES );
        } else {
            if( prop.dwCurrentTxQueue ) {
                dwDefaultTxBufferSize = prop.dwCurrentTxQueue;
            } else if( prop.dwMaxTxQueue ) {
                dwDefaultTxBufferSize = prop.dwMaxTxQueue;
            }

					  if( prop.dwCurrentRxQueue ) {
                dwDefaultRxBufferSize = prop.dwCurrentRxQueue;
            } else if( prop.dwMaxRxQueue ) {
                dwDefaultRxBufferSize = prop.dwMaxRxQueue;
            }

						if( options->TransmitBuffer )
							dwDefaultTxBufferSize = options->TransmitBuffer;

						if( options->ReceiveBuffer )
							dwDefaultRxBufferSize = options->ReceiveBuffer;


            if( !SetupComm( hDevice,
                            dwDefaultRxBufferSize,
                            dwDefaultTxBufferSize ) )
            {
                res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL );
            }
        }
    }

    /* set timeouts */
    if( res==FB_RTERROR_OK ) {
        COMMTIMEOUTS timeouts;
        if( !GetCommTimeouts( hDevice, &timeouts ) ) {
            res = fb_ErrorSetNum( FB_RTERROR_NOPRIVILEDGES );
        } else {
            if( options->DurationCTS!=0 ) {
                timeouts.ReadIntervalTimeout = options->DurationCTS;
                timeouts.ReadTotalTimeoutMultiplier =
                    timeouts.ReadTotalTimeoutConstant = 0;
            }
            if( !SetCommTimeouts( hDevice, &timeouts ) ) {
                res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL );
            }
        }
    }

    /* setup generic COM port configuration */
    if( res==FB_RTERROR_OK ) {
        DCB dcb;
        if( !GetCommState( hDevice, &dcb ) ) {
            res = fb_ErrorSetNum( FB_RTERROR_NOPRIVILEDGES );
        } else {
            dcb.BaudRate = options->uiSpeed;
            dcb.fBinary = !options->AddLF; /* FIXME: Windows only supports binary mode */
            dcb.fParity = options->CheckParity;
            dcb.fOutxCtsFlow = options->DurationCTS!=0;
            dcb.fDtrControl = ( (options->KeepDTREnabled) ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE );

            /* Not sure about this one ... */
            dcb.fDsrSensitivity = options->DurationDSR!=0;
            dcb.fOutxDsrFlow = FALSE;

            /* No XON/XOFF */
            dcb.fOutX = FALSE;
            dcb.fInX = FALSE;
            dcb.fNull = FALSE;

            /* Not sure about this one ... */
            dcb.fRtsControl = ( ( options->SuppressRTS ) ? RTS_CONTROL_DISABLE : RTS_CONTROL_HANDSHAKE );

            dcb.fAbortOnError = FALSE;
            dcb.ByteSize = (BYTE) options->uiDataBits;

            switch ( options->Parity ) {
            case FB_SERIAL_PARITY_NONE:
                dcb.Parity = NOPARITY;
                break;
            case FB_SERIAL_PARITY_EVEN:
                dcb.Parity = EVENPARITY;
                break;
            case FB_SERIAL_PARITY_ODD:
                dcb.Parity = ODDPARITY;
                break;
            case FB_SERIAL_PARITY_SPACE:
                dcb.Parity = SPACEPARITY;
                break;
            case FB_SERIAL_PARITY_MARK:
                dcb.Parity = MARKPARITY;
                break;
            }

            switch ( options->StopBits ) {
            case FB_SERIAL_STOP_BITS_1:
                dcb.StopBits = ONESTOPBIT;
                break;
            case FB_SERIAL_STOP_BITS_1_5:
                dcb.StopBits = ONE5STOPBITS;
                break;
            case FB_SERIAL_STOP_BITS_2:
                dcb.StopBits = TWOSTOPBITS;
                break;
            }

            if( !SetCommState( hDevice, &dcb ) ) {
                res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL );
            } else {
                EscapeCommFunction( hDevice, SETDTR );
						}
        }
    }

    if( !fb_hSerialCheckLines( hDevice, options ) ) {
        res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL );
    }

    if( res!=FB_RTERROR_OK ) {
        CloseHandle( hDevice );
    } else {
        W32_SERIAL_INFO *pInfo = calloc( 1, sizeof(W32_SERIAL_INFO) );
        DBG_ASSERT( ppvHandle!=NULL );
        *ppvHandle = pInfo;
        pInfo->hDevice = hDevice;
        pInfo->iPort = iPort;
        pInfo->pOptions = options;
    }

    return res;
}