1 /*
2 * This file is part of the MicroPython project, http://micropython.org/
3 *
4 * Development of the code in this file was sponsored by Microbric Pty Ltd
5 * and Mnemote Pty Ltd
6 *
7 * The MIT License (MIT)
8 *
9 * Copyright (c) 2016, 2017 Nick Moore @mnemote
10 * Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 * THE SOFTWARE.
29 */
30
31 #include "modnetwork.h"
32
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include "shared/netutils/netutils.h"
38 #include "lwip/dns.h"
39 #include "netmgr_wifi.h"
40 #include "py/mperrno.h"
41 #include "py/mphal.h"
42 #include "py/nlr.h"
43 #include "py/objlist.h"
44 #include "py/runtime.h"
45 #include "ulog/ulog.h"
46
47 #define LOG_TAG "mod_network"
48
49 #define DNS_MAIN TCPIP_ADAPTER_DNS_MAIN
50 #define MODNETWORK_INCLUDE_CONSTANTS (1)
51
52 #define QS(x) (uintptr_t) MP_OBJ_NEW_QSTR(x)
53
54 typedef enum {
55 WIFI_MODE_NULL = 0x00,
56 WIFI_MODE_STA = 0x01,
57 WIFI_MODE_AP = 0x02,
58 } wifi_mode_t;
59
60 enum {
61 STAT_IDLE = 1000,
62 STAT_CONNECTING = 1001,
63 STAT_GOT_IP = 1010,
64 };
65
_haas_wifi_exceptions(wifi_result_t e)66 NORETURN void _haas_wifi_exceptions(wifi_result_t e)
67 {
68 switch (e) {
69 case RET_WIFI_COMMON_FAIL:
70 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Common Fail"));
71 case RET_WIFI_INVALID_ARG:
72 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Arguments"));
73 case RET_WIFI_INVALID_PASSWORD:
74 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Password"));
75 case RET_WIFI_MEMORY_ERROR:
76 mp_raise_OSError(MP_ENOMEM);
77 case RET_WIFI_INIT_FAIL:
78 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Init Fail"));
79 case RET_WIFI_NOT_INITED:
80 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Initialized"));
81 case RET_WIFI_STATUS_ERROR:
82 mp_raise_msg(&mp_type_OSError,
83 MP_ERROR_TEXT("Wifi Request In Error Status"));
84 case RET_WIFI_SCAN_REQ_FAIL:
85 mp_raise_msg(&mp_type_OSError,
86 MP_ERROR_TEXT("Wifi Scan Fail To Start"));
87 case RET_WIFI_SCAN_NO_AP_FOUND:
88 mp_raise_msg(&mp_type_OSError,
89 MP_ERROR_TEXT("Wifi Can Not Find Any SSID"));
90 case RET_WIFI_NO_SUITABLE_NETWORK:
91 mp_raise_msg(&mp_type_OSError,
92 MP_ERROR_TEXT("Wifi No Suitable Network To Connect"));
93 case RET_WIFI_CONN_REQ_FAIL:
94 mp_raise_msg(&mp_type_OSError,
95 MP_ERROR_TEXT("Wifi Connect Fail To Start"));
96 case RET_WIFI_CONN_FAIL:
97 mp_raise_msg(&mp_type_OSError,
98 MP_ERROR_TEXT("Wifi Connect Procedure Result In Fail"));
99 case RET_WIFI_CONN_NO_SSID_CONFIG:
100 mp_raise_msg(&mp_type_OSError,
101 MP_ERROR_TEXT("Wifi No Saved SSID Config To Connect"));
102 case RET_WIFI_DISC_FAIL:
103 mp_raise_msg(&mp_type_OSError,
104 MP_ERROR_TEXT("Wifi Disconnect Procedure Result In Fail"));
105 case RET_WIFI_WPS_NOT_FOUND:
106 mp_raise_msg(&mp_type_OSError,
107 MP_ERROR_TEXT("Wifi Can Not Find WPS AP"));
108 case RET_WIFI_WPS_REQ_FAIL:
109 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Fail To Start WPS"));
110 default:
111 mp_raise_msg_varg(&mp_type_RuntimeError,
112 MP_ERROR_TEXT("Wifi Unknown Error 0x%04x"), e);
113 }
114 }
115
haas_exceptions(wifi_result_t e)116 static inline void haas_exceptions(wifi_result_t e)
117 {
118 if (e != RET_WIFI_OK) {
119 _haas_wifi_exceptions(e);
120 }
121 }
122
123 #define HAAS_EXCEPTIONS(x) \
124 do { \
125 haas_exceptions(x); \
126 } while (0);
127
128 typedef struct _wlan_if_obj_t {
129 mp_obj_base_t base;
130 netmgr_hdl_t hdl; // can get through netmgr_wifi_get_dev
131 netmgr_wifi_mode_t if_id;
132 } wlan_if_obj_t;
133
134 const mp_obj_type_t wlan_if_type;
135 STATIC const wlan_if_obj_t wlan_sta_obj = { { &wlan_if_type },
136 NETMGR_WIFI_MODE_STA };
137 STATIC const wlan_if_obj_t wlan_ap_obj = { { &wlan_if_type },
138 NETMGR_WIFI_MODE_AP };
139
140 // Set to "true" if haas_wifi_start() was called
141 static bool wifi_started = false;
142
143 // Set to "true" if the STA interface is requested to be connected by the
144 // user, used for automatic reassociation.
145 static bool wifi_sta_connect_requested = false;
146
147 // Set to "true" if the STA interface is connected to wifi and has IP address.
148 static bool wifi_sta_connected = false;
149
150 // Store the current status. 0 means None here, safe to do so as first enum
151 // value is WIFI_REASON_UNSPECIFIED=1.
152 static uint8_t wifi_sta_disconn_reason = 0;
153
wifi_set_mac(netmgr_hdl_t hdl,uint8_t * mac)154 static int wifi_set_mac(netmgr_hdl_t hdl, uint8_t *mac)
155 {
156 return ioctl(hdl, WIFI_DEV_CMD_SET_MAC, mac);
157 }
158
wifi_get_mac(netmgr_hdl_t hdl,uint8_t * mac)159 static int wifi_get_mac(netmgr_hdl_t hdl, uint8_t *mac)
160 {
161 return ioctl(hdl, WIFI_DEV_CMD_GET_MAC, mac);
162 }
163
wifi_get_rssi(netmgr_hdl_t hdl,int * rssi)164 static int wifi_get_rssi(netmgr_hdl_t hdl, int *rssi)
165 {
166 int state = -1;
167 wifi_ap_record_t out = { 0 };
168 int ret = ioctl(hdl, WIFI_DEV_CMD_STA_GET_LINK_STATUS, &out));
169 if (ret == 0) {
170 memcpy(rssi, &out.rssi, sizeof(out.rssi));
171 state = 0;
172 }
173
174 return state;
175 }
176
177 // This function is called by the system-event task and so runs in a different
178 // thread to the main MicroPython task. It must not raise any Python
179 // exceptions.
event_handler(void * ctx,system_event_t * event)180 static wifi_result_t event_handler(void *ctx, system_event_t *event)
181 {
182 switch (event->event_id) {
183 case CONN_STATE_DISCONNECTING:
184 LOGD(LOG_TAG, "wifi CONN_STATE_DISCONNECTING");
185 break;
186 case CONN_STATE_DISCONNECTED:
187 LOGI(LOG_TAG, "wifi STA_DISCONNECTED");
188 break;
189 case CONN_STATE_CONNECTING:
190 LOGD(LOG_TAG, "wifi CONN_STATE_CONNECTING");
191 break;
192 case CONN_STATE_CONNECTED:
193 LOGI(LOG_TAG, "wifi CONN_STATE_CONNECTED");
194 break;
195 case CONN_STATE_OBTAINING_IP:
196 LOGI(LOG_TAG, "wifi CONN_STATE_OBTAINING_IP");
197 wifi_sta_connected = true;
198 wifi_sta_disconn_reason = 0;
199 break;
200 case CONN_STATE_NETWORK_CONNECTED:
201 LOGI(LOG_TAG, "wifi CONN_STATE_NETWORK_CONNECTED");
202 break;
203 case CONN_STATE_FAILED:
204 LOGI(LOG_TAG, "wifi CONN_STATE_FAILED");
205 break;
206 default:
207 LOGI(LOG_TAG, "event %d", event->event_id);
208 break;
209 }
210 return RET_WIFI_OK;
211 }
212
require_if(mp_obj_t wlan_if,int if_no)213 STATIC void require_if(mp_obj_t wlan_if, int if_no)
214 {
215 wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
216 if (self->if_id != if_no) {
217 mp_raise_msg(&mp_type_OSError, if_no == NETMGR_WIFI_MODE_STA
218 ? MP_ERROR_TEXT("STA required")
219 : MP_ERROR_TEXT("AP required"));
220 }
221 }
222
get_wlan(size_t n_args,const mp_obj_t * args)223 STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args)
224 {
225 static int initialized = 0;
226 if (!initialized) {
227 LOGD(LOG_TAG, "modnetwork get WLAN start");
228 HAAS_EXCEPTIONS(event_service_init(NULL));
229 HAAS_EXCEPTIONS(netmgr_service_init(NULL));
230 LOGD(LOG_TAG, "modnetwork got WLAN");
231 initialized = 1;
232 }
233
234 int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : NETMGR_WIFI_MODE_STA;
235 if (idx == NETMGR_WIFI_MODE_STA) {
236 return MP_OBJ_FROM_PTR(&wlan_sta_obj);
237 } else if (idx == NETMGR_WIFI_MODE_AP) {
238 return MP_OBJ_FROM_PTR(&wlan_ap_obj);
239 } else {
240 mp_raise_ValueError(MP_ERROR_TEXT("invalid WLAN interface identifier"));
241 }
242 }
243 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
244
wlan_initialize()245 STATIC mp_obj_t wlan_initialize()
246 {
247 static int initialized = 0;
248 if (!initialized) {
249 LOGD(LOG_TAG, "modnetwork Initializing start");
250 HAAS_EXCEPTIONS(event_service_init(NULL));
251 HAAS_EXCEPTIONS(netmgr_service_init(NULL));
252 LOGD(LOG_TAG, "modnetwork Initialized");
253 initialized = 1;
254 }
255 return mp_const_none;
256 }
257 STATIC MP_DEFINE_CONST_FUN_OBJ_0(wlan_initialize_obj, wlan_initialize);
258
haas_wlan_active(size_t n_args,const mp_obj_t * args)259 STATIC mp_obj_t haas_wlan_active(size_t n_args, const mp_obj_t *args)
260 {
261 wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
262 wifi_mode_t mode;
263 if (!wifi_started) {
264 mode = WIFI_MODE_NULL;
265 } else {
266 HAAS_EXCEPTIONS(haas_wlan_wifi_get_mode(&mode));
267 }
268
269 int bit =
270 (self->if_id == NETMGR_WIFI_MODE_STA) ? WIFI_MODE_STA : WIFI_MODE_AP;
271 if (n_args > 1) {
272 bool active = mp_obj_is_true(args[1]);
273 mode = active ? (mode | bit) : (mode & ~bit);
274 if (mode == WIFI_MODE_NULL) {
275 if (wifi_started) {
276 HAAS_EXCEPTIONS(haas_wlan_wifi_stop());
277 wifi_started = false;
278 }
279 } else {
280 HAAS_EXCEPTIONS(haas_wlan_wifi_set_mode(mode));
281 if (!wifi_started) {
282 HAAS_EXCEPTIONS(haas_wlan_wifi_start());
283 wifi_started = true;
284 }
285 }
286 }
287
288 return (mode & bit) ? mp_const_true : mp_const_false;
289 }
290
291 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(haas_wlan_active_obj, 1, 2,
292 haas_wlan_active);
293
haas_wlan_connect(size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)294 STATIC mp_obj_t haas_wlan_connect(size_t n_args, const mp_obj_t *pos_args,
295 mp_map_t *kw_args)
296 {
297 enum {
298 ARG_ssid,
299 ARG_password,
300 ARG_bssid
301 };
302 static const mp_arg_t allowed_args[] = {
303 { MP_QSTR_, MP_ARG_OBJ, { .u_obj = mp_const_none } },
304 { MP_QSTR_, MP_ARG_OBJ, { .u_obj = mp_const_none } },
305 { MP_QSTR_bssid,
306 MP_ARG_KW_ONLY | MP_ARG_OBJ,
307 { .u_obj = mp_const_none } },
308 };
309
310 wlan_if_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
311
312 // parse args
313 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
314 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
315 MP_ARRAY_SIZE(allowed_args), allowed_args, args);
316
317 netmgr_connect_params_t wifi_sta_config = { 0 };
318
319 // configure any parameters that are given
320 if (n_args > 1) {
321 size_t len;
322 const char *p;
323 if (args[ARG_ssid].u_obj != mp_const_none) {
324 p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len);
325 memcpy(wifi_sta_config.wifi_params.ssid, p,
326 MIN(len, sizeof(wifi_sta_config.wifi_params.ssid)));
327 }
328 if (args[ARG_password].u_obj != mp_const_none) {
329 p = mp_obj_str_get_data(args[ARG_password].u_obj, &len);
330 memcpy(wifi_sta_config.wifi_params.pwd, p,
331 MIN(len, sizeof(wifi_sta_config.wifi_params.pwd)));
332 }
333 if (args[ARG_bssid].u_obj != mp_const_none) {
334 p = mp_obj_str_get_data(args[ARG_bssid].u_obj, &len);
335 if (len != sizeof(wifi_sta_config.wifi_params.bssid)) {
336 mp_raise_ValueError(NULL);
337 }
338 wifi_sta_config.wifi_params.bssid_set = 1;
339 memcpy(wifi_sta_config.wifi_params.bssid, p,
340 sizeof(wifi_sta_config.wifi_params.bssid));
341 }
342 // HAAS_EXCEPTIONS(haas_wlan_wifi_set_config(NETMGR_WIFI_MODE_STA,
343 // &wifi_sta_config));
344 }
345
346 // connect to the WiFi AP
347 MP_THREAD_GIL_EXIT();
348 HAAS_EXCEPTIONS(netmgr_connect(self->hdl, &wifi_sta_config));
349 MP_THREAD_GIL_ENTER();
350 wifi_sta_connect_requested = true;
351
352 return mp_const_none;
353 }
354 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(haas_wlan_connect_obj, 1, haas_wlan_connect);
355
haas_wlan_disconnect(mp_obj_t self_in)356 STATIC mp_obj_t haas_wlan_disconnect(mp_obj_t self_in)
357 {
358 wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
359 wifi_sta_connect_requested = false;
360 HAAS_EXCEPTIONS(netmgr_disconnect(self->hdl));
361 return mp_const_none;
362 }
363 STATIC MP_DEFINE_CONST_FUN_OBJ_1(haas_wlan_disconnect_obj,
364 haas_wlan_disconnect);
365
haas_wlan_status(size_t n_args,const mp_obj_t * args)366 STATIC mp_obj_t haas_wlan_status(size_t n_args, const mp_obj_t *args)
367 {
368 wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
369 if (n_args == 1) {
370 if (self->if_id == NETMGR_WIFI_MODE_STA) {
371 // Case of no arg is only for the STA interface
372 if (wifi_sta_connected) {
373 // Happy path, connected with IP
374 return MP_OBJ_NEW_SMALL_INT(STAT_GOT_IP);
375 } else if (wifi_sta_connect_requested) {
376 // No connection or error, but is requested = Still connecting
377 return MP_OBJ_NEW_SMALL_INT(STAT_CONNECTING);
378 } else if (wifi_sta_disconn_reason == 0) {
379 // No activity, No error = Idle
380 return MP_OBJ_NEW_SMALL_INT(STAT_IDLE);
381 } else {
382 // Simply pass the error through from haas_wlan-identifier
383 return MP_OBJ_NEW_SMALL_INT(wifi_sta_disconn_reason);
384 }
385 }
386 return mp_const_none;
387 }
388
389 #if 0
390 // one argument: return status based on query parameter
391 switch ((uintptr_t)args[1]) {
392 case QS(MP_QSTR_stations): {
393 // return list of connected stations, only if in soft-AP mode
394 require_if(args[0], NETMGR_WIFI_MODE_AP);
395 netmgr_wifi_config_t station_list = {0};
396 HAAS_EXCEPTIONS(netmgr_wifi_get_config(self->hdl, &station_list));
397 netmgr_wifi_ap_info_t *stations = &station_list.config;
398 mp_obj_t list = mp_obj_new_list(0, NULL);
399 for (int i = 0; i < station_list.ap_num; ++i) {
400 mp_obj_tuple_t *t = mp_obj_new_tuple(1, NULL);
401 t->items[0] = mp_obj_new_bytes(stations[i].mac, sizeof(stations[i].mac));
402 mp_obj_list_append(list, t);
403 }
404 return list;
405 }
406 case QS(MP_QSTR_rssi): {
407 // return signal of AP, only in STA mode
408 require_if(args[0], NETMGR_WIFI_MODE_STA);
409
410 netmgr_ifconfig_info_t info;
411 HAAS_EXCEPTIONS(netmgr_get_ifconfig(self->hdl, &info));
412 return MP_OBJ_NEW_SMALL_INT(info.rssi);
413 }
414 default:
415 mp_raise_ValueError(MP_ERROR_TEXT("unknown status param"));
416 }
417 #endif
418
419 return mp_const_none;
420 }
421 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(haas_wlan_status_obj, 1, 2,
422 haas_wlan_status);
423
haas_wlan_scan(mp_obj_t self_in)424 STATIC mp_obj_t haas_wlan_scan(mp_obj_t self_in)
425 {
426 wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
427
428 // check that STA mode is active
429 wifi_mode_t mode;
430 HAAS_EXCEPTIONS(haas_wlan_wifi_get_mode(&mode));
431 if ((mode & WIFI_MODE_STA) == 0) {
432 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("STA must be active"));
433 }
434
435 mp_obj_t list = mp_obj_new_list(0, NULL);
436 netmgr_wifi_ap_list_t wifi_ap_records[16] = { 0 };
437 // XXX how do we scan hidden APs (and if we can scan them, are they really
438 // hidden?)
439 MP_THREAD_GIL_EXIT();
440 int ap_num = netmgr_wifi_scan_result(&wifi_ap_records, 16,
441 NETMGR_WIFI_SCAN_TYPE_FULL);
442 MP_THREAD_GIL_ENTER();
443 if ((ap_num != -1) && (ap_num < 16)) {
444 for (uint16_t i = 0; i < ap_num; i++) {
445 mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL);
446 int8_t *x = memchr(wifi_ap_records[i].ssid, 0,
447 sizeof(wifi_ap_records[i].ssid));
448 int ssid_len = x ? x - wifi_ap_records[i].ssid
449 : sizeof(wifi_ap_records[i].ssid);
450 t->items[0] = mp_obj_new_bytes(wifi_ap_records[i].ssid, ssid_len);
451 t->items[1] = mp_obj_new_bytes(wifi_ap_records[i].bssid,
452 sizeof(wifi_ap_records[i].bssid));
453 t->items[2] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].ap_power);
454 t->items[3] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].channel);
455 t->items[4] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].sec_type);
456 mp_obj_list_append(list, MP_OBJ_FROM_PTR(t));
457 }
458 free(wifi_ap_records);
459 }
460 return list;
461 }
462 STATIC MP_DEFINE_CONST_FUN_OBJ_1(haas_wlan_scan_obj, haas_wlan_scan);
463
haas_wlan_isconnected(mp_obj_t self_in)464 STATIC mp_obj_t haas_wlan_isconnected(mp_obj_t self_in)
465 {
466 wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
467 if (self->if_id == NETMGR_WIFI_MODE_STA) {
468 return mp_obj_new_bool(wifi_sta_connected);
469 } else {
470 wifi_sta_list_t sta;
471 haas_wlan_wifi_ap_get_sta_list(&sta);
472 return mp_obj_new_bool(sta.num != 0);
473 }
474 }
475 STATIC MP_DEFINE_CONST_FUN_OBJ_1(haas_wlan_isconnected_obj,
476 haas_wlan_isconnected);
477
haas_wlan_ifconfig(size_t n_args,const mp_obj_t * args)478 STATIC mp_obj_t haas_wlan_ifconfig(size_t n_args, const mp_obj_t *args)
479 {
480 wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
481 netmgr_ifconfig_info_t info = { 0 };
482 if (n_args == 1) {
483 // get
484 HAAS_EXCEPTIONS(netmgr_get_ifconfig(self->hdl, &info));
485 mp_obj_t tuple[4] = {
486 netutils_format_ipv4_addr((uint8_t *)&info.ip_addr, NETUTILS_BIG),
487 netutils_format_ipv4_addr((uint8_t *)&info.mask, NETUTILS_BIG),
488 netutils_format_ipv4_addr((uint8_t *)&info.gw, NETUTILS_BIG),
489 netutils_format_ipv4_addr((uint8_t *)&info.dns_server,
490 NETUTILS_BIG),
491 };
492 return mp_obj_new_tuple(4, tuple);
493 } else {
494 // set
495 if (mp_obj_is_type(args[1], &mp_type_tuple) ||
496 mp_obj_is_type(args[1], &mp_type_list)) {
497 mp_obj_t *items;
498 mp_obj_get_array_fixed_n(args[1], 4, &items);
499 netutils_parse_ipv4_addr(items[0], (void *)&info.ip_addr,
500 NETUTILS_BIG);
501 if (mp_obj_is_integer(items[1])) {
502 // allow numeric mask, i.e.:
503 // 24 -> 255.255.255.0
504 // 16 -> 255.255.0.0
505 // etc...
506 uint32_t *m = (uint32_t *)&info.mask;
507 *m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1])));
508 } else {
509 netutils_parse_ipv4_addr(items[1], (void *)&info.mask,
510 NETUTILS_BIG);
511 }
512 netutils_parse_ipv4_addr(items[2], (void *)&info.gw, NETUTILS_BIG);
513 netutils_parse_ipv4_addr(items[3], (void *)&info.dns_server,
514 NETUTILS_BIG);
515 } else {
516 // check for the correct string
517 const char *mode = mp_obj_str_get_str(args[1]);
518 if (self->if_id != NETMGR_WIFI_MODE_STA || strcmp("dhcp", mode)) {
519 mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
520 }
521 }
522 HAAS_EXCEPTIONS(netmgr_set_ifconfig(self->hdl, &info));
523 return mp_const_none;
524 }
525 }
526 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(haas_wlan_ifconfig_obj, 1, 2,
527 haas_wlan_ifconfig);
528
haas_wlan_config(size_t n_args,const mp_obj_t * args,mp_map_t * kwargs)529 STATIC mp_obj_t haas_wlan_config(size_t n_args, const mp_obj_t *args,
530 mp_map_t *kwargs)
531 {
532 if (n_args != 1 && kwargs->used != 0) {
533 mp_raise_TypeError(MP_ERROR_TEXT("either pos or kw args are allowed"));
534 }
535
536 wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
537 bool is_wifi = self->if_id == NETMGR_WIFI_MODE_AP ||
538 self->if_id == NETMGR_WIFI_MODE_STA;
539
540 netmgr_config_t cfg = { 0 };
541 if (is_wifi) {
542 HAAS_EXCEPTIONS(netmgr_get_config(self->if_id, &cfg));
543 }
544
545 mp_obj_t val = mp_const_none;
546
547 // if (kwargs->used != 0) {
548 // if (!is_wifi) {
549 // goto unknown;
550 // }
551
552 // for (size_t i = 0; i < kwargs->alloc; i++) {
553 // if (mp_map_slot_is_filled(kwargs, i)) {
554 // int req_if = -1;
555
556 // switch ((uintptr_t)kwargs->table[i].key) {
557 // case QS(MP_QSTR_mac): {
558 // mp_buffer_info_t bufinfo;
559 // mp_get_buffer_raise(kwargs->table[i].value, &bufinfo,
560 // MP_BUFFER_READ); if (bufinfo.len != 6) {
561 // mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer
562 // length"));
563 // }
564 // HAAS_EXCEPTIONS(wifi_set_mac(self->hdl,
565 // bufinfo.buf)); break;
566 // }
567 // case QS(MP_QSTR_essid): {
568 // req_if = NETMGR_WIFI_MODE_AP;
569 // size_t len;
570 // const char *s =
571 // mp_obj_str_get_data(kwargs->table[i].value, &len);
572 // len = MIN(len, sizeof(cfg.ap.ssid));
573 // memcpy(cfg.ap.ssid, s, len);
574 // cfg.ap.ssid_len = len;
575 // break;
576 // }
577 // case QS(MP_QSTR_hidden): {
578 // req_if = NETMGR_WIFI_MODE_AP;
579 // cfg.ap.ssid_hidden =
580 // mp_obj_is_true(kwargs->table[i].value); break;
581 // }
582 // case QS(MP_QSTR_authmode): {
583 // req_if = NETMGR_WIFI_MODE_AP;
584 // cfg.ap.authmode =
585 // mp_obj_get_int(kwargs->table[i].value); break;
586 // }
587 // case QS(MP_QSTR_password): {
588 // req_if = NETMGR_WIFI_MODE_AP;
589 // size_t len;
590 // const char *s =
591 // mp_obj_str_get_data(kwargs->table[i].value, &len);
592 // len = MIN(len, sizeof(cfg.ap.password) - 1);
593 // memcpy(cfg.ap.password, s, len);
594 // cfg.ap.password[len] = 0;
595 // break;
596 // }
597 // case QS(MP_QSTR_channel): {
598 // req_if = NETMGR_WIFI_MODE_AP;
599 // cfg.ap.channel =
600 // mp_obj_get_int(kwargs->table[i].value); break;
601 // }
602 // case QS(MP_QSTR_dhcp_hostname): {
603 // const char *s =
604 // mp_obj_str_get_str(kwargs->table[i].value);
605 // HAAS_EXCEPTIONS(tcpip_adapter_set_hostname(self->if_id,
606 // s)); break;
607 // }
608 // case QS(MP_QSTR_max_clients): {
609 // req_if = NETMGR_WIFI_MODE_AP;
610 // cfg.ap.max_connection =
611 // mp_obj_get_int(kwargs->table[i].value); break;
612 // }
613 // default:
614 // goto unknown;
615 // }
616
617 // // We post-check interface requirements to save on code size
618 // if (req_if >= 0) {
619 // require_if(args[0], req_if);
620 // }
621 // }
622 // }
623
624 // HAAS_EXCEPTIONS(haas_wlan_wifi_set_config(self->if_id, &cfg));
625 // return mp_const_none;
626 // }
627
628 // // Get config
629 // if (n_args != 2) {
630 // mp_raise_TypeError(MP_ERROR_TEXT("can query only one param"));
631 // }
632
633 // int req_if = -1;
634
635 // switch ((uintptr_t)args[1]) {
636 // case QS(MP_QSTR_mac): {
637 // uint8_t mac[6];
638 // switch (self->if_id) {
639 // case NETMGR_WIFI_MODE_AP: // fallthrough intentional
640 // case NETMGR_WIFI_MODE_STA:
641 // HAAS_EXCEPTIONS(wifi_get_mac(self->hdl, mac));
642 // return mp_obj_new_bytes(mac, sizeof(mac));
643
644 // default:
645 // goto unknown;
646 // }
647 // }
648 // break;
649 // case QS(MP_QSTR_essid):
650 // switch (self->if_id) {
651 // case NETMGR_WIFI_MODE_STA:
652 // val = mp_obj_new_str((char *)cfg.sta.ssid, strlen((char
653 // *)cfg.sta.ssid)); break;
654 // case NETMGR_WIFI_MODE_AP:
655 // val = mp_obj_new_str((char *)cfg.ap.ssid,
656 // cfg.ap.ssid_len); break;
657 // default:
658 // req_if = NETMGR_WIFI_MODE_AP;
659 // }
660 // break;
661 // case QS(MP_QSTR_hidden):
662 // req_if = NETMGR_WIFI_MODE_AP;
663 // val = mp_obj_new_bool(cfg.ap.ssid_hidden);
664 // break;
665 // case QS(MP_QSTR_authmode):
666 // req_if = NETMGR_WIFI_MODE_AP;
667 // val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
668 // break;
669 // case QS(MP_QSTR_channel):
670 // req_if = NETMGR_WIFI_MODE_AP;
671 // val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
672 // break;
673 // case QS(MP_QSTR_dhcp_hostname): {
674 // const char *s;
675 // HAAS_EXCEPTIONS(tcpip_adapter_get_hostname(self->if_id, &s));
676 // val = mp_obj_new_str(s, strlen(s));
677 // break;
678 // }
679 // case QS(MP_QSTR_max_clients): {
680 // val = MP_OBJ_NEW_SMALL_INT(cfg.ap.max_connection);
681 // break;
682 // }
683 // default:
684 // goto unknown;
685 // }
686
687 // // We post-check interface requirements to save on code size
688 // if (req_if >= 0) {
689 // require_if(args[0], req_if);
690 // }
691
692 return val;
693
694 unknown:
695 mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
696 }
697 MP_DEFINE_CONST_FUN_OBJ_KW(haas_wlan_config_obj, 1, haas_wlan_config);
698
699 STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
700 { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&haas_wlan_active_obj) },
701 { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&haas_wlan_connect_obj) },
702 { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&haas_wlan_disconnect_obj) },
703 { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&haas_wlan_status_obj) },
704 { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&haas_wlan_scan_obj) },
705 { MP_ROM_QSTR(MP_QSTR_isconnected),
706 MP_ROM_PTR(&haas_wlan_isconnected_obj) },
707 { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&haas_wlan_config_obj) },
708 { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&haas_wlan_ifconfig_obj) },
709 };
710
711 STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
712
713 const mp_obj_type_t wlan_if_type = {
714 { &mp_type_type },
715 .name = MP_QSTR_WLAN,
716 .locals_dict = (mp_obj_t)&wlan_if_locals_dict,
717 };
718
719 STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
720 { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
721 { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&wlan_initialize_obj) },
722 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) },
723
724 #if MODNETWORK_INCLUDE_CONSTANTS
725 { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(NETMGR_WIFI_MODE_STA) },
726 { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(NETMGR_WIFI_MODE_AP) },
727
728 #if 0
729 { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) },
730 { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) },
731 { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) },
732
733 { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) },
734 { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) },
735 { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(WIFI_AUTH_WPA_PSK) },
736 { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_PSK) },
737 { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA_WPA2_PSK) },
738 { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_ENTERPRISE), MP_ROM_INT(WIFI_AUTH_WPA2_ENTERPRISE) },
739 { MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) },
740
741 { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STAT_IDLE)},
742 { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STAT_CONNECTING)},
743 { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STAT_GOT_IP)},
744 { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND)},
745 { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(WIFI_REASON_AUTH_FAIL)},
746 { MP_ROM_QSTR(MP_QSTR_STAT_BEACON_TIMEOUT), MP_ROM_INT(WIFI_REASON_BEACON_TIMEOUT)},
747 { MP_ROM_QSTR(MP_QSTR_STAT_ASSOC_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)},
748 { MP_ROM_QSTR(MP_QSTR_STAT_HANDSHAKE_TIMEOUT), MP_ROM_INT(WIFI_REASON_HANDSHAKE_TIMEOUT)},
749 #endif
750 #endif
751 };
752
753 STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals,
754 mp_module_network_globals_table);
755
756 const mp_obj_module_t mp_module_network = {
757 .base = { &mp_type_module },
758 .globals = (mp_obj_dict_t *)&mp_module_network_globals,
759 };
760