Merge pull request #6032 from jarlamsa/status-callbacks

Status callbacks
pull/6112/head
Kevin Bracey 2018-02-15 13:02:10 +02:00 committed by GitHub
commit 984cc1ab50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 597 additions and 100 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

@ -178,9 +178,11 @@ lwip_hook_tcp_isn(const void *local_ip_ptr, u16_t local_port,
/* The secret and padding are already filled in. */
/* Generate the hash, using MD5. */
lwip_md5_init(&ctx);
lwip_md5_starts(&ctx);
lwip_md5_update(&ctx, input, sizeof(input));
lwip_md5_finish(&ctx, output);
lwip_md5_free(&ctx);
/* Arbitrarily take the first 32 bits from the generated hash. */
MEMCPY(&isn, output, sizeof(isn));

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,66 @@ 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);
netif_set_down(lwip_netif);
}
}
static char lwip_has_addr_state = 0;
#define HAS_ANY_ADDR 1
@ -452,28 +502,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 +692,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 +700,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 +724,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 +771,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 +828,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 +843,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 +904,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 +925,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 +935,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 +970,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 +1081,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

@ -67,6 +67,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);
@ -91,6 +110,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

@ -45,9 +45,12 @@ typedef enum {
*/
typedef enum {
MESH_CONNECTED = 0, /*<! connected to network */
MESH_CONNECTED_LOCAL, /*<! connected to network, got local IP */
MESH_CONNECTED_GLOBAL, /*<! connected to network, got global IP */
MESH_DISCONNECTED, /*<! disconnected from network */
MESH_BOOTSTRAP_START_FAILED, /*<! error during bootstrap start */
MESH_BOOTSTRAP_FAILED /*<! error in bootstrap */
MESH_BOOTSTRAP_FAILED, /*<! error in bootstrap */
MESH_BOOTSTRAP_STARTED /*<! bootstrap started */
} mesh_connection_status_t;
/*

View File

@ -17,10 +17,15 @@
#include "MeshInterfaceNanostack.h"
#include "NanostackInterface.h"
#include "mesh_system.h"
#include "net_interface.h"
#include "thread_management_if.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 +50,37 @@ void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t statu
{
nanostack_lock();
if (status == MESH_CONNECTED) {
if ((status == MESH_CONNECTED || status == MESH_CONNECTED_LOCAL ||
status == MESH_CONNECTED_GLOBAL) && _blocking) {
connect_semaphore.release();
}
nanostack_unlock();
if (status == MESH_CONNECTED) {
uint8_t temp_ipv6_global[16];
uint8_t temp_ipv6_local[16];
if (arm_net_address_get(_network_interface_id, ADDR_IPV6_LL, temp_ipv6_local) == 0) {
_connect_status = NSAPI_STATUS_LOCAL_UP;
}
if (arm_net_address_get(_network_interface_id, ADDR_IPV6_GP, temp_ipv6_global) == 0
&& (memcmp(temp_ipv6_global, temp_ipv6_local, 16) != 0)) {
_connect_status = NSAPI_STATUS_GLOBAL_UP;
}
} else if (status == MESH_CONNECTED_LOCAL ) {
_connect_status = NSAPI_STATUS_LOCAL_UP;
} else if (status == MESH_CONNECTED_GLOBAL) {
_connect_status = NSAPI_STATUS_GLOBAL_UP;
} else if (status == MESH_BOOTSTRAP_STARTED) {
_connect_status = NSAPI_STATUS_CONNECTING;
} 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 +129,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

@ -58,9 +58,12 @@ typedef enum {
typedef struct {
void (*mesh_api_cb)(mesh_connection_status_t nwk_status);
tasklet_state_t tasklet_state;
mesh_connection_status_t connection_status;
timeout_t *poll_network_status_timeout;
int8_t node_main_tasklet_id;
int8_t network_interface_id;
int8_t tasklet;
uint8_t ip[16];
} tasklet_data_str_t;
/* Tasklet data */
@ -74,7 +77,7 @@ static void enet_tasklet_main(arm_event_s *event);
static void enet_tasklet_network_state_changed(mesh_connection_status_t status);
static void enet_tasklet_parse_network_event(arm_event_s *event);
static void enet_tasklet_configure_and_connect_to_network(void);
static void enet_tasklet_poll_network_status(void *param);
/*
* \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver.
* @param event, describes the sender, receiver and event type.
@ -145,18 +148,20 @@ void enet_tasklet_parse_network_event(arm_event_s *event)
if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) {
tr_info("IPv6 bootstrap ready");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY;
enet_tasklet_network_state_changed(MESH_CONNECTED);
enet_tasklet_poll_network_status(NULL);
}
break;
case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
/* No ND Router at current Channel Stack is Already at Idle state */
tr_info("Bootstrap fail");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
enet_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_NWK_CONNECTION_DOWN:
/* Connection to Access point is lost wait for Scan Result */
tr_info("Connection lost");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
enet_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
default:
tr_warn("Unknown event %d", status);
@ -172,6 +177,31 @@ void enet_tasklet_parse_network_event(arm_event_s *event)
}
}
static void enet_tasklet_poll_network_status(void *param)
{
/* Check if we do have an IP */
uint8_t temp_ipv6[16];
if (arm_net_address_get(tasklet_data_ptr->network_interface_id, ADDR_IPV6_GP, temp_ipv6) == 0) {
/* Check if this is link local address or not */
if (memcmp(temp_ipv6, tasklet_data_ptr->ip, 16) == 0) {
return;
} else {
memcpy(tasklet_data_ptr->ip, temp_ipv6, 16);
uint8_t temp_ipv6_local[16];
if (arm_net_address_get(tasklet_data_ptr->network_interface_id, ADDR_IPV6_LL, temp_ipv6_local) == 0
&& (memcmp(temp_ipv6, temp_ipv6_local, 16) != 0)) {
enet_tasklet_network_state_changed(MESH_CONNECTED_GLOBAL);
} else {
enet_tasklet_network_state_changed(MESH_CONNECTED_LOCAL);;
}
}
} else {
if (tasklet_data_ptr->connection_status != MESH_DISCONNECTED &&
tasklet_data_ptr->connection_status != MESH_BOOTSTRAP_STARTED)
enet_tasklet_network_state_changed(MESH_DISCONNECTED);
}
}
/*
* \brief Configure and establish network connection
*
@ -179,6 +209,7 @@ void enet_tasklet_parse_network_event(arm_event_s *event)
void enet_tasklet_configure_and_connect_to_network(void)
{
arm_nwk_interface_up(tasklet_data_ptr->network_interface_id);
enet_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
}
/*
@ -186,6 +217,7 @@ void enet_tasklet_configure_and_connect_to_network(void)
*/
void enet_tasklet_network_state_changed(mesh_connection_status_t status)
{
tasklet_data_ptr->connection_status = status;
if (tasklet_data_ptr->mesh_api_cb) {
(tasklet_data_ptr->mesh_api_cb)(status);
}
@ -219,6 +251,8 @@ int8_t enet_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id)
tasklet_data_ptr->mesh_api_cb = callback;
tasklet_data_ptr->network_interface_id = nwk_interface_id;
tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED;
tasklet_data_ptr->poll_network_status_timeout =
eventOS_timeout_every_ms(enet_tasklet_poll_network_status, 2000, NULL);
if (re_connecting == false) {
tasklet_data_ptr->tasklet = eventOS_event_handler_create(&enet_tasklet_main,
@ -248,6 +282,7 @@ int8_t enet_tasklet_disconnect(bool send_cb)
}
}
tasklet_data_ptr->mesh_api_cb = NULL;
eventOS_timeout_cancel(tasklet_data_ptr->poll_network_status_timeout);
}
return status;
}

