I'm working on a C application that evaluates data from a USB laser scanner, which acts as a serial device. For testing purpose, I'm also allowing test data to be read from a file, because it is not convenient to always have the scanner connected.
I open the file/device like this:
FILE *fp = fopen(argv[1], "a+b");
And depending on whether I want to read from a file or the device, I pass a file path or something like /dev/cu.usbmodemfd121
(I'm on a Mac).
This works fine as long as I've previously initialized the laser scanner, but I'd rather have my application do that. In order to do that, though, I must first figure out if I'm reading from a file or the device. How can I do that, given the FILE *
returned by fopen
?
I've tried to use fseek(fp, 1, SEEK_END)
which I expected to fail for the scanner, since it's stream doesn't have an "end", but for some reasons fseek
does not fail..
To test if the computer COM port is functioning correctly, you can do a simple loopback test. (In a loopback test, a signal is sent from a device and returned, or looped back, to the device.) For this test, connect a serial cable to the COM port that you want to test. Then short pin 2 and pin 3 of the cable together.
By looping the transmit and receive pins, you can test serial cable port communication by checking if the serial ports connections transmit and receive valid information. This is called a loopback test and can be used to test rs232 communication. Use a screwdriver to loop pins for testing.
Linux uses ttySx for a serial port device name. For example, COM1 (DOS/Windows name) is ttyS0, COM2 is ttyS1, and so on. USB based serial ports might use a name such as ttySUSB0. All these devices are located under /dev/ directory.
On a Windows computerPress the Windows key + R, then type "cmd.exe" and click OK. Enter "telnet + IP address or hostname + port number" (e.g., telnet www.example.com 1723 or telnet 10.17.xxx.xxx 5000) to run the telnet command in Command Prompt and test the TCP port status.
You could get the file descriptor using fileno
and then do a fstat
on it. The struct stat
it populates contains thinks like st_mode
which shows the type of fd. I am guessing for your non-file device S_ISCHR
will be true or at least S_ISREG
will be false.
If you have control over it, don't do fopen
at all. Use open
directly to get the file descriptor and then use fdopen
if you really want C streams.
@cnicutar's solution worked just fine. Here's what I ended up with, in case it helps somebody (error checking removed for clarity):
#include <fcntl.h> /* open syscall */
#include <sys/stat.h>
int fd = -1;
int status;
FILE *fp = NULL;
struct stat fd_stat;
bool serial_device = false;
fd = open("/foo/bar/baz", O_RDONLY);
fp = fdopen(fd, "rb");
status = fstat(fd, &fd_stat);
printf("S_ISCHR: %d\n", S_ISCHR(fd_stat.st_mode));
printf("S_ISREG %d\n", S_ISREG(fd_stat.st_mode));
if(!S_ISREG(fd_stat.st_mode)) {
serial_device = true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With