Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if a C filestream points to a file or a serial device?

Tags:

c

unix

file-io

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..

like image 738
fresskoma Avatar asked Mar 21 '14 18:03

fresskoma


People also ask

How do I know if my device has a serial port?

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.

How do you test serial communication?

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.

How do you check if a device is connected to serial port Linux?

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.

How do I test a COM port using CMD?

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.


2 Answers

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.

like image 199
cnicutar Avatar answered Sep 21 '22 05:09

cnicutar


@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;
}
like image 36
fresskoma Avatar answered Sep 22 '22 05:09

fresskoma