I suppose I could somehow brute-force my way through a list of known
device names and attempt to connect to each, but that seems ugly.
Thanks,
Jeff
Does MS-Windows even support more than four (COM1, COM2, COM3, and COM4)
hardware RS232 ports? While ugly, it might be that hitting each of
these 4 device names might be the simplest way to go.
This is what I have done under Linux:
proc GetAllSerialPorts {} {
set portlist [eval [concat exec /bin/setserial -gb \
[glob -nocomplain /dev/ttyS*] 2>/dev/null]]
set result {}
foreach line [split $portlist "\n"] {
if {[regexp {^(.*) at } "$line" => port] > 0} {
lappend result [string trim "$port"]
}
}
return $result
}
Note: '/bin/setserial -gb' is more or less much the same as this
cross-platform code (the code above pre-dates Tcl's serial port
support):
proc setserial {dev} {
if {[catch {open $dev r} chan]} {return {}}
if {[catch {fconfigure $chan -mode} mode]} {
close $chan
return {}
} else {
close $chan
return [list $dev -mode $mode]
}
}
What my code is doing is just gathering all of the serial port device names in
/dev/ (/dev/ttyS*), and then attempting to get their port settings.
setserial is 'mute' for device names that are not connected to an actual
port. I then strip off the first 'word' (the device name) of each line
that setserial writes out. setserial is basically just doing a
'brute-force' open of each of its command line arguments and returning
some info about those arguments that it successfully opens.
>
> Thanks,
>
> Jeff
>
--
Robert Heller -- 978-544-6933
Deepwoods Software -- Download the Model Railroad System
http://www.deepsoft.com/ -- Binaries for Linux and MS-Windows
hel...@deepsoft.com -- http://www.deepsoft.com/ModelRailroadSystem/
Robert,
Thanks for the input and the code. Unless someone has a cleaner, more
Windows-centric way of accomplishing this, I may end up using a
brute-force method.
Jeff
See http://paste.tclers.tk/164
--
Pat Thoyts http://www.patthoyts.tk/
PGP fingerprint 2C 6E 98 07 2C 59 C8 97 10 CE 11 E6 04 E0 B9 DD
Pat,
Thanks for the link. At this point, I'm really not looking to go the
'C' route, but you never know.
Jeff
Here's a proc I've used in several scripts. It will interrogate the
registry for a list of COM ports and return it to the calling procedure
(in list form).
proc comList {} {
set keyname "HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM"
set rtn [registry values $keyname]
set coms {}
foreach i $rtn {
lappend coms [registry get $keyname $i]
}
return $coms
}
HTH,
Dave
--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---
Dave,
Thanks for the code - that looks interesting. Looking on a few systems
(both XP and Win7), that key seems to contain exactly what I want. The
only exception seems to be if the hardware in question doesn't have any
RS232 ports (such as a modern laptop), in which case the key doesn't
even exist.
That should be get me going.
Thanks,
Jeff
Jeff
That should be easy enough to detect by using the catch statement to
evaluate the "set rtn [registry values $keyname]" statement. For example:
if [catch {registry values $keyname} rtn] {
<your error processing here>
} else {
<rest of the proc as previously shown>
Jeff,
If you want to try Pat's way:
1) grab Visual Studio Express from
http://www.microsoft.com/express/Downloads/#2008-Visual-CPP and install
it. If it give you the install option named something like 'Use command
prompt tools' allow that.
2) save his code from http://paste.tclers.tk/164 to a text file named
lscomport.c
3) open a command prompt in the same directory as the source file and type:
cl -nologo /MT lscomport.c -link -out:lscomport.exe -subsystem:console
you should have a nice fresh compile of it sitting right there in your
current path after it finishes.
If the command prompt complains about not finding cl.exe, run
vcvars32.bat. info @
http://msdn.microsoft.com/en-us/library/f2ccy3wt(v=VS.90).aspx
this might be your path to it:
"C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\vcvars32.bat"
--
Hi David,
I already have a full VS installation, but the remainder of your above
instructions should be very handy if I decide to go that route. Thanks
for the providing the details.
Jeff
This retrieves the GUID for the Ports class
(bin) 76 % set guid [lindex [device_setup_class_name_to_guids Ports]
0]
{4D36E978-E325-11CE-BFC1-08002BE10318}
Collect a devinfoset containing all device elements for that guid.
Returns a handle
(bin) 77 % set h [update_devinfoset -guid $guid]
_80b11600_HDEVINFO
Get the properties "service" and "friendlyname" for each element in
the device set
(bin) 78 % set props [get_devinfoset_registry_properties $h service
friendlyname]
{-deviceelement {{{4D36E978-E325-11CE-BFC1-08002BE10318}} 2640
1486344} 4 {success {sz Parport}} 12 {success {sz {Printer Port
(LPT1)}}}} {-deviceelement {{{4D36E978-E325-11CE-BFC1-08002BE10318}}
2696 1484232} 4 {success {sz Parport}} 12 {success {sz {ECP Printer
Port (LPT1)}}}} {-deviceelement {{{4D36E978-E325-11CE-
BFC1-08002BE10318}} 2752 1483232} 4 {success {sz Serial}} 12 {success
{sz {Communications Port (COM1)}}}}
The above format is a bit complex. Basically, there is one element in
the list for each device. This is element is itself a list. For
example, the 3rd element in the list is
(bin) 79 % lindex $props 2
-deviceelement {{{4D36E978-E325-11CE-BFC1-08002BE10318}} 2752 1483232}
4 {success {sz Serial}} 12 {success {sz {Communications Port (COM1)}}}
This element is itself a list consisting of key, value pairs. The
first key "-devicelement" identifies the device element. Subsequent
pairs are the requested registry values. 4 -> service, and 12 ->
friendlyname. The value associated with each is associated with a
success/fail indicator followed by the actual registry value itself.
So in the above, we can see the service is "Serial" and the
friendlyname is "Communications Port (COM1)".
So you basically need to filter on $props, matching on service being
"Serial".
Unfortunately, this is not documented, being such a horrible
complicated mess that I'm not even sure where to begin documenting it.
You can look in the device.tcl file in the twapi distribution for
more.
Alternatively, you can also use the raw calls that Pat posted directly
from twapi but that would be more involved than the above.
/Ashok
> 1) grab Visual Studio Express from
> http://www.microsoft.com/express/Downloads/#2008-Visual-CPP and install
> it. If it give you the install option named something like 'Use command
> prompt tools' allow that.
David, is there a reason to prefer the 2008 version versus the 2010 version?
craig
Sadly, I saw Dave Harper's reply only after I wrote my response using
twapi. Certainly, Dave's method is a hell of a lot easier. As an
aside, where you need more detail, using the WMI interfaces would be
another option.
/Ashok
Ashok,
Thanks for providing yet another solution.
Jeff
Yes it does. In a Warehouse project I lead, we used a windows XP pc to
talk to
7 cranes
1 conveyor
4 scanners
2 scales
all via rs232.
We bought a 'rocket port card' (http://www.comtrol.com/pub/products/
category/cid/67)
with 16 rs232 ports, and counting the motherboard we had 18 serial
ports.
The scanners and scales were controlled via a tcl-script i wrote, that
mapped a tcp-port to a serial port, giving access to the scanners from
a AIX-machine on the LAN.
What I found out was that using names COM1: through COM9: is ok, but
COM10: and above does not work.
see http://support.microsoft.com/kb/115831
use \\.\COM10 (no ':') and I think escape the '\' so it becomes
\\\\.\\COM10
works on less than 10 as well, like \\\\.\\COM3
/Bjöen
-eric