Hayes AT Commands: Detect Remote Hangup? - c

How are you supposed to programatically detect when the remote modem on your call hangs up? I am writing a C program which interfaces with a SoftModem device /dev/ttySL0 in Ubuntu linux. I am able to configure the modem using Hayes AT commands and communicate with the remote modem. However, I haven't been able to determine how I'm supposed to detect that the other end has hung up the line.
I have the modem configured so that when the other end hangs up, the device prints NO CARRIER and switches to command mode. However, I can't use the NO CARRIER string because I can't guarantee that the modem won't receive that string while in data mode.
How do you "listen" for remote hang up?

This is a hardware signal on modems, the Carrier Detect (CD) line. You'll need to monitor it to know that the connection was lost. Basics in linux are described in this how-to, you obtain the signal state with ioctl() using the TIOCM_CAR command.

Testing for NO CARRIER as text will not suffice. This text frequently occurs on sites in the net, even on Q&A sites.
Coming from the modem, it should be enclosed in line breaks.
Besides, after you detect that text, you can try to switch to command mode with +++. If that works, your connection persists and you can reattach it and continue using it. If it doesn't (because you are already there and +++ is an invalid command), the connection has gone.

Related

Linux serial port (tty) redirection

I have a question linked to Linux and serial port.
I want to be able to receive and send messages to a dedicated serial port and to redirect it to another port (/dev/tty).
For the first part, I’m able to dialog with my hardware equipment without any problem, but I’m just wondering if it’s possible to intercept and redirect message coming from a serial port #1 to another port #2.
To give more context, I had used a GPS Antenna and NTP open source software for years.
Since 2018, the new GPS antenna protocol has modified the order of bytes in the message used by NTP to steer and now it’s not working anymore.
So my idea is to put a simple C program (middleware) which fixes this byte ordering; but I’m wondering if I have to build a kernel-specific module or if it can be done in another way. The NTP software uses the symbolic link to dialog.
Thanks for your help.
You can probably use a simple redirect, look here:
Pipe One Serial Port to Another in Linux
If the ports are in different rates you can use stty or perhaps screen to adjust: https://unix.stackexchange.com/a/117064
If you need it to be in c program to manipulate it you can use the following: https://stackoverflow.com/a/6947758/8901188
Using c it will need to run in an infinite loop so it can constantly read, manipulate and write the data.

C program stalls when the serial device's path changes

In Linux I am running in the background a program written in C, which periodically communicates with a device connected to one of the USB ports. Although the device is always plugged into the same port, over time it switches from /dev/ttyACM0 to /dev/ttyACM1 and back, even when no other devices are connected. Consequently every time a switch occurs, I have to restart the program.
To cope with the problem I have tried setting up a UDEV rule for a new symlink and the the symlink works regardless of the changes in the connected device's path. However, when the switch occurs, the program still stalls and needs to be restarted.
Is there a system rule I can implement for the device to keep the same path at all times, or is there another more general approach?
First approach (easier):
If you have access to the other's device code, I would implement a ping message from it.
Then, I would listen for that ping message, on both tty devices, to see on which port it is received (/dev/ttyACM0 or /dev/ttyACM1).
Second approach:
On a separate thread implement an UDEV monitor.
The monitor checks which TTY port is used by your device.
In case of a port change, just reinit the communication thread...
See udev_monitor_usb.c for a udev monitor usb code.

Termios.h serial communication. Check for device disconnection

I'm using termios.h to communicate with a USB Dongle. I would like to close the file descriptor when I disconnect the dongle. Is there a way to do this. I know that for f.e. a TCP/IP connection you get a EOF if the other party closes the connection. However, with a serial connection, my program basically runs wild (I'm using a loop to read from the descriptor...).
Basically I would like to have some indication that the connection was closed so that i can gracefully shut down the program. Maybe by changing the settings with ioctl?
I Googled a bit using the search phrase how to receive usb disconnect notification in C for windows and came across Detecting USB Insertion / Removal Events in Windows using C++ on stackoverflow.com. If you run on Linux, you can adapt the seach phrase and try those answers.

How can I flush the serial port before reading?

I am trying to get a microcontroller to communicate with a Windows PC over serial port.
It looks to me like Windows is buffering the input on COM1 such that if I stop both programs running, then restart only the Windows program it is still receiving some output from the previous run of the microcontroller's program.
After I open COM1 can I some how flush its receive buffer before beginning to read? Is there a function call to do that?
I believe the function you are looking for is PurgeComm, to which you pass the HANDLE you got from CreateFile() when you opened the port. I'm not sure, but I believe the serial port is also automatically flushed each time you open it.
However, a better method is to use ReadFile (or ReadFileEx) until you encounter something meaningful. Serial protocols are always designed with one or more sync bytes for this very purpose. Unless you are writing a terminal program or similar, you will have to do like this anyhow, since the Windows PC will never be in sync with the microcontroller otherwise.

pcap C check if in monitor mode

I am capturing in C with libpcap on a device, that does not support to be set in monitor mode via pcap (pcap_can_set_rfmon returns -6). But i can set it in monitor mode with iw and iwconfig on command line, so I do that manually and then run the program.
I am also capturing on my Mac where I can set the network device to monitor mode with the pcap function pcap_set_rfmon.
I was wondering if there is a way with pcap to actually check if the device already is in monitor mode, just for error handling and convenience reasons. I didn't find an answer (either positive nor negative). So maybe someone here can answer this?
I am capturing in C with libpcap on a device, that does not support to be set in monitor mode via pcap (pcap_can_set_rfmon returns -6).
pcap_can_set_rfmon() returns -6? That's PCAP_ERROR_RFMON_NOTSUP, which pcap_can_set_rfmon() isn't supposed to return; it's only supposed to return an error value if a problem occurs, it's supposed to return 0 if it thinks you can't set monitor mode and 1 if it thinks you can. Do you mean that pcap_set_rfmon() returns -6? And does pcap_can_set_rfmon(), which means "pcap_set_rfmon() should work"?
But i can set it in monitor mode with iw and iwconfig on command line, so I do that manually and then run the program.
Do you run either of those commands as root, e.g. with sudo?
I was wondering if there is a way with pcap to actually check if the device already is in monitor mode,
No. The idea is that the result of pcap_can_set_rfmon() should correctly indicate whether pcap_set_rfmon() will succeed, and that programs should request monitor mode regardless of whether it's already on, just as they do with promiscuous mode.
Unfortunately, there are currently some issues with Linux - mostly a combination of the non-mac80211 mechanisms not working as well with libpcap as the mac80211 mechanisms (requiring more privileges, colliding with NetworkManager, etc.) and of the mac80211 mechanisms not being available to libpcap because libpcap currently requires the ever-changing-API libnl in order to use them (which may need to be fixed by directly using the netlink sockets). This causes pcap_set_rfmon() not to work in cases where it should be able to work.

Resources