Trying to Retrieve a List of Active Serial/Com Ports

K

kudruu

Hi,
I am trying to find a way to populate a list of active Com ports on a
computer. There may be around 30 on one computer and all connected to
different Buses but I am looking for one in particular that is
emitting packets that I need to monitor.
Is there a function in C (maybe using winAPI) that will return the
list of com ports?

Another question I have is whether I am using CreateFile correctly.
For debugging purposes you can see I have declared "char
activecomports" to contain three com ports that I have on my current
computer, although there is nothing connected to them, I expect the
program to cycle through them anyway.
The program runs until the first action after the do{} loop (nBuf =
read1...) where it halts and does not continue, am I passing in my com
ports incorrectly or does my "fd" value get messed up somewhere? Here
is the relevant code I am using:

char comPort[20];
UCHAR *adrs; //This is an unsigned char
time_t TimeSec = 0;

int i,j,udi,k, nBuf, readAgain=0;
int Msg_ID, length, elmThree;
const char *activecomports[3] = {"COM1", "COM3", "COM4"};
for (i=0; i<4;i++)
{

(HANDLE)fd[0] = CreateFile(&activecomports[0], GENERIC_READ, 0,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
if( (HANDLE)fd[0] == INVALID_HANDLE_VALUE ) {
printf("CreateFile error");
exit(0);
}
do {

nBuf = read1( fd[0], (buf[0]+nData[0]), (RS232BUFSIZ-nData[0]) );

if( nBuf > 0 ) {
nData[0] += nBuf;
readAgain = ( nData[0] == RS232BUFSIZ );
while( (i = findNextPacket( TimeSec, buf[0], &strt[0],
&nData[0] )) != -1 ) {
Msg_ID = *(buf[0]+i+1);
length = *(buf[0]+i+2);
elmThree = *(buf[0]+i+3);
adrs = buf[0]+i+4;
switch( Msg_ID ) {
default:
continue;
case EVENT_MSG_TYPE:
break;
} } }
} while( readAgain );
}
updateConnection( (HANDLE)fd[0] );

int read1( int fd, UCHAR *buf, int bufSiz ) {
int nBytesRead;
ReadFile( (HANDLE)fd, (LPVOID)buf, (DWORD)bufSiz,
(LPDWORD)&nBytesRead, NULL );
return nBytesRead;
}

Thank you so much in advance for any help you can provide!
 
W

Walter Roberson

I am trying to find a way to populate a list of active Com ports on a
computer. There may be around 30 on one computer and all connected to
different Buses but I am looking for one in particular that is
emitting packets that I need to monitor.
Is there a function in C (maybe using winAPI) that will return the
list of com ports?

Not in standard C; standard C does not know anything about devices.
For information about winAPI, you will need to ask in a Windows
programming newsgroup.

Another question I have is whether I am using CreateFile correctly.

CreateFile is not part of standard C, so we don't know. I seem
to recall having seen it mentioned in connection witn winAPI, so
possibly that would be an appropriate place to ask about it.
For debugging purposes you can see I have declared "char
activecomports" to contain three com ports that I have on my current
computer, although there is nothing connected to them, I expect the
program to cycle through them anyway.

(HANDLE)fd[0] = CreateFile(&activecomports[0], GENERIC_READ, 0,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );


Your code showed no definition for fd, and no information
about the type or macro HANDLE. Syntatically, it appears that you
are coverting the type of fd[0] *after* the assignment, which
seems like a waste of effort.

Thank you so much in advance for any help you can provide!

Lots of undefined stuff there. Looks suspiciously like Windows
specific.
 
A

Army1987

char comPort[20];
UCHAR *adrs; //This is an unsigned char
time_t TimeSec = 0;

int i,j,udi,k, nBuf, readAgain=0;
int Msg_ID, length, elmThree;
const char *activecomports[3] = {"COM1", "COM3", "COM4"};
for (i=0; i<4;i++)
{

Where were all these defined?
(This newsgroup is about standard C, for extensions you should find
a group about your system).
(HANDLE)fd[0] = CreateFile(&activecomports[0], GENERIC_READ, 0,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
if( (HANDLE)fd[0] == INVALID_HANDLE_VALUE ) {
printf("CreateFile error");


Write that to stderr, not to stdout. Also, adding a newline as the
last character of output is usually a good idea.

0 signals success. Use exit(EXIT_FAILURE); instead.
}
do {

nBuf = read1( fd[0], (buf[0]+nData[0]), (RS232BUFSIZ-nData[0]) );

if( nBuf > 0 ) {
nData[0] += nBuf;
readAgain = ( nData[0] == RS232BUFSIZ );
while( (i = findNextPacket( TimeSec, buf[0], &strt[0],
&nData[0] )) != -1 ) {
Msg_ID = *(buf[0]+i+1);
length = *(buf[0]+i+2);
elmThree = *(buf[0]+i+3);
adrs = buf[0]+i+4;
switch( Msg_ID ) {
default:
continue;
case EVENT_MSG_TYPE:
break;

What's so bad with if (Msg_ID != EVENT_MSG_TYPE) continue; ?
} } }
} while( readAgain );
}
updateConnection( (HANDLE)fd[0] );

int read1( int fd, UCHAR *buf, int bufSiz ) {
int nBytesRead;
ReadFile( (HANDLE)fd, (LPVOID)buf, (DWORD)bufSiz,
(LPDWORD)&nBytesRead, NULL );
return nBytesRead;
}

Can't you simplily declare it as
int read1(HANDLE fd, LPVOID buf, DWORD bufSiz)?
And are you sure that LPDWORD is always the same as a pointer to
int? (If so, why do you cast?)
 
K

kudruu

I am trying to find a way to populate a list of active Com ports on a
computer. There may be around 30 on one computer and all connected to
different Buses but I am looking for one in particular that is
emitting packets that I need to monitor.
Is there a function in C (maybe using winAPI) that will return the
list of com ports?

Not in standard C; standard C does not know anything about devices.
For information about winAPI, you will need to ask in a Windows
programming newsgroup.
Another question I have is whether I am using CreateFile correctly.

CreateFile is not part of standard C, so we don't know. I seem
to recall having seen it mentioned in connection witn winAPI, so
possibly that would be an appropriate place to ask about it.
For debugging purposes you can see I have declared "char
activecomports" to contain three com ports that I have on my current
computer, although there is nothing connected to them, I expect the
program to cycle through them anyway.
(HANDLE)fd[0] = CreateFile(&activecomports[0], GENERIC_READ, 0,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );


Your code showed no definition for fd, and no information
about the type or macro HANDLE. Syntatically, it appears that you
are coverting the type of fd[0] *after* the assignment, which
seems like a waste of effort.
Thank you so much in advance for any help you can provide!

Lots of undefined stuff there. Looks suspiciously like Windows
specific.


Thanks for your input...
fd is defined in the same document as a public: int fd[2] = {-1,-1};
CreateFile returns type HANDLE which is another winAPI defined type
and is built with an AutoClose function so I keep fd as an int both
for the invalid definition, and for a kind of ease while passing it
around to functions (was having trouble passing HANDLE types before).
 
K

kudruu

<[email protected]> ha scritto nel messaggionews:[email protected]...
Where were all these defined?
(This newsgroup is about standard C, for extensions you should find
a group about your system).
Some of them are defined in my header file, point taken about the
extensions group.
Write that to stderr, not to stdout. Also, adding a newline as the
last character of output is usually a good idea.
Sorry, just put that in to signal what it was - it's just a placebo.
0 signals success. Use exit(EXIT_FAILURE); instead.
Good point!

What's so bad with if (Msg_ID != EVENT_MSG_TYPE) continue; ?
Nothing at all. My previous version which contained this as another
function call contained several other MSG cases.
Can't you simplily declare it as
int read1(HANDLE fd, LPVOID buf, DWORD bufSiz)?
And are you sure that LPDWORD is always the same as a pointer to
int? (If so, why do you cast?)- Hide quoted text -

- Show quoted text -
Good idea, i had just passed them the way I had to avoid confusion.
And I will check on LPDWORD pointers.
Thanks a bunch!
 
K

kudruu

Can't you simplily declare it as
int read1(HANDLE fd, LPVOID buf, DWORD bufSiz)?
And are you sure that LPDWORD is always the same as a pointer to
int? (If so, why do you cast?)- Hide quoted text -

- Show quoted text -

Gives a runtime error
 
W

Walter Roberson

(HANDLE)fd[0] = CreateFile(&activecomports[0], GENERIC_READ, 0,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );

Your code showed no definition for fd, and no information
about the type or macro HANDLE. Syntatically, it appears that you
are coverting the type of fd[0] *after* the assignment, which
seems like a waste of effort.

fd is defined in the same document as a public: int fd[2] = {-1,-1};
CreateFile returns type HANDLE which is another winAPI defined type

I gather that when you coded (HANDLE)fd[0] that your
intention was to store the HANDLE returned by CreateFile
into the storage location fd[0] . In the information given
we don't know that HANDLE is the same size as int. Suppose HANDLE
is bigger than int; then your code -intention- would be to
somehow store the wider handle stuffed into the space only big enough
for an int, without losing information. You can't do that in C,
expand a variable's size on the fly.

if HANDLE is an integral type (and not a pointer!) and
sizeof(HANDLE) <= sizeof(int), then your code should perhaps be

fd[0] = (int) CreateFile(etc);

if you want to emphasize the type conversion. If, though,
HANDLE and int have the same type qualifiers (e.g., HANDLE isn't
something silly like 'const int' or 'volatile int') and
HANDLE is not unsigned -- i.e., if HANDLE is a signed integral
type no wider than int, then the coercion is redundant and the
code could just be

fd[0] = CreateFile(etc);

If that doesn't compile then HANDLE is not compatible with being
stored as an int (though the API might perhaps provide some
way to extract an fd from a HANDLE).


I'm writing this all in the conditional, as HANDLE is not
a standard C type and so we don't know how here it behaves
(unless you happen to show us the type definition for it.)
The Windows newsgroups know about such things; we don't.
 
K

kudruu

I gather that when you coded (HANDLE)fd[0] that your
intention was to store the HANDLE returned by CreateFile
into the storage location fd[0] . In the information given
we don't know that HANDLE is the same size as int. Suppose HANDLE
is bigger than int; then your code -intention- would be to
somehow store the wider handle stuffed into the space only big enough
for an int, without losing information. You can't do that in C,
expand a variable's size on the fly.

if HANDLE is an integral type (and not a pointer!) and
sizeof(HANDLE) <= sizeof(int), then your code should perhaps be

fd[0] = (int) CreateFile(etc);

if you want to emphasize the type conversion. If, though,
HANDLE and int have the same type qualifiers (e.g., HANDLE isn't
something silly like 'const int' or 'volatile int') and
HANDLE is not unsigned -- i.e., if HANDLE is a signed integral
type no wider than int, then the coercion is redundant and the
code could just be

fd[0] = CreateFile(etc);

If that doesn't compile then HANDLE is not compatible with being
stored as an int (though the API might perhaps provide some
way to extract an fd from a HANDLE).

I'm writing this all in the conditional, as HANDLE is not
a standard C type and so we don't know how here it behaves
(unless you happen to show us the type definition for it.)
The Windows newsgroups know about such things; we don't.

Here is the definition for HANDLE:
#ifdef STRICT
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef
struct name##__ *name
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
typedef HANDLE *PHANDLE;

This whole thing compiles, but I think something is happening between
my new declaration of "activecomport" and the handling of "fd" in fact
my error is stemming from attempting to automate the process.
Previously the program takes in the COM port from a text file:

configFile( CONFIG_FILE, "LEFT_PORT", comPort );
(HANDLE)fd[0] = CreateFile( comPort,
GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
if( (HANDLE)fd[0] == INVALID_HANDLE_VALUE ) {
printf("ester -- CreateFile right error - %s\n", comPort );
exit(1);
}

updateConnection( (HANDLE)fd[0] );

while( 1 ) {
getAllRs232( 0 ); // left rs232 data
}

This syntax works. getAllRs232() performs a similar check to the one
in my first posthowever upon receiving Bus packets it generates an
event ID and outputs it to the screen. I am only looking for a
certain hex preamble from the bus to check which port to use. Once I
see the one with the correct preamble I use it, getAllRs232 accepts an
int that is the port location of "fd." So in the instance above
CreateFile functions properly as does read1. This came after a
significant amount of fooling around with the declaration types.
 
K

kudruu

I gather that when you coded (HANDLE)fd[0] that your
intention was to store the HANDLE returned by CreateFile
into the storage location fd[0] . In the information given
we don't know that HANDLE is the same size as int. Suppose HANDLE
is bigger than int; then your code -intention- would be to
somehow store the wider handle stuffed into the space only big enough
for an int, without losing information. You can't do that in C,
expand a variable's size on the fly.

if HANDLE is an integral type (and not a pointer!) and
sizeof(HANDLE) <= sizeof(int), then your code should perhaps be

fd[0] = (int) CreateFile(etc);

if you want to emphasize the type conversion. If, though,
HANDLE and int have the same type qualifiers (e.g., HANDLE isn't
something silly like 'const int' or 'volatile int') and
HANDLE is not unsigned -- i.e., if HANDLE is a signed integral
type no wider than int, then the coercion is redundant and the
code could just be

fd[0] = CreateFile(etc);

If that doesn't compile then HANDLE is not compatible with being
stored as an int (though the API might perhaps provide some
way to extract an fd from a HANDLE).

I'm writing this all in the conditional, as HANDLE is not
a standard C type and so we don't know how here it behaves
(unless you happen to show us the type definition for it.)
The Windows newsgroups know about such things; we don't.

Here is the HANDLE declaration:
#ifdef STRICT
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef
struct name##__ *name
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
typedef HANDLE *PHANDLE;

My previous version of this program did not automate the process,
there was a config text file that specified the com port to be used.
This code works. getAllRs232 is a function similar to the one that
checks for port packets in my first post. It checks to make sure the
com port specified is sending a proper preamble then begins generating
specific event messages. Now that I am not specifically telling it
which port to use it seems to be hanging up at the read1 call.

configFile( CONFIG_FILE, "LEFT_PORT", comPort );
(HANDLE)fd[1] = CreateFile( comPort,
GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
if( (HANDLE)fd[1] == INVALID_HANDLE_VALUE ) {
printf("CreateFile left error - %s\n", comPort );
exit(0);
}

updateConnection( (HANDLE)fd[1] );

while( 1 ) {
getAllRs232( 0 ); // left rs232 data
}

return 0;
 
W

Walter Roberson

Here is the definition for HANDLE:
#ifdef STRICT
typedef void *HANDLE;
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef
struct name##__ *name
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
typedef HANDLE *PHANDLE;

So HANDLE is a void* or a PVOID, which I would -guess- is just
another name for a void* . Either way, HANDLE is probably a pointer.
(HANDLE)fd[0] = CreateFile( comPort,
GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );

And earlier you told us int fd[2], so fd[0] is an int. You are
trying to store a pointer in an int. The conversion between
pointer and int is implementation specified in C, and need not be
meaningful at all. On most systems, a pointer is wider than an int,
so even if the implementation specified that it's a bitwise copy,
you'd be losing bits out of the pointer; the converted value would
probably never be usable as a pointer again.

The moral: don't try to store a HANDLE in an int.
 
R

Richard Tobin

(HANDLE)fd[0] = CreateFile( comPort, ....
This syntax works.

Only because your compiler accepts non-standard C. Casts aren't
allowed on the target of an assignment. Assuming that int is suitable
for storing a pointer in your implementation (which presumably it is),

fd[0] = (int)CreateFile( comPort,

would be correct.

-- Richard
 
J

Johan Bengtsson

Your code showed no definition for fd, and no information
about the type or macro HANDLE. Syntatically, it appears that you
are coverting the type of fd[0] *after* the assignment, which
seems like a waste of effort.
Thank you so much in advance for any help you can provide!
Lots of undefined stuff there. Looks suspiciously like Windows
specific.

Thanks for your input...
fd is defined in the same document as a public: int fd[2] = {-1,-1};
CreateFile returns type HANDLE which is another winAPI defined type
and is built with an AutoClose function so I keep fd as an int both
for the invalid definition, and for a kind of ease while passing it
around to functions (was having trouble passing HANDLE types before).

What would be wrong with declaring it like this:

HANDLE fd[2]={NULL,NULL};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top