diff --git a/ports/stm32/modnetwork.c b/extmod/modnetwork.c similarity index 98% rename from ports/stm32/modnetwork.c rename to extmod/modnetwork.c index dea23b40512e1..cf90a78b1a561 100644 --- a/ports/stm32/modnetwork.c +++ b/extmod/modnetwork.c @@ -109,6 +109,9 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { #if MICROPY_PY_CC3K { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) }, #endif + #if MICROPY_PY_CC31K + { MP_ROM_QSTR(MP_QSTR_CC31K), MP_ROM_PTR(&mod_network_nic_type_cc31k) }, + #endif { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, }; diff --git a/ports/stm32/modnetwork.h b/extmod/modnetwork.h similarity index 91% rename from ports/stm32/modnetwork.h rename to extmod/modnetwork.h index f45e00fbc28dc..ccbeeefb3fc9e 100644 --- a/ports/stm32/modnetwork.h +++ b/extmod/modnetwork.h @@ -35,6 +35,10 @@ #define MOD_NETWORK_SOCK_DGRAM (2) #define MOD_NETWORK_SOCK_RAW (3) +#define MOD_NETWORK_IPPROTO_TCP (1) +#define MOD_NETWORK_IPPROTO_UDP (2) +#define MOD_NETWORK_IPPROTO_SECURE (3) + #if MICROPY_PY_LWIP struct netif; @@ -56,7 +60,7 @@ typedef struct _mod_network_nic_type_t { mp_obj_type_t base; // API for non-socket operations - int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out); + int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out, uint8_t family); // API for socket operations; return -1 on error int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno); @@ -83,13 +87,22 @@ typedef struct _mod_network_socket_obj_t { uint8_t domain; uint8_t type; int8_t fileno; + uint8_t proto; } u_param; +#if (MICROPY_PY_CC31K) + int16_t sd; +#endif mp_uint_t u_state; }; +#if (MICROPY_PY_CC31K) + uint32_t timeout_ms; // 0 for no timeout + bool cert_req; +#endif } mod_network_socket_obj_t; extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; extern const mod_network_nic_type_t mod_network_nic_type_cc3k; +extern const mod_network_nic_type_t mod_network_nic_type_cc31k; #endif diff --git a/ports/cc3200/mods/modwlan.c b/extmod/modnwcc31k.c similarity index 75% rename from ports/cc3200/mods/modwlan.c rename to extmod/modnwcc31k.c index 8acc89da38b5a..e469de72a8e88 100644 --- a/ports/cc3200/mods/modwlan.c +++ b/extmod/modnwcc31k.c @@ -28,28 +28,441 @@ #include #include -#include "simplelink.h" #include "py/mpconfig.h" + +#if (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) +#include "simplelink.h" #include "py/obj.h" #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" +#include "py/mperrno.h" #include "lib/timeutils/timeutils.h" #include "lib/netutils/netutils.h" #include "modnetwork.h" -#include "modusocket.h" -#include "modwlan.h" +#include "modnwcc31k.h" +#include "simplelink.h" + +#if (TARGET_IS_CC3200) #include "pybrtc.h" #include "debug.h" -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) -#include "serverstask.h" -#endif -#include "mpexception.h" #include "mpirq.h" #include "pybsleep.h" +#include "mpexception.h" +#else +const char mpexception_value_invalid_arguments[] = "invalid argument(s) value"; +const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type"; +const char mpexception_uncaught[] = "uncaught exception"; +#endif // (TARGET_IS_CC3200) + +#if (MICROPY_HW_ANTENNA_DIVERSITY) #include "antenna.h" +#endif + +#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) +#include "serverstask.h" +#endif + +#define WLAN_MAX_RX_SIZE 16000 +#define WLAN_MAX_TX_SIZE 1476 + +#define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \ + addr.sa_family = SL_AF_INET; \ + addr.sa_data[0] = port >> 8; \ + addr.sa_data[1] = port; \ + addr.sa_data[2] = ip[0]; \ + addr.sa_data[3] = ip[1]; \ + addr.sa_data[4] = ip[2]; \ + addr.sa_data[5] = ip[3]; + +#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \ + ip[0] = addr.sa_data[2]; \ + ip[1] = addr.sa_data[3]; \ + ip[2] = addr.sa_data[4]; \ + ip[3] = addr.sa_data[5]; + +#define SOCKET_TIMEOUT_QUANTA_MS (20) + +STATIC int convert_sl_errno(int sl_errno) { + return -sl_errno; +} + +// This function is left as non-static so it's not inlined. +int check_timedout(mod_network_socket_obj_t *s, int ret, uint32_t *timeout_ms, int *_errno) { + if (*timeout_ms == 0 || ret != SL_EAGAIN) { + if (s->timeout_ms > 0 && ret == SL_EAGAIN) { + *_errno = MP_ETIMEDOUT; + } else { + *_errno = convert_sl_errno(ret); + } + return -1; + } + mp_hal_delay_ms(SOCKET_TIMEOUT_QUANTA_MS); + if (*timeout_ms < SOCKET_TIMEOUT_QUANTA_MS) { + *timeout_ms = 0; + } else { + *timeout_ms -= SOCKET_TIMEOUT_QUANTA_MS; + } + return 0; +} + +STATIC int cc31k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { + uint32_t ip; + if (family == MOD_NETWORK_AF_INET) { + int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)SL_AF_INET); + out_ip[3] = ip; + out_ip[2] = ip >> 8; + out_ip[1] = ip >> 16; + out_ip[0] = ip >> 24; + return result; + } + return -1; +} + +STATIC int cc31k_socket_socket(mod_network_socket_obj_t *s, int *_errno) { + int domain; + if (s->u_param.domain == MOD_NETWORK_AF_INET) { + domain = SL_AF_INET; + } else { + *_errno = MP_EAFNOSUPPORT; + return -1; + } + + int type; + if (s->u_param.type == MOD_NETWORK_SOCK_STREAM) { + type = SL_SOCK_STREAM; + } else if (s->u_param.type == MOD_NETWORK_SOCK_DGRAM) { + type = SL_SOCK_DGRAM; + } else { + *_errno = MP_EINVAL; + return -1; + } + + int proto; + if (s->u_param.proto == MOD_NETWORK_IPPROTO_TCP) { + proto = SL_IPPROTO_TCP; + } else if (s->u_param.proto == MOD_NETWORK_IPPROTO_UDP) { + proto = SL_IPPROTO_UDP; + } else if (s->u_param.proto == MOD_NETWORK_IPPROTO_SECURE) { + proto = SL_SEC_SOCKET; + } else { + *_errno = MP_EINVAL; + return -1; + } + + int16_t sd = sl_Socket(domain, type, proto); + if (sd < 0) { + *_errno = sd; + return -1; + } + s->sd = sd; + return 0; +} + +STATIC void cc31k_socket_close(mod_network_socket_obj_t *s) { + // this is to prevent the finalizer to close a socket that failed when being created + if (s->sd >= 0) { + modusocket_socket_delete(s->sd); + sl_Close(s->sd); + s->sd = -1; + } +} + +STATIC int cc31k_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { + MAKE_SOCKADDR(addr, ip, port) + int ret = sl_Bind(s->sd, &addr, sizeof(addr)); + if (ret != 0) { + *_errno = ret; + return -1; + } + return 0; +} + +STATIC int cc31k_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) { + int ret = sl_Listen(s->sd, backlog); + if (ret != 0) { + *_errno = ret; + return -1; + } + return 0; +} + +STATIC int cc31k_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) { + // accept incoming connection + int16_t sd; + SlSockAddr_t addr; + SlSocklen_t addr_len = sizeof(addr); + + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + sd = sl_Accept(s->sd, &addr, &addr_len); + if (sd >= 0) { + // save the socket descriptor + s2->sd = sd; + // return ip and port + UNPACK_SOCKADDR(addr, ip, *port); + return 0; + } + if (check_timedout(s, sd, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC int cc31k_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { + MAKE_SOCKADDR(addr, ip, port) + uint32_t timeout_ms = s->timeout_ms; + + // For a non-blocking connect the CC3100 will return SL_EALREADY while the + // connection is in progress. + for (;;) { + int ret = sl_Connect(s->sd, &addr, sizeof(addr)); + if (ret == 0) { + return 0; + } + + // Check if we are in non-blocking mode and the connection is in progress + if (s->timeout_ms == 0 && ret == SL_EALREADY) { + // To match BSD we return EINPROGRESS here + *_errno = MP_EINPROGRESS; + return -1; + } + + // We are in blocking mode, so if the connection isn't in progress then error out + if (ret != SL_EALREADY) { + *_errno = convert_sl_errno(ret); + return -1; + } + + if (check_timedout(s, SL_EAGAIN, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) { + if (len == 0) { + return 0; + } + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_Send(s->sd, (const void *)buf, len, 0); + if (ret > 0) { + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) { + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_Recv(s->sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0); + if (ret >= 0) { + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { + MAKE_SOCKADDR(addr, ip, port) + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_SendTo(s->sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr)); + if (ret >= 0) { + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { + SlSockAddr_t addr; + SlSocklen_t addr_len = sizeof(addr); + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_RecvFrom(s->sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len); + if (ret >= 0) { + UNPACK_SOCKADDR(addr, ip, *port); + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC int cc31k_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { + int ret = sl_SetSockOpt(s->sd, level, opt, optval, optlen); + if (ret < 0) { + *_errno = ret; + return -1; + } + return 0; +} + +STATIC int cc31k_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) { + SlSockNonblocking_t option; + if (timeout_s == 0 || timeout_s == -1) { + if (timeout_s == 0) { + // set non-blocking mode + option.NonblockingEnabled = 1; + } else { + // set blocking mode + option.NonblockingEnabled = 0; + } + timeout_s = 0; + } else { + // synthesize timeout via non-blocking behaviour with a loop + option.NonblockingEnabled = 1; + } + + int ret = sl_SetSockOpt(s->sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option)); + if (ret != 0) { + *_errno = convert_sl_errno(ret); + return -1; + } + + s->timeout_ms = timeout_s * 1000; + return 0; +} + +STATIC int cc31k_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) { + mp_int_t ret; + if (request == MP_STREAM_POLL) { + mp_uint_t flags = arg; + ret = 0; + int32_t sd = s->sd; + + // init fds + SlFdSet_t rfds, wfds, xfds; + SL_FD_ZERO(&rfds); + SL_FD_ZERO(&wfds); + SL_FD_ZERO(&xfds); + + // set fds if needed + if (flags & MP_STREAM_POLL_RD) { + SL_FD_SET(sd, &rfds); + } + if (flags & MP_STREAM_POLL_WR) { + SL_FD_SET(sd, &wfds); + } + if (flags & MP_STREAM_POLL_HUP) { + SL_FD_SET(sd, &xfds); + } + + // call simplelink's select with minimum timeout + SlTimeval_t tv; + tv.tv_sec = 0; + tv.tv_usec = 1; + int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv); + + // check for errors + if (nfds == -1) { + *_errno = nfds; + return -1; + } + + // check return of select + if (SL_FD_ISSET(sd, &rfds)) { + ret |= MP_STREAM_POLL_RD; + } + if (SL_FD_ISSET(sd, &wfds)) { + ret |= MP_STREAM_POLL_WR; + } + if (SL_FD_ISSET(sd, &xfds)) { + ret |= MP_STREAM_POLL_HUP; + } + } else if (request == MP_STREAM_CLOSE) { + cc31k_socket_close(s); + ret = 0; + } else { + *_errno = MP_EINVAL; + ret = MP_STREAM_ERROR; + } + return ret; +} + +/****************************************************************************** + DEFINE PRIVATE CONSTANTS + ******************************************************************************/ +#define MOD_NETWORK_MAX_SOCKETS 10 + +/****************************************************************************** + DEFINE PRIVATE TYPES + ******************************************************************************/ +typedef struct { + int16_t sd; + bool user; +} modusocket_sock_t; + +/****************************************************************************** + DEFINE PRIVATE DATA + ******************************************************************************/ +STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, + {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}}; + +/****************************************************************************** + DEFINE PUBLIC FUNCTIONS + ******************************************************************************/ +__attribute__ ((section (".boot"))) +void modusocket_pre_init (void) { +} + +void modusocket_socket_add (int16_t sd, bool user) { + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd < 0) { + modusocket_sockets[i].sd = sd; + modusocket_sockets[i].user = user; + break; + } + } +} + +void modusocket_socket_delete (int16_t sd) { + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd == sd) { + modusocket_sockets[i].sd = -1; + break; + } + } +} + +void modusocket_enter_sleep (void) { + SlFdSet_t socketset; + int16_t maxfd = 0; + + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + int16_t sd; + if ((sd = modusocket_sockets[i].sd) >= 0) { + SL_FD_SET(sd, &socketset); + maxfd = (maxfd > sd) ? maxfd : sd; + } + } + + if (maxfd > 0) { + // wait for any of the sockets to become ready... + sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL); + } +} + +void modusocket_close_all_user_sockets (void) { + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) { + sl_Close(modusocket_sockets[i].sd); + modusocket_sockets[i].sd = -1; + } + } +} /****************************************************************************** DEFINE TYPES @@ -112,6 +525,12 @@ typedef enum{ #define ASSERT_ON_ERROR(x) ASSERT((x) >= 0) +#if defined(DEBUG) +#define ASSERT(expr) assert(expr) +#else +#define ASSERT(expr) (void)(expr) +#endif + /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ @@ -131,7 +550,9 @@ STATIC wlan_obj_t wlan_obj = { #endif }; +#if (TARGET_IS_CC3200) STATIC const mp_irq_methods_t wlan_irq_methods; +#endif // (TARGET_IS_CC3200) /****************************************************************************** DECLARE PUBLIC DATA @@ -165,8 +586,8 @@ STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, co const char* key, uint32_t key_len, int32_t timeout); STATIC void wlan_get_sl_mac (void); STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out); -STATIC void wlan_lpds_irq_enable (mp_obj_t self_in); -STATIC void wlan_lpds_irq_disable (mp_obj_t self_in); +//STATIC void wlan_lpds_irq_enable (mp_obj_t self_in); +//STATIC void wlan_lpds_irq_disable (mp_obj_t self_in); STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid); //***************************************************************************** @@ -478,11 +899,12 @@ void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 1, 0, 0, 0), NULL, 0)); } +#if (TARGET_IS_CC3200) // set current time and date (needed to validate certificates) wlan_set_current_time (pyb_rtc_get_seconds()); - // start the servers before returning wlan_servers_start(); +#endif // (TARGET_IS_CC3200) } void wlan_update(void) { @@ -736,6 +1158,7 @@ STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out) { } } +#if (TARGET_IS_CC3200) STATIC void wlan_lpds_irq_enable (mp_obj_t self_in) { wlan_obj_t *self = self_in; self->irq_enabled = true; @@ -750,6 +1173,7 @@ STATIC int wlan_irq_flags (mp_obj_t self_in) { wlan_obj_t *self = self_in; return self->irq_flags; } +#endif // (TARGET_IS_CC3200) STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid) { for (int i = 0; i < nets->len; i++) { @@ -810,7 +1234,14 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) { } STATIC const mp_arg_t wlan_init_args[] = { +#if (TARGET_IS_CC3200) { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, +#else + { MP_QSTR_spi, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_cs, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_en, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_irq, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, +#endif { MP_QSTR_mode, MP_ARG_INT, {.u_int = ROLE_STA} }, { MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -819,7 +1250,8 @@ STATIC const mp_arg_t wlan_init_args[] = { { MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} }, #endif }; -STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + +STATIC mp_obj_t cc31k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); @@ -828,8 +1260,8 @@ STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n // setup the object wlan_obj_t *self = &wlan_obj; - self->base.type = (mp_obj_t)&mod_network_nic_type_wlan; - + self->base.type = (mp_obj_t)&mod_network_nic_type_cc31k; +#if (TARGET_IS_CC3200) // give it to the sleep module pyb_sleep_set_wlan_obj(self); @@ -841,6 +1273,21 @@ STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n // start the peripheral wlan_init_helper(self, &args[1]); } +#else + // set the pins to use + cc3100_drv_init( + args[0].u_obj, + pin_find(args[1].u_obj), + pin_find(args[2].u_obj), + pin_find(args[3].u_obj) + ); + + // start the peripheral + wlan_init_helper(self, &args[4]); +#endif + + // register with network module + mod_network_register_nic((mp_obj_t)self); return (mp_obj_t)self; } @@ -1052,7 +1499,7 @@ STATIC mp_obj_t wlan_ifconfig(size_t n_args, const mp_obj_t *pos_args, mp_map_t // config values have changed, so reset wlan_reset(); // set current time and date (needed to validate certificates) - wlan_set_current_time (pyb_rtc_get_seconds()); + //wlan_set_current_time (pyb_rtc_get_seconds()); return mp_const_none; } } @@ -1164,6 +1611,7 @@ STATIC mp_obj_t wlan_mac(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mac_obj, 1, 2, wlan_mac); +#if (TARGET_IS_CC3200) STATIC mp_obj_t wlan_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); @@ -1193,6 +1641,7 @@ STATIC mp_obj_t wlan_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq); +#endif // (TARGET_IS_CC3200) //STATIC mp_obj_t wlan_connections (mp_obj_t self_in) { // mp_obj_t device[2]; @@ -1254,7 +1703,7 @@ STATIC mp_obj_t wlan_print_ver(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(wlan_print_ver_fun_obj, wlan_print_ver); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(wlan_print_ver_obj, MP_ROM_PTR(&wlan_print_ver_fun_obj)); -STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = { +STATIC const mp_rom_map_elem_t cc31k_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&wlan_init_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&wlan_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&wlan_connect_obj) }, @@ -1267,7 +1716,9 @@ STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wlan_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_antenna), MP_ROM_PTR(&wlan_antenna_obj) }, { MP_ROM_QSTR(MP_QSTR_mac), MP_ROM_PTR(&wlan_mac_obj) }, +#if (TARGET_IS_CC3200) { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&wlan_irq_obj) }, +#endif // (TARGET_IS_CC3200) //{ MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&wlan_connections_obj) }, //{ MP_ROM_QSTR(MP_QSTR_urn), MP_ROM_PTR(&wlan_urn_obj) }, { MP_ROM_QSTR(MP_QSTR_print_ver), MP_ROM_PTR(&wlan_print_ver_obj) }, @@ -1284,20 +1735,37 @@ STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_ANY_EVENT), MP_ROM_INT(MODWLAN_WIFI_EVENT_ANY) }, }; -STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(cc31k_locals_dict, cc31k_locals_dict_table); -const mod_network_nic_type_t mod_network_nic_type_wlan = { +const mod_network_nic_type_t mod_network_nic_type_cc31k = { .base = { { &mp_type_type }, - .name = MP_QSTR_WLAN, - .make_new = wlan_make_new, - .locals_dict = (mp_obj_t)&wlan_locals_dict, + .name = MP_QSTR_CC31K, + .make_new = cc31k_make_new, + .locals_dict = (mp_obj_dict_t*)&cc31k_locals_dict, }, + .gethostbyname = cc31k_gethostbyname, + .socket = cc31k_socket_socket, + .close = cc31k_socket_close, + .bind = cc31k_socket_bind, + .listen = cc31k_socket_listen, + .accept = cc31k_socket_accept, + .connect = cc31k_socket_connect, + .send = cc31k_socket_send, + .recv = cc31k_socket_recv, + .sendto = cc31k_socket_sendto, + .recvfrom = cc31k_socket_recvfrom, + .setsockopt = cc31k_socket_setsockopt, + .settimeout = cc31k_socket_settimeout, + .ioctl = cc31k_socket_ioctl, }; +#if (TARGET_IS_CC3200) STATIC const mp_irq_methods_t wlan_irq_methods = { .init = wlan_irq, .enable = wlan_lpds_irq_enable, .disable = wlan_lpds_irq_disable, .flags = wlan_irq_flags, }; +#endif // (TARGET_IS_CC3200) +#endif // (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) diff --git a/ports/cc3200/mods/modwlan.h b/extmod/modnwcc31k.h similarity index 93% rename from ports/cc3200/mods/modwlan.h rename to extmod/modnwcc31k.h index b806644f55e93..c47343f1e7c75 100644 --- a/ports/cc3200/mods/modwlan.h +++ b/extmod/modnwcc31k.h @@ -26,6 +26,8 @@ #ifndef MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H #define MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H +#include "py/stream.h" + /****************************************************************************** DEFINE CONSTANTS ******************************************************************************/ @@ -96,4 +98,10 @@ extern bool wlan_is_connected (void); extern void wlan_set_current_time (uint32_t seconds_since_2000); extern void wlan_off_on (void); +extern void modusocket_pre_init (void); +extern void modusocket_socket_add (int16_t sd, bool user); +extern void modusocket_socket_delete (int16_t sd); +extern void modusocket_enter_sleep (void); +extern void modusocket_close_all_user_sockets (void); + #endif // MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H diff --git a/ports/stm32/modusocket.c b/extmod/modusocket.c similarity index 95% rename from ports/stm32/modusocket.c rename to extmod/modusocket.c index 7503ecbd68d20..0cda64ad7ab01 100644 --- a/ports/stm32/modusocket.c +++ b/extmod/modusocket.c @@ -53,13 +53,17 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t s->nic_type = NULL; s->u_param.domain = MOD_NETWORK_AF_INET; s->u_param.type = MOD_NETWORK_SOCK_STREAM; + s->u_param.proto = MOD_NETWORK_IPPROTO_TCP; s->u_param.fileno = -1; if (n_args >= 1) { s->u_param.domain = mp_obj_get_int(args[0]); if (n_args >= 2) { s->u_param.type = mp_obj_get_int(args[1]); - if (n_args >= 4) { - s->u_param.fileno = mp_obj_get_int(args[3]); + if (n_args >= 3) { + s->u_param.proto = mp_obj_get_int(args[2]); + if (n_args >= 4) { + s->u_param.fileno = mp_obj_get_int(args[3]); + } } } } @@ -160,7 +164,6 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { // get address uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); - // check if we need to select a NIC socket_select_nic(self, ip); @@ -351,9 +354,15 @@ STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, + + // stream methods + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read1_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); +MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -367,7 +376,7 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int * return self->nic_type->ioctl(self, request, arg, errcode); } -STATIC const mp_stream_p_t socket_stream_p = { +const mp_stream_p_t socket_stream_p = { .ioctl = socket_ioctl, .is_text = false, }; @@ -409,7 +418,7 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); if (nic_type->gethostbyname != NULL) { - int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); + int ret = nic_type->gethostbyname(nic, host, hlen, out_ip, MOD_NETWORK_AF_INET); if (ret != 0) { mp_raise_OSError(ret); } @@ -458,7 +467,7 @@ STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = { */ }; -STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); +MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); const mp_obj_module_t mp_module_usocket = { .base = { &mp_type_module }, diff --git a/ports/cc3200/mods/modusocket.h b/extmod/modusocket.h similarity index 77% rename from ports/cc3200/mods/modusocket.h rename to extmod/modusocket.h index aaee04ce1927e..bd4d5079657ae 100644 --- a/ports/cc3200/mods/modusocket.h +++ b/extmod/modusocket.h @@ -23,18 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H -#define MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H +#ifndef MICROPY_INCLUDED_EXTMOD_MODUSOCKET_H +#define MICROPY_INCLUDED_EXTMOD_MODUSOCKET_H #include "py/stream.h" extern const mp_obj_dict_t socket_locals_dict; extern const mp_stream_p_t socket_stream_p; -extern void modusocket_pre_init (void); -extern void modusocket_socket_add (int16_t sd, bool user); -extern void modusocket_socket_delete (int16_t sd); -extern void modusocket_enter_sleep (void); -extern void modusocket_close_all_user_sockets (void); - -#endif // MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H +#endif // MICROPY_INCLUDED_EXTMOD_MODUSOCKET_H diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk index 19abe661631ae..71a7453a03fcf 100644 --- a/ports/cc3200/application.mk +++ b/ports/cc3200/application.mk @@ -19,8 +19,9 @@ APP_INC += -Ibootmgr APP_INC += -I$(BUILD) APP_INC += -I$(BUILD)/genhdr APP_INC += -I$(TOP)/ports/stm32 +APP_INC += -I$(TOP)/extmod -APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS +APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS -DMICROPY_PY_CC31K=1 APP_FATFS_SRC_C = $(addprefix fatfs/src/,\ drivers/sflash_diskio.c \ @@ -78,14 +79,11 @@ APP_MISC_SRC_C = $(addprefix misc/,\ APP_MODS_SRC_C = $(addprefix mods/,\ modmachine.c \ - modnetwork.c \ modubinascii.c \ moduos.c \ - modusocket.c \ modussl.c \ modutime.c \ modwipy.c \ - modwlan.c \ pybadc.c \ pybpin.c \ pybi2c.c \ @@ -156,13 +154,20 @@ APP_STM_SRC_C = $(addprefix ports/stm32/,\ irq.c \ ) +APP_EXTMOD_SRC_C = $(addprefix extmod/,\ + modnetwork.c \ + modnwcc31k.c \ + modusocket.c \ + ) + + OBJ = $(PY_O) $(addprefix $(BUILD)/, $(APP_FATFS_SRC_C:.c=.o) $(APP_RTOS_SRC_C:.c=.o) $(APP_FTP_SRC_C:.c=.o) $(APP_HAL_SRC_C:.c=.o) $(APP_MISC_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_CC3100_SRC_C:.c=.o) $(APP_SL_SRC_C:.c=.o) $(APP_TELNET_SRC_C:.c=.o) $(APP_UTIL_SRC_C:.c=.o) $(APP_UTIL_SRC_S:.s=.o)) -OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o) $(APP_EXTMOD_SRC_C:.c=.o)) OBJ += $(BUILD)/pins.o # List of sources for qstr extraction -SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) +SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) $(APP_EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += diff --git a/ports/cc3200/fatfs/src/drivers/sflash_diskio.c b/ports/cc3200/fatfs/src/drivers/sflash_diskio.c index 6a1fc406855d3..4b63afd509b80 100644 --- a/ports/cc3200/fatfs/src/drivers/sflash_diskio.c +++ b/ports/cc3200/fatfs/src/drivers/sflash_diskio.c @@ -10,7 +10,7 @@ #include "sflash_diskio.h" #include "debug.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #define SFLASH_TIMEOUT_MAX_MS 5500 #define SFLASH_WAIT_TIME_MS 5 diff --git a/ports/cc3200/ftp/ftp.c b/ports/cc3200/ftp/ftp.c index ee80e51f5269e..2a550f5e843f8 100644 --- a/ports/cc3200/ftp/ftp.c +++ b/ports/cc3200/ftp/ftp.c @@ -41,7 +41,7 @@ #include "ftp.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "modusocket.h" #include "debug.h" #include "serverstask.h" diff --git a/ports/cc3200/ftp/updater.c b/ports/cc3200/ftp/updater.c index 5be2c6063c9ba..c8a21e3076f4c 100644 --- a/ports/cc3200/ftp/updater.c +++ b/ports/cc3200/ftp/updater.c @@ -34,7 +34,7 @@ #include "updater.h" #include "shamd5.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "debug.h" #include "osi.h" diff --git a/ports/cc3200/mods/modmachine.c b/ports/cc3200/mods/modmachine.c index 6051497e30d99..e68a1d968810e 100644 --- a/ports/cc3200/mods/modmachine.c +++ b/ports/cc3200/mods/modmachine.c @@ -42,7 +42,7 @@ #include "pybrtc.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "moduos.h" #include "FreeRTOS.h" #include "portable.h" diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c deleted file mode 100644 index 37dffe731f11d..0000000000000 --- a/ports/cc3200/mods/modnetwork.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2015 Daniel Campora - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "modnetwork.h" -#include "mpexception.h" -#include "serverstask.h" -#include "simplelink.h" - - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ -typedef struct { - mp_obj_base_t base; -} network_server_obj_t; - -/****************************************************************************** - DECLARE PRIVATE DATA - ******************************************************************************/ -STATIC network_server_obj_t network_server_obj; -STATIC const mp_obj_type_t network_server_type; - -/// \module network - network configuration -/// -/// This module provides network drivers and server configuration. - -void mod_network_init0(void) { -} - -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) -STATIC mp_obj_t network_server_init_helper(mp_obj_t self, const mp_arg_val_t *args) { - const char *user = SERVERS_DEF_USER; - const char *pass = SERVERS_DEF_PASS; - if (args[0].u_obj != MP_OBJ_NULL) { - mp_obj_t *login; - mp_obj_get_array_fixed_n(args[0].u_obj, 2, &login); - user = mp_obj_str_get_str(login[0]); - pass = mp_obj_str_get_str(login[1]); - } - - uint32_t timeout = SERVERS_DEF_TIMEOUT_MS / 1000; - if (args[1].u_obj != MP_OBJ_NULL) { - timeout = mp_obj_get_int(args[1].u_obj); - } - - // configure the new login - servers_set_login ((char *)user, (char *)pass); - - // configure the timeout - servers_set_timeout(timeout * 1000); - - // start the servers - servers_start(); - - return mp_const_none; -} - -STATIC const mp_arg_t network_server_args[] = { - { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_login, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, -}; -STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // parse args - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); - mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args)]; - mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), network_server_args, args); - - // check the server id - if (args[0].u_obj != MP_OBJ_NULL) { - if (mp_obj_get_int(args[0].u_obj) != 0) { - mp_raise_OSError(MP_ENODEV); - } - } - - // setup the object and initialize it - network_server_obj_t *self = &network_server_obj; - self->base.type = &network_server_type; - network_server_init_helper(self, &args[1]); - - return (mp_obj_t)self; -} - -STATIC mp_obj_t network_server_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args) - 1]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &network_server_args[1], args); - return network_server_init_helper(pos_args[0], args); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_server_init_obj, 1, network_server_init); - -// timeout value given in seconds -STATIC mp_obj_t network_server_timeout(size_t n_args, const mp_obj_t *args) { - if (n_args > 1) { - uint32_t timeout = mp_obj_get_int(args[1]); - servers_set_timeout(timeout * 1000); - return mp_const_none; - } else { - // get - return mp_obj_new_int(servers_get_timeout() / 1000); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_timeout_obj, 1, 2, network_server_timeout); - -STATIC mp_obj_t network_server_running(mp_obj_t self_in) { - // get - return mp_obj_new_bool(servers_are_enabled()); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_running_obj, network_server_running); - -STATIC mp_obj_t network_server_deinit(mp_obj_t self_in) { - // simply stop the servers - servers_stop(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_deinit_obj, network_server_deinit); -#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_WLAN), MP_ROM_PTR(&mod_network_nic_type_wlan) }, - -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - { MP_ROM_QSTR(MP_QSTR_Server), MP_ROM_PTR(&network_server_type) }, -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); - -const mp_obj_module_t mp_module_network = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_network_globals, -}; - -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) -STATIC const mp_rom_map_elem_t network_server_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_server_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_server_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&network_server_timeout_obj) }, - { MP_ROM_QSTR(MP_QSTR_isrunning), MP_ROM_PTR(&network_server_running_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_dict_table); - -STATIC const mp_obj_type_t network_server_type = { - { &mp_type_type }, - .name = MP_QSTR_Server, - .make_new = network_server_make_new, - .locals_dict = (mp_obj_t)&network_server_locals_dict, -}; -#endif diff --git a/ports/cc3200/mods/modnetwork.h b/ports/cc3200/mods/modnetwork.h deleted file mode 100644 index 6ec90a2bac189..0000000000000 --- a/ports/cc3200/mods/modnetwork.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2015 Daniel Campora - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H -#define MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H - -/****************************************************************************** - DEFINE CONSTANTS - ******************************************************************************/ -#define MOD_NETWORK_IPV4ADDR_BUF_SIZE (4) - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ -typedef struct _mod_network_nic_type_t { - mp_obj_type_t base; -} mod_network_nic_type_t; - -typedef struct _mod_network_socket_base_t { - union { - struct { - // this order is important so that fileno gets > 0 once - // the socket descriptor is assigned after being created. - uint8_t domain; - int8_t fileno; - uint8_t type; - uint8_t proto; - } u_param; - int16_t sd; - }; - uint32_t timeout_ms; // 0 for no timeout - bool cert_req; -} mod_network_socket_base_t; - -typedef struct _mod_network_socket_obj_t { - mp_obj_base_t base; - mod_network_socket_base_t sock_base; -} mod_network_socket_obj_t; - -/****************************************************************************** - EXPORTED DATA - ******************************************************************************/ -extern const mod_network_nic_type_t mod_network_nic_type_wlan; - -/****************************************************************************** - DECLARE FUNCTIONS - ******************************************************************************/ -void mod_network_init0(void); - -#endif // MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c deleted file mode 100644 index 286b1fb02bfb2..0000000000000 --- a/ports/cc3200/mods/modusocket.c +++ /dev/null @@ -1,819 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2015 Daniel Campora - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "simplelink.h" -#include "py/mpconfig.h" -#include "py/obj.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mphal.h" -#include "lib/netutils/netutils.h" -#include "modnetwork.h" -#include "modusocket.h" -#include "mpexception.h" - -/******************************************************************************/ -// The following set of macros and functions provide a glue between the CC3100 -// simplelink layer and the functions/methods provided by the usocket module. -// They were historically in a separate file because usocket was designed to -// work with multiple NICs, and the wlan_XXX functions just provided one -// particular NIC implementation (that of the CC3100). But the CC3200 port only -// supports a single NIC (being the CC3100) so it's unnecessary and inefficient -// to provide an intermediate wrapper layer. Hence the wlan_XXX functions -// are provided below as static functions so they can be inlined directly by -// the corresponding usocket calls. - -#define WLAN_MAX_RX_SIZE 16000 -#define WLAN_MAX_TX_SIZE 1476 - -#define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \ - addr.sa_family = SL_AF_INET; \ - addr.sa_data[0] = port >> 8; \ - addr.sa_data[1] = port; \ - addr.sa_data[2] = ip[3]; \ - addr.sa_data[3] = ip[2]; \ - addr.sa_data[4] = ip[1]; \ - addr.sa_data[5] = ip[0]; - -#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \ - ip[0] = addr.sa_data[5]; \ - ip[1] = addr.sa_data[4]; \ - ip[2] = addr.sa_data[3]; \ - ip[3] = addr.sa_data[2]; - -#define SOCKET_TIMEOUT_QUANTA_MS (20) - -STATIC int convert_sl_errno(int sl_errno) { - return -sl_errno; -} - -// This function is left as non-static so it's not inlined. -int check_timedout(mod_network_socket_obj_t *s, int ret, uint32_t *timeout_ms, int *_errno) { - if (*timeout_ms == 0 || ret != SL_EAGAIN) { - if (s->sock_base.timeout_ms > 0 && ret == SL_EAGAIN) { - *_errno = MP_ETIMEDOUT; - } else { - *_errno = convert_sl_errno(ret); - } - return -1; - } - mp_hal_delay_ms(SOCKET_TIMEOUT_QUANTA_MS); - if (*timeout_ms < SOCKET_TIMEOUT_QUANTA_MS) { - *timeout_ms = 0; - } else { - *timeout_ms -= SOCKET_TIMEOUT_QUANTA_MS; - } - return 0; -} - -STATIC int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { - uint32_t ip; - int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family); - out_ip[0] = ip; - out_ip[1] = ip >> 8; - out_ip[2] = ip >> 16; - out_ip[3] = ip >> 24; - return result; -} - -STATIC int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) { - int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto); - if (sd < 0) { - *_errno = sd; - return -1; - } - s->sock_base.sd = sd; - return 0; -} - -STATIC void wlan_socket_close(mod_network_socket_obj_t *s) { - // this is to prevent the finalizer to close a socket that failed when being created - if (s->sock_base.sd >= 0) { - modusocket_socket_delete(s->sock_base.sd); - sl_Close(s->sock_base.sd); - s->sock_base.sd = -1; - } -} - -STATIC int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr)); - if (ret != 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) { - int ret = sl_Listen(s->sock_base.sd, backlog); - if (ret != 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) { - // accept incoming connection - int16_t sd; - SlSockAddr_t addr; - SlSocklen_t addr_len = sizeof(addr); - - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - sd = sl_Accept(s->sock_base.sd, &addr, &addr_len); - if (sd >= 0) { - // save the socket descriptor - s2->sock_base.sd = sd; - // return ip and port - UNPACK_SOCKADDR(addr, ip, *port); - return 0; - } - if (check_timedout(s, sd, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - uint32_t timeout_ms = s->sock_base.timeout_ms; - - // For a non-blocking connect the CC3100 will return SL_EALREADY while the - // connection is in progress. - - for (;;) { - int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr)); - if (ret == 0) { - return 0; - } - - // Check if we are in non-blocking mode and the connection is in progress - if (s->sock_base.timeout_ms == 0 && ret == SL_EALREADY) { - // To match BSD we return EINPROGRESS here - *_errno = MP_EINPROGRESS; - return -1; - } - - // We are in blocking mode, so if the connection isn't in progress then error out - if (ret != SL_EALREADY) { - *_errno = convert_sl_errno(ret); - return -1; - } - - if (check_timedout(s, SL_EAGAIN, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) { - if (len == 0) { - return 0; - } - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_Send(s->sock_base.sd, (const void *)buf, len, 0); - if (ret > 0) { - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) { - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0); - if (ret >= 0) { - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr)); - if (ret >= 0) { - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { - SlSockAddr_t addr; - SlSocklen_t addr_len = sizeof(addr); - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len); - if (ret >= 0) { - UNPACK_SOCKADDR(addr, ip, *port); - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { - int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen); - if (ret < 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) { - SlSockNonblocking_t option; - if (timeout_s == 0 || timeout_s == -1) { - if (timeout_s == 0) { - // set non-blocking mode - option.NonblockingEnabled = 1; - } else { - // set blocking mode - option.NonblockingEnabled = 0; - } - timeout_s = 0; - } else { - // synthesize timeout via non-blocking behaviour with a loop - option.NonblockingEnabled = 1; - } - - int ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option)); - if (ret != 0) { - *_errno = convert_sl_errno(ret); - return -1; - } - - s->sock_base.timeout_ms = timeout_s * 1000; - return 0; -} - -STATIC int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) { - mp_int_t ret; - if (request == MP_STREAM_POLL) { - mp_uint_t flags = arg; - ret = 0; - int32_t sd = s->sock_base.sd; - - // init fds - SlFdSet_t rfds, wfds, xfds; - SL_FD_ZERO(&rfds); - SL_FD_ZERO(&wfds); - SL_FD_ZERO(&xfds); - - // set fds if needed - if (flags & MP_STREAM_POLL_RD) { - SL_FD_SET(sd, &rfds); - } - if (flags & MP_STREAM_POLL_WR) { - SL_FD_SET(sd, &wfds); - } - if (flags & MP_STREAM_POLL_HUP) { - SL_FD_SET(sd, &xfds); - } - - // call simplelink's select with minimum timeout - SlTimeval_t tv; - tv.tv_sec = 0; - tv.tv_usec = 1; - int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv); - - // check for errors - if (nfds == -1) { - *_errno = nfds; - return -1; - } - - // check return of select - if (SL_FD_ISSET(sd, &rfds)) { - ret |= MP_STREAM_POLL_RD; - } - if (SL_FD_ISSET(sd, &wfds)) { - ret |= MP_STREAM_POLL_WR; - } - if (SL_FD_ISSET(sd, &xfds)) { - ret |= MP_STREAM_POLL_HUP; - } - } else if (request == MP_STREAM_CLOSE) { - wlan_socket_close(s); - ret = 0; - } else { - *_errno = MP_EINVAL; - ret = MP_STREAM_ERROR; - } - return ret; -} - -/****************************************************************************** - DEFINE PRIVATE CONSTANTS - ******************************************************************************/ -#define MOD_NETWORK_MAX_SOCKETS 10 - -/****************************************************************************** - DEFINE PRIVATE TYPES - ******************************************************************************/ -typedef struct { - int16_t sd; - bool user; -} modusocket_sock_t; - -/****************************************************************************** - DEFINE PRIVATE DATA - ******************************************************************************/ -STATIC const mp_obj_type_t socket_type; -STATIC OsiLockObj_t modusocket_LockObj; -STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, - {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}}; - -/****************************************************************************** - DEFINE PUBLIC FUNCTIONS - ******************************************************************************/ -__attribute__ ((section (".boot"))) -void modusocket_pre_init (void) { - // create the wlan lock - ASSERT(OSI_OK == sl_LockObjCreate(&modusocket_LockObj, "SockLock")); - sl_LockObjUnlock (&modusocket_LockObj); -} - -void modusocket_socket_add (int16_t sd, bool user) { - sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - if (modusocket_sockets[i].sd < 0) { - modusocket_sockets[i].sd = sd; - modusocket_sockets[i].user = user; - break; - } - } - sl_LockObjUnlock (&modusocket_LockObj); -} - -void modusocket_socket_delete (int16_t sd) { - sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - if (modusocket_sockets[i].sd == sd) { - modusocket_sockets[i].sd = -1; - break; - } - } - sl_LockObjUnlock (&modusocket_LockObj); -} - -void modusocket_enter_sleep (void) { - SlFdSet_t socketset; - int16_t maxfd = 0; - - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - int16_t sd; - if ((sd = modusocket_sockets[i].sd) >= 0) { - SL_FD_SET(sd, &socketset); - maxfd = (maxfd > sd) ? maxfd : sd; - } - } - - if (maxfd > 0) { - // wait for any of the sockets to become ready... - sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL); - } -} - -void modusocket_close_all_user_sockets (void) { - sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) { - sl_Close(modusocket_sockets[i].sd); - modusocket_sockets[i].sd = -1; - } - } - sl_LockObjUnlock (&modusocket_LockObj); -} - -/******************************************************************************/ -// socket class - -// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None) -STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 4, false); - - // create socket object - mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t); - s->base.type = (mp_obj_t)&socket_type; - s->sock_base.u_param.domain = SL_AF_INET; - s->sock_base.u_param.type = SL_SOCK_STREAM; - s->sock_base.u_param.proto = SL_IPPROTO_TCP; - s->sock_base.u_param.fileno = -1; - s->sock_base.timeout_ms = 0; - s->sock_base.cert_req = false; - - if (n_args > 0) { - s->sock_base.u_param.domain = mp_obj_get_int(args[0]); - if (n_args > 1) { - s->sock_base.u_param.type = mp_obj_get_int(args[1]); - if (n_args > 2) { - s->sock_base.u_param.proto = mp_obj_get_int(args[2]); - if (n_args > 3) { - s->sock_base.u_param.fileno = mp_obj_get_int(args[3]); - } - } - } - } - - // create the socket - int _errno; - if (wlan_socket_socket(s, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - // add the socket to the list - modusocket_socket_add(s->sock_base.sd, true); - return s; -} - -// method socket.bind(address) -STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { - mod_network_socket_obj_t *self = self_in; - - // get address - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); - - // call the NIC to bind the socket - int _errno = 0; - if (wlan_socket_bind(self, ip, port, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); - -// method socket.listen([backlog]) -STATIC mp_obj_t socket_listen(size_t n_args, const mp_obj_t *args) { - mod_network_socket_obj_t *self = args[0]; - - int32_t backlog = 0; - if (n_args > 1) { - backlog = mp_obj_get_int(args[1]); - backlog = (backlog < 0) ? 0 : backlog; - } - - int _errno; - if (wlan_socket_listen(self, backlog, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen); - -// method socket.accept() -STATIC mp_obj_t socket_accept(mp_obj_t self_in) { - mod_network_socket_obj_t *self = self_in; - - // create new socket object - mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); - // the new socket inherits all properties from its parent - memcpy (socket2, self, sizeof(mod_network_socket_obj_t)); - - // accept the incoming connection - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = 0; - int _errno = 0; - if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) { - mp_raise_OSError(_errno); - } - - // add the socket to the list - modusocket_socket_add(socket2->sock_base.sd, true); - - // make the return value - mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); - client->items[0] = socket2; - client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); - return client; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); - -// method socket.connect(address) -STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { - mod_network_socket_obj_t *self = self_in; - - // get address - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); - - // connect the socket - int _errno; - if (wlan_socket_connect(self, ip, port, &_errno) != 0) { - if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) { - return mp_const_none; - } - mp_raise_OSError(_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); - -// method socket.send(bytes) -STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { - mod_network_socket_obj_t *self = self_in; - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - int _errno; - mp_int_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - return mp_obj_new_int_from_uint(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); - -// method socket.recv(bufsize) -STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { - mod_network_socket_obj_t *self = self_in; - mp_int_t len = mp_obj_get_int(len_in); - vstr_t vstr; - vstr_init_len(&vstr, len); - int _errno; - mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - if (ret == 0) { - return mp_const_empty_bytes; - } - vstr.len = ret; - vstr.buf[vstr.len] = '\0'; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); - -// method socket.sendto(bytes, address) -STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { - mod_network_socket_obj_t *self = self_in; - - // get the data - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); - - // get address - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); - - // call the nic to sendto - int _errno = 0; - mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); - -// method socket.recvfrom(bufsize) -STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { - mod_network_socket_obj_t *self = self_in; - vstr_t vstr; - vstr_init_len(&vstr, mp_obj_get_int(len_in)); - byte ip[4]; - mp_uint_t port = 0; - int _errno = 0; - mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - mp_obj_t tuple[2]; - if (ret == 0) { - tuple[0] = mp_const_empty_bytes; - } else { - vstr.len = ret; - vstr.buf[vstr.len] = '\0'; - tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); - } - tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); - return mp_obj_new_tuple(2, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); - -// method socket.setsockopt(level, optname, value) -STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { - mod_network_socket_obj_t *self = args[0]; - - mp_int_t level = mp_obj_get_int(args[1]); - mp_int_t opt = mp_obj_get_int(args[2]); - - const void *optval; - mp_uint_t optlen; - mp_int_t val; - if (mp_obj_is_integer(args[3])) { - val = mp_obj_get_int_truncated(args[3]); - optval = &val; - optlen = sizeof(val); - } else { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - optval = bufinfo.buf; - optlen = bufinfo.len; - } - - int _errno; - if (wlan_socket_setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); - -// method socket.settimeout(value) -// timeout=0 means non-blocking -// timeout=None means blocking -// otherwise, timeout is in seconds -STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { - mod_network_socket_obj_t *self = self_in; - mp_uint_t timeout; - if (timeout_in == mp_const_none) { - timeout = -1; - } else { - timeout = mp_obj_get_int(timeout_in); - } - int _errno = 0; - if (wlan_socket_settimeout(self, timeout, &_errno) != 0) { - mp_raise_OSError(_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); - -// method socket.setblocking(flag) -STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { - if (mp_obj_is_true(blocking)) { - return socket_settimeout(self_in, mp_const_none); - } else { - return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0)); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); - -STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { - (void)n_args; - return args[0]; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 6, socket_makefile); - -STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, - { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, - { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_send_obj) }, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, - { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, - { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, - { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, - { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, - { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, - - // stream methods - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read1_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, -}; - -MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); - -STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { - mod_network_socket_obj_t *self = self_in; - mp_int_t ret = wlan_socket_recv(self, buf, size, errcode); - if (ret < 0) { - // we need to ignore the socket closed error here because a read() without params - // only returns when the socket is closed by the other end - if (*errcode != -SL_ESECCLOSED) { - ret = MP_STREAM_ERROR; - } else { - ret = 0; - } - } - return ret; -} - -STATIC mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { - mod_network_socket_obj_t *self = self_in; - mp_int_t ret = wlan_socket_send(self, buf, size, errcode); - if (ret < 0) { - ret = MP_STREAM_ERROR; - } - return ret; -} - -STATIC mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { - mod_network_socket_obj_t *self = self_in; - return wlan_socket_ioctl(self, request, arg, errcode); -} - -const mp_stream_p_t socket_stream_p = { - .read = socket_read, - .write = socket_write, - .ioctl = socket_ioctl, - .is_text = false, -}; - -STATIC const mp_obj_type_t socket_type = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .make_new = socket_make_new, - .protocol = &socket_stream_p, - .locals_dict = (mp_obj_t)&socket_locals_dict, -}; - -/******************************************************************************/ -// usocket module - -// function usocket.getaddrinfo(host, port) -/// \function getaddrinfo(host, port) -STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { - size_t hlen; - const char *host = mp_obj_str_get_data(host_in, &hlen); - mp_int_t port = mp_obj_get_int(port_in); - - // ipv4 only - uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - int32_t result = wlan_gethostbyname(host, hlen, out_ip, SL_AF_INET); - if (result < 0) { - mp_raise_OSError(-result); - } - mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); - tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SL_AF_INET); - tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM); - tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); - tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); - tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE); - return mp_obj_new_list(1, (mp_obj_t*)&tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo); - -STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, - - { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, - { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_usocket_getaddrinfo_obj) }, - - // class constants - { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(SL_AF_INET) }, - - { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SL_SOCK_STREAM) }, - { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SL_SOCK_DGRAM) }, - - { MP_ROM_QSTR(MP_QSTR_IPPROTO_SEC), MP_ROM_INT(SL_SEC_SOCKET) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(SL_IPPROTO_TCP) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(SL_IPPROTO_UDP) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); - -const mp_obj_module_t mp_module_usocket = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, -}; diff --git a/ports/cc3200/mods/modussl.c b/ports/cc3200/mods/modussl.c index 3211570499247..76d0617e421f0 100644 --- a/ports/cc3200/mods/modussl.c +++ b/ports/cc3200/mods/modussl.c @@ -47,7 +47,7 @@ ******************************************************************************/ typedef struct _mp_obj_ssl_socket_t { mp_obj_base_t base; - mod_network_socket_base_t sock_base; + mod_network_socket_obj_t sock_base; mp_obj_t o_sock; } mp_obj_ssl_socket_t; @@ -102,7 +102,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ } _i16 _errno; - _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd; + _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sd; // set the requested SSL method _u8 method = args[5].u_int; @@ -122,7 +122,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ // create the ssl socket mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t); // ssl sockets inherit all properties from the original socket - memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t)); + memcpy (&ssl_sock->sock_base, ((mod_network_socket_obj_t *)args[0].u_obj), sizeof(mod_network_socket_obj_t)); ssl_sock->base.type = &ssl_socket_type; ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false; ssl_sock->o_sock = args[0].u_obj; diff --git a/ports/cc3200/mods/pybrtc.c b/ports/cc3200/mods/pybrtc.c index e7b9cf258f483..18150a1060da2 100644 --- a/ports/cc3200/mods/pybrtc.c +++ b/ports/cc3200/mods/pybrtc.c @@ -40,7 +40,7 @@ #include "pybsleep.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "mpexception.h" /// \moduleref pyb diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c index b5990e9267c0c..cff8c515ff54d 100644 --- a/ports/cc3200/mods/pybsleep.c +++ b/ports/cc3200/mods/pybsleep.c @@ -46,7 +46,7 @@ #include "pybpin.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "osi.h" #include "debug.h" #include "mpexception.h" diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index ee9a226e5c996..576a27021c8e5 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -33,7 +33,6 @@ #endif // options to control how MicroPython is built - #define MICROPY_ALLOC_PATH_MAX (128) #define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_THUMB (0) @@ -117,6 +116,8 @@ #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_NETWORK (1) +#define MICROPY_PY_USOCKET (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) @@ -195,6 +196,7 @@ extern const struct _mp_obj_module_t mp_module_ussl; mp_obj_list_t pyb_timer_channel_obj_list; \ struct _pyb_uart_obj_t *pyb_uart_objs[2]; \ struct _os_term_dup_obj_t *os_term_dup_obj; \ + mp_obj_list_t mod_network_nic_list; \ // type definitions for the specific machine diff --git a/ports/cc3200/mptask.c b/ports/cc3200/mptask.c index 6143f72a7a68f..d0b42cebb9ea9 100644 --- a/ports/cc3200/mptask.c +++ b/ports/cc3200/mptask.c @@ -56,7 +56,7 @@ #include "simplelink.h" #include "modnetwork.h" #include "modusocket.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "serverstask.h" #include "telnet.h" #include "debug.h" @@ -149,7 +149,7 @@ void TASK_MicroPython (void *pvParameters) { uart_init0(); timer_init0(); readline_init0(); - mod_network_init0(); + mod_network_init(); rng_init0(); pybsleep_reset_cause_t rstcause = pyb_sleep_get_reset_cause(); diff --git a/ports/cc3200/serverstask.c b/ports/cc3200/serverstask.c index 100b8d33b0e1e..eb0b94cd7095b 100644 --- a/ports/cc3200/serverstask.c +++ b/ports/cc3200/serverstask.c @@ -40,7 +40,7 @@ #include "modusocket.h" #include "mpexception.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" /****************************************************************************** DEFINE PRIVATE TYPES diff --git a/ports/cc3200/telnet/telnet.c b/ports/cc3200/telnet/telnet.c index dbb77cd6d762f..e1cc2f51eb921 100644 --- a/ports/cc3200/telnet/telnet.c +++ b/ports/cc3200/telnet/telnet.c @@ -33,7 +33,7 @@ #include "telnet.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "modusocket.h" #include "debug.h" #include "mpexception.h" diff --git a/ports/cc3200/util/random.c b/ports/cc3200/util/random.c index f8e9cdf0cb21f..eb006fe7be169 100644 --- a/ports/cc3200/util/random.c +++ b/ports/cc3200/util/random.c @@ -35,7 +35,7 @@ #include "pybrtc.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "random.h" #include "debug.h" diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 6ca83f1e6e331..6576df4467126 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -60,7 +60,9 @@ INC += -I./modules/ble INC += -I./modules/board INC += -I../../lib/mp-readline INC += -I./drivers/bluetooth +INC += -I./drivers/wifi INC += -I./drivers +INC += -I../../extmod INC += -I../../lib/nrfx/ INC += -I../../lib/nrfx/drivers INC += -I../../lib/nrfx/drivers/include @@ -158,6 +160,7 @@ SRC_LIB += $(addprefix lib/,\ utils/pyexec.c \ utils/interrupt_char.c \ timeutils/timeutils.c \ + netutils/netutils.c \ ) ifeq ($(MICROPY_FATFS), 1) @@ -187,6 +190,13 @@ SRC_NRFX_HAL += $(addprefix lib/nrfx/hal/,\ nrf_nvmc.c \ ) +EXTMOD_SRC_C += $(addprefix extmod/,\ + modnetwork.c \ + modusocket.c \ + modnwcc31k.c \ + ) + + SRC_C += \ main.c \ mphalport.c \ @@ -199,6 +209,7 @@ SRC_C += \ drivers/ticker.c \ drivers/bluetooth/ble_drv.c \ drivers/bluetooth/ble_uart.c \ + drivers/wifi/cc3100_drv.c \ DRIVERS_SRC_C += $(addprefix modules/,\ machine/modmachine.c \ @@ -232,6 +243,24 @@ DRIVERS_SRC_C += $(addprefix modules/,\ random/modrandom.c \ ) +ifeq ($(MICROPY_PY_CC31K),1) +CC3100_DIR=drivers/cc3100 +INC += -I$(TOP)/$(CC3100_DIR)/inc +CFLAGS_MOD += -DMICROPY_PY_CC31K=1 +DRIVERS_SRC_C += $(addprefix $(CC3100_DIR)/src/,\ + device.c \ + driver.c \ + flowcont.c \ + fs.c \ + netapp.c \ + netcfg.c \ + nonos.c \ + socket.c \ + spawn.c \ + wlan.c \ + ) +endif + # Custom micropython startup file with smaller interrupt vector table # than the file provided in nrfx. SRC_C += \ @@ -244,7 +273,7 @@ endif OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) @@ -304,7 +333,7 @@ $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(Q)$(SIZE) $@ # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) +SRC_QSTR += $(SRC_C) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) $(EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR diff --git a/ports/nrf/boards/pca10040/mpconfigboard.h b/ports/nrf/boards/pca10040/mpconfigboard.h index 82b74d9284916..b11c99c3544a3 100644 --- a/ports/nrf/boards/pca10040/mpconfigboard.h +++ b/ports/nrf/boards/pca10040/mpconfigboard.h @@ -38,6 +38,9 @@ #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) +#define MICROPY_PY_USOCKET (1) +#define MICROPY_PY_NETWORK (1) + #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) diff --git a/ports/nrf/drivers/wifi/cc3100_drv.c b/ports/nrf/drivers/wifi/cc3100_drv.c new file mode 100644 index 0000000000000..78688bf989f8f --- /dev/null +++ b/ports/nrf/drivers/wifi/cc3100_drv.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpconfig.h" + +#if (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) +#include "cc3100_drv.h" +#include "nrf_gpio.h" +#include "nrf_gpiote.h" +#include "pin.h" +#include "spi.h" +#include "mphalport.h" + +#if NRFX_SPI_ENABLED +#include "nrfx_spi.h" +#else +#include "nrfx_spim.h" +#endif + +#define CS_LOW() nrf_gpio_pin_clear(mp_pin_cs->pin) +#define CS_HIGH() nrf_gpio_pin_set(mp_pin_cs->pin) + +STATIC const machine_hard_spi_obj_t * mp_spi = NULL; + +STATIC const pin_obj_t * mp_pin_cs = NULL; +STATIC const pin_obj_t * mp_pin_en = NULL; +STATIC const pin_obj_t * mp_pin_irq = NULL; + +STATIC volatile irq_handler_t mp_cc3100_irq_handler = NULL; + +STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj; + +STATIC mp_obj_t irq_callback(mp_obj_t pin_obj) { + if (mp_cc3100_irq_handler) + { + mp_cc3100_irq_handler(0); + } + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback); + +void cc3100_drv_enable(void) { + nrf_gpio_pin_set(mp_pin_en->pin); +} + +void cc3100_drv_disable(void) { + nrf_gpio_pin_clear(mp_pin_en->pin); +} + +void cc3100_drv_init(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) { + machine_hard_spi_obj_t * spi_obj = spi; + + mp_spi = spi_obj; + mp_pin_cs = pin_cs; + mp_pin_en = pin_en; + mp_pin_irq = pin_irq; +} + +int cc3100_drv_open(char * interface, unsigned long flags) { + nrf_gpio_cfg_output(mp_pin_cs->pin); + nrf_gpio_cfg_output(mp_pin_en->pin); + + nrf_gpio_pin_set(mp_pin_cs->pin); + nrf_gpio_cfg_input(mp_pin_irq->pin, NRF_GPIO_PIN_PULLUP); + + // register interrupt handler + extint_register(mp_pin_irq->pin, NRF_GPIOTE_POLARITY_LOTOHI, NRF_GPIO_PIN_PULLDOWN, (mp_obj_t)&irq_callback_obj); + extint_enable(mp_pin_irq->pin); + + nrf_gpio_pin_clear(mp_pin_en->pin); + mp_hal_delay_ms(500); + + return 0; +} + +int cc3100_drv_close(int handle) { + return -1; +} + +int cc3100_drv_read(int handle, unsigned char * p_buffer, int len) { + nrfx_spi_xfer_desc_t xfer_desc = { + .p_tx_buffer = NULL, + .tx_length = 0, + .p_rx_buffer = p_buffer, + .rx_length = len + }; + + CS_LOW(); + (void)nrfx_spi_xfer(mp_spi->p_spi, &xfer_desc, 0); + CS_HIGH(); + + return 0; +} + +int cc3100_drv_write(int handle, unsigned char * p_buffer, int len) { + nrfx_spi_xfer_desc_t xfer_desc = { + .p_tx_buffer = p_buffer, + .tx_length = len, + .p_rx_buffer = NULL, + .rx_length = 0 + }; + + CS_LOW(); + (void)nrfx_spi_xfer(mp_spi->p_spi, &xfer_desc, 0); + CS_HIGH(); + + return 0; +} + +int cc3100_drv_irq_handler_register(irq_handler_t handler, void * p_val) { + mp_cc3100_irq_handler = handler; + + return 0; +} + +void cc3100_drv_irq_handler_mask(void) { +} + +void cc3100_drv_irq_handler_unmask(void) { +} + +#endif // (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) diff --git a/ports/nrf/drivers/wifi/cc3100_drv.h b/ports/nrf/drivers/wifi/cc3100_drv.h new file mode 100644 index 0000000000000..2638e9b4be946 --- /dev/null +++ b/ports/nrf/drivers/wifi/cc3100_drv.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef CC3100_DRV_H +#define CC3100_DRV_H + +typedef void (*irq_handler_t)(void *p_val); + +void cc3100_drv_enable(void); +void cc3100_drv_disable(void); +void cc3100_drv_init(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq); +int cc3100_drv_open(char * interface, unsigned long flags); +int cc3100_drv_close(int handle); +int cc3100_drv_read(int handle, unsigned char * p_buffer, int len); +int cc3100_drv_write(int handle, unsigned char * p_buffer, int len); +int cc3100_drv_irq_handler_register(irq_handler_t handler, void * p_val); +void cc3100_drv_irq_handler_mask(void); +void cc3100_drv_irq_handler_unmask(void); + +#endif // CC3100_DRV_H diff --git a/ports/nrf/drivers/wifi/user.h b/ports/nrf/drivers/wifi/user.h new file mode 100644 index 0000000000000..169935b9f62c8 --- /dev/null +++ b/ports/nrf/drivers/wifi/user.h @@ -0,0 +1,1023 @@ +/* + * user.h - CC31xx/CC32xx Host Driver Implementation + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + + +#ifndef __USER_H__ +#define __USER_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + ****************************************************************************** + + \defgroup porting_user_include Porting - User Include Files + + This section IS NOT REQUIRED in case user provided primitives are handled + in makefiles or project configurations (IDE) + + PORTING ACTION: + - Include all required header files for the definition of: + -# Transport layer library API (e.g. SPI, UART) + -# OS primitives definitions (e.g. Task spawn, Semaphores) + -# Memory management primitives (e.g. alloc, free) + + ****************************************************************************** + */ + +#include +#include "cc3100_drv.h" + +typedef void (*irq_handler_t)(void *pVal); + + +typedef irq_handler_t SL_P_EVENT_HANDLER; +/*! + \def MAX_CONCURRENT_ACTIONS + + \brief Defines the maximum number of concurrent action in the system + Min:1 , Max: 32 + + Actions which has async events as return, can be + + \sa + + \note In case there are not enough resources for the actions needed in the system, + error is received: POOL_IS_EMPTY + one option is to increase MAX_CONCURRENT_ACTIONS + (improves performance but results in memory consumption) + Other option is to call the API later (decrease performance) + + \warning In case of setting to one, recommend to use non-blocking recv\recvfrom to allow + multiple socket recv +*/ +#define MAX_CONCURRENT_ACTIONS 10 + +/*! + ****************************************************************************** + + \defgroup porting_capabilities Porting - Capabilities Set + + This section IS NOT REQUIRED in case one of the following pre defined + capabilities set is in use: + - SL_TINY + - SL_SMALL + - SL_FULL + + PORTING ACTION: + - Define one of the pre-defined capabilities set or uncomment the + relevant definitions below to select the required capabilities + + @{ + + ******************************************************************************* + */ + +/*! + \def SL_INC_ARG_CHECK + + \brief Defines whether the SimpleLink driver perform argument check + or not + + When defined, the SimpleLink driver perform argument check on + function call. Removing this define could reduce some code + size and improve slightly the performances but may impact in + unpredictable behavior in case of invalid arguments + + \sa + + \note belongs to \ref porting_sec + + \warning Removing argument check may cause unpredictable behavior in + case of invalid arguments. + In this case the user is responsible to argument validity + (for example all handlers must not be NULL) +*/ +#define SL_INC_ARG_CHECK + + +/*! + \def SL_INC_STD_BSD_API_NAMING + + \brief Defines whether SimpleLink driver should expose standard BSD + APIs or not + + When defined, the SimpleLink driver in addtion to its alternative + BSD APIs expose also standard BSD APIs. + Stadrad BSD API includs the following functions: + socket , close , accept , bind , listen , connect , select , + setsockopt , getsockopt , recv , recvfrom , write , send , sendto , + gethostbyname + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define SL_INC_STD_BSD_API_NAMING + + +/*! + \brief Defines whether to include extended API in SimpleLink driver + or not + + When defined, the SimpleLink driver will include also all + exteded API of the included packages + + \sa ext_api + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_EXT_API + +/*! + \brief Defines whether to include WLAN package in SimpleLink driver + or not + + When defined, the SimpleLink driver will include also + the WLAN package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_WLAN_PKG + +/*! + \brief Defines whether to include SOCKET package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also + the SOCKET package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCKET_PKG + +/*! + \brief Defines whether to include NET_APP package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also the + NET_APP package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_NET_APP_PKG + +/*! + \brief Defines whether to include NET_CFG package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also + the NET_CFG package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_NET_CFG_PKG + +/*! + \brief Defines whether to include NVMEM package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also the + NVMEM package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_NVMEM_PKG + +/*! + \brief Defines whether to include socket server side APIs + in SimpleLink driver or not + + When defined, the SimpleLink driver will include also socket + server side APIs + + \sa server_side + + \note + + \warning +*/ +#define SL_INC_SOCK_SERVER_SIDE_API + +/*! + \brief Defines whether to include socket client side APIs in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also socket + client side APIs + + \sa client_side + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCK_CLIENT_SIDE_API + +/*! + \brief Defines whether to include socket receive APIs in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also socket + receive side APIs + + \sa recv_api + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCK_RECV_API + +/*! + \brief Defines whether to include socket send APIs in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also socket + send side APIs + + \sa send_api + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCK_SEND_API + +/*! + + Close the Doxygen group. + @} + + */ + + +/*! + ****************************************************************************** + + \defgroup porting_enable_device Porting - Device Enable/Disable + + The enable/disable API provide mechanism to enable/disable the network processor + + + PORTING ACTION: + - None + @{ + + ****************************************************************************** + */ + +/*! + \brief Preamble to the enabling the Network Processor. + Placeholder to implement any pre-process operations + before enabling networking operations. + + \sa sl_DeviceEnable + + \note belongs to \ref ported_sec + +*/ +#define sl_DeviceEnablePreamble() + +/*! + \brief Enable the Network Processor + + \sa sl_DeviceDisable + + \note belongs to \ref porting_sec + +*/ +#define sl_DeviceEnable cc3100_drv_enable + +/*! + \brief Disable the Network Processor + + \sa sl_DeviceEnable + + \note belongs to \ref porting_sec +*/ +#define sl_DeviceDisable cc3100_drv_disable + +/*! + + Close the Doxygen group. + @} + + */ + +/*! + ****************************************************************************** + + \defgroup porting_interface Porting - Communication Interface + + The simple link device can work with different communication + channels (e.g. spi/uart). Texas Instruments provides single driver + that can work with all these types. This section bind between the + physical communication interface channel and the SimpleLink driver + + + \note Correct and efficient implementation of this driver is critical + for the performances of the SimpleLink device on this platform. + + + PORTING ACTION: + - None + + @{ + + ****************************************************************************** + */ + +#define _SlFd_t int + +/*! + \brief Opens an interface communication port to be used for communicating + with a SimpleLink device + + Given an interface name and option flags, this function opens + the communication port and creates a file descriptor. + This file descriptor is used afterwards to read and write + data from and to this specific communication channel. + The speed, clock polarity, clock phase, chip select and all other + specific attributes of the channel are all should be set to hardcoded + in this function. + + \param ifName - points to the interface name/path. The interface name is an + optional attributes that the simple link driver receives + on opening the driver (sl_Start). + In systems that the spi channel is not implemented as + part of the os device drivers, this parameter could be NULL. + + \param flags - optional flags parameters for future use + + \return upon successful completion, the function shall open the channel + and return a non-negative integer representing the file descriptor. + Otherwise, -1 shall be returned + + \sa sl_IfClose , sl_IfRead , sl_IfWrite + + \note The prototype of the function is as follow: + Fd_t xxx_IfOpen(char* pIfName , unsigned long flags); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfOpen cc3100_drv_open + +/*! + \brief Closes an opened interface communication port + + \param fd - file descriptor of opened communication channel + + \return upon successful completion, the function shall return 0. + Otherwise, -1 shall be returned + + \sa sl_IfOpen , sl_IfRead , sl_IfWrite + + \note The prototype of the function is as follow: + int xxx_IfClose(Fd_t Fd); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfClose cc3100_drv_close + +/*! + \brief Attempts to read up to len bytes from an opened communication channel + into a buffer starting at pBuff. + + \param fd - file descriptor of an opened communication channel + + \param pBuff - pointer to the first location of a buffer that contains enough + space for all expected data + + \param len - number of bytes to read from the communication channel + + \return upon successful completion, the function shall return the number of read bytes. + Otherwise, 0 shall be returned + + \sa sl_IfClose , sl_IfOpen , sl_IfWrite + + + \note The prototype of the function is as follow: + int xxx_IfRead(Fd_t Fd , char* pBuff , int Len); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfRead cc3100_drv_read + +/*! + \brief attempts to write up to len bytes to the SPI channel + + \param fd - file descriptor of an opened communication channel + + \param pBuff - pointer to the first location of a buffer that contains + the data to send over the communication channel + + \param len - number of bytes to write to the communication channel + + \return upon successful completion, the function shall return the number of sent bytes. + therwise, 0 shall be returned + + \sa sl_IfClose , sl_IfOpen , sl_IfRead + + \note This function could be implemented as zero copy and return only upon successful completion + of writing the whole buffer, but in cases that memory allocation is not too tight, the + function could copy the data to internal buffer, return back and complete the write in + parallel to other activities as long as the other SPI activities would be blocked until + the entire buffer write would be completed + + The prototype of the function is as follow: + int xxx_IfWrite(Fd_t Fd , char* pBuff , int Len); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfWrite cc3100_drv_write + +/*! + \brief register an interrupt handler routine for the host IRQ + + \param InterruptHdl - pointer to interrupt handler routine + + \param pValue - pointer to a memory structure that is passed + to the interrupt handler. + + \return upon successful registration, the function shall return 0. + Otherwise, -1 shall be returned + + \sa + + \note If there is already registered interrupt handler, the function + should overwrite the old handler with the new one + + \note If the handler is a null pointer, the function should un-register the + interrupt handler, and the interrupts can be disabled. + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfRegIntHdlr(InterruptHdl , pValue) \ + cc3100_drv_irq_handler_register(InterruptHdl, pValue) +/*! + \brief Masks the Host IRQ + + \sa sl_IfUnMaskIntHdlr + + + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_IfMaskIntHdlr() cc3100_drv_irq_handler_mask() + +/*! + \brief Unmasks the Host IRQ + + \sa sl_IfMaskIntHdlr + + + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_IfUnMaskIntHdlr() cc3100_drv_irq_handler_unmask() + +/*! + \brief Write Handers for statistics debug on write + + \param interface handler - pointer to interrupt handler routine + + + \return no return value + + \sa + + \note An optional hooks for monitoring before and after write info + + \note belongs to \ref porting_sec + + \warning +*/ +/* +#define SL_START_WRITE_STAT +*/ + +#ifdef SL_START_WRITE_STAT +#define sl_IfStartWriteSequence +#define sl_IfEndWriteSequence +#endif +/*! + + Close the Doxygen group. + @} + + */ + +/*! + ****************************************************************************** + + \defgroup porting_mem_mgm Porting - Memory Management + + This section declare in which memory management model the SimpleLink driver + will run: + -# Static + -# Dynamic + + This section IS NOT REQUIRED in case Static model is selected. + + The default memory model is Static + + PORTING ACTION: + - If dynamic model is selected, define the alloc and free functions. + + @{ + + ***************************************************************************** + */ + +/*! + \brief Defines whether the SimpleLink driver is working in dynamic + memory model or not + + When defined, the SimpleLink driver use dynamic allocations + if dynamic allocation is selected malloc and free functions + must be retrieved + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define SL_MEMORY_MGMT_DYNAMIC 0 +#define SL_MEMORY_MGMT_STATIC 1 + +#define SL_MEMORY_MGMT SL_MEMORY_MGMT_STATIC + +#ifdef SL_MEMORY_MGMT_DYNAMIC + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_Malloc(Size) malloc(Size) + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_Free(pMem) free(pMem) + +#endif + +/*! + + Close the Doxygen group. + @} + + */ + +/*! + ****************************************************************************** + + \defgroup porting_os Porting - Operating System + + The simple link driver can run on multi-threaded environment as well + as non-os environment (mail loop) + + This section IS NOT REQUIRED in case you are working on non-os environment. + + If you choose to work in multi-threaded environment under any operating system + you will have to provide some basic adaptation routines to allow the driver + to protect access to resources from different threads (locking object) and + to allow synchronization between threads (sync objects). + + PORTING ACTION: + -# Uncomment SL_PLATFORM_MULTI_THREADED define + -# Bind locking object routines + -# Bind synchronization object routines + -# Optional - Bind spawn thread routine + + @{ + + ****************************************************************************** + */ + +/* +#define SL_PLATFORM_MULTI_THREADED +*/ + +#ifdef SL_PLATFORM_MULTI_THREADED + +/*! + \brief + \sa + \note belongs to \ref porting_sec + \warning +*/ +#define SL_OS_RET_CODE_OK ((int)OSI_OK) + +/*! + \brief + \sa + \note belongs to \ref porting_sec + \warning +*/ +#define SL_OS_WAIT_FOREVER ((OsiTime_t)OSI_WAIT_FOREVER) + +/*! + \brief + \sa + \note belongs to \ref porting_sec + \warning +*/ +#define SL_OS_NO_WAIT ((OsiTime_t)OSI_NO_WAIT) + +/*! + \brief type definition for a time value + + \note On each porting or platform the type could be whatever is needed - integer, pointer to structure etc. + + \note belongs to \ref porting_sec +*/ +#define _SlTime_t + +/*! + \brief type definition for a sync object container + + Sync object is object used to synchronize between two threads or thread and interrupt handler. + One thread is waiting on the object and the other thread send a signal, which then + release the waiting thread. + The signal must be able to be sent from interrupt context. + This object is generally implemented by binary semaphore or events. + + \note On each porting or platform the type could be whatever is needed - integer, structure etc. + + \note belongs to \ref porting_sec +*/ +#define _SlSyncObj_t + + +/*! + \brief This function creates a sync object + + The sync object is used for synchronization between diffrent thread or ISR and + a thread. + + \param pSyncObj - pointer to the sync object control block + + \return upon successful creation the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + + \note belongs to \ref porting_sec + \warning +*/ +#define sl_SyncObjCreate(pSyncObj,pName) + + +/*! + \brief This function deletes a sync object + + \param pSyncObj - pointer to the sync object control block + + \return upon successful deletion the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_SyncObjDelete(pSyncObj) + + +/*! + \brief This function generates a sync signal for the object. + + All suspended threads waiting on this sync object are resumed + + \param pSyncObj - pointer to the sync object control block + + \return upon successful signaling the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note the function could be called from ISR context + \warning +*/ +#define sl_SyncObjSignal(pSyncObj) + +/*! + \brief This function generates a sync signal for the object from Interrupt + + This is for RTOS that should signal from IRQ using a dedicated API + + \param pSyncObj - pointer to the sync object control block + + \return upon successful signaling the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note the function could be called from ISR context + \warning +*/ +#define sl_SyncObjSignalFromIRQ(pSyncObj) +/*! + \brief This function waits for a sync signal of the specific sync object + + \param pSyncObj - pointer to the sync object control block + \param Timeout - numeric value specifies the maximum number of mSec to + stay suspended while waiting for the sync signal + Currently, the simple link driver uses only two values: + - OSI_WAIT_FOREVER + - OSI_NO_WAIT + + \return upon successful reception of the signal within the timeout window return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_SyncObjWait(pSyncObj,Timeout) + +/*! + \brief type definition for a locking object container + + Locking object are used to protect a resource from mutual accesses of two or more threads. + The locking object should suppurt reentrant locks by a signal thread. + This object is generally implemented by mutex semaphore + + \note On each porting or platform the type could be whatever is needed - integer, structure etc. + \note belongs to \ref porting_sec +*/ +#define _SlLockObj_t + +/*! + \brief This function creates a locking object. + + The locking object is used for protecting a shared resources between different + threads. + + \param pLockObj - pointer to the locking object control block + + \return upon successful creation the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjCreate(pLockObj,pName) + +/*! + \brief This function deletes a locking object. + + \param pLockObj - pointer to the locking object control block + + \return upon successful deletion the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjDelete(pLockObj) + +/*! + \brief This function locks a locking object. + + All other threads that call this function before this thread calls + the osi_LockObjUnlock would be suspended + + \param pLockObj - pointer to the locking object control block + \param Timeout - numeric value specifies the maximum number of mSec to + stay suspended while waiting for the locking object + Currently, the simple link driver uses only two values: + - OSI_WAIT_FOREVER + - OSI_NO_WAIT + + + \return upon successful reception of the locking object the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjLock(pLockObj,Timeout) + +/*! + \brief This function unlock a locking object. + + \param pLockObj - pointer to the locking object control block + + \return upon successful unlocking the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjUnlock(pLockObj) + +#endif +/*! + \brief This function call the pEntry callback from a different context + + \param pEntry - pointer to the entry callback function + + \param pValue - pointer to any type of memory structure that would be + passed to pEntry callback from the execution thread. + + \param flags - execution flags - reserved for future usage + + \return upon successful registration of the spawn the function should return 0 + (the function is not blocked till the end of the execution of the function + and could be returned before the execution is actually completed) + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +/* +#define SL_PLATFORM_EXTERNAL_SPAWN +*/ + +#ifdef SL_PLATFORM_EXTERNAL_SPAWN +#define sl_Spawn(pEntry,pValue,flags) +#endif + +/*! + + Close the Doxygen group. + @} + + */ + + +/*! + ****************************************************************************** + + \defgroup porting_events Porting - Event Handlers + + This section includes the asynchronous event handlers routines + + PORTING ACTION: + -Uncomment the required handler and define your routine as the value + of this handler + + @{ + + ****************************************************************************** + */ + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_GeneralEvtHdlr SimpleLinkGeneralEventHandler + +/*! + \brief An event handler for WLAN connection or disconnection indication + This event handles async WLAN events. + Possible events are: + SL_WLAN_CONNECT_EVENT - indicates WLAN is connected + SL_WLAN_DISCONNECT_EVENT - indicates WLAN is disconnected + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_WlanEvtHdlr SimpleLinkWlanEventHandler + +/*! + \brief An event handler for IP address asynchronous event. Usually accepted after new WLAN connection. + This event handles networking events. + Possible events are: + SL_NETAPP_IPV4_ACQUIRED - IP address was acquired (DHCP or Static) + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_NetAppEvtHdlr SimpleLinkNetAppEventHandler + +/*! + \brief A callback for HTTP server events. + Possible events are: + SL_NETAPP_HTTPGETTOKENVALUE - NWP requests to get the value of a specific token + SL_NETAPP_HTTPPOSTTOKENVALUE - NWP post to the host a new value for a specific token + + \param pServerEvent - Contains the relevant event information (SL_NETAPP_HTTPGETTOKENVALUE or SL_NETAPP_HTTPPOSTTOKENVALUE) + + \param pServerResponse - Should be filled by the user with the relevant response information (i.e SL_NETAPP_HTTPSETTOKENVALUE as a response to SL_NETAPP_HTTPGETTOKENVALUE event) + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_HttpServerCallback SimpleLinkHttpServerCallback + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_SockEvtHdlr SimpleLinkSockEventHandler + + +/*! + + Close the Doxygen group. + @} + + */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __USER_H__ */ diff --git a/ports/nrf/main.c b/ports/nrf/main.c index b9c29e7538d8c..63ec551718dde 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -70,6 +70,10 @@ #include "softpwm.h" #endif +#if MICROPY_PY_NETWORK +#include "modnetwork.h" +#endif + void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { @@ -225,6 +229,11 @@ pin_init0(); pwm_start(); #endif +#if MICROPY_PY_NETWORK + mod_network_init(); +#endif + + #if MICROPY_VFS || MICROPY_MBFS // run boot.py and main.py if they exist. if (mp_import_stat("boot.py") == MP_IMPORT_STAT_FILE) { diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index df4eb471e33b3..73b5e18f3587c 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -535,39 +535,54 @@ STATIC void pin_common_irq_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t mp_call_function_1(pin_handler, (mp_obj_t)pin_obj); } +void extint_register(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t sense, nrf_gpio_pin_pull_t pull, mp_obj_t callback) { + nrfx_gpiote_in_config_t config = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); + config.sense = sense; + config.pull = pull; + + nrfx_err_t err_code = nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); + if (err_code == NRFX_ERROR_INVALID_STATE) { + // Re-init if already configured. + nrfx_gpiote_in_uninit(pin); + nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); + } + + MP_STATE_PORT(pin_irq_handlers)[pin] = callback; +} + +void extint_enable(nrfx_gpiote_pin_t pin) { + nrfx_gpiote_in_event_enable(pin, true); +} + +void extint_disable(nrfx_gpiote_pin_t pin) { + nrfx_gpiote_in_event_disable(pin); +} + STATIC mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum {ARG_handler, ARG_trigger, ARG_wake}; + enum {ARG_handler, ARG_trigger, ARG_wake}; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = mp_const_none} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = NRF_GPIOTE_POLARITY_LOTOHI | NRF_GPIOTE_POLARITY_HITOLO} }, { MP_QSTR_wake, MP_ARG_BOOL, {.u_bool = false} }, }; + pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - nrfx_gpiote_pin_t pin = self->pin; + nrfx_gpiote_pin_t pin = self->pin; + nrf_gpio_pin_pull_t pull = NRF_GPIO_PIN_PULLUP; + nrf_gpiote_polarity_t sense = NRF_GPIOTE_POLARITY_LOTOHI; - nrfx_gpiote_in_config_t config = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); if (args[ARG_trigger].u_int == NRF_GPIOTE_POLARITY_LOTOHI) { - config.sense = NRF_GPIOTE_POLARITY_LOTOHI; + sense = NRF_GPIOTE_POLARITY_LOTOHI; } else if (args[ARG_trigger].u_int == NRF_GPIOTE_POLARITY_HITOLO) { - config.sense = NRF_GPIOTE_POLARITY_HITOLO; + sense = NRF_GPIOTE_POLARITY_HITOLO; } - config.pull = NRF_GPIO_PIN_PULLUP; - nrfx_err_t err_code = nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); - if (err_code == NRFX_ERROR_INVALID_STATE) { - // Re-init if already configured. - nrfx_gpiote_in_uninit(pin); - nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); - } - - MP_STATE_PORT(pin_irq_handlers)[pin] = args[ARG_handler].u_obj; - - nrfx_gpiote_in_event_enable(pin, true); + extint_register(pin, sense, pull, args[ARG_handler].u_obj); + extint_enable(pin); - // return the irq object return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_irq_obj, 1, pin_irq); diff --git a/ports/nrf/modules/machine/pin.h b/ports/nrf/modules/machine/pin.h index 7004b320b1b6b..bb6d96cd07e33 100644 --- a/ports/nrf/modules/machine/pin.h +++ b/ports/nrf/modules/machine/pin.h @@ -32,6 +32,7 @@ #include MICROPY_PIN_DEFS_PORT_H #include "py/obj.h" +#include "nrfx_gpiote.h" typedef struct { mp_obj_base_t base; @@ -96,4 +97,11 @@ const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit); const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx); const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name); +void extint_register(nrfx_gpiote_pin_t pin, + nrf_gpiote_polarity_t sense, + nrf_gpio_pin_pull_t pull, + mp_obj_t callback); +void extint_enable(nrfx_gpiote_pin_t pin); +void extint_disable(nrfx_gpiote_pin_t pin); + #endif // __MICROPY_INCLUDED_NRF5_PIN_H__ diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index ce75b6cafe233..cc8b3e956030e 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -69,40 +69,6 @@ /// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf /// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf -#if NRFX_SPIM_ENABLED - -#define nrfx_spi_t nrfx_spim_t -#define nrfx_spi_config_t nrfx_spim_config_t -#define nrfx_spi_xfer_desc_t nrfx_spim_xfer_desc_t - -#define NRFX_SPI_PIN_NOT_USED NRFX_SPIM_PIN_NOT_USED -#define NRFX_SPI_INSTANCE NRFX_SPIM_INSTANCE -#define NRF_SPI_BIT_ORDER_LSB_FIRST NRF_SPIM_BIT_ORDER_LSB_FIRST -#define NRF_SPI_BIT_ORDER_MSB_FIRST NRF_SPIM_BIT_ORDER_MSB_FIRST -#define NRF_SPI_MODE_0 NRF_SPIM_MODE_0 -#define NRF_SPI_MODE_1 NRF_SPIM_MODE_1 -#define NRF_SPI_MODE_2 NRF_SPIM_MODE_2 -#define NRF_SPI_MODE_3 NRF_SPIM_MODE_3 -#define NRF_SPI_FREQ_125K NRF_SPIM_FREQ_125K -#define NRF_SPI_FREQ_250K NRF_SPIM_FREQ_250K -#define NRF_SPI_FREQ_500K NRF_SPIM_FREQ_500K -#define NRF_SPI_FREQ_1M NRF_SPIM_FREQ_1M -#define NRF_SPI_FREQ_2M NRF_SPIM_FREQ_2M -#define NRF_SPI_FREQ_4M NRF_SPIM_FREQ_4M -#define NRF_SPI_FREQ_8M NRF_SPIM_FREQ_8M - -#define nrfx_spi_init nrfx_spim_init -#define nrfx_spi_uninit nrfx_spim_uninit -#define nrfx_spi_xfer nrfx_spim_xfer - -#endif // NRFX_SPIM_ENABLED - -typedef struct _machine_hard_spi_obj_t { - mp_obj_base_t base; - const nrfx_spi_t * p_spi; // Driver instance - nrfx_spi_config_t * p_config; // pointer to volatile part -} machine_hard_spi_obj_t; - STATIC const nrfx_spi_t machine_spi_instances[] = { NRFX_SPI_INSTANCE(0), NRFX_SPI_INSTANCE(1), @@ -156,9 +122,9 @@ STATIC int spi_find(mp_obj_t id) { void spi_transfer(const machine_hard_spi_obj_t * self, size_t len, const void * src, void * dest) { nrfx_spi_xfer_desc_t xfer_desc = { .p_tx_buffer = src, - .tx_length = len, - .p_rx_buffer = dest, - .rx_length = len + .tx_length = len, + .p_rx_buffer = dest, + .rx_length = len }; nrfx_spi_xfer(self->p_spi, &xfer_desc, 0); diff --git a/ports/nrf/modules/machine/spi.h b/ports/nrf/modules/machine/spi.h index c6f64a19da2a7..3d1761a8dacc1 100644 --- a/ports/nrf/modules/machine/spi.h +++ b/ports/nrf/modules/machine/spi.h @@ -26,9 +26,49 @@ */ #include "py/obj.h" +#if NRFX_SPI_ENABLED +#include "nrfx_spi.h" +#else +#include "nrfx_spim.h" +#endif + +#if NRFX_SPIM_ENABLED + +#define nrfx_spi_t nrfx_spim_t +#define nrfx_spi_config_t nrfx_spim_config_t +#define nrfx_spi_xfer_desc_t nrfx_spim_xfer_desc_t + +#define NRFX_SPI_PIN_NOT_USED NRFX_SPIM_PIN_NOT_USED +#define NRFX_SPI_INSTANCE NRFX_SPIM_INSTANCE +#define NRF_SPI_BIT_ORDER_LSB_FIRST NRF_SPIM_BIT_ORDER_LSB_FIRST +#define NRF_SPI_BIT_ORDER_MSB_FIRST NRF_SPIM_BIT_ORDER_MSB_FIRST +#define NRF_SPI_MODE_0 NRF_SPIM_MODE_0 +#define NRF_SPI_MODE_1 NRF_SPIM_MODE_1 +#define NRF_SPI_MODE_2 NRF_SPIM_MODE_2 +#define NRF_SPI_MODE_3 NRF_SPIM_MODE_3 +#define NRF_SPI_FREQ_125K NRF_SPIM_FREQ_125K +#define NRF_SPI_FREQ_250K NRF_SPIM_FREQ_250K +#define NRF_SPI_FREQ_500K NRF_SPIM_FREQ_500K +#define NRF_SPI_FREQ_1M NRF_SPIM_FREQ_1M +#define NRF_SPI_FREQ_2M NRF_SPIM_FREQ_2M +#define NRF_SPI_FREQ_4M NRF_SPIM_FREQ_4M +#define NRF_SPI_FREQ_8M NRF_SPIM_FREQ_8M + +#define nrfx_spi_init nrfx_spim_init +#define nrfx_spi_uninit nrfx_spim_uninit +#define nrfx_spi_xfer nrfx_spim_xfer + +#endif // NRFX_SPIM_ENABLED + typedef struct _machine_hard_spi_obj_t machine_hard_spi_obj_t; extern const mp_obj_type_t machine_hard_spi_type; +typedef struct _machine_hard_spi_obj_t { + mp_obj_base_t base; + const nrfx_spi_t * p_spi; // Driver instance + nrfx_spi_config_t * p_config; // pointer to volatile part +} machine_hard_spi_obj_t; + void spi_init0(void); void spi_transfer(const machine_hard_spi_obj_t * self, size_t len, diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index a5e16421cc844..d6e24cdf8cf2a 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -219,6 +219,8 @@ extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_ubluepy; extern const struct _mp_obj_module_t music_module; extern const struct _mp_obj_module_t random_module; +extern const struct _mp_obj_module_t mp_module_usocket; +extern const struct _mp_obj_module_t mp_module_network; #if MICROPY_PY_UBLUEPY #define UBLUEPY_MODULE { MP_ROM_QSTR(MP_QSTR_ubluepy), MP_ROM_PTR(&mp_module_ubluepy) }, @@ -245,6 +247,24 @@ extern const struct _mp_obj_module_t random_module; #define MICROPY_BOARD_BUILTINS #endif // BOARD_SPECIFIC_MODULES +#if MICROPY_PY_USOCKET +// usocket implementation provided by skeleton wrapper +#define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, +#define SOCKET_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) }, +#define SOCKET_POLL +#else +// no usocket module +#define SOCKET_BUILTIN_MODULE +#define SOCKET_BUILTIN_MODULE_WEAK_LINKS +#define SOCKET_POLL +#endif + +#if MICROPY_PY_NETWORK +#define NETWORK_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_network), MP_ROM_PTR(&mp_module_network) }, +#else +#define NETWORK_BUILTIN_MODULE +#endif + #if BLUETOOTH_SD #if MICROPY_PY_BLE @@ -264,6 +284,8 @@ extern const struct _mp_obj_module_t ble_module; MUSIC_MODULE \ UBLUEPY_MODULE \ RANDOM_MODULE \ + SOCKET_BUILTIN_MODULE \ + NETWORK_BUILTIN_MODULE \ MICROPY_BOARD_BUILTINS \ @@ -276,6 +298,8 @@ extern const struct _mp_obj_module_t ble_module; { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ MUSIC_MODULE \ RANDOM_MODULE \ + SOCKET_BUILTIN_MODULE \ + NETWORK_BUILTIN_MODULE \ MICROPY_BOARD_BUILTINS \ @@ -284,6 +308,7 @@ extern const struct _mp_obj_module_t ble_module; #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&mp_module_uos) }, \ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ + SOCKET_BUILTIN_MODULE_WEAK_LINKS \ // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ @@ -333,6 +358,10 @@ extern const struct _mp_obj_module_t ble_module; \ /* micro:bit root pointers */ \ void *async_data[2]; \ + \ + /* list of registered NICs */ \ + mp_obj_list_t mod_network_nic_list; \ + #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) @@ -342,3 +371,12 @@ extern const struct _mp_obj_module_t ble_module; #define MICROPY_PIN_DEFS_PORT_H "pin_defs_nrf5.h" #endif + +//#define MICROPY_MPHALPORT_H "cc3200_hal.h" +#define MICROPY_PORT_HAS_TELNET (0) +#define MICROPY_PORT_HAS_FTP (0) + +#define MICROPY_PORT_WLAN_AP_SSID "SSID" +#define MICROPY_PORT_WLAN_AP_KEY "PASSKEY" +#define MICROPY_PORT_WLAN_AP_SECURITY SL_SEC_TYPE_WPA_WPA2 +#define MICROPY_PORT_WLAN_AP_CHANNEL 5 diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 24e12d669dd48..d6d1fdeb233cc 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -193,9 +193,12 @@ SRC_LIBM += lib/libm/thumb_vfp_sqrtf.c endif endif +INC += -I$(TOP)/extmod EXTMOD_SRC_C = $(addprefix extmod/,\ modlwip.c \ modonewire.c \ + modnetwork.c \ + modusocket.c \ ) DRIVERS_SRC_C = $(addprefix drivers/,\ @@ -242,8 +245,6 @@ SRC_C = \ modstm.c \ moduos.c \ modutime.c \ - modusocket.c \ - modnetwork.c \ extint.c \ usrsw.c \ rng.c \ diff --git a/ports/stm32/modnwcc3k.c b/ports/stm32/modnwcc3k.c index 8723994f45251..0576bca7c644d 100644 --- a/ports/stm32/modnwcc3k.c +++ b/ports/stm32/modnwcc3k.c @@ -112,7 +112,7 @@ STATIC void cc3k_callback(long event_type, char *data, unsigned char length) { } } -STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { +STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { uint32_t ip; // CC3000 gethostbyname is unreliable and usually returns -95 on first call for (int retry = 5; CC3000_EXPORT(gethostbyname)((char*)name, len, &ip) < 0; retry--) { diff --git a/ports/stm32/modnwwiznet5k.c b/ports/stm32/modnwwiznet5k.c index bf4b72ff215c3..3f19bbf8f8c2a 100644 --- a/ports/stm32/modnwwiznet5k.c +++ b/ports/stm32/modnwwiznet5k.c @@ -83,7 +83,7 @@ STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { (void)status; } -STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { +STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8}; uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); DNS_init(0, buf);