diff --git a/stmhal/Makefile b/stmhal/Makefile index f14a881c5b..ba844d97cc 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -103,6 +103,8 @@ SRC_C = \ modstm.c \ modtime.c \ modselect.c \ + modusocket.c \ + modnetwork.c \ import.c \ lexerfatfs.c \ extint.c \ diff --git a/stmhal/main.c b/stmhal/main.c index 84ce6353a4..20db6ca4a3 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -64,11 +64,10 @@ #include "dac.h" #include "pybwlan.h" #include "pybstdio.h" +#include "modnetwork.h" void SystemClock_Config(void); -int errno; - static FATFS fatfs0; #if MICROPY_HW_HAS_SDCARD static FATFS fatfs1; @@ -510,6 +509,8 @@ soft_reset: pyb_wlan_start(); #endif + mod_network_init(); + // At this point everything is fully configured and initialised. // Run the main script from the current directory. diff --git a/stmhal/modcc3k.c b/stmhal/modcc3k.c index dda8d06f67..71b29fb86d 100644 --- a/stmhal/modcc3k.c +++ b/stmhal/modcc3k.c @@ -44,8 +44,10 @@ #include "qstr.h" #include "obj.h" #include "objtuple.h" +#include "objlist.h" #include "stream.h" #include "runtime.h" +#include "modnetwork.h" #include "pin.h" #include "genhdr/pins.h" #include "spi.h" @@ -61,10 +63,9 @@ #include "netapp.h" #include "patch_prog.h" -STATIC const mp_obj_type_t cc3k_type; -STATIC const mp_obj_type_t cc3k_socket_type; +int errno; // for cc3000 driver -STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol); +STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol, int *_errno); STATIC volatile uint32_t fd_closed_state = 0; STATIC volatile bool wlan_connected = false; @@ -102,6 +103,42 @@ STATIC void cc3k_callback(long event_type, char *data, unsigned char length) { } } +STATIC mp_obj_t cc3k_socket(mp_obj_t nic, int domain, int type, int fileno, int *_errno) { + switch (domain) { + case MOD_NETWORK_AF_INET: domain = AF_INET; break; + case MOD_NETWORK_AF_INET6: domain = AF_INET6; break; + default: *_errno = EAFNOSUPPORT; return MP_OBJ_NULL; + } + + switch (type) { + case MOD_NETWORK_SOCK_STREAM: type = SOCK_STREAM; break; + case MOD_NETWORK_SOCK_DGRAM: type = SOCK_DGRAM; break; + case MOD_NETWORK_SOCK_RAW: type = SOCK_RAW; break; + default: *_errno = EINVAL; return MP_OBJ_NULL; + } + + return cc3k_socket_new(domain, type, 0, _errno); +} + +STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { + uint32_t ip; + if (gethostbyname((char*)name, len, &ip) < 0) { + return errno; + } + + if (ip == 0) { + // unknown host + return ENOENT; + } + + out_ip[0] = ip >> 24; + out_ip[1] = ip >> 16; + out_ip[2] = ip >> 8; + out_ip[3] = ip; + + return 0; +} + /******************************************************************************/ // Micro Python bindings; CC3k class @@ -148,54 +185,54 @@ STATIC mp_obj_t cc3k_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE); cc3k_obj_t *cc3k = m_new_obj(cc3k_obj_t); - cc3k->base.type = &cc3k_type; + cc3k->base.type = (mp_obj_type_t*)&mod_network_nic_type_cc3k; + + // register with network module + mod_network_register_nic(cc3k); return cc3k; } -STATIC mp_obj_t cc3k_connect(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - int ssid_len =0; - const char *ssid = NULL; - const char *bssid = NULL; +/// \method connect(ssid, key=None, *, security=WPA2, bssid=None) +STATIC mp_obj_t cc3k_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = WLAN_SEC_WPA2} }, + { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; - int key_len =0; - int sec = WLAN_SEC_UNSEC; - const char *key = NULL; + // parse args + 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); - mp_map_elem_t *kw_key, *kw_sec, *kw_bssid; - - ssid = mp_obj_str_get_str(args[1]); - ssid_len = strlen(ssid); - - // get KW args - kw_key = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("key")), MP_MAP_LOOKUP); - kw_sec = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("sec")), MP_MAP_LOOKUP); - kw_bssid = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("bssid")), MP_MAP_LOOKUP); + // get ssid + mp_uint_t ssid_len; + const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len); // get key and sec - if (kw_key && kw_sec) { - key = mp_obj_str_get_str(kw_key->value); - key_len = strlen(key); - - sec = mp_obj_get_int(kw_sec->value); - if (!(WLAN_SEC_UNSEC < sec && sec <= WLAN_SEC_WPA2)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid security mode")); - } + mp_uint_t key_len = 0; + const char *key = NULL; + mp_uint_t sec = WLAN_SEC_UNSEC; + if (args[1].u_obj != mp_const_none) { + key = mp_obj_str_get_data(args[1].u_obj, &key_len); + sec = args[2].u_int; } // get bssid - if (kw_bssid != NULL) { - bssid = mp_obj_str_get_str(kw_bssid->value); + const char *bssid = NULL; + if (args[3].u_obj != mp_const_none) { + bssid = mp_obj_str_get_str(args[3].u_obj); } // connect to AP - if (wlan_connect(sec, (char*) ssid, ssid_len, (uint8_t*)bssid, (uint8_t*)key, key_len) != 0) { + if (wlan_connect(sec, (char*)ssid, ssid_len, (uint8_t*)bssid, (uint8_t*)key, key_len) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "could not connect to ssid=%s, sec=%d, key=%s\n", ssid, sec, key)); } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_connect_obj, 2, cc3k_connect); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_connect_obj, 1, cc3k_connect); STATIC mp_obj_t cc3k_disconnect(mp_obj_t self_in) { int ret = wlan_disconnect(); @@ -259,49 +296,6 @@ STATIC mp_obj_t cc3k_patch_program(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_patch_program_obj, cc3k_patch_program); -/// \method socket(family=AF_INET, type=SOCK_STREAM, fileno=-1) -/// Create a socket. -STATIC const mp_arg_t cc3k_socket_args[] = { - { MP_QSTR_family, MP_ARG_INT, {.u_int = AF_INET} }, - { MP_QSTR_type, MP_ARG_INT, {.u_int = SOCK_STREAM} }, -}; -#define PYB_CC3K_SOCKET_NUM_ARGS MP_ARRAY_SIZE(cc3k_socket_args) -STATIC mp_obj_t cc3k_socket(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - // parse args - mp_arg_val_t vals[PYB_CC3K_SOCKET_NUM_ARGS]; - mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_CC3K_SOCKET_NUM_ARGS, cc3k_socket_args, vals); - - return cc3k_socket_new(vals[0].u_int, vals[1].u_int, 0); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_socket_obj, 1, cc3k_socket); - -STATIC mp_obj_t cc3k_gethostbyname(mp_obj_t self_in, mp_obj_t hostname) { - mp_uint_t len; - const char *host = mp_obj_str_get_data(hostname, &len); - uint32_t ip; - - if (gethostbyname((char*)host, len, &ip) < 0) { - // TODO raise appropriate exception - printf("gethostbyname failed\n"); - return mp_const_none; - } - - if (ip == 0) { - // unknown host - // TODO CPython raises: socket.gaierror: [Errno -2] Name or service not known - printf("Name or service not known\n"); - return mp_const_none; - } - - // turn the ip address into a string (could use inet_ntop, but this here is much more efficient) - VSTR_FIXED(ip_str, 16); - vstr_printf(&ip_str, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); - mp_obj_t ret = mp_obj_new_str(ip_str.buf, ip_str.len, false); - - return ret; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_gethostbyname_obj, cc3k_gethostbyname); - STATIC const mp_map_elem_t cc3k_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&cc3k_connect_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&cc3k_disconnect_obj }, @@ -310,37 +304,24 @@ STATIC const mp_map_elem_t cc3k_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_patch_version), (mp_obj_t)&cc3k_patch_version_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_patch_program), (mp_obj_t)&cc3k_patch_program_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&cc3k_socket_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_gethostbyname), (mp_obj_t)&cc3k_gethostbyname_obj }, - // class constants - { MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WEP) }, { MP_OBJ_NEW_QSTR(MP_QSTR_WPA), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WPA) }, { MP_OBJ_NEW_QSTR(MP_QSTR_WPA2), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WPA2) }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(SOCK_RAW) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IP), MP_OBJ_NEW_SMALL_INT(IPPROTO_IP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_ICMP), MP_OBJ_NEW_SMALL_INT(IPPROTO_ICMP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV4), MP_OBJ_NEW_SMALL_INT(IPPROTO_IPV4) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV6), MP_OBJ_NEW_SMALL_INT(IPPROTO_IPV6) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_RAW), MP_OBJ_NEW_SMALL_INT(IPPROTO_RAW) }, }; STATIC MP_DEFINE_CONST_DICT(cc3k_locals_dict, cc3k_locals_dict_table); -STATIC const mp_obj_type_t cc3k_type = { - { &mp_type_type }, - .name = MP_QSTR_CC3k, - //.print = cc3k_print, - .make_new = cc3k_make_new, - .locals_dict = (mp_obj_t)&cc3k_locals_dict, +const mod_network_nic_type_t mod_network_nic_type_cc3k = { + .base = { + { &mp_type_type }, + .name = MP_QSTR_CC3k, + //.print = cc3k_print, + .make_new = cc3k_make_new, + .locals_dict = (mp_obj_t)&cc3k_locals_dict, + }, + .socket = cc3k_socket, + .gethostbyname = cc3k_gethostbyname, }; /******************************************************************************/ @@ -355,7 +336,9 @@ typedef struct _cc3k_socket_obj_t { int fd; } cc3k_socket_obj_t; -STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol) { +STATIC const mp_obj_type_t cc3k_socket_type; + +STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol, int *_errno) { // create socket object cc3k_socket_obj_t *s = m_new_obj_with_finaliser(cc3k_socket_obj_t); s->base.type = (mp_obj_t)&cc3k_socket_type; @@ -364,7 +347,8 @@ STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t prot s->fd = socket(family, type, protocol); if (s->fd < 0) { m_del_obj(cc3k_socket_obj_t, s); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "socket failed")); + *_errno = errno; + return MP_OBJ_NULL; } // clear socket state @@ -667,33 +651,6 @@ STATIC const mp_obj_type_t cc3k_socket_type = { { &mp_type_type }, .name = MP_QSTR_socket, .print = cc3k_socket_print, - .getiter = NULL, - .iternext = NULL, .stream_p = &cc3k_socket_stream_p, .locals_dict = (mp_obj_t)&cc3k_socket_locals_dict, }; - -/******************************************************************************/ -// Micro Python bindings; CC3k module - -STATIC const mp_map_elem_t mp_module_cc3k_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_cc3k) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_CC3k), (mp_obj_t)&cc3k_type }, -}; - -STATIC const mp_obj_dict_t mp_module_cc3k_globals = { - .base = {&mp_type_dict}, - .map = { - .all_keys_are_qstrs = 1, - .table_is_fixed_array = 1, - .used = MP_ARRAY_SIZE(mp_module_cc3k_globals_table), - .alloc = MP_ARRAY_SIZE(mp_module_cc3k_globals_table), - .table = (mp_map_elem_t*)mp_module_cc3k_globals_table, - }, -}; - -const mp_obj_module_t mp_module_cc3k = { - .base = { &mp_type_module }, - .name = MP_QSTR_cc3k, - .globals = (mp_obj_dict_t*)&mp_module_cc3k_globals, -}; diff --git a/stmhal/modnetwork.c b/stmhal/modnetwork.c new file mode 100644 index 0000000000..a0cd24de6b --- /dev/null +++ b/stmhal/modnetwork.c @@ -0,0 +1,141 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * 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 +#include + +#include "stm32f4xx_hal.h" + +#include "mpconfig.h" +#include "nlr.h" +#include "misc.h" +#include "qstr.h" +#include "obj.h" +#include "objlist.h" +#include "runtime.h" +#include "modnetwork.h" + +mp_obj_list_t mod_network_nic_list; + +void mod_network_init(void) { + mp_obj_list_init(&mod_network_nic_list, 0); +} + +void mod_network_register_nic(mp_obj_t nic) { + for (mp_uint_t i = 0; i < mod_network_nic_list.len; i++) { + if (mod_network_nic_list.items[i] == nic) { + // nic already registered + return; + } + } + // nic not registered so add to list + mp_obj_list_append(&mod_network_nic_list, nic); +} + +STATIC mp_obj_t network_route(void) { + return &mod_network_nic_list; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route); + +STATIC const mp_map_elem_t mp_module_network_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) }, + + #if MICROPY_PY_WIZNET5K + { MP_OBJ_NEW_QSTR(MP_QSTR_WIZnet5k), (mp_obj_t)&mod_network_nic_type_wiznet5k }, + #endif + #if MICROPY_PY_CC3K + { MP_OBJ_NEW_QSTR(MP_QSTR_CC3k), (mp_obj_t)&mod_network_nic_type_cc3k }, + #endif + + { MP_OBJ_NEW_QSTR(MP_QSTR_route), (mp_obj_t)&network_route_obj }, +}; + +STATIC const mp_obj_dict_t mp_module_network_globals = { + .base = {&mp_type_dict}, + .map = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = MP_ARRAY_SIZE(mp_module_network_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_network_globals_table), + .table = (mp_map_elem_t*)mp_module_network_globals_table, + }, +}; + +const mp_obj_module_t mp_module_network = { + .base = { &mp_type_module }, + .name = MP_QSTR_network, + .globals = (mp_obj_dict_t*)&mp_module_network_globals, +}; + +/******************************************************************************/ +// Miscellaneous helpers + +void mod_network_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip) { + const char *addr_str = mp_obj_str_get_str(addr_in); + const char *s = addr_str; + for (mp_uint_t i = 0;; i++) { + mp_uint_t val = 0; + for (; *s && *s != '.'; s++) { + val = val * 10 + *s - '0'; + } + out_ip[i] = val; + if (i == 3 && *s == '\0') { + return; + } else if (i < 3 && *s == '.') { + s++; + } else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid IP address")); + } + } +} + +// Takes an address of the form ('192.168.0.1', 8080), returns the port and +// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes). +mp_uint_t mod_network_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip) { + mp_obj_t *addr_items; + mp_obj_get_array_fixed_n(addr_in, 2, &addr_items); + mod_network_parse_ipv4_addr(addr_items[0], out_ip); + return mp_obj_get_int(addr_items[1]); +} + +// Takes an array with a raw IPv4 address and returns something like '192.168.0.1'. +mp_obj_t mod_network_format_ipv4_addr(uint8_t *ip) { + char ip_str[16]; + mp_uint_t ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + return mp_obj_new_str(ip_str, ip_len, false); +} + +// Takes an array with a raw IP address, and a port, and returns a net-address +// tuple such as ('192.168.0.1', 8080). +mp_obj_t mod_network_format_inet_addr(uint8_t *ip, mp_uint_t port) { + mp_obj_t tuple[2] = { + tuple[0] = mod_network_format_ipv4_addr(ip), + tuple[1] = mp_obj_new_int(port), + }; + return mp_obj_new_tuple(2, tuple); +} diff --git a/stmhal/modnetwork.h b/stmhal/modnetwork.h new file mode 100644 index 0000000000..ed31a602f2 --- /dev/null +++ b/stmhal/modnetwork.h @@ -0,0 +1,54 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * 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. + */ + +#define MOD_NETWORK_IPADDR_BUF_SIZE (4) + +#define MOD_NETWORK_AF_INET (2) +#define MOD_NETWORK_AF_INET6 (10) + +#define MOD_NETWORK_SOCK_STREAM (1) +#define MOD_NETWORK_SOCK_DGRAM (2) +#define MOD_NETWORK_SOCK_RAW (3) + +typedef struct _mod_network_nic_type_t { + mp_obj_type_t base; + + // API for a generic NIC + mp_obj_t (*socket)(mp_obj_t nic, int domain, int type, int fileno, int *_errno); + int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out); +} mod_network_nic_type_t; + +extern struct _mp_obj_list_t mod_network_nic_list; +extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; +extern const mod_network_nic_type_t mod_network_nic_type_cc3k; + +void mod_network_init(void); +void mod_network_register_nic(mp_obj_t nic); + +void mod_network_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip); +mp_uint_t mod_network_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip); +mp_obj_t mod_network_format_ipv4_addr(uint8_t *ip); +mp_obj_t mod_network_format_inet_addr(uint8_t *ip, mp_uint_t port); diff --git a/stmhal/modusocket.c b/stmhal/modusocket.c new file mode 100644 index 0000000000..6a544cb3e0 --- /dev/null +++ b/stmhal/modusocket.c @@ -0,0 +1,149 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * 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 +#include + +#include "stm32f4xx_hal.h" + +#include "mpconfig.h" +#include "nlr.h" +#include "misc.h" +#include "qstr.h" +#include "obj.h" +#include "objtuple.h" +#include "objlist.h" +#include "runtime.h" +#include "modnetwork.h" + +/// \module usocket + +/// \method socket(family=AF_INET, type=SOCK_STREAM, fileno=-1) +/// Create a socket. +STATIC mp_obj_t mod_usocket_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_family, MP_ARG_INT, {.u_int = MOD_NETWORK_AF_INET} }, + { MP_QSTR_type, MP_ARG_INT, {.u_int = MOD_NETWORK_SOCK_STREAM} }, + { MP_QSTR_fileno, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // find a NIC that can create a socket and call it + for (mp_uint_t i = 0; i < mod_network_nic_list.len; i++) { + mp_obj_t nic = 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->socket != NULL) { + int _errno; + mp_obj_t obj = nic_type->socket(nic, args[0].u_int, args[1].u_int, args[2].u_int, &_errno); + if (obj == MP_OBJ_NULL) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); + } else { + return obj; + } + } + } + + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_usocket_socket_obj, 0, mod_usocket_socket); + +/// \method getaddrinfo(host, port) +STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { + mp_uint_t hlen; + const char *host = mp_obj_str_get_data(host_in, &hlen); + mp_int_t port = mp_obj_get_int(port_in); + + // find a NIC that can do a name lookup + for (mp_uint_t i = 0; i < mod_network_nic_list.len; i++) { + mp_obj_t nic = 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) { + uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); + if (ret != 0) { + // TODO CPython raises: socket.gaierror: [Errno -2] Name or service not known + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ret))); + } + mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); + tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); + tuple->items[4] = mod_network_format_inet_addr(out_ip, port); + return mp_obj_new_list(1, (mp_obj_t*)&tuple); + } + } + + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo); + +STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mod_usocket_socket_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_usocket_getaddrinfo_obj }, + + // class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET6) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_DGRAM) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_RAW) }, + + /* + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_ICMP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_ICMP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV4), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IPV4) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_TCP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_UDP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV6), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IPV6) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_RAW), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_RAW) }, + */ +}; + +STATIC const mp_obj_dict_t mp_module_usocket_globals = { + .base = {&mp_type_dict}, + .map = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = MP_ARRAY_SIZE(mp_module_usocket_globals_table), + .alloc = MP_ARRAY_SIZE(mp_module_usocket_globals_table), + .table = (mp_map_elem_t*)mp_module_usocket_globals_table, + }, +}; + +const mp_obj_module_t mp_module_usocket = { + .base = { &mp_type_module }, + .name = MP_QSTR_usocket, + .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, +}; diff --git a/stmhal/modwiznet5k.c b/stmhal/modwiznet5k.c index 3996c29944..3a4b25c0f6 100644 --- a/stmhal/modwiznet5k.c +++ b/stmhal/modwiznet5k.c @@ -36,7 +36,9 @@ #include "misc.h" #include "qstr.h" #include "obj.h" +#include "objlist.h" #include "runtime.h" +#include "modnetwork.h" #include "pin.h" #include "genhdr/pins.h" #include "spi.h" @@ -64,17 +66,14 @@ #define IPADDR_BUF_SIZE (4) -STATIC const mp_obj_type_t wiznet5k_type; -STATIC const mp_obj_type_t wiznet5k_socket_type; - STATIC mp_obj_t wiznet5k_socket_new(uint8_t sn, mp_uint_t type); typedef struct _wiznet5k_obj_t { mp_obj_base_t base; mp_uint_t cris_state; + SPI_HandleTypeDef *spi; const pin_obj_t *cs; const pin_obj_t *rst; - SPI_HandleTypeDef *spi; uint8_t socket_used; } wiznet5k_obj_t; @@ -106,9 +105,6 @@ STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { (void)status; } -/******************************************************************************/ -// Miscellaneous helpers - // Check the return value from Wiz socket calls: // - on error (<0) an exception is raised // - SOCK_OK or SOCK_BUSY does nothing @@ -120,51 +116,50 @@ STATIC void check_sock_return_value(int8_t ret) { } } -STATIC void parse_ip_addr(mp_obj_t addr_in, uint8_t *out_ip) { - const char *addr_str = mp_obj_str_get_str(addr_in); - const char *s = addr_str; - for (mp_uint_t i = 0;; i++) { - mp_uint_t val = 0; - for (; *s && *s != '.'; s++) { - val = val * 10 + *s - '0'; +STATIC mp_obj_t wiznet5k_socket(mp_obj_t self_in, int domain, int type, int fileno, int *_errno) { + if (domain != MOD_NETWORK_AF_INET) { + *_errno = EAFNOSUPPORT; + return MP_OBJ_NULL; + } + + switch (type) { + case MOD_NETWORK_SOCK_STREAM: type = Sn_MR_TCP; break; + case MOD_NETWORK_SOCK_DGRAM: type = Sn_MR_UDP; break; + default: *_errno = EINVAL; return MP_OBJ_NULL; + } + + if (fileno < 0) { + // get first unused socket number + for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) { + if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) { + fileno = sn; + break; + } } - out_ip[i] = val; - if (i == 3 && *s == '\0') { - return; - } else if (i < 3 && *s == '.') { - s++; - } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid IP address")); + if (fileno < 0) { + // too many open sockets + *_errno = EMFILE; + return MP_OBJ_NULL; } } + + return wiznet5k_socket_new(fileno, type); } -// Takes an address of the form ('192.168.0.1', 8080), returns the port and -// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes). -STATIC mp_uint_t parse_net_addr(mp_obj_t addr_in, uint8_t *out_ip) { - mp_obj_t *addr_items; - mp_obj_get_array_fixed_n(addr_in, 2, &addr_items); - parse_ip_addr(addr_items[0], out_ip); - return mp_obj_get_int(addr_items[1]); +STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { + uint8_t dns_ip[IPADDR_BUF_SIZE] = {8, 8, 8, 8}; + uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); + DNS_init(0, buf); + mp_int_t ret = DNS_run(dns_ip, (uint8_t*)name, out_ip); + m_del(uint8_t, buf, MAX_DNS_BUF_SIZE); + if (ret == 1) { + // success + return 0; + } else { + // failure + return ENOENT; + } } - -// Takes an array with a raw IP address and returns something like '192.168.0.1'. -STATIC mp_obj_t format_ip_addr(uint8_t *ip) { - char ip_str[16]; - mp_uint_t ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); - return mp_obj_new_str(ip_str, ip_len, false); -} - -// Takes an array with a raw IP address, and a port, and returns a net-address -// tuple such as ('192.168.0.1', 8080). -STATIC mp_obj_t format_net_addr(uint8_t *ip, mp_uint_t port) { - mp_obj_t tuple[2] = { - tuple[0] = format_ip_addr(ip), - tuple[1] = mp_obj_new_int(port), - }; - return mp_obj_new_tuple(2, tuple); -} - /******************************************************************************/ // Micro Python bindings @@ -174,18 +169,18 @@ STATIC void wiznet5k_print(void (*print)(void *env, const char *fmt, ...), void print(env, "WIZnet5k()"); } -/// \classmethod \constructor() +/// \classmethod \constructor(spi, pin_cs, pin_rst) /// Create and return a WIZnet5k object. STATIC mp_obj_t wiznet5k_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); + mp_arg_check_num(n_args, n_kw, 3, 3, false); // init the wiznet5k object - wiznet5k_obj.base.type = &wiznet5k_type; + wiznet5k_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_wiznet5k; wiznet5k_obj.cris_state = 0; - wiznet5k_obj.cs = &pin_B12; // Y5 - wiznet5k_obj.rst = &pin_B9; // Y4 - wiznet5k_obj.spi = &SPIHandle2; // Y-skin + wiznet5k_obj.spi = spi_get_handle(args[0]); + wiznet5k_obj.cs = pin_find(args[1]); + wiznet5k_obj.rst = pin_find(args[2]); wiznet5k_obj.socket_used = 0; /*!< SPI configuration */ @@ -200,7 +195,7 @@ STATIC mp_obj_t wiznet5k_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t SPIHandle2.Init.TIMode = SPI_TIMODE_DISABLED; SPIHandle2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; SPIHandle2.Init.CRCPolynomial = 7; // unused - spi_init(wiznet5k_obj.spi); + spi_init(wiznet5k_obj.spi, false); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; @@ -238,6 +233,9 @@ STATIC mp_obj_t wiznet5k_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t }; ctlnetwork(CN_SET_NETINFO, (void*)&netinfo); + // register with network module + mod_network_register_nic(&wiznet5k_obj); + // return wiznet5k object return &wiznet5k_obj; } @@ -275,98 +273,43 @@ STATIC mp_obj_t wiznet5k_ipaddr(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 1) { // get mp_obj_t tuple[4] = { - format_ip_addr(netinfo.ip), - format_ip_addr(netinfo.sn), - format_ip_addr(netinfo.gw), - format_ip_addr(netinfo.dns), + mod_network_format_ipv4_addr(netinfo.ip), + mod_network_format_ipv4_addr(netinfo.sn), + mod_network_format_ipv4_addr(netinfo.gw), + mod_network_format_ipv4_addr(netinfo.dns), }; return mp_obj_new_tuple(4, tuple); } else { // set mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 4, &items); - parse_ip_addr(items[0], netinfo.ip); - parse_ip_addr(items[1], netinfo.sn); - parse_ip_addr(items[2], netinfo.gw); - parse_ip_addr(items[3], netinfo.dns); + mod_network_parse_ipv4_addr(items[0], netinfo.ip); + mod_network_parse_ipv4_addr(items[1], netinfo.sn); + mod_network_parse_ipv4_addr(items[2], netinfo.gw); + mod_network_parse_ipv4_addr(items[3], netinfo.dns); ctlnetwork(CN_SET_NETINFO, &netinfo); return mp_const_none; } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ipaddr_obj, 1, 2, wiznet5k_ipaddr); -/// \method socket(family=AF_INET, type=SOCK_STREAM, fileno=-1) -/// Create a socket. -STATIC const mp_arg_t wiznet5k_socket_args[] = { - { MP_QSTR_family, MP_ARG_INT, {.u_int = 0} }, // ignored, only AF_INET supported - { MP_QSTR_type, MP_ARG_INT, {.u_int = Sn_MR_TCP} }, // SOCK_STREAM or SOCK_DGRAM - { MP_QSTR_fileno, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, -}; -#define PYB_WIZNET5K_SOCKET_NUM_ARGS MP_ARRAY_SIZE(wiznet5k_socket_args) - -STATIC mp_obj_t wiznet5k_socket(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - // parse args - mp_arg_val_t vals[PYB_WIZNET5K_SOCKET_NUM_ARGS]; - mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_WIZNET5K_SOCKET_NUM_ARGS, wiznet5k_socket_args, vals); - - if (vals[2].u_int < 0) { - // get first unused socket number - for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) { - if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) { - vals[2].u_int = sn; - break; - } - } - if (vals[2].u_int < 0) { - // too many open sockets - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EMFILE))); - } - } - - return wiznet5k_socket_new(vals[2].u_int, vals[1].u_int); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wiznet5k_socket_obj, 1, wiznet5k_socket); - -/// \method gethostbyname(name) -/// Use DNS to lookup a host name. Returns an IP address. -STATIC mp_obj_t wiznet5k_gethostbyname(mp_obj_t self_in, mp_obj_t name_in) { - uint8_t dns_ip[IPADDR_BUF_SIZE] = {8, 8, 8, 8}; - const char *name = mp_obj_str_get_str(name_in); - uint8_t out_ip[IPADDR_BUF_SIZE]; - uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); - DNS_init(0, buf); - mp_int_t ret = DNS_run(dns_ip, (uint8_t*)name, out_ip); - m_del(uint8_t, buf, MAX_DNS_BUF_SIZE); - if (ret == 1) { - // success - return format_ip_addr(out_ip); - } else { - // failure - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "DNS error %d", ret)); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_gethostbyname_obj, wiznet5k_gethostbyname); - STATIC const mp_map_elem_t wiznet5k_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_regs), (mp_obj_t)&wiznet5k_regs_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_ipaddr), (mp_obj_t)&wiznet5k_ipaddr_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&wiznet5k_socket_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_gethostbyname), (mp_obj_t)&wiznet5k_gethostbyname_obj }, - - // class constants - { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(0) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(Sn_MR_TCP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(Sn_MR_UDP) }, }; STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table); -STATIC const mp_obj_type_t wiznet5k_type = { - { &mp_type_type }, - .name = MP_QSTR_WIZnet5k, - .print = wiznet5k_print, - .make_new = wiznet5k_make_new, - .locals_dict = (mp_obj_t)&wiznet5k_locals_dict, +const mod_network_nic_type_t mod_network_nic_type_wiznet5k = { + .base = { + { &mp_type_type }, + .name = MP_QSTR_WIZnet5k, + .print = wiznet5k_print, + .make_new = wiznet5k_make_new, + .locals_dict = (mp_obj_t)&wiznet5k_locals_dict, + }, + .socket = wiznet5k_socket, + .gethostbyname = wiznet5k_gethostbyname, }; /******************************************************************************/ @@ -378,6 +321,8 @@ typedef struct _wiznet5k_socket_obj_t { uint8_t type; } wiznet5k_socket_obj_t; +STATIC const mp_obj_type_t wiznet5k_socket_type; + STATIC mp_obj_t wiznet5k_socket_new(uint8_t sn, mp_uint_t type) { wiznet5k_socket_obj_t *s = m_new_obj(wiznet5k_socket_obj_t); s->base.type = &wiznet5k_socket_type; @@ -404,7 +349,7 @@ STATIC mp_obj_t wiznet5k_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { wiznet5k_socket_obj_t *self = self_in; uint8_t ip[IPADDR_BUF_SIZE]; - mp_uint_t port = parse_net_addr(addr_in, ip); + mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip); // open the socket in server mode mp_int_t ret = socket(self->sn, self->type, port, 0); @@ -441,7 +386,7 @@ STATIC mp_obj_t wiznet5k_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { // now connect uint8_t ip[IPADDR_BUF_SIZE]; - mp_uint_t port = parse_net_addr(addr_in, ip); + mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip); ret = connect(self->sn, ip, port); check_sock_return_value(ret); @@ -484,7 +429,7 @@ STATIC mp_obj_t wiznet5k_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_ob mp_buffer_info_t bufinfo; mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); uint8_t ip[IPADDR_BUF_SIZE]; - mp_uint_t port = parse_net_addr(addr_in, ip); + mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip); mp_int_t ret = sendto(self->sn, bufinfo.buf, bufinfo.len, ip, port); check_sock_return_value(ret); return mp_obj_new_int(ret); @@ -501,7 +446,7 @@ STATIC mp_obj_t wiznet5k_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { check_sock_return_value(ret); mp_obj_t tuple[2] = { mp_obj_new_bytes(buf, ret), - format_net_addr(ip, port), + mod_network_format_inet_addr(ip, port), }; return mp_obj_new_tuple(2, tuple); } @@ -528,28 +473,3 @@ STATIC const mp_obj_type_t wiznet5k_socket_type = { .print = wiznet5k_socket_print, .locals_dict = (mp_obj_t)&wiznet5k_socket_locals_dict, }; - -/******************************************************************************/ -// Micro Python bindings; WIZnet5x00 module - -STATIC const mp_map_elem_t mp_module_wiznet5k_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_wiznet5k) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WIZnet5k), (mp_obj_t)&wiznet5k_type }, -}; - -STATIC const mp_obj_dict_t mp_module_wiznet5k_globals = { - .base = {&mp_type_dict}, - .map = { - .all_keys_are_qstrs = 1, - .table_is_fixed_array = 1, - .used = MP_ARRAY_SIZE(mp_module_wiznet5k_globals_table), - .alloc = MP_ARRAY_SIZE(mp_module_wiznet5k_globals_table), - .table = (mp_map_elem_t*)mp_module_wiznet5k_globals_table, - }, -}; - -const mp_obj_module_t mp_module_wiznet5k = { - .base = { &mp_type_module }, - .name = MP_QSTR_wiznet5k, - .globals = (mp_obj_dict_t*)&mp_module_wiznet5k_globals, -}; diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 8fe2f21027..e9b76414ad 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -77,20 +77,8 @@ extern const struct _mp_obj_module_t pyb_module; extern const struct _mp_obj_module_t stm_module; extern const struct _mp_obj_module_t time_module; extern const struct _mp_obj_module_t mp_module_select; - -#if MICROPY_PY_WIZNET5K -extern const struct _mp_obj_module_t mp_module_wiznet5k; -#define MICROPY_PY_WIZNET5K_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_wiznet5k), (mp_obj_t)&mp_module_wiznet5k }, -#else -#define MICROPY_PY_WIZNET5K_DEF -#endif - -#if MICROPY_PY_CC3K -extern const struct _mp_obj_module_t mp_module_cc3k; -#define MICROPY_PY_CC3K_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_cc3k), (mp_obj_t)&mp_module_cc3k }, -#else -#define MICROPY_PY_CC3K_DEF -#endif +extern const struct _mp_obj_module_t mp_module_usocket; +extern const struct _mp_obj_module_t mp_module_network; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&os_module }, \ @@ -98,8 +86,9 @@ extern const struct _mp_obj_module_t mp_module_cc3k; { MP_OBJ_NEW_QSTR(MP_QSTR_stm), (mp_obj_t)&stm_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_module_select }, \ - MICROPY_PY_WIZNET5K_DEF \ - MICROPY_PY_CC3K_DEF \ + { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ // extra constants #define MICROPY_PORT_CONSTANTS \ diff --git a/stmhal/portmodules.h b/stmhal/portmodules.h index d71f74e73c..ebeaae796d 100644 --- a/stmhal/portmodules.h +++ b/stmhal/portmodules.h @@ -29,6 +29,7 @@ extern const mp_obj_module_t pyb_module; extern const mp_obj_module_t stm_module; extern const mp_obj_module_t time_module; extern const mp_obj_module_t mp_module_select; +extern const mp_obj_module_t mp_module_usocket; // additional helper functions exported by the modules diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index 674b8f3f8b..d0d8c113b8 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -320,6 +320,20 @@ Q(pixel) Q(text) Q(show) +// for usocket module +Q(usocket) +Q(socket) +Q(getaddrinfo) +Q(AF_INET) +Q(AF_INET6) +Q(SOCK_STREAM) +Q(SOCK_DGRAM) +Q(SOCK_RAW) + +// for network module +Q(network) +Q(route) + // for WIZnet5k class #if MICROPY_PY_WIZNET5K Q(wiznet5k) @@ -356,25 +370,13 @@ Q(is_connected) Q(ifconfig) Q(patch_version) Q(patch_program) -Q(socket) -Q(family) -Q(type) -Q(gethostbyname) Q(WEP) Q(WPA) Q(WPA2) -Q(AF_INET) -Q(AF_INET6) -Q(SOCK_STREAM) -Q(SOCK_DGRAM) -Q(SOCK_RAW) -Q(IPPROTO_IP) -Q(IPPROTO_ICMP) -Q(IPPROTO_IPV4) -Q(IPPROTO_TCP) -Q(IPPROTO_UDP) -Q(IPPROTO_IPV6) -Q(IPPROTO_RAW) +Q(ssid) +Q(key) +Q(security) +Q(bssid) Q(send) Q(recv) Q(bind)