From 29bdcc3ff5c080cb1bf0fdb9306737c8a9ed4fa4 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Thu, 28 Mar 2024 08:03:41 +0100 Subject: [PATCH] extmod/network_ninaw10: Implement the ipconfig() methods for NINAW10. Due to a omission in the NINAW10 driver stack, setting the DNS address has no effect. But the interface is kept here just in case it's fixed eventually. dhcp4 and has_dhcp4 are dummy arguments. NINAW10 seems to use always DHCP. Signed-off-by: robert-hh --- extmod/modnetwork.c | 5 +- extmod/modnetwork.h | 4 + extmod/network_ninaw10.c | 151 +++++++++++++++++++++++++++++++++++++ shared/netutils/netutils.c | 8 +- 4 files changed, 166 insertions(+), 2 deletions(-) diff --git a/extmod/modnetwork.c b/extmod/modnetwork.c index aa237bd93c..88f9d37180 100644 --- a/extmod/modnetwork.c +++ b/extmod/modnetwork.c @@ -144,12 +144,15 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_hostname_obj, 0, 1, mod_n #if LWIP_VERSION_MAJOR >= 2 MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, mod_network_ipconfig); #endif +#if MICROPY_PY_NETWORK_NINAW10 +MP_DEFINE_CONST_FUN_OBJ_KW(mod_network_ipconfig_obj, 0, network_ninaw10_ipconfig); +#endif static const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) }, { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mod_network_hostname_obj) }, - #if LWIP_VERSION_MAJOR >= 2 + #if LWIP_VERSION_MAJOR >= 2 || MICROPY_PY_NETWORK_NINAW10 { MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&mod_network_ipconfig_obj) }, #endif diff --git a/extmod/modnetwork.h b/extmod/modnetwork.h index 2ff9ce09de..1a4aa7797e 100644 --- a/extmod/modnetwork.h +++ b/extmod/modnetwork.h @@ -83,6 +83,10 @@ extern int mp_mod_network_prefer_dns_use_ip_version; #endif #elif defined(MICROPY_PORT_NETWORK_INTERFACES) +#if MICROPY_PY_NETWORK_NINAW10 +mp_obj_t network_ninaw10_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); +#endif + struct _mod_network_socket_obj_t; typedef struct _mod_network_nic_protocol_t { diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c index 90cdafc7a4..678143904e 100644 --- a/extmod/network_ninaw10.c +++ b/extmod/network_ninaw10.c @@ -41,6 +41,7 @@ #include "py/runtime.h" #include "py/misc.h" #include "py/mperrno.h" +#include "py/parsenum.h" #include "shared/netutils/netutils.h" #include "shared/runtime/softtimer.h" #include "extmod/modnetwork.h" @@ -75,6 +76,8 @@ typedef struct _nina_obj_t { #define SO_NO_CHECK (0x100a) #define NINAW10_POLL_INTERVAL (100) +#define IPADDR_STRLEN_MAX 46 + #define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS) #define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__) @@ -87,6 +90,8 @@ static mp_sched_node_t mp_wifi_poll_node; static soft_timer_entry_t mp_wifi_poll_timer; static void network_ninaw10_deinit(void); +static bool network_ninaw10_dhcp_active = false; + static bool network_ninaw10_poll_list_is_empty(void) { return MP_STATE_PORT(mp_wifi_poll_list) == NULL || MP_STATE_PORT(mp_wifi_poll_list)->len == 0; @@ -199,6 +204,7 @@ static mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) { mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("failed to initialize Nina-W10 module, error: %d"), error); } + network_ninaw10_dhcp_active = true; // check firmware version uint8_t semver[NINA_FW_VER_LEN]; if (nina_fw_version(semver) != 0) { @@ -367,11 +373,155 @@ static mp_obj_t network_ninaw10_ifconfig(size_t n_args, const mp_obj_t *args) { netutils_parse_ipv4_addr(items[2], ifconfig.gateway_addr, NETUTILS_BIG); netutils_parse_ipv4_addr(items[3], ifconfig.dns_addr, NETUTILS_BIG); nina_ifconfig(&ifconfig, true); + network_ninaw10_dhcp_active = false; return mp_const_none; } } static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ninaw10_ifconfig_obj, 1, 2, network_ninaw10_ifconfig); +mp_obj_t network_ninaw10_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + nina_ifconfig_t ifconfig; + // get ifconfig info + nina_ifconfig(&ifconfig, false); + + if (kwargs->used == 0) { + // Get config value + if (n_args != 1) { + mp_raise_TypeError(MP_ERROR_TEXT("must query one param")); + } + switch (mp_obj_str_get_qstr(args[0])) { + case MP_QSTR_dns: { + return netutils_format_ipv4_addr(ifconfig.dns_addr, NETUTILS_BIG); + } + default: { + mp_raise_ValueError(MP_ERROR_TEXT("unexpected key")); + break; + } + } + } else { + // Set config value(s) + if (n_args != 0) { + mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args")); + } + + for (size_t i = 0; i < kwargs->alloc; ++i) { + if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { + mp_map_elem_t *e = &kwargs->table[i]; + switch (mp_obj_str_get_qstr(e->key)) { + case MP_QSTR_dns: { + netutils_parse_ipv4_addr(e->value, ifconfig.dns_addr, NETUTILS_BIG); + nina_ifconfig(&ifconfig, true); + break; + } + default: { + mp_raise_ValueError(MP_ERROR_TEXT("unexpected key")); + break; + } + } + } + } + } + return mp_const_none; +} + +static mp_obj_t network_ninaw10_nic_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + nina_ifconfig_t ifconfig; + // get ifconfig info + nina_ifconfig(&ifconfig, false); + + if (kwargs->used == 0) { + // Get config value + if (n_args != 2) { + mp_raise_TypeError(MP_ERROR_TEXT("must query one param")); + } + + switch (mp_obj_str_get_qstr(args[1])) { + case MP_QSTR_dhcp4: { + return mp_obj_new_bool(network_ninaw10_dhcp_active); + } + case MP_QSTR_has_dhcp4: { + uint16_t ip_sum = + ifconfig.ip_addr[0] + ifconfig.ip_addr[1] + ifconfig.ip_addr[2] + ifconfig.ip_addr[3]; + if (network_ninaw10_dhcp_active) { + return mp_obj_new_bool(ip_sum != 0); + } else { + return mp_const_false; + } + } + case MP_QSTR_addr4: { + mp_obj_t tuple[2] = { + netutils_format_ipv4_addr(ifconfig.ip_addr, NETUTILS_BIG), + netutils_format_ipv4_addr(ifconfig.subnet_addr, NETUTILS_BIG), + }; + return mp_obj_new_tuple(2, tuple); + } + case MP_QSTR_gw4: { + return netutils_format_ipv4_addr(ifconfig.gateway_addr, NETUTILS_BIG); + } + default: { + mp_raise_ValueError(MP_ERROR_TEXT("unexpected key")); + break; + } + } + return mp_const_none; + } else { + // Set config value(s) + if (n_args != 1) { + mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args")); + } + + for (size_t i = 0; i < kwargs->alloc; ++i) { + if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { + mp_map_elem_t *e = &kwargs->table[i]; + switch (mp_obj_str_get_qstr(e->key)) { + case MP_QSTR_dhcp4: { + mp_raise_ValueError(MP_ERROR_TEXT("DHCP control unsupported")); + break; + } + case MP_QSTR_addr4: { + int prefix_bits = 32; + if (e->value != mp_const_none && mp_obj_is_str(e->value)) { + size_t addr_len; + const char *input_str = mp_obj_str_get_data(e->value, &addr_len); + char *split = strchr(input_str, '/'); + if (split) { + mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL); + prefix_bits = mp_obj_get_int(prefix_obj); + uint32_t mask = -(1u << (32 - prefix_bits)); + ifconfig.subnet_addr[0] = (mask >> 24) & 0xFF; + ifconfig.subnet_addr[1] = (mask >> 16) & 0xFF; + ifconfig.subnet_addr[2] = (mask >> 8) & 0xFF; + ifconfig.subnet_addr[3] = mask & 0xFF; + } + netutils_parse_ipv4_addr(e->value, ifconfig.ip_addr, NETUTILS_BIG); + } else if (e->value != mp_const_none) { + mp_obj_t *items; + mp_obj_get_array_fixed_n(e->value, 2, &items); + netutils_parse_ipv4_addr(items[0], ifconfig.ip_addr, NETUTILS_BIG); + netutils_parse_ipv4_addr(items[1], ifconfig.subnet_addr, NETUTILS_BIG); + } + nina_ifconfig(&ifconfig, true); + network_ninaw10_dhcp_active = false; + break; + } + case MP_QSTR_gw4: { + netutils_parse_ipv4_addr(e->value, ifconfig.gateway_addr, NETUTILS_BIG); + nina_ifconfig(&ifconfig, true); + network_ninaw10_dhcp_active = false; + break; + } + default: { + mp_raise_ValueError(MP_ERROR_TEXT("unexpected key")); + break; + } + } + } + } + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_KW(network_ninaw10_nic_ipconfig_obj, 1, network_ninaw10_nic_ipconfig); + static mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { nina_obj_t *self = MP_OBJ_TO_PTR(args[0]); (void)self; @@ -856,6 +1006,7 @@ static const mp_rom_map_elem_t nina_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_ninaw10_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_ninaw10_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_ninaw10_ifconfig_obj) }, + { MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&network_ninaw10_nic_ipconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_ninaw10_config_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_ninaw10_status_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_ninaw10_ioctl_obj) }, diff --git a/shared/netutils/netutils.c b/shared/netutils/netutils.c index 84b4405c41..cd1422f7c8 100644 --- a/shared/netutils/netutils.c +++ b/shared/netutils/netutils.c @@ -63,7 +63,13 @@ void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian return; } const char *s = addr_str; - const char *s_top = addr_str + addr_len; + const char *s_top; + // Scan for the end of valid address characters + for (s_top = addr_str; s_top < addr_str + addr_len; s_top++) { + if (!(*s_top == '.' || (*s_top >= '0' && *s_top <= '9'))) { + break; + } + } for (mp_uint_t i = 3; ; i--) { mp_uint_t val = 0; for (; s < s_top && *s != '.'; s++) {