Skip to content

Commit 3a1c4c5

Browse files
committed
stmhal: Add network and usocket module.
As per issue adafruit#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.
1 parent bfa7b48 commit 3a1c4c5

10 files changed

Lines changed: 531 additions & 315 deletions

File tree

stmhal/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ SRC_C = \
103103
modstm.c \
104104
modtime.c \
105105
modselect.c \
106+
modusocket.c \
107+
modnetwork.c \
106108
import.c \
107109
lexerfatfs.c \
108110
extint.c \

stmhal/main.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,10 @@
6464
#include "dac.h"
6565
#include "pybwlan.h"
6666
#include "pybstdio.h"
67+
#include "modnetwork.h"
6768

6869
void SystemClock_Config(void);
6970

70-
int errno;
71-
7271
static FATFS fatfs0;
7372
#if MICROPY_HW_HAS_SDCARD
7473
static FATFS fatfs1;
@@ -510,6 +509,8 @@ int main(void) {
510509
pyb_wlan_start();
511510
#endif
512511

512+
mod_network_init();
513+
513514
// At this point everything is fully configured and initialised.
514515

515516
// Run the main script from the current directory.

stmhal/modcc3k.c

Lines changed: 84 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@
4444
#include "qstr.h"
4545
#include "obj.h"
4646
#include "objtuple.h"
47+
#include "objlist.h"
4748
#include "stream.h"
4849
#include "runtime.h"
50+
#include "modnetwork.h"
4951
#include "pin.h"
5052
#include "genhdr/pins.h"
5153
#include "spi.h"
@@ -61,10 +63,9 @@
6163
#include "netapp.h"
6264
#include "patch_prog.h"
6365

64-
STATIC const mp_obj_type_t cc3k_type;
65-
STATIC const mp_obj_type_t cc3k_socket_type;
66+
int errno; // for cc3000 driver
6667

67-
STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol);
68+
STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol, int *_errno);
6869

6970
STATIC volatile uint32_t fd_closed_state = 0;
7071
STATIC volatile bool wlan_connected = false;
@@ -102,6 +103,42 @@ STATIC void cc3k_callback(long event_type, char *data, unsigned char length) {
102103
}
103104
}
104105

106+
STATIC mp_obj_t cc3k_socket(mp_obj_t nic, int domain, int type, int fileno, int *_errno) {
107+
switch (domain) {
108+
case MOD_NETWORK_AF_INET: domain = AF_INET; break;
109+
case MOD_NETWORK_AF_INET6: domain = AF_INET6; break;
110+
default: *_errno = EAFNOSUPPORT; return MP_OBJ_NULL;
111+
}
112+
113+
switch (type) {
114+
case MOD_NETWORK_SOCK_STREAM: type = SOCK_STREAM; break;
115+
case MOD_NETWORK_SOCK_DGRAM: type = SOCK_DGRAM; break;
116+
case MOD_NETWORK_SOCK_RAW: type = SOCK_RAW; break;
117+
default: *_errno = EINVAL; return MP_OBJ_NULL;
118+
}
119+
120+
return cc3k_socket_new(domain, type, 0, _errno);
121+
}
122+
123+
STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
124+
uint32_t ip;
125+
if (gethostbyname((char*)name, len, &ip) < 0) {
126+
return errno;
127+
}
128+
129+
if (ip == 0) {
130+
// unknown host
131+
return ENOENT;
132+
}
133+
134+
out_ip[0] = ip >> 24;
135+
out_ip[1] = ip >> 16;
136+
out_ip[2] = ip >> 8;
137+
out_ip[3] = ip;
138+
139+
return 0;
140+
}
141+
105142
/******************************************************************************/
106143
// Micro Python bindings; CC3k class
107144

@@ -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
148185
HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE);
149186

150187
cc3k_obj_t *cc3k = m_new_obj(cc3k_obj_t);
151-
cc3k->base.type = &cc3k_type;
188+
cc3k->base.type = (mp_obj_type_t*)&mod_network_nic_type_cc3k;
189+
190+
// register with network module
191+
mod_network_register_nic(cc3k);
152192

153193
return cc3k;
154194
}
155195

156-
STATIC mp_obj_t cc3k_connect(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
157-
int ssid_len =0;
158-
const char *ssid = NULL;
159-
const char *bssid = NULL;
160-
161-
int key_len =0;
162-
int sec = WLAN_SEC_UNSEC;
163-
const char *key = NULL;
164-
165-
mp_map_elem_t *kw_key, *kw_sec, *kw_bssid;
196+
/// \method connect(ssid, key=None, *, security=WPA2, bssid=None)
197+
STATIC mp_obj_t cc3k_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
198+
static const mp_arg_t allowed_args[] = {
199+
{ MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
200+
{ MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} },
201+
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = WLAN_SEC_WPA2} },
202+
{ MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
203+
};
166204