View File

@ -187,23 +187,28 @@ void nd_tasklet_parse_network_event(arm_event_s *event)
/* Link Layer Active Scan Fail, Stack is Already at Idle state */
tr_debug("Link Layer Scan Fail: No Beacons");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
/* No ND Router at current Channel Stack is Already at Idle state */
tr_debug("ND Scan/ GP REG fail");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_NWK_CONNECTION_DOWN:
/* Connection to Access point is lost wait for Scan Result */
tr_debug("ND/RPL scan new network");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_NWK_PARENT_POLL_FAIL:
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_AUHTENTICATION_FAIL:
tr_debug("Network authentication fail");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
nd_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
default:
tr_warn("Unknown event %d", status);
@ -277,6 +282,7 @@ void nd_tasklet_configure_and_connect_to_network(void)
if (status >= 0) {
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
tr_info("Start 6LoWPAN ND Bootstrap");
nd_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
} else {
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
tr_err("Bootstrap start failed, %d", status);

View File

@ -67,6 +67,8 @@ typedef struct {
void (*mesh_api_cb)(mesh_connection_status_t nwk_status);
channel_list_s channel_list;
tasklet_state_t tasklet_state;
mesh_connection_status_t connection_status;
timeout_t *poll_network_status_timeout;
int8_t tasklet;
net_6lowpan_mode_e operating_mode;
@ -75,7 +77,8 @@ typedef struct {
/** Default network ID*/
uint8_t networkid[16];
uint8_t extented_panid[8];
uint8_t extented_panid[8];
uint8_t ip[16];
} thread_tasklet_data_str_t;
@ -88,6 +91,7 @@ void thread_tasklet_main(arm_event_s *event);
void thread_tasklet_network_state_changed(mesh_connection_status_t status);
void thread_tasklet_parse_network_event(arm_event_s *event);
void thread_tasklet_configure_and_connect_to_network(void);
void thread_tasklet_poll_network_status(void *param);
#define TRACE_THREAD_TASKLET
#ifndef TRACE_THREAD_TASKLET
#define thread_tasklet_trace_bootstrap_info() ((void) 0)
@ -127,8 +131,19 @@ void thread_tasklet_main(arm_event_s *event)
thread_tasklet_data_ptr->tasklet);
if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) {
int8_t status;
tr_debug("Restart bootstrap");
arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id);
status = arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id);
if (status >= 0) {
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router");
thread_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
} else {
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
tr_err("Bootstrap start failed, %d", status);
thread_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED);
}
}
break;
@ -165,30 +180,36 @@ void thread_tasklet_parse_network_event(arm_event_s *event)
tr_info("Thread bootstrap ready");
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY;
thread_tasklet_trace_bootstrap_info();
thread_tasklet_network_state_changed(MESH_CONNECTED);
/* We are connected, for Local or Global IP */
thread_tasklet_poll_network_status(NULL);
}
break;
case ARM_NWK_NWK_SCAN_FAIL:
/* Link Layer Active Scan Fail, Stack is Already at Idle state */
tr_debug("Link Layer Scan Fail: No Beacons");
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
/* No ND Router at current Channel Stack is Already at Idle state */
tr_debug("ND Scan/ GP REG fail");
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_NWK_CONNECTION_DOWN:
/* Connection to Access point is lost wait for Scan Result */
tr_debug("ND/RPL scan new network");
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_NWK_PARENT_POLL_FAIL:
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
case ARM_NWK_AUHTENTICATION_FAIL:
tr_debug("Network authentication fail");
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
break;
default:
tr_warn("Unknown event %d", status);
@ -204,6 +225,30 @@ void thread_tasklet_parse_network_event(arm_event_s *event)
}
}
void thread_tasklet_poll_network_status(void *param)
{
/* Check if we do have an IP */
uint8_t temp_ipv6[16];
if (arm_net_address_get(thread_tasklet_data_ptr->nwk_if_id, ADDR_IPV6_GP, temp_ipv6) == 0) {
/* Check if this is the same IP than previously */
if (memcmp(temp_ipv6, thread_tasklet_data_ptr->ip, 16) == 0) {
return;
} else {
memcpy(thread_tasklet_data_ptr->ip, temp_ipv6, 16);
link_configuration_s *link_cfg = thread_management_configuration_get(thread_tasklet_data_ptr->nwk_if_id);
if (memcmp(thread_tasklet_data_ptr->ip, link_cfg->mesh_local_ula_prefix, 8) == 0) {
thread_tasklet_network_state_changed(MESH_CONNECTED_LOCAL);
} else {
thread_tasklet_network_state_changed(MESH_CONNECTED_GLOBAL);
}
}
} else {
if (thread_tasklet_data_ptr->connection_status != MESH_DISCONNECTED &&
thread_tasklet_data_ptr->connection_status != MESH_BOOTSTRAP_STARTED)
thread_tasklet_network_state_changed(MESH_DISCONNECTED);
}
}
void read_link_configuration() {
thread_tasklet_data_ptr->link_config.panId = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PANID;
@ -298,6 +343,7 @@ void thread_tasklet_configure_and_connect_to_network(void)
if (status >= 0) {
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router");
thread_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
} else {
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
tr_err("Bootstrap start failed, %d", status);
@ -310,6 +356,7 @@ void thread_tasklet_configure_and_connect_to_network(void)
*/
void thread_tasklet_network_state_changed(mesh_connection_status_t status)
{
thread_tasklet_data_ptr->connection_status = status;
if (thread_tasklet_data_ptr->mesh_api_cb) {
(thread_tasklet_data_ptr->mesh_api_cb)(status);
}
@ -374,6 +421,8 @@ int8_t thread_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_i
thread_tasklet_data_ptr->mesh_api_cb = callback;
thread_tasklet_data_ptr->nwk_if_id = nwk_interface_id;
thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED;
thread_tasklet_data_ptr->poll_network_status_timeout =
eventOS_timeout_every_ms(thread_tasklet_poll_network_status, 2000, NULL);
if (re_connecting == false) {
thread_tasklet_data_ptr->tasklet = eventOS_event_handler_create(&thread_tasklet_main,
@ -383,6 +432,7 @@ int8_t thread_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_i
// -2 memory allocation failure
return thread_tasklet_data_ptr->tasklet;
}
ns_event_loop_thread_start();
} else {
thread_tasklet_data_ptr->tasklet = tasklet;
@ -407,6 +457,8 @@ int8_t thread_tasklet_disconnect(bool send_cb)
// Clear callback, it will be set again in next connect
thread_tasklet_data_ptr->mesh_api_cb = NULL;
// Cancel the callback timeout
eventOS_timeout_cancel(thread_tasklet_data_ptr->poll_network_status_timeout);
}
return status;
}
@ -469,4 +521,3 @@ int8_t thread_tasklet_data_poll_rate_set(uint32_t timeout)
return status;
}

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,30 @@ public:
*/
virtual nsapi_error_t add_dns_server(const SocketAddress &address);
/** Register callback for status reporting
*
* The specified status callback function will be called on status changes
* on the network. The parameters on the callback are the event type and
* event-type dependent reason parameter.
*
* @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