| /* |
| * This file is part of the Micro Python project, http://micropython.org/ |
| * |
| * The MIT License (MIT) |
| * |
| * Copyright (c) 2015 Paul Sokolovsky |
| * |
| * 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 <stdio.h> |
| #include <string.h> |
| #include <stdbool.h> |
| #include <errno.h> |
| |
| #include "py/nlr.h" |
| #include "py/obj.h" |
| #include "py/gc.h" |
| #include "py/runtime.h" |
| #include "netutils.h" |
| #include "queue.h" |
| #include "ets_sys.h" |
| #include "uart.h" |
| #include "user_interface.h" |
| #include "espconn.h" |
| #include "spi_flash.h" |
| #include "utils.h" |
| #include "espneopixel.h" |
| #include "modpyb.h" |
| |
| #define MODESP_ESPCONN (0) |
| |
| #if MODESP_ESPCONN |
| STATIC const mp_obj_type_t esp_socket_type; |
| |
| typedef struct _esp_socket_obj_t { |
| mp_obj_base_t base; |
| struct espconn *espconn; |
| |
| mp_obj_t cb_connect; |
| mp_obj_t cb_recv; |
| mp_obj_t cb_sent; |
| mp_obj_t cb_disconnect; |
| |
| uint8_t *recvbuf; |
| mp_uint_t recvbuf_len; |
| |
| bool fromserver; |
| |
| mp_obj_list_t *connlist; |
| } esp_socket_obj_t; |
| |
| // Due to the onconnect callback not being able to recognize the parent esp_socket, |
| // we can have only one esp_socket listening at a time |
| // This should be solvable by some PIC hacking |
| STATIC esp_socket_obj_t *esp_socket_listening; |
| |
| STATIC mp_obj_t esp_socket_make_new_base() { |
| esp_socket_obj_t *s = m_new_obj_with_finaliser(esp_socket_obj_t); |
| s->recvbuf = NULL; |
| s->base.type = (mp_obj_t)&esp_socket_type; |
| s->cb_connect = mp_const_none; |
| s->cb_recv = mp_const_none; |
| s->cb_disconnect = mp_const_none; |
| s->cb_sent = mp_const_none; |
| s->fromserver = false; |
| s->connlist = NULL; |
| return s; |
| } |
| |
| // constructor esp_socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None) |
| // Arguments ignored as we do not support UDP (yet) |
| STATIC mp_obj_t esp_socket_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, |
| mp_uint_t n_kw, const mp_obj_t *args) { |
| mp_arg_check_num(n_args, n_kw, 0, 4, false); |
| |
| esp_socket_obj_t *s = esp_socket_make_new_base(); |
| s->espconn = m_new_obj(struct espconn); |
| |
| s->espconn->reverse = s; |
| // TODO: UDP Support |
| s->espconn->type = ESPCONN_TCP; |
| s->espconn->state = ESPCONN_NONE; |
| |
| s->espconn->proto.tcp = m_new_obj(esp_tcp); |
| |
| return s; |
| } |
| |
| // method socket.close() |
| STATIC mp_obj_t esp_socket_close(mp_obj_t self_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| if (esp_socket_listening == s) { |
| esp_socket_listening = NULL; |
| } |
| |
| if (s->espconn->state != ESPCONN_NONE && s->espconn->state != ESPCONN_CLOSE) { |
| espconn_disconnect(s->espconn); |
| } |
| |
| if (s->connlist != NULL) { |
| mp_obj_list_set_len(s->connlist, 0); |
| } |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_close_obj, esp_socket_close); |
| |
| // method socket.__del__() |
| STATIC mp_obj_t esp_socket___del__(mp_obj_t self_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| esp_socket_close(self_in); |
| |
| if (s->fromserver) { |
| espconn_delete(s->espconn); |
| } |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket___del___obj, esp_socket___del__); |
| |
| // method socket.bind(address) |
| STATIC mp_obj_t esp_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| mp_uint_t port = netutils_parse_inet_addr(addr_in, |
| s->espconn->proto.tcp->remote_ip, NETUTILS_BIG); |
| s->espconn->proto.tcp->local_port = port; |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_bind_obj, esp_socket_bind); |
| |
| STATIC void esp_socket_recv_callback(void *arg, char *pdata, unsigned short len) { |
| struct espconn *conn = arg; |
| esp_socket_obj_t *s = conn->reverse; |
| |
| if (s->cb_recv != mp_const_none) { |
| call_function_2_protected(s->cb_recv, s, mp_obj_new_bytes((byte *)pdata, len)); |
| } else { |
| if (s->recvbuf == NULL) { |
| s->recvbuf = m_new(uint8_t, len); |
| s->recvbuf_len = len; |
| if (s->recvbuf != NULL) { |
| memcpy(s->recvbuf, pdata, len); |
| } |
| } else { |
| s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len + len); |
| if (s->recvbuf != NULL) { |
| memcpy(&s->recvbuf[s->recvbuf_len], pdata, len); |
| s->recvbuf_len += len; |
| } |
| } |
| if (s->recvbuf == NULL) { |
| esp_socket_close(s); |
| return; |
| } |
| } |
| } |
| |
| STATIC void esp_socket_sent_callback(void *arg) { |
| struct espconn *conn = arg; |
| esp_socket_obj_t *s = conn->reverse; |
| |
| if (s->cb_sent != mp_const_none) { |
| call_function_1_protected(s->cb_sent, s); |
| } |
| } |
| |
| STATIC void esp_socket_disconnect_callback(void *arg) { |
| struct espconn *conn = arg; |
| esp_socket_obj_t *s = conn->reverse; |
| |
| if (s->cb_disconnect != mp_const_none) { |
| call_function_1_protected(s->cb_disconnect, s); |
| } |
| |
| esp_socket_close(s); |
| } |
| |
| STATIC void esp_socket_connect_callback_server(void *arg) { |
| struct espconn *conn = arg; |
| |
| esp_socket_obj_t *s = esp_socket_make_new_base(); |
| s->espconn = conn; |
| s->fromserver = true; |
| conn->reverse = s; |
| |
| espconn_regist_recvcb(conn, esp_socket_recv_callback); |
| espconn_regist_sentcb(conn, esp_socket_sent_callback); |
| espconn_regist_disconcb(conn, esp_socket_disconnect_callback); |
| espconn_regist_time(conn, 15, 0); |
| |
| if (esp_socket_listening->cb_connect != mp_const_none) { |
| call_function_1_protected(esp_socket_listening->cb_connect, s); |
| } else { |
| mp_obj_list_append(esp_socket_listening->connlist, s); |
| } |
| } |
| |
| STATIC void esp_socket_connect_callback_client(void *arg) { |
| struct espconn *conn = arg; |
| esp_socket_obj_t *s = conn->reverse; |
| |
| if (s->cb_connect != mp_const_none) { |
| call_function_1_protected(s->cb_connect, s); |
| } |
| } |
| |
| // method socket.listen(backlog) |
| STATIC mp_obj_t esp_socket_listen(mp_obj_t self_in, mp_obj_t backlog) { |
| esp_socket_obj_t *s = self_in; |
| |
| if (esp_socket_listening != NULL) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, |
| "only one espconn can listen at a time")); |
| } |
| |
| esp_socket_listening = s; |
| |
| s->connlist = mp_obj_new_list(0, NULL); |
| |
| espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_server); |
| espconn_accept(s->espconn); |
| espconn_regist_time(s->espconn, 1500, 0); |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_listen_obj, esp_socket_listen); |
| |
| // method socket.accept() |
| STATIC mp_obj_t esp_socket_accept(mp_obj_t self_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| if (s->connlist == NULL) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, |
| "not listening")); |
| } |
| |
| do { |
| mp_uint_t len; |
| mp_obj_t *items; |
| |
| mp_obj_list_get(s->connlist, &len, &items); |
| if (len == 0) { |
| break; |
| } |
| |
| esp_socket_obj_t *rs = items[0]; |
| mp_obj_list_remove(s->connlist, rs); |
| if (rs->espconn->state != ESPCONN_CLOSE) { |
| return rs; |
| } |
| } while (true); |
| |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, |
| "no connection in queue")); |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_accept_obj, esp_socket_accept); |
| |
| // method socket.connect(address) |
| STATIC mp_obj_t esp_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| if (s->espconn == NULL || s->espconn->state != ESPCONN_NONE) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, |
| "transport endpoint is already connected or closed")); |
| } |
| |
| espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_client); |
| espconn_regist_recvcb(s->espconn, esp_socket_recv_callback); |
| espconn_regist_sentcb(s->espconn, esp_socket_sent_callback); |
| espconn_regist_disconcb(s->espconn, esp_socket_disconnect_callback); |
| |
| s->espconn->proto.tcp->remote_port = |
| netutils_parse_inet_addr(addr_in, s->espconn->proto.tcp->remote_ip, |
| NETUTILS_BIG); |
| espconn_connect(s->espconn); |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_connect_obj, esp_socket_connect); |
| |
| // method socket.send(bytes) |
| STATIC mp_obj_t esp_socket_send(mp_obj_t self_in, mp_obj_t buf_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| if (s->espconn->state == ESPCONN_NONE || s->espconn->state == ESPCONN_CLOSE) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, |
| "not connected")); |
| } |
| |
| mp_buffer_info_t bufinfo; |
| mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); |
| |
| espconn_sent(s->espconn, bufinfo.buf, bufinfo.len); |
| |
| return mp_obj_new_int(bufinfo.len); |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_send_obj, esp_socket_send); |
| |
| // method socket.recv(bufsize) |
| STATIC mp_obj_t esp_socket_recv(mp_obj_t self_in, mp_obj_t len_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| if (s->recvbuf == NULL) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, |
| "no data available")); |
| } |
| |
| mp_uint_t mxl = mp_obj_get_int(len_in); |
| if (mxl >= s->recvbuf_len) { |
| mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, s->recvbuf_len); |
| m_del(uint8_t, s->recvbuf, s->recvbuf_len); |
| s->recvbuf = NULL; |
| return trt; |
| } else { |
| mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, mxl); |
| memmove(s->recvbuf, &s->recvbuf[mxl], s->recvbuf_len - mxl); |
| s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len - mxl); |
| s->recvbuf_len -= mxl; |
| return trt; |
| } |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recv_obj, esp_socket_recv); |
| |
| // method socket.sendto(bytes, address) |
| STATIC mp_obj_t esp_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported")); |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_socket_sendto_obj, esp_socket_sendto); |
| |
| // method socket.recvfrom(bufsize) |
| STATIC mp_obj_t esp_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported")); |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recvfrom_obj, esp_socket_recvfrom); |
| |
| // method socket.getpeername() |
| STATIC mp_obj_t esp_socket_getpeername(mp_obj_t self_in) { |
| esp_socket_obj_t *s = self_in; |
| |
| if (s->espconn->state == ESPCONN_NONE) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, |
| "not connected")); |
| } |
| |
| mp_obj_t tuple[2] = { |
| netutils_format_ipv4_addr(s->espconn->proto.tcp->remote_ip, NETUTILS_BIG), |
| mp_obj_new_int(s->espconn->proto.tcp->remote_port), |
| }; |
| |
| return mp_obj_new_tuple(2, tuple); |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_getpeername_obj, esp_socket_getpeername); |
| |
| STATIC mp_obj_t esp_socket_onconnect(mp_obj_t self_in, mp_obj_t lambda_in) { |
| esp_socket_obj_t *s = self_in; |
| s->cb_connect = lambda_in; |
| |
| if (s->connlist != NULL) { |
| do { |
| mp_uint_t len; |
| mp_obj_t *items; |
| |
| mp_obj_list_get(s->connlist, &len, &items); |
| if (len == 0) { |
| break; |
| } |
| |
| esp_socket_obj_t *rs = items[0]; |
| mp_obj_list_remove(s->connlist, rs); |
| if (s->espconn->state != ESPCONN_CLOSE) { |
| call_function_1_protected(s->cb_connect, rs); |
| } |
| } while (true); |
| } |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onconnect_obj, esp_socket_onconnect); |
| |
| STATIC mp_obj_t esp_socket_onrecv(mp_obj_t self_in, mp_obj_t lambda_in) { |
| esp_socket_obj_t *s = self_in; |
| s->cb_recv = lambda_in; |
| if (s->recvbuf != NULL) { |
| call_function_2_protected(s->cb_recv, s, |
| mp_obj_new_bytes((byte *)s->recvbuf, s->recvbuf_len)); |
| s->recvbuf = NULL; |
| } |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onrecv_obj, esp_socket_onrecv); |
| |
| STATIC mp_obj_t esp_socket_onsent(mp_obj_t self_in, mp_obj_t lambda_in) { |
| esp_socket_obj_t *s = self_in; |
| s->cb_sent = lambda_in; |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onsent_obj, esp_socket_onsent); |
| |
| STATIC mp_obj_t esp_socket_ondisconnect(mp_obj_t self_in, mp_obj_t lambda_in) { |
| esp_socket_obj_t *s = self_in; |
| s->cb_disconnect = lambda_in; |
| |
| if (s->espconn->state == ESPCONN_CLOSE) { |
| call_function_1_protected(s->cb_disconnect, s); |
| } |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_ondisconnect_obj, esp_socket_ondisconnect); |
| |
| typedef struct _esp_getaddrinfo_cb_struct_t { |
| mp_obj_t lambda; |
| mp_uint_t port; |
| } esp_getaddrinfo_cb_struct_t; |
| |
| STATIC esp_getaddrinfo_cb_struct_t esp_getaddrinfo_cb_struct; |
| |
| STATIC void esp_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) { |
| mp_obj_t namestr = mp_obj_new_str(name, strlen(name), true); |
| if (ipaddr != NULL) { |
| uint8_t ip[4]; |
| ip[0] = (ipaddr->addr >> 24) & 0xff; |
| ip[1] = (ipaddr->addr >> 16) & 0xff; |
| ip[2] = (ipaddr->addr >> 8) & 0xff; |
| ip[3] = (ipaddr->addr >> 0) & 0xff; |
| |
| mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); |
| |
| tuple->items[0] = MP_OBJ_NEW_SMALL_INT(0); |
| tuple->items[1] = MP_OBJ_NEW_SMALL_INT(0); |
| tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); |
| tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); |
| tuple->items[4] = netutils_format_inet_addr(ip, |
| esp_getaddrinfo_cb_struct.port, NETUTILS_LITTLE); |
| call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, tuple); |
| } else { |
| call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, mp_const_none); |
| } |
| } |
| |
| STATIC mp_obj_t esp_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in, |
| mp_obj_t lambda_in) { |
| mp_uint_t hlen; |
| const char *host = mp_obj_str_get_data(host_in, &hlen); |
| ip_addr_t ipaddr; |
| |
| esp_getaddrinfo_cb_struct.lambda = lambda_in; |
| esp_getaddrinfo_cb_struct.port = mp_obj_get_int(port_in); |
| |
| err_t ret = espconn_gethostbyname(NULL, host, &ipaddr, |
| esp_getaddrinfo_cb); |
| |
| if (ret == ESPCONN_OK) { |
| esp_getaddrinfo_cb(host, &ipaddr, NULL); |
| } |
| |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_getaddrinfo_obj, esp_getaddrinfo); |
| |
| STATIC const mp_map_elem_t esp_socket_locals_dict_table[] = { |
| { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&esp_socket___del___obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&esp_socket_close_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&esp_socket_bind_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&esp_socket_listen_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&esp_socket_accept_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_socket_connect_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&esp_socket_send_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&esp_socket_recv_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&esp_socket_sendto_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&esp_socket_recvfrom_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_getpeername), (mp_obj_t)&esp_socket_getpeername_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_onconnect), (mp_obj_t)&esp_socket_onconnect_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_onrecv), (mp_obj_t)&esp_socket_onrecv_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_onsent), (mp_obj_t)&esp_socket_onsent_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_ondisconnect), (mp_obj_t)&esp_socket_ondisconnect_obj }, |
| }; |
| STATIC MP_DEFINE_CONST_DICT(esp_socket_locals_dict, esp_socket_locals_dict_table); |
| |
| STATIC const mp_obj_type_t esp_socket_type = { |
| { &mp_type_type }, |
| .name = MP_QSTR_socket, |
| .make_new = esp_socket_make_new, |
| .locals_dict = (mp_obj_t)&esp_socket_locals_dict, |
| }; |
| #endif |
| |
| #define MODESP_INCLUDE_CONSTANTS (1) |
| |
| void error_check(bool status, const char *msg) { |
| if (!status) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg)); |
| } |
| } |
| |
| STATIC mp_obj_t esp_osdebug(mp_obj_t val) { |
| if (val == mp_const_none) { |
| uart_os_config(-1); |
| } else { |
| uart_os_config(mp_obj_get_int(val)); |
| } |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_osdebug_obj, esp_osdebug); |
| |
| STATIC mp_obj_t esp_sleep_type(mp_uint_t n_args, const mp_obj_t *args) { |
| if (n_args == 0) { |
| return mp_obj_new_int(wifi_get_sleep_type()); |
| } else { |
| wifi_set_sleep_type(mp_obj_get_int(args[0])); |
| return mp_const_none; |
| } |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_sleep_type_obj, 0, 1, esp_sleep_type); |
| |
| STATIC mp_obj_t esp_deepsleep(mp_uint_t n_args, const mp_obj_t *args) { |
| system_deep_sleep(n_args > 0 ? mp_obj_get_int(args[0]) : 0); |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_deepsleep_obj, 0, 1, esp_deepsleep); |
| |
| STATIC mp_obj_t esp_flash_id() { |
| return mp_obj_new_int(spi_flash_get_id()); |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_id_obj, esp_flash_id); |
| |
| STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t len_or_buf_in) { |
| mp_int_t offset = mp_obj_get_int(offset_in); |
| |
| mp_int_t len; |
| byte *buf; |
| bool alloc_buf = MP_OBJ_IS_INT(len_or_buf_in); |
| |
| if (alloc_buf) { |
| len = mp_obj_get_int(len_or_buf_in); |
| buf = m_new(byte, len); |
| } else { |
| mp_buffer_info_t bufinfo; |
| mp_get_buffer_raise(len_or_buf_in, &bufinfo, MP_BUFFER_WRITE); |
| len = bufinfo.len; |
| buf = bufinfo.buf; |
| } |
| |
| // We know that allocation will be 4-byte aligned for sure |
| SpiFlashOpResult res = spi_flash_read(offset, (uint32_t*)buf, len); |
| if (res == SPI_FLASH_RESULT_OK) { |
| if (alloc_buf) { |
| return mp_obj_new_bytes(buf, len); |
| } |
| return mp_const_none; |
| } |
| if (alloc_buf) { |
| m_del(byte, buf, len); |
| } |
| nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO))); |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read); |
| |
| STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) { |
| mp_int_t offset = mp_obj_get_int(offset_in); |
| mp_buffer_info_t bufinfo; |
| mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); |
| if (bufinfo.len & 0x3) { |
| nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "len must be multiple of 4")); |
| } |
| SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, bufinfo.len); |
| if (res == SPI_FLASH_RESULT_OK) { |
| return mp_const_none; |
| } |
| nlr_raise(mp_obj_new_exception_arg1( |
| &mp_type_OSError, |
| MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO))); |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write); |
| |
| STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) { |
| mp_int_t sector = mp_obj_get_int(sector_in); |
| SpiFlashOpResult res = spi_flash_erase_sector(sector); |
| if (res == SPI_FLASH_RESULT_OK) { |
| return mp_const_none; |
| } |
| nlr_raise(mp_obj_new_exception_arg1( |
| &mp_type_OSError, |
| MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO))); |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase); |
| |
| STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) { |
| mp_buffer_info_t bufinfo; |
| mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); |
| esp_neopixel_write(mp_obj_get_pin_obj(pin)->phys_port, |
| (uint8_t*)bufinfo.buf, bufinfo.len, mp_obj_is_true(is800k)); |
| return mp_const_none; |
| } |
| STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_); |
| |
| STATIC const mp_map_elem_t esp_module_globals_table[] = { |
| { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_esp) }, |
| |
| { MP_OBJ_NEW_QSTR(MP_QSTR_osdebug), (mp_obj_t)&esp_osdebug_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_type), (mp_obj_t)&esp_sleep_type_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&esp_deepsleep_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_flash_id), (mp_obj_t)&esp_flash_id_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_flash_read), (mp_obj_t)&esp_flash_read_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_flash_write), (mp_obj_t)&esp_flash_write_obj }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_flash_erase), (mp_obj_t)&esp_flash_erase_obj }, |
| #if MODESP_ESPCONN |
| { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj }, |
| #endif |
| { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj }, |
| |
| #if MODESP_INCLUDE_CONSTANTS |
| { MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_NONE), |
| MP_OBJ_NEW_SMALL_INT(NONE_SLEEP_T) }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_LIGHT), |
| MP_OBJ_NEW_SMALL_INT(LIGHT_SLEEP_T) }, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_MODEM), |
| MP_OBJ_NEW_SMALL_INT(MODEM_SLEEP_T) }, |
| |
| { MP_OBJ_NEW_QSTR(MP_QSTR_STA_MODE), |
| MP_OBJ_NEW_SMALL_INT(STATION_MODE)}, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_AP_MODE), |
| MP_OBJ_NEW_SMALL_INT(SOFTAP_MODE)}, |
| { MP_OBJ_NEW_QSTR(MP_QSTR_STA_AP_MODE), |
| MP_OBJ_NEW_SMALL_INT(STATIONAP_MODE)}, |
| #endif |
| }; |
| |
| STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table); |
| |
| const mp_obj_module_t esp_module = { |
| .base = { &mp_type_module }, |
| .name = MP_QSTR_esp, |
| .globals = (mp_obj_dict_t*)&esp_module_globals, |
| }; |