COMM ports

Questions and discussion about the ZBasic IDE.
Post Reply
DH*

COMM ports

Post by DH* »

The machine I use for development has 11 serial ports.

The IDE presents an empty combo box for selecting a serial port.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

We use a process called "comm port enumeration" where we look at entries in the registry to see what devices are available. The actual code used is:

Code: Select all

//
// Enumerate the existing comm ports, invoking a caller-supplied function
// for each port.
//
void CommPort::
EnumCommPorts(EnumCommPortProc func, void *arg)
{
	HKEY hkCommMap;
	if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0,
			KEY_QUERY_VALUE, &hkCommMap) != ERROR_SUCCESS)
		return;

	char *nameBuf = 0;
	char *valBuf = 0;
	DWORD cnt, maxNameLen, maxValLen;
	if (::RegQueryInfoKey(hkCommMap, NULL, NULL, NULL, NULL, NULL, NULL,
			&cnt, &maxNameLen, &maxValLen, NULL, NULL) == ERROR_SUCCESS)
	{
		// The max value name size is returned in TCHARs not including
		// the terminating null character.
		nameBuf = new char[++maxNameLen * sizeof(char)];

		// The max value size is returned in bytes needed to hold the UNICODE
		// strings including terminating null character regardless of the
		// function type (ANSI or UNICODE).
		maxValLen = (maxValLen / 2) * sizeof(char);
		valBuf = new char[maxValLen];

		if (nameBuf && valBuf)
		{
			for &#40;DWORD idx = 0; idx < cnt; ++idx&#41;
			&#123;
				DWORD nameLen = maxNameLen;
				DWORD valLen = maxValLen;
				DWORD type;
				LONG nRes = &#58;&#58;RegEnumValue&#40;hkCommMap, idx, reinterpret_cast<LPTSTR>&#40;nameBuf&#41;,
						&nameLen, NULL, &type, reinterpret_cast<LPBYTE>&#40;valBuf&#41;, &valLen&#41;;

				unsigned port = GetPort&#40;valBuf&#41;;
				if &#40;&#40;nRes == ERROR_SUCCESS&#41; && &#40;type == REG_SZ&#41; && !func&#40;valBuf, port, arg&#41;&#41;
					break;
			&#125;
		&#125;
	&#125;
	delete&#91;&#93; valBuf;
	delete&#91;&#93; nameBuf;
	&#58;&#58;RegCloseKey&#40;hkCommMap&#41;;
&#125;

//
// Extract the comm port number from a string in the form COMnnn.
// Return zero for an invalid string or other error.
//
unsigned CommPort&#58;&#58;
GetPort&#40;const char *str&#41;
&#123;
	unsigned port = 0;
	if &#40;str != NULL&#41;
	&#123;
		while &#40;isspace&#40;*str&#41;&#41;
			str++;
		if &#40;memicmp&#40;str, "COM", 3&#41; == 0&#41;
		&#123;
			str += 3;
			while &#40;isdigit&#40;*str&#41;&#41;
				port = port * 10 + &#40;*str++ - '0'&#41;;
		&#125;
	&#125;
	return&#40;port&#41;;
&#125;

Another user has reported that this does not work on Win98SE. So far, there have been no reports of it not working on Win2K or later.

As a workaround, you can set the comm port and related parameters by adding/editing lines in the User Options file. The lines have the following form:

Code: Select all

debug.comport=2
debug.speed=19200
debug.capture=1
debug.reset=1
download.verify=1
download.clear=1
download.quiet=0
The first two lines set the port and speed (other than for downloading). These should be all that you need. The remaining entries correspond to checkboxes on the Device Options dialog.
- Don Kinzer
DH*

Post by DH* »

This is a 98SE machine but all of the ports are listed in the registry where you're looking.

I'll try the workaround.
pjc30943
Posts: 220
Joined: 01 December 2005, 18:45 PM

Post by pjc30943 »

dhouston wrote:This is a 98SE machine but all of the ports are listed in the registry where you're looking.

I'll try the workaround.
That happened to me as well: in the registry, but not the box. The workaround has functioned perfectly, including using the zload instead of the default F5 (see one of Don's previous emails).
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

The downloader may not function correctly on Win98SE. See viewtopic.php?t=74 for a way to work around the problem using ZLoad.
- Don Kinzer
DH*

Post by DH* »

The registry location you are looking to is not accurate. It's possible for a user to edit the registry adding ports or modifying those listed. In my case port numbers 40, 50, and 99 were still listed from where I had renamed some ports (a few years back) in order to test some VB code on ports higher than those usually seen.

REALbasic was also failing to correctly enumerate ports if more than nine were present. They found a function in a MS setup DLL that fixed this. If I saved the email exchange I'll send you the details. Device Manager appears to always list the ports correctly.

While I have an XP machine (also with extra serial ports) I still use an old laptop that's not capable of running XP. My preferred development machine has an older motherboard with ISA slots in order to use an oscilloscope card that needs ISA. 98SE is about its limit as well.

Everything I do is freeware and I like to avoid support problems whenever possible.
Post Reply