NSAPI status callback changes

This is the original content of feature-status-callbacks, reviewed in
https://github.com/ARMmbed/mbed-os/pull/5457
pull/6032/head
Teemu Kultala 2017-11-06 14:18:03 +02:00 committed by Jarno Lamsa
parent 04f0f2b1aa
commit 5a7482667e
14 changed files with 477 additions and 93 deletions

View File

@ -19,11 +19,17 @@
/* Interface implementation */
EthernetInterface::EthernetInterface()
: _dhcp(true), _ip_address(), _netmask(), _gateway()
EthernetInterface::EthernetInterface() :
_dhcp(true),
_ip_address(),
_netmask(),
_gateway(),
_connection_status_cb(NULL),
_connect_status(NSAPI_STATUS_DISCONNECTED)
{
}
nsapi_error_t EthernetInterface::set_network(const char *ip_address, const char *netmask, const char *gateway)
{
_dhcp = false;
@ -94,3 +100,32 @@ NetworkStack *EthernetInterface::get_stack()
{
return nsapi_create_stack(&lwip_stack);
}
void EthernetInterface::attach(
Callback<void(nsapi_event_t, intptr_t)> status_cb)
{
_connection_status_cb = status_cb;
mbed_lwip_attach(netif_status_cb, this);
}
nsapi_connection_status_t EthernetInterface::get_connection_status() const
{
return _connect_status;
}
void EthernetInterface::netif_status_cb(void *ethernet_if_ptr,
nsapi_event_t reason, intptr_t parameter)
{
EthernetInterface *eth_ptr = static_cast<EthernetInterface*>(ethernet_if_ptr);
eth_ptr->_connect_status = (nsapi_connection_status_t)parameter;
if (eth_ptr->_connection_status_cb)
{
eth_ptr->_connection_status_cb(reason, parameter);
}
}
nsapi_error_t EthernetInterface::set_blocking(bool blocking)
{
mbed_lwip_set_blocking(blocking);
return NSAPI_ERROR_OK;
}

View File

@ -100,6 +100,26 @@ public:
*/
virtual const char *get_gateway();
/** Register callback for status reporting
*
* @param status_cb The callback for status changes
*/
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
/** Get the connection status
*
* @return The connection status according to nsapi_connection_status_t
*/
virtual nsapi_connection_status_t get_connection_status() const;
/** Set blocking status of connect() which by default should be blocking
*
* @param blocking true if connect is blocking
* @return 0 on success, negative error code on failure
*/
virtual nsapi_error_t set_blocking(bool blocking);
protected:
/** Provide access to the underlying stack
*
@ -111,6 +131,11 @@ protected:
char _ip_address[IPADDR_STRLEN_MAX];
char _netmask[NSAPI_IPv4_SIZE];
char _gateway[NSAPI_IPv4_SIZE];
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
nsapi_connection_status_t _connect_status;
static void netif_status_cb(void *, nsapi_event_t, intptr_t);
};

View File

@ -71,7 +71,7 @@ static struct lwip_socket {
} lwip_arena[MEMP_NUM_NETCONN];
static bool lwip_inited = false;
static bool lwip_connected = false;
static nsapi_connection_status_t lwip_connected = NSAPI_STATUS_DISCONNECTED;
static bool netif_inited = false;
static bool netif_is_ppp = false;
@ -155,6 +155,7 @@ static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u
static struct netif lwip_netif;
#if LWIP_DHCP
static bool lwip_dhcp = false;
static bool lwip_dhcp_has_to_be_set = false;
#endif
static char lwip_mac_address[NSAPI_MAC_SIZE];
@ -428,17 +429,65 @@ static void mbed_lwip_tcpip_init_irq(void *eh)
sys_sem_signal(&lwip_tcpip_inited);
}
/** This is a pointer to an Ethernet IF, whose callback will be called in case
* of network connection status changes
*/
static void *lwip_status_cb_handle = NULL;
/** This function is called when the netif state is set to up or down
*/
static mbed_lwip_client_callback lwip_client_callback = NULL;
/** The blocking status of the if
*/
static bool lwip_blocking = true;
static bool lwip_ppp = false;
static nsapi_error_t mbed_set_dhcp(struct netif *lwip_netif)
{
if (!lwip_ppp) {
netif_set_up(lwip_netif);
}
#if LWIP_DHCP
if (lwip_dhcp && lwip_dhcp_has_to_be_set) {
err_t err = dhcp_start(lwip_netif);
lwip_dhcp_has_to_be_set = false;
if (err) {
lwip_connected = NSAPI_STATUS_DISCONNECTED;
if (lwip_client_callback) {
lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
return NSAPI_ERROR_DHCP_FAILURE;
}
}
#endif
return NSAPI_ERROR_OK;
}
static sys_sem_t lwip_netif_linked;
static sys_sem_t lwip_netif_unlinked;
static void mbed_lwip_netif_link_irq(struct netif *lwip_netif)
{
if (netif_is_link_up(lwip_netif)) {
sys_sem_signal(&lwip_netif_linked);
nsapi_error_t dhcp_status = mbed_set_dhcp(lwip_netif);
if (lwip_blocking && dhcp_status == NSAPI_ERROR_OK) {
sys_sem_signal(&lwip_netif_linked);
} else if (dhcp_status != NSAPI_ERROR_OK) {
netif_set_down(lwip_netif);
}
} else {
sys_sem_signal(&lwip_netif_unlinked);
}
}
static char lwip_has_addr_state = 0;
#define HAS_ANY_ADDR 1
@ -452,28 +501,71 @@ static sys_sem_t lwip_netif_has_pref_addr;
static sys_sem_t lwip_netif_has_both_addr;
#endif
static void mbed_lwip_netif_status_irq(struct netif *lwip_netif)
{
if (netif_is_up(lwip_netif)) {
bool dns_addr_has_to_be_added = false;
if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) {
sys_sem_signal(&lwip_netif_has_any_addr);
if (lwip_blocking) {
sys_sem_signal(&lwip_netif_has_any_addr);
}
lwip_has_addr_state |= HAS_ANY_ADDR;
dns_addr_has_to_be_added = true;
}
#if PREF_ADDR_TIMEOUT
if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) {
sys_sem_signal(&lwip_netif_has_pref_addr);
if (lwip_blocking) {
sys_sem_signal(&lwip_netif_has_pref_addr);
}
lwip_has_addr_state |= HAS_PREF_ADDR;
dns_addr_has_to_be_added = true;
}
#endif
#if BOTH_ADDR_TIMEOUT
if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) {
sys_sem_signal(&lwip_netif_has_both_addr);
if (lwip_blocking) {
sys_sem_signal(&lwip_netif_has_both_addr);
}
lwip_has_addr_state |= HAS_BOTH_ADDR;
dns_addr_has_to_be_added = true;
}
#endif
if (dns_addr_has_to_be_added && !lwip_blocking) {
add_dns_addr(lwip_netif);
}
if (lwip_has_addr_state & HAS_ANY_ADDR) {
lwip_connected = NSAPI_STATUS_GLOBAL_UP;
}
} else {
lwip_connected = NSAPI_STATUS_DISCONNECTED;
}
if (lwip_client_callback) {
lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, lwip_connected);
}
}
void mbed_lwip_set_blocking(bool blocking)
{
lwip_blocking = blocking;
}
void mbed_lwip_attach(mbed_lwip_client_callback client_callback, void *status_cb_handle)
{
lwip_client_callback = client_callback;
lwip_status_cb_handle = status_cb_handle;
}
nsapi_connection_status_t mbed_lwip_netif_status_check(void)
{
return lwip_connected;
}
#if LWIP_ETHERNET
static void mbed_lwip_set_mac_address(struct netif *netif)
{
@ -599,7 +691,6 @@ nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac)
#if LWIP_ETHERNET
// Choose a MAC address - driver can override
mbed_lwip_set_mac_address(&lwip_netif);
// Set up network
if (!netif_add(&lwip_netif,
#if LWIP_IPV4
@ -608,10 +699,8 @@ nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac)
emac, MBED_NETIF_INIT_FN, tcpip_input)) {
return NSAPI_ERROR_DEVICE_ERROR;
}
// Note the MAC address actually in use
mbed_lwip_record_mac_address(&lwip_netif);
#if !DEVICE_EMAC
eth_arch_enable_interrupts();
#endif
@ -634,19 +723,34 @@ nsapi_error_t mbed_lwip_init(emac_interface_t *emac)
return ret;
}
// Backwards compatibility with people using DEVICE_EMAC
nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
{
return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw, DEFAULT_STACK);
}
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack)
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw,
const nsapi_ip_stack_t stack)
{
// Check if we've already connected
if (lwip_connected) {
return NSAPI_ERROR_PARAMETER;
if (lwip_connected == NSAPI_STATUS_GLOBAL_UP) {
return NSAPI_ERROR_IS_CONNECTED;
} else if (lwip_connected == NSAPI_STATUS_CONNECTING) {
return NSAPI_ERROR_ALREADY;
}
lwip_connected = NSAPI_STATUS_CONNECTING;
lwip_ppp = ppp;
#if LWIP_DHCP
lwip_dhcp_has_to_be_set = true;
if (stack != IPV6_STACK) {
lwip_dhcp = dhcp;
} else {
lwip_dhcp = false;
}
#endif
mbed_lwip_core_init();
nsapi_error_t ret;
@ -666,9 +770,15 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
}
if (ret != NSAPI_ERROR_OK) {
lwip_connected = NSAPI_STATUS_DISCONNECTED;
return ret;
}
if (lwip_client_callback) {
lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING);
}
netif_inited = true;
if (ppp) {
netif_is_ppp = ppp;
@ -717,6 +827,10 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
if (!inet_aton(ip, &ip_addr) ||
!inet_aton(netmask, &netmask_addr) ||
!inet_aton(gw, &gw_addr)) {
lwip_connected = NSAPI_STATUS_DISCONNECTED;
if (lwip_client_callback) {
lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
return NSAPI_ERROR_PARAMETER;
}
@ -728,45 +842,44 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
if (ppp) {
err_t err = ppp_lwip_connect();
if (err) {
lwip_connected = NSAPI_STATUS_DISCONNECTED;
if (lwip_client_callback) {
lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
return mbed_lwip_err_remap(err);
}
}
if (!netif_is_link_up(&lwip_netif)) {
if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) {
if (ppp) {
(void) ppp_lwip_disconnect();
if (lwip_blocking) {
if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) {
if (ppp) {
ppp_lwip_disconnect();
}
return NSAPI_ERROR_NO_CONNECTION;
}
return NSAPI_ERROR_NO_CONNECTION;
}
} else {
ret = mbed_set_dhcp(&lwip_netif);
if (ret != NSAPI_ERROR_OK) {
return ret;
}
}
if (!ppp) {
netif_set_up(&lwip_netif);
}
#if LWIP_DHCP
if (stack != IPV6_STACK) {
// Connect to the network
lwip_dhcp = dhcp;
if (lwip_dhcp) {
err_t err = dhcp_start(&lwip_netif);
if (err) {
if (lwip_blocking) {
// If doesn't have address
if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) {
if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) {
if (ppp) {
ppp_lwip_disconnect();
}
return NSAPI_ERROR_DHCP_FAILURE;
}
}
}
#endif
// If doesn't have address
if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) {
if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) {
if (ppp) {
(void) ppp_lwip_disconnect();
}
return NSAPI_ERROR_DHCP_FAILURE;
}
} else {
return NSAPI_ERROR_OK;
}
#if PREF_ADDR_TIMEOUT
@ -790,8 +903,7 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
add_dns_addr(&lwip_netif);
lwip_connected = true;
return 0;
return NSAPI_ERROR_OK;
}
#if LWIP_IPV6
@ -812,7 +924,7 @@ nsapi_error_t mbed_lwip_bringdown(void)
nsapi_error_t mbed_lwip_bringdown_2(bool ppp)
{
// Check if we've connected
if (!lwip_connected) {
if (lwip_connected == NSAPI_STATUS_DISCONNECTED) {
return NSAPI_ERROR_PARAMETER;
}
@ -822,6 +934,7 @@ nsapi_error_t mbed_lwip_bringdown_2(bool ppp)
dhcp_release(&lwip_netif);
dhcp_stop(&lwip_netif);
lwip_dhcp = false;
lwip_dhcp_has_to_be_set = false;
}
#endif
@ -856,7 +969,7 @@ nsapi_error_t mbed_lwip_bringdown_2(bool ppp)
sys_sem_new(&lwip_netif_has_both_addr, 0);
#endif
lwip_has_addr_state = 0;
lwip_connected = false;
lwip_connected = NSAPI_STATUS_DISCONNECTED;
return 0;
}
@ -967,7 +1080,7 @@ static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t
static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto)
{
// check if network is connected
if (!lwip_connected) {
if (lwip_connected == NSAPI_STATUS_DISCONNECTED) {
return NSAPI_ERROR_NO_CONNECTION;
}

View File

@ -20,6 +20,7 @@
#include "nsapi.h"
#include "emac_api.h"
#include "lwip/opt.h"
#include "netif.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -28,11 +29,15 @@ extern "C" {
// drivers attach through these.
nsapi_error_t mbed_lwip_init(emac_interface_t *emac);
nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac);
nsapi_connection_status_t mbed_lwip_netif_status_check(void);
nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw);
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack);
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw,
const nsapi_ip_stack_t stack);
typedef void (*mbed_lwip_client_callback)(void *ethernet_if_ptr, nsapi_event_t reason, intptr_t parameter);
void mbed_lwip_attach(mbed_lwip_client_callback status_cb, void *status_cb_handle);
void mbed_lwip_set_blocking(bool blocking);
nsapi_error_t mbed_lwip_bringdown(void);
nsapi_error_t mbed_lwip_bringdown_2(bool ppp);
const char *mbed_lwip_get_mac_address(void);
char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen);
char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen);

