Using DCD line to invoke poll() HUP

POSIX poll() provides a mechanism to attach a POLL_HUP event
if the modem or device hangs up on you. POLL_HUP and POLL_OUT are
mutually exclusive. We poll in the PPP_input() routine if the modem
hung up. If it did we stop the data consumption, close PPP and go back
to the driver for reserruction of AT parser and subsequent retries or
application specific actions.
This is achieved by attaching an interrupt to the DCD line of the modem.
When DCD line goes high (off), we have lost the carrier. So we record an
POLLHUP event using _poll_change().
pull/4119/head
Hasnain Virk 2017-02-22 13:10:28 +02:00
parent 87a4580e5f
commit 93f436ebe0
3 changed files with 62 additions and 42 deletions

View File

@ -197,47 +197,22 @@ static void ppp_link_status(ppp_pcb *pcb, int err_code, void *ctx)
}
}
#if 0
/*
* This should be in the switch case, this is put outside of the switch
* case for example readability.
*/
if (err_code == PPPERR_NONE) {
return;
}
/* ppp_close() was previously called, don't reconnect */
if (err_code == PPPERR_USER) {
/* ppp_free(); -- can be called here */
return;
}
/*
* Try to reconnect in 30 seconds, if you need a modem chatscript you have
* to do a much better signaling here ;-)
*/
ppp_connect(pcb, 30);
/* OR ppp_listen(pcb); */
#endif
}
static void flush(FileHandle *stream)
{
char buffer[8];
for (;;) {
ssize_t ret = stream->read(buffer, sizeof buffer);
if (ret <= 0) {
break;
ppp_link_up = true;
} else {
if (ppp_link_up) {
ppp_link_up = false;
sys_sem_signal(&ppp_close_sem);
}
}
notify_ppp_link_status(err_code);
}
#if !PPP_INPROC_IRQ_SAFE
#error "PPP_INPROC_IRQ_SAFE must be enabled"
#endif
static void ppp_input(FileHandle *stream)
static void ppp_input()
{
// Allow new events from now, avoiding potential races around the read
event_queued = false;
@ -259,7 +234,7 @@ static void ppp_input(FileHandle *stream)
// serial, so we will fairly rapidly hit -EAGAIN.
for (;;) {
u8_t buffer[16];
ssize_t len = stream->read(buffer, sizeof buffer);
ssize_t len = my_stream->read(buffer, sizeof buffer);
if (len == -EAGAIN) {
break;
} else if (len <= 0) {

View File

@ -26,12 +26,38 @@ namespace mbed {
BufferedSerial::BufferedSerial(PinName tx, PinName rx, int baud) :
SerialBase(tx, rx, baud),
_blocking(true),
_tx_irq_enabled(false)
_tx_irq_enabled(false),
_dcd(NULL)
{
/* Attatch IRQ routines to the serial device. */
SerialBase::attach(callback(this, &BufferedSerial::rx_irq), RxIrq);
}
BufferedSerial::~BufferedSerial()
{
delete _dcd;
}
void BufferedSerial::DCD_IRQ()
{
_poll_change(this);
}
void BufferedSerial::set_data_carrier_detect(PinName DCD_pin, bool active_high)
{
delete _dcd;
_dcd = NULL;
if (DCD_pin != NC) {
_dcd = new InterruptIn(DCD_pin);
if (active_high) {
_dcd->fall(callback(this, &BufferedSerial::DCD_IRQ));
} else {
_dcd->rise(callback(this, &BufferedSerial::DCD_IRQ));
}
}
}
int BufferedSerial::close()
{
/* Does not let us pass a file descriptor. So how to close ?
@ -133,18 +159,28 @@ ssize_t BufferedSerial::read(void* buffer, size_t length)
return data_read;
}
bool BufferedSerial::hup() const
{
return _dcd && _dcd->read() != 0;
}
short BufferedSerial::poll(short events) const {
short revents = 0;
/* Check the Circular Buffer if space available for writing out */
if (!_txbuf.full()) {
revents |= POLLOUT;
}
if (!_rxbuf.empty()) {
revents |= POLLIN;
}
/* POLLHUP and POLLOUT are mutually exclusive */
if (hup()) {
revents |= POLLHUP;
} else if (!_txbuf.full()) {
revents |= POLLOUT;
}
/*TODO Handle other event types */
return revents;
@ -200,12 +236,11 @@ void BufferedSerial::tx_irq(void)
}
/* Report the File handler that data can be written to peripheral. */
if (was_full && !_txbuf.full()) {
if (was_full && !_txbuf.full() && !hup()) {
_poll_change(this);
}
}
} //namespace mbed
#endif //DEVICE_SERIAL

View File

@ -23,6 +23,7 @@
#include "FileHandle.h"
#include "SerialBase.h"
#include "InterruptIn.h"
#include "PlatformMutex.h"
#include "serial_api.h"
#include "CircularBuffer.h"
@ -36,6 +37,7 @@ public:
* @param baud The baud rate of the serial port (optional, defaults to MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE)
*/
BufferedSerial(PinName tx, PinName rx, int baud = MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
virtual ~BufferedSerial();
/** Equivalent to POSIX poll(). Derived from FileHandle.
* Provides a mechanism to multiplex input/output over a set of file handles.
@ -62,6 +64,8 @@ public:
virtual int set_blocking(bool blocking) { _blocking = blocking; return 0; }
void set_data_carrier_detect(PinName DCD_pin, bool active_high=false);
private:
/** Software serial buffers
@ -74,8 +78,14 @@ private:
bool _blocking;
bool _tx_irq_enabled;
InterruptIn *_dcd;
/** Device Hanged up
* Determines if the device hanged up on us.
*
* @return True, if hanged up
*/
bool hup() const;
/** ISRs for serial
* Routines to handle interrupts on serial pins.
@ -85,7 +95,7 @@ private:
void tx_irq(void);
void rx_irq(void);
void DCD_IRQ(void);
};
} //namespace mbed