167-
ssid = mp_obj_str_get_str(args[1]);
168-
ssid_len = strlen(ssid);
205+
// parse args
206+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
207+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
169208

170-
// get KW args
171-
kw_key = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("key")), MP_MAP_LOOKUP);
172-
kw_sec = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("sec")), MP_MAP_LOOKUP);
173-
kw_bssid = mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(qstr_from_str("bssid")), MP_MAP_LOOKUP);
209+
// get ssid
210+
mp_uint_t ssid_len;
211+
const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len);
174212

175213
// get key and sec
176-
if (kw_key && kw_sec) {
177-
key = mp_obj_str_get_str(kw_key->value);
178-
key_len = strlen(key);
179-
180-
sec = mp_obj_get_int(kw_sec->value);
181-
if (!(WLAN_SEC_UNSEC < sec && sec <= WLAN_SEC_WPA2)) {
182-
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid security mode"));
183-
}
214+
mp_uint_t key_len = 0;
215+
const char *key = NULL;
216+
mp_uint_t sec = WLAN_SEC_UNSEC;
217+
if (args[1].u_obj != mp_const_none) {
218+
key = mp_obj_str_get_data(args[1].u_obj, &key_len);
219+
sec = args[2].u_int;
184220
}
185221

186222
// get bssid
187-
if (kw_bssid != NULL) {
188-
bssid = mp_obj_str_get_str(kw_bssid->value);
223+
const char *bssid = NULL;
224+
if (args[3].u_obj != mp_const_none) {
225+
bssid = mp_obj_str_get_str(args[3].u_obj);
189226
}
190227

191228
// connect to AP
192-
if (wlan_connect(sec, (char*) ssid, ssid_len, (uint8_t*)bssid, (uint8_t*)key, key_len) != 0) {
229+
if (wlan_connect(sec, (char*)ssid, ssid_len, (uint8_t*)bssid, (uint8_t*)key, key_len) != 0) {
193230
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));
194231
}
195232

196233
return mp_const_none;
197234
}
198-
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_connect_obj, 2, cc3k_connect);
235+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_connect_obj, 1, cc3k_connect);
199236

200237
STATIC mp_obj_t cc3k_disconnect(mp_obj_t self_in) {
201238
int ret = wlan_disconnect();
@@ -259,49 +296,6 @@ STATIC mp_obj_t cc3k_patch_program(mp_obj_t self_in) {
259296
}
260297
STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_patch_program_obj, cc3k_patch_program);
261298

262-
/// \method socket(family=AF_INET, type=SOCK_STREAM, fileno=-1)
263-
/// Create a socket.
264-
STATIC const mp_arg_t cc3k_socket_args[] = {
265-
{ MP_QSTR_family, MP_ARG_INT, {.u_int = AF_INET} },
266-
{ MP_QSTR_type, MP_ARG_INT, {.u_int = SOCK_STREAM} },
267-
};
268-
#define PYB_CC3K_SOCKET_NUM_ARGS MP_ARRAY_SIZE(cc3k_socket_args)
269-
STATIC mp_obj_t cc3k_socket(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
270-
// parse args
271-
mp_arg_val_t vals[PYB_CC3K_SOCKET_NUM_ARGS];
272-
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_CC3K_SOCKET_NUM_ARGS, cc3k_socket_args, vals);
273-
274-
return cc3k_socket_new(vals[0].u_int, vals[1].u_int, 0);
275-
}
276-
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_socket_obj, 1, cc3k_socket);
277-
278-
STATIC mp_obj_t cc3k_gethostbyname(mp_obj_t self_in, mp_obj_t hostname) {
279-
mp_uint_t len;
280-
const char *host = mp_obj_str_get_data(hostname, &len);
281-
uint32_t ip;
282-
283-
if (gethostbyname((char*)host, len, &ip) < 0) {
284-
// TODO raise appropriate exception
285-
printf("gethostbyname failed\n");
286-
return mp_const_none;
287-
}
288-
289-
if (ip == 0) {
290-
// unknown host
291-
// TODO CPython raises: socket.gaierror: [Errno -2] Name or service not known
292-
printf("Name or service not known\n");
293-
return mp_const_none;
294-
}
295-
296-
// turn the ip address into a string (could use inet_ntop, but this here is much more efficient)
297-
VSTR_FIXED(ip_str, 16);
298-
vstr_printf(&ip_str, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
299-
mp_obj_t ret = mp_obj_new_str(ip_str.buf, ip_str.len, false);
300-
301-
return ret;
302-
}
303-
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_gethostbyname_obj, cc3k_gethostbyname);
304-
305299
STATIC const mp_map_elem_t cc3k_locals_dict_table[] = {
306300
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&cc3k_connect_obj },
307301
{ 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[] = {
310304
{ MP_OBJ_NEW_QSTR(MP_QSTR_patch_version), (mp_obj_t)&cc3k_patch_version_obj },
311305
{ MP_OBJ_NEW_QSTR(MP_QSTR_patch_program), (mp_obj_t)&cc3k_patch_program_obj },
312306

313-
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&cc3k_socket_obj },
314-
{ MP_OBJ_NEW_QSTR(MP_QSTR_gethostbyname), (mp_obj_t)&cc3k_gethostbyname_obj },
315-
316307
// class constants
317-
318308
{ MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WEP) },
319309
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WPA) },
320310
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA2), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WPA2) },
321-
322-
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
323-
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) },
324-
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) },
325-
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) },
326-
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(SOCK_RAW) },
327-
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IP), MP_OBJ_NEW_SMALL_INT(IPPROTO_IP) },
328-
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_ICMP), MP_OBJ_NEW_SMALL_INT(IPPROTO_ICMP) },
329-
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV4), MP_OBJ_NEW_SMALL_INT(IPPROTO_IPV4) },
330-
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) },
331-
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) },
332-
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV6), MP_OBJ_NEW_SMALL_INT(IPPROTO_IPV6) },
333-
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_RAW), MP_OBJ_NEW_SMALL_INT(IPPROTO_RAW) },
334311
};
335312