View File

@ -59,7 +59,7 @@ static bool ppp_active = false;
static const char *login;
static const char *pwd;
static sys_sem_t ppp_close_sem;
static Callback<void(nsapi_error_t)> connection_status_cb;
static Callback<void(nsapi_event_t, intptr_t)> connection_status_cb;
static EventQueue *prepare_event_queue()
{
@ -207,8 +207,10 @@ static void ppp_link_status(ppp_pcb *pcb, int err_code, void *ctx)
}
if (err_code == PPPERR_NONE) {
/* suppress generating a callback event for connection up
* Because connect() call is blocking, why wait for a callback */
/* status changes have to be reported */
if (connection_status_cb) {
connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_GLOBAL_UP);
}
return;
}
@ -221,7 +223,7 @@ static void ppp_link_status(ppp_pcb *pcb, int err_code, void *ctx)
/* Alright, PPP interface is down, we need to notify upper layer */
if (connection_status_cb) {
connection_status_cb(mapped_err_code);
connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
}
@ -351,7 +353,13 @@ nsapi_error_t nsapi_ppp_error_code()
return connect_error_code;
}
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_error_t)> cb, const char *uname, const char *password, const nsapi_ip_stack_t stack)
nsapi_error_t nsapi_ppp_set_blocking(bool blocking)
{
mbed_lwip_set_blocking(blocking);
return NSAPI_ERROR_OK;
}
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_event_t, intptr_t)> cb, const char *uname, const char *password, const nsapi_ip_stack_t stack)
{
if (my_stream) {
return NSAPI_ERROR_PARAMETER;

View File

@ -62,6 +62,25 @@ public:
* */
void mesh_network_handler(mesh_connection_status_t status);
/** Register callback for status reporting
*
* @param status_cb The callback for status changes
*/
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
/** Get the connection status
*
* @return The connection status according to ConnectionStatusType
*/
virtual nsapi_connection_status_t get_connection_status() const;
/** Set blocking status of connect() which by default should be blocking
*
* @param blocking true if connect is blocking
* @return 0 on success, negative error code on failure
*/
virtual nsapi_error_t set_blocking(bool blocking);
protected:
MeshInterfaceNanostack();
MeshInterfaceNanostack(NanostackPhy *phy);
@ -86,6 +105,10 @@ protected:
char ip_addr_str[40];
char mac_addr_str[24];
Semaphore connect_semaphore;
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
nsapi_connection_status_t _connect_status;
bool _blocking;
};
#endif /* MESHINTERFACENANOSTACK_H */

View File

@ -17,10 +17,14 @@
#include "MeshInterfaceNanostack.h"
#include "NanostackInterface.h"
#include "mesh_system.h"
#include "net_interface.h"
MeshInterfaceNanostack::MeshInterfaceNanostack()
: phy(NULL), _network_interface_id(-1), _device_id(-1), _eui64(),
ip_addr_str(), mac_addr_str(), connect_semaphore(0)
ip_addr_str(), mac_addr_str(), connect_semaphore(0),
_connection_status_cb(NULL), _connect_status(NSAPI_STATUS_DISCONNECTED),
_blocking(true)
{
// Nothing to do
}
@ -45,11 +49,27 @@ void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t statu
{
nanostack_lock();
if (status == MESH_CONNECTED) {
if (status == MESH_CONNECTED && _blocking) {
connect_semaphore.release();
}
nanostack_unlock();
if (status == MESH_CONNECTED) {
uint8_t temp_ipv6[16];
if (!arm_net_address_get(_network_interface_id, ADDR_IPV6_GP, temp_ipv6)) {
_connect_status = NSAPI_STATUS_GLOBAL_UP;
} else {
_connect_status = NSAPI_STATUS_LOCAL_UP;
}
} else {
_connect_status = NSAPI_STATUS_DISCONNECTED;
}
if (_connection_status_cb) {
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
}
}
nsapi_error_t MeshInterfaceNanostack::register_phy()
@ -98,3 +118,20 @@ const char *MeshInterfaceNanostack::get_mac_address()
{
return mac_addr_str;
}
nsapi_connection_status_t MeshInterfaceNanostack::get_connection_status() const
{
return _connect_status;
}
void MeshInterfaceNanostack::attach(
Callback<void(nsapi_event_t, intptr_t)> status_cb)
{
_connection_status_cb = status_cb;
}
nsapi_error_t MeshInterfaceNanostack::set_blocking(bool blocking)
{
_blocking = blocking;
return NSAPI_ERROR_OK;
}

View File

@ -14,6 +14,12 @@ nsapi_error_t ThreadInterface::initialize(NanostackRfPhy *phy)
int ThreadInterface::connect()
{
if (_connect_status == NSAPI_STATUS_GLOBAL_UP || _connect_status == NSAPI_STATUS_LOCAL_UP) {
return NSAPI_ERROR_IS_CONNECTED;
} else if (_connect_status == NSAPI_STATUS_CONNECTING) {
return NSAPI_ERROR_ALREADY;
}
nanostack_lock();
if (register_phy() < 0) {
@ -42,10 +48,16 @@ int ThreadInterface::connect()
// -routers will create new network and get local connectivity
// -end devices will get connectivity once attached to existing network
// -devices without network settings gets connectivity once commissioned and attached to network
int32_t count = connect_semaphore.wait(osWaitForever);
_connect_status = NSAPI_STATUS_CONNECTING;
if (_connection_status_cb) {
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING);
}
if (_blocking) {
int32_t count = connect_semaphore.wait(osWaitForever);
if (count <= 0) {
return NSAPI_ERROR_DHCP_FAILURE; // sort of...
if (count <= 0) {
return NSAPI_ERROR_DHCP_FAILURE; // sort of...
}
}
return 0;
}

View File

@ -65,3 +65,17 @@ nsapi_error_t NetworkInterface::add_dns_server(const SocketAddress &address)
return get_stack()->add_dns_server(address);
}
void NetworkInterface::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
{
}
nsapi_connection_status_t NetworkInterface::get_connection_status() const
{
return NSAPI_STATUS_ERROR_UNSUPPORTED;
}
nsapi_error_t NetworkInterface::set_blocking(bool blocking)
{
return NSAPI_ERROR_UNSUPPORTED;
}

View File

@ -19,6 +19,7 @@
#include "netsocket/nsapi_types.h"
#include "netsocket/SocketAddress.h"
#include "Callback.h"
// Predeclared class
class NetworkStack;
@ -31,6 +32,9 @@ class NetworkStack;
*/
class NetworkInterface {
public:
virtual ~NetworkInterface() {};
/** Get the local MAC address
@ -126,6 +130,26 @@ public:
*/
virtual nsapi_error_t add_dns_server(const SocketAddress &address);
/** Register callback for status reporting
*
* @param status_cb The callback for status changes
*/
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
/** Get the connection status
*
* @return The connection status according to ConnectionStatusType
*/
virtual nsapi_connection_status_t get_connection_status() const;
/** Set blocking status of connect() which by default should be blocking
*
* @param blocking true if connect is blocking
* @return 0 on success, negative error code on failure
*/
virtual nsapi_error_t set_blocking(bool blocking);
protected:
friend class Socket;
friend class UDPSocket;

View File

@ -263,9 +263,11 @@ PPPCellularInterface::PPPCellularInterface(FileHandle *fh, bool debug)
_fh = fh;
_debug_trace_on = debug;
_stack = DEFAULT_STACK;
_connection_status_cb = NULL;
_connect_status = NSAPI_STATUS_DISCONNECTED;
_connect_is_blocking = true;
dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
dev_info.ppp_connection_up = false;
}
@ -304,9 +306,13 @@ void PPPCellularInterface::modem_debug_on(bool on)
_debug_trace_on = on;
}
void PPPCellularInterface::connection_status_cb(Callback<void(nsapi_error_t)> cb)
void PPPCellularInterface::ppp_status_cb(nsapi_event_t event, intptr_t parameter)
{
_connection_status_cb = cb;
_connect_status = (nsapi_connection_status_t)parameter;
if (_connection_status_cb) {
_connection_status_cb(event, parameter);
}
}
/**
@ -398,7 +404,7 @@ bool PPPCellularInterface::nwk_registration(uint8_t nwk_type)
bool PPPCellularInterface::is_connected()
{
return dev_info.ppp_connection_up;
return (_connect_status == NSAPI_STATUS_GLOBAL_UP || _connect_status == NSAPI_STATUS_LOCAL_UP);
}
// Get the SIM card going.
@ -560,13 +566,23 @@ nsapi_error_t PPPCellularInterface::connect()
bool did_init = false;
const char *apn_config = NULL;
if (dev_info.ppp_connection_up) {
if (is_connected()) {
return NSAPI_ERROR_IS_CONNECTED;
} else if (_connect_status == NSAPI_STATUS_CONNECTING) {
return NSAPI_ERROR_ALREADY;
}
_connect_status = NSAPI_STATUS_CONNECTING;
if (_connection_status_cb) {
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING);
}
do {
retry_init:
retcode = NSAPI_ERROR_OK;
/* setup AT parser */
setup_at_parser();
@ -578,12 +594,13 @@ nsapi_error_t PPPCellularInterface::connect()
enable_hup(false);
if (!power_up()) {
return NSAPI_ERROR_DEVICE_ERROR;
retcode = NSAPI_ERROR_DEVICE_ERROR;
break;
}
retcode = initialize_sim_card();
if (retcode != NSAPI_ERROR_OK) {
return retcode;
break;
}
success = nwk_registration(PACKET_SWITCHED) //perform network registration
@ -595,7 +612,8 @@ nsapi_error_t PPPCellularInterface::connect()
&& set_CNMI(_at);//set new SMS indication
if (!success) {
return NSAPI_ERROR_NO_CONNECTION;
retcode = NSAPI_ERROR_NO_CONNECTION;
break;
}
#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
@ -608,7 +626,7 @@ nsapi_error_t PPPCellularInterface::connect()
if (set_sim_pin_check_request) {
retcode = do_sim_pin_check(_at, _pin);
if (retcode != NSAPI_ERROR_OK) {
return retcode;
break;
}
/* set this request to false, as it is unnecessary to repeat in case of retry */
set_sim_pin_check_request = false;
@ -618,7 +636,7 @@ nsapi_error_t PPPCellularInterface::connect()
if (change_pin) {
retcode = do_change_sim_pin(_at, _pin, _new_pin);
if (retcode != NSAPI_ERROR_OK) {
return retcode;
break;
}
/* set this request to false, as it is unnecessary to repeat in case of retry */
change_pin = false;
@ -636,12 +654,13 @@ nsapi_error_t PPPCellularInterface::connect()
//sets up APN and IP protocol for external PDP context
retcode = setup_context_and_credentials();
if (retcode != NSAPI_ERROR_OK) {
return retcode;
break;
}
if (!success) {
shutdown_at_parser();
return NSAPI_ERROR_NO_CONNECTION;
retcode = NSAPI_ERROR_NO_CONNECTION;
break;
}
initialized = true;
@ -668,7 +687,8 @@ nsapi_error_t PPPCellularInterface::connect()
/* shutdown AT parser before notifying application of the failure */
shutdown_at_parser();
return NSAPI_ERROR_NO_CONNECTION;
retcode = NSAPI_ERROR_NO_CONNECTION;
break;
}
/* This is the success case.
@ -681,12 +701,18 @@ nsapi_error_t PPPCellularInterface::connect()
/* Initialize PPP
* mbed_ppp_init() is a blocking call, it will block until
* connected, or timeout after 30 seconds*/
retcode = nsapi_ppp_connect(_fh, _connection_status_cb, _uname, _pwd, _stack);
if (retcode == NSAPI_ERROR_OK) {
dev_info.ppp_connection_up = true;
}
retcode = nsapi_ppp_connect(_fh, callback(this, &PPPCellularInterface::ppp_status_cb), _uname, _pwd, _stack);
} while ((_connect_status == NSAPI_STATUS_CONNECTING && _connect_is_blocking) &&
apn_config && *apn_config);
if (retcode != NSAPI_ERROR_OK) {
_connect_status = NSAPI_STATUS_DISCONNECTED;
if (_connection_status_cb) {
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
}
}while(!dev_info.ppp_connection_up && apn_config && *apn_config);
return retcode;
}
@ -699,13 +725,7 @@ nsapi_error_t PPPCellularInterface::connect()
*/
nsapi_error_t PPPCellularInterface::disconnect()
{
nsapi_error_t ret = nsapi_ppp_disconnect(_fh);
if (ret == NSAPI_ERROR_OK) {
dev_info.ppp_connection_up = false;
return NSAPI_ERROR_OK;
}
return ret;
return nsapi_ppp_disconnect(_fh);
}
const char *PPPCellularInterface::get_ip_address()
@ -797,4 +817,23 @@ NetworkStack *PPPCellularInterface::get_stack()
return nsapi_ppp_get_stack();
}
void PPPCellularInterface::attach(
Callback<void(nsapi_event_t, intptr_t)> status_cb)
{
_connection_status_cb = status_cb;
}
nsapi_connection_status_t PPPCellularInterface::get_connection_status() const
{
return _connect_status;
}
nsapi_error_t PPPCellularInterface::set_blocking(bool blocking)
{
return nsapi_ppp_set_blocking(blocking);
}
#endif // NSAPI_PPP_AVAILABLE

