I have seen a lot of unresolved questions on how to do FORTRAN I/O to a USB device.
All suggested solutions are for your FORTRAN program to call a mass of ugly-C code
that in turn calls a mass of ugly Windows APIs. But it ought to be as simple as
executing a FORTRAN OPEN statement to get a FORTRAN unit number.
I am well on the way to figuring out how to do that, but there are still a few
gaps in my knowledge. So I post what I have found so far in the hope that it may
inspire other FORTRAN programmers to persevere and help fill in the blanks.
It is already possible in FORTRAN to do I/O to a serial or parallel port simply by
OPEN(UNIT=12,FILE="COM1") or OPEN(UNIT=12,FILE="LPT1)
"COM1" and "LPT1" are aliasses known to the system for the serial and parallel
ports respectively.
Compaq Visual Fortran and I guess IVF too publish the following list of I/O device
names:
Device Description
CON Console (standard output)
PRN Printer
COM1 Serial port #1
COM2 Serial port #2
COM3 Serial port #3
COM4 Serial port #4
LPT1 Parallel Port #1
LPT2 Parallel Port #2
LPT3 Parallel Port #3
LPT4 Parallel Port #4
NUL NULL device. Discards all output; contains no input
AUX Serial port #1
LINE 1 Serial port #1
USER 1 Standard output
ERR 1 Standard error
CONOUT$ Standard output
CONIN$ Standard input
You see nothing about USB devices there.
The reason is, different things can be plugeed into a USB port at different times.
So names for USB devices have to be created ad-hoc, and are very long strings.
You can find the first part of the required string to be used as a filename in
a FORTRAN OPEN statement as follows (at least in XP):
Go to Start, right click on My Computer, and select Properties from the dropdown
list. Select Hardware in the window that opens, then Device Manager.
The screen that opens shows all hardware devices with human-recognizable names.
Double click on your desired USB device and then choose "details" in the window
that opens next.
You will then see a "Device Instance ID" displayed.
This is the first part of the string you will need.
You can't cut and paste it, so I took a screenshot and trimmed it in Paint before
saving it as a .jpg.
The second part of the string that has to be appended to the first part,
I believe is the address of a registry entry that contains the driver filename.
You can get the second part of the string as follows:
Download Winobj.exe from here
then run Winobj.exe
In the left pane of the window that opens, select the folder "Globals"
In the right pane you will now have all the names in the system nametable listed.
Scroll down until you find the string (or strings) whose first part matches the
Device Instance Id you found above. You now have the whole string that has to be
assigned to a Fortran character variable to be used as the filename in an OPEN
statement.
I find two matches, and I believe one is for I and one is for O. You have to
replace the # characters that separate parts of the string by the \ character.
You also may have to preface the string with \\.\ or \\?
So Fortran I/O to a USB device should boil down to something as simple as
CHARACTER*64 USBIN,USBOUT
USBIN="\\.\USB\...........\............\{;;;;;;;;;;;;;;;;;;;}"
USBOUT="\\.\USB\...........\............\{;;;;;;;;;;;;;;;;;;;}"
OPEN(UNIT=12,FILE=USBOUT)
OPEN(UNIT=13,USBIN)
WRITE(12,100)BUFOUT
READ(13,200)BUFIN
where of course the formats 100 and 200 and the structure of BUFIN and BUFOUT will
be dependent on what your USB device is expecting.
I write the strings as I am seeing them. You do not have to add additional {}
brackets; they should be in the namestring already. But you do have to switch the #
characters to \ characters.
I have also determined that the entries in the nametable only exist as long as your
USB device is connected, and disappear when it is diconnected. However, when it is
reconnected, the whole namestring fortunately is identical to what it was before.
However, I can't guarantee that it would be the same on a different machine.
So a big question, if you want to write portable programs
(which I don't need to do at present), is how the program
itself could find these strings. Even more fundamental:
How do you even describe to the program what to look for?
I can't imagine needing a program so smart that you could
just ask it to "find me a GPIB-USB adapter".
This sounds like the "service discovery" operation that Bluetooth
performs, that enables it look for a device in a predefined class,
such as "Printer".
Are there such device classes, defined by predetermined strings,
and is "GPIB adapter" one of them?
This is the gap in my knowledge that I hope others can fill in.
Preferably with code (in FORTRAN!)
All suggested solutions are for your FORTRAN program to call a mass of ugly-C code
that in turn calls a mass of ugly Windows APIs. But it ought to be as simple as
executing a FORTRAN OPEN statement to get a FORTRAN unit number.
I am well on the way to figuring out how to do that, but there are still a few
gaps in my knowledge. So I post what I have found so far in the hope that it may
inspire other FORTRAN programmers to persevere and help fill in the blanks.
It is already possible in FORTRAN to do I/O to a serial or parallel port simply by
OPEN(UNIT=12,FILE="COM1") or OPEN(UNIT=12,FILE="LPT1)
"COM1" and "LPT1" are aliasses known to the system for the serial and parallel
ports respectively.
Compaq Visual Fortran and I guess IVF too publish the following list of I/O device
names:
Device Description
CON Console (standard output)
PRN Printer
COM1 Serial port #1
COM2 Serial port #2
COM3 Serial port #3
COM4 Serial port #4
LPT1 Parallel Port #1
LPT2 Parallel Port #2
LPT3 Parallel Port #3
LPT4 Parallel Port #4
NUL NULL device. Discards all output; contains no input
AUX Serial port #1
LINE 1 Serial port #1
USER 1 Standard output
ERR 1 Standard error
CONOUT$ Standard output
CONIN$ Standard input
You see nothing about USB devices there.
The reason is, different things can be plugeed into a USB port at different times.
So names for USB devices have to be created ad-hoc, and are very long strings.
You can find the first part of the required string to be used as a filename in
a FORTRAN OPEN statement as follows (at least in XP):
Go to Start, right click on My Computer, and select Properties from the dropdown
list. Select Hardware in the window that opens, then Device Manager.
The screen that opens shows all hardware devices with human-recognizable names.
Double click on your desired USB device and then choose "details" in the window
that opens next.
You will then see a "Device Instance ID" displayed.
This is the first part of the string you will need.
You can't cut and paste it, so I took a screenshot and trimmed it in Paint before
saving it as a .jpg.
The second part of the string that has to be appended to the first part,
I believe is the address of a registry entry that contains the driver filename.
You can get the second part of the string as follows:
Download Winobj.exe from here
then run Winobj.exe
In the left pane of the window that opens, select the folder "Globals"
In the right pane you will now have all the names in the system nametable listed.
Scroll down until you find the string (or strings) whose first part matches the
Device Instance Id you found above. You now have the whole string that has to be
assigned to a Fortran character variable to be used as the filename in an OPEN
statement.
I find two matches, and I believe one is for I and one is for O. You have to
replace the # characters that separate parts of the string by the \ character.
You also may have to preface the string with \\.\ or \\?
So Fortran I/O to a USB device should boil down to something as simple as
CHARACTER*64 USBIN,USBOUT
USBIN="\\.\USB\...........\............\{;;;;;;;;;;;;;;;;;;;}"
USBOUT="\\.\USB\...........\............\{;;;;;;;;;;;;;;;;;;;}"
OPEN(UNIT=12,FILE=USBOUT)
OPEN(UNIT=13,USBIN)
WRITE(12,100)BUFOUT
READ(13,200)BUFIN
where of course the formats 100 and 200 and the structure of BUFIN and BUFOUT will
be dependent on what your USB device is expecting.
I write the strings as I am seeing them. You do not have to add additional {}
brackets; they should be in the namestring already. But you do have to switch the #
characters to \ characters.
I have also determined that the entries in the nametable only exist as long as your
USB device is connected, and disappear when it is diconnected. However, when it is
reconnected, the whole namestring fortunately is identical to what it was before.
However, I can't guarantee that it would be the same on a different machine.
So a big question, if you want to write portable programs
(which I don't need to do at present), is how the program
itself could find these strings. Even more fundamental:
How do you even describe to the program what to look for?
I can't imagine needing a program so smart that you could
just ask it to "find me a GPIB-USB adapter".
This sounds like the "service discovery" operation that Bluetooth
performs, that enables it look for a device in a predefined class,
such as "Printer".
Are there such device classes, defined by predetermined strings,
and is "GPIB adapter" one of them?
This is the gap in my knowledge that I hope others can fill in.
Preferably with code (in FORTRAN!)