diff options
author | Damien George <damien.p.george@gmail.com> | 2014-09-30 22:29:49 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-09-30 22:36:47 +0100 |
commit | 3a1c4c5bc6212310f5c0469300263290758217d7 (patch) | |
tree | 17091c4aebe75be08f49f6cc8a77940bdd2f76e0 /stmhal/modwiznet5k.c | |
parent | bfa7b480a7a537fc5496c8d9ffbf560f3a02314d (diff) |
stmhal: Add network and usocket module.
As per issue #876, the network module is used to configure NICs
(hardware modules) and configure routing. The usocket module is
supposed to implement the normal Python socket module and selects the
underlying NIC using routing logic.
Right now the routing logic is brain dead: first-initialised,
first-used. And the routing table is just a list of registered NICs.
cc3k and wiznet5k work, but not at the same time due to C name clashes
(to be fixed).
Note that the usocket module has alias socket, so that one can import
socket and it works as normal. But you can also override socket with
your own module, using usocket at the backend.
Diffstat (limited to 'stmhal/modwiznet5k.c')
-rw-r--r-- | stmhal/modwiznet5k.c | 228 |
1 files changed, 74 insertions, 154 deletions
diff --git a/stmhal/modwiznet5k.c b/stmhal/modwiznet5k.c index 3996c2994..3a4b25c0f 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; } } -} - -// 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]); -} -// 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); + return wiznet5k_socket_new(fileno, type); } -// 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); +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; + } } - /******************************************************************************/ // 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, -}; |