336313
STATIC MP_DEFINE_CONST_DICT(cc3k_locals_dict, cc3k_locals_dict_table);
337314

338-
STATIC const mp_obj_type_t cc3k_type = {
339-
{ &mp_type_type },
340-
.name = MP_QSTR_CC3k,
341-
//.print = cc3k_print,
342-
.make_new = cc3k_make_new,
343-
.locals_dict = (mp_obj_t)&cc3k_locals_dict,
315+
const mod_network_nic_type_t mod_network_nic_type_cc3k = {
316+
.base = {
317+
{ &mp_type_type },
318+
.name = MP_QSTR_CC3k,
319+
//.print = cc3k_print,
320+
.make_new = cc3k_make_new,
321+
.locals_dict = (mp_obj_t)&cc3k_locals_dict,
322+
},
323+
.socket = cc3k_socket,
324+
.gethostbyname = cc3k_gethostbyname,
344325
};
345326

346327
/******************************************************************************/
@@ -355,7 +336,9 @@ typedef struct _cc3k_socket_obj_t {
355336
int fd;
356337
} cc3k_socket_obj_t;
357338

358-
STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol) {
339+
STATIC const mp_obj_type_t cc3k_socket_type;
340+
341+
STATIC mp_obj_t cc3k_socket_new(mp_uint_t family, mp_uint_t type, mp_uint_t protocol, int *_errno) {
359342
// create socket object
360343
cc3k_socket_obj_t *s = m_new_obj_with_finaliser(cc3k_socket_obj_t);
361344
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
364347
s->fd = socket(family, type, protocol);
365348
if (s->fd < 0) {
366349
m_del_obj(cc3k_socket_obj_t, s);
367-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "socket failed"));
350+
*_errno = errno;
351+
return MP_OBJ_NULL;
368352
}
369353

370354
// clear socket state
@@ -667,33 +651,6 @@ STATIC const mp_obj_type_t cc3k_socket_type = {
667651
{ &mp_type_type },
668652
.name = MP_QSTR_socket,
669653
.print = cc3k_socket_print,
670-
.getiter = NULL,
671-
.iternext = NULL,
672654
.stream_p = &cc3k_socket_stream_p,
673655
.locals_dict = (mp_obj_t)&cc3k_socket_locals_dict,
674656
};
675-
676-
/******************************************************************************/
677-
// Micro Python bindings; CC3k module
678-
679-
STATIC const mp_map_elem_t mp_module_cc3k_globals_table[] = {
680-
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_cc3k) },
681-
{ MP_OBJ_NEW_QSTR(MP_QSTR_CC3k), (mp_obj_t)&cc3k_type },
682-
};
683-
684-
STATIC const mp_obj_dict_t mp_module_cc3k_globals = {
685-
.base = {&mp_type_dict},
686-
.map = {
687-
.all_keys_are_qstrs = 1,
688-
.table_is_fixed_array = 1,
689-
.used = MP_ARRAY_SIZE(mp_module_cc3k_globals_table),
690-
.alloc = MP_ARRAY_SIZE(mp_module_cc3k_globals_table),
691-
.table = (mp_map_elem_t*)mp_module_cc3k_globals_table,
692-
},
693-
};
694-
695-
const mp_obj_module_t mp_module_cc3k = {
696-
.base = { &mp_type_module },
697-
.name = MP_QSTR_cc3k,
698-
.globals = (mp_obj_dict_t*)&mp_module_cc3k_globals,
699-
};

0 commit comments

Comments
 (0)