View File

@ -85,7 +85,6 @@ typedef struct {
char imei[15+1]; //!< International Mobile Equipment Identity
char meid[18+1]; //!< Mobile Equipment IDentifier
int flags;
bool ppp_connection_up;
radio_access_nwk_type rat;
nwk_registration_status_csd reg_status_csd;
nwk_registration_status_psd reg_status_psd;
@ -166,7 +165,6 @@ public:
* the lookup table then the driver tries to resort to default APN settings.
*
* Preferred method is to setup APN using 'set_credentials()' API.
* @return 0 on success, negative error code on failure
*/
virtual nsapi_error_t connect();
@ -231,11 +229,6 @@ public:
*/
virtual const char *get_gateway();
/** Get notified if the connection gets lost
*
* @param cb user defined callback
*/
void connection_status_cb(Callback<void(nsapi_error_t)> cb);
/** Turn modem debug traces on
*
@ -243,6 +236,25 @@ public:
*/
void modem_debug_on(bool on);
/** Register callback for status reporting
*
* @param status_cb The callback for status changes
*/
virtual void attach(Callback<void(nsapi_event_t, intptr_t)> status_cb);
/** Get the connection status
*
* @return The connection status according to nsapi_connection_status_t
*/
virtual nsapi_connection_status_t get_connection_status() const;
/** Set blocking status of connect() which by default should be blocking
*
* @param blocking true if connect is blocking
* @return 0 on success, negative error code on failure
*/
virtual nsapi_error_t set_blocking(bool blocking);
private:
FileHandle *_fh;
ATCmdParser *_at;
@ -253,14 +265,17 @@ private:
const char *_pwd;
bool _debug_trace_on;
nsapi_ip_stack_t _stack;
Callback<void(nsapi_error_t)> _connection_status_cb;
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
nsapi_connection_status_t _connect_status;
bool _connect_is_blocking;
void base_initialization();
void setup_at_parser();
void shutdown_at_parser();
nsapi_error_t initialize_sim_card();
nsapi_error_t setup_context_and_credentials();
bool power_up();
void power_down();
void power_down();
void ppp_status_cb(nsapi_event_t, intptr_t);
protected:
/** Enable or disable hang-up detection

View File

@ -29,6 +29,13 @@ namespace mbed {
*/
NetworkStack *nsapi_ppp_get_stack();
/** Set connection blocking parameter
*
* @param blocking True if connection is blocking
*
* @return 0 on success, negative error code on failure
*/
nsapi_error_t nsapi_ppp_set_blocking(bool blocking);
/** Connect to a PPP pipe
*
@ -40,7 +47,7 @@ NetworkStack *nsapi_ppp_get_stack();
*
* @return 0 on success, negative error code on failure
*/
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_error_t)> status_cb=0, const char *uname=0, const char *pwd=0, const nsapi_ip_stack_t stack=DEFAULT_STACK);
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_event_t, intptr_t)> status_cb=0, const char *uname=0, const char *pwd=0, const nsapi_ip_stack_t stack=DEFAULT_STACK);
/** Close a PPP connection
*

View File

@ -56,6 +56,33 @@ enum nsapi_error {
NSAPI_ERROR_ADDRESS_IN_USE = -3018, /*!< Address already in use */
};
/** Enum of connection status types
*
* Valid error codes have negative values.
*
* @enum nsapi_connection_status
*/
typedef enum nsapi_connection_status {
NSAPI_STATUS_LOCAL_UP = 0, /*!< local IP address set */
NSAPI_STATUS_GLOBAL_UP = 1, /*!< global IP address set */
NSAPI_STATUS_DISCONNECTED = 2, /*!< no connection to network */
NSAPI_STATUS_CONNECTING = 3, /*!< connecting to network */
NSAPI_STATUS_ERROR_UNSUPPORTED = NSAPI_ERROR_UNSUPPORTED
} nsapi_connection_status_t;
/** Enum of event types
*
* Event callbacks are accompanied with an event-dependent parameter passed as an intptr_t.
*
* @enum nsapi_event
*/
typedef enum nsapi_event {
NSAPI_EVENT_CONNECTION_STATUS_CHANGE = 0 /*!< network connection status has changed, the parameter = new status (nsapi_connection_status_t) */
} nsapi_event_t;
/** Type used to represent error codes
*
* This is a separate type from enum nsapi_error to avoid breaking