mirror of https://github.com/ARMmbed/mbed-os.git
commit
984cc1ab50
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue