From 1687719212df5a2ea29f87d466c287e9dba517c8 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 11 Mar 2024 23:21:03 +0000 Subject: [PATCH] Experimental: PINT module bindings. P.I.N.T Python Implementation of Network Transports. --- .github/workflows/micropython.yml | 2 + micropython/board/RPI_PICO_PINT/board.json | 20 + micropython/board/RPI_PICO_PINT/manifest.py | 5 + .../board/RPI_PICO_PINT/mpconfigboard.cmake | 7 + .../board/RPI_PICO_PINT/mpconfigboard.h | 15 + micropython/board/RPI_PICO_PINT/pins.csv | 28 ++ .../modules/micropython-pico_pint.cmake | 14 + micropython/modules/pint/README.md | 82 ++++ micropython/modules/pint/micropython.cmake | 18 + micropython/modules/pint/pint.c | 52 +++ micropython/modules/pint/pint.cpp | 366 ++++++++++++++++++ micropython/modules/pint/pint.h | 26 ++ 12 files changed, 635 insertions(+) create mode 100644 micropython/board/RPI_PICO_PINT/board.json create mode 100644 micropython/board/RPI_PICO_PINT/manifest.py create mode 100644 micropython/board/RPI_PICO_PINT/mpconfigboard.cmake create mode 100644 micropython/board/RPI_PICO_PINT/mpconfigboard.h create mode 100644 micropython/board/RPI_PICO_PINT/pins.csv create mode 100644 micropython/modules/micropython-pico_pint.cmake create mode 100644 micropython/modules/pint/README.md create mode 100644 micropython/modules/pint/micropython.cmake create mode 100644 micropython/modules/pint/pint.c create mode 100644 micropython/modules/pint/pint.cpp create mode 100644 micropython/modules/pint/pint.h diff --git a/.github/workflows/micropython.yml b/.github/workflows/micropython.yml index 454ad040..e93f3e45 100644 --- a/.github/workflows/micropython.yml +++ b/.github/workflows/micropython.yml @@ -21,6 +21,8 @@ jobs: board: RPI_PICO - name: picow board: RPI_PICO_W + - name: pico_pint + board: RPI_PICO_PINT - name: tiny2040_8mb board: PIMORONI_TINY2040 - name: picolipo_4mb diff --git a/micropython/board/RPI_PICO_PINT/board.json b/micropython/board/RPI_PICO_PINT/board.json new file mode 100644 index 00000000..5a67a25e --- /dev/null +++ b/micropython/board/RPI_PICO_PINT/board.json @@ -0,0 +1,20 @@ +{ + "deploy": [ + "../deploy.md" + ], + "docs": "", + "features": [ + "Breadboard friendly", + "Castellated Pads", + "Micro USB" + ], + "id": "rp2-pico", + "images": [ + "rp2-pico.jpg" + ], + "mcu": "rp2040", + "product": "Pico", + "thumbnail": "", + "url": "https://www.raspberrypi.com/products/raspberry-pi-pico/", + "vendor": "Raspberry Pi" +} \ No newline at end of file diff --git a/micropython/board/RPI_PICO_PINT/manifest.py b/micropython/board/RPI_PICO_PINT/manifest.py new file mode 100644 index 00000000..f8ee3f93 --- /dev/null +++ b/micropython/board/RPI_PICO_PINT/manifest.py @@ -0,0 +1,5 @@ +include("$(PORT_DIR)/boards/manifest.py") + +require("bundle-networking") + +include("../manifest_pico.py") \ No newline at end of file diff --git a/micropython/board/RPI_PICO_PINT/mpconfigboard.cmake b/micropython/board/RPI_PICO_PINT/mpconfigboard.cmake new file mode 100644 index 00000000..c89ff780 --- /dev/null +++ b/micropython/board/RPI_PICO_PINT/mpconfigboard.cmake @@ -0,0 +1,7 @@ +# cmake file for Raspberry Pi Pico +set(PICO_BOARD "pico") + +# Board specific version of the frozen manifest +set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py) + +set(MICROPY_C_HEAP_SIZE 4096) \ No newline at end of file diff --git a/micropython/board/RPI_PICO_PINT/mpconfigboard.h b/micropython/board/RPI_PICO_PINT/mpconfigboard.h new file mode 100644 index 00000000..91c3d8e5 --- /dev/null +++ b/micropython/board/RPI_PICO_PINT/mpconfigboard.h @@ -0,0 +1,15 @@ +// Board and hardware specific configuration +#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico" +#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024) + +// Enable networking. +#define MICROPY_PY_NETWORK 1 +#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "Pico" + +extern const struct _mp_obj_type_t mod_network_nic_type_pint; +#define MICROPY_HW_NIC_PINT { MP_ROM_QSTR(MP_QSTR_PINT), MP_ROM_PTR(&mod_network_nic_type_pint) }, + +#define MICROPY_BOARD_NETWORK_INTERFACES \ + MICROPY_HW_NIC_PINT + +#define MICROPY_PY_SOCKET_EXTENDED_STATE 1 \ No newline at end of file diff --git a/micropython/board/RPI_PICO_PINT/pins.csv b/micropython/board/RPI_PICO_PINT/pins.csv new file mode 100644 index 00000000..9c40b41c --- /dev/null +++ b/micropython/board/RPI_PICO_PINT/pins.csv @@ -0,0 +1,28 @@ +GP0,GPIO0 +GP1,GPIO1 +GP2,GPIO2 +GP3,GPIO3 +GP4,GPIO4 +GP5,GPIO5 +GP6,GPIO6 +GP7,GPIO7 +GP8,GPIO8 +GP9,GPIO9 +GP10,GPIO10 +GP11,GPIO11 +GP12,GPIO12 +GP13,GPIO13 +GP14,GPIO14 +GP15,GPIO15 +GP16,GPIO16 +GP17,GPIO17 +GP18,GPIO18 +GP19,GPIO19 +GP20,GPIO20 +GP21,GPIO21 +GP22,GPIO22 +GP25,GPIO25 +GP26,GPIO26 +GP27,GPIO27 +GP28,GPIO28 +LED,GPIO25 \ No newline at end of file diff --git a/micropython/modules/micropython-pico_pint.cmake b/micropython/modules/micropython-pico_pint.cmake new file mode 100644 index 00000000..cd8e093e --- /dev/null +++ b/micropython/modules/micropython-pico_pint.cmake @@ -0,0 +1,14 @@ +include_directories(${CMAKE_CURRENT_LIST_DIR}/../../) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../") + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +include(micropython-common) +include(pint/micropython) + +# C++ Magic Memory +include(cppmem/micropython) diff --git a/micropython/modules/pint/README.md b/micropython/modules/pint/README.md new file mode 100644 index 00000000..77bc78c4 --- /dev/null +++ b/micropython/modules/pint/README.md @@ -0,0 +1,82 @@ +# P.I.N.T + +### Python Implementation of Network Transports. + +Want to glue your esoteric network device into MicroPython without delving +into C or trying to figure out lwIP? PINT is just the refreshment you need. + +### Reference Implementation + +PINT uses a Python class to implement a socket-based networking driver. + +How you implement these functions is down to you- but you must expect/return +the correct data. Here's the basic skeleton: + +```python +class PINT_Socket(): + """An arbitrary structure for storing data about your sockets. + + Does not have to be a class, you could just return an int with the + socket ID of your target device. + """ + def __init__(self): + pass + + +class PINT_NIC: + """The actual NIC implementation. + + Most of the heavy lifting is sockets based, you might want to implement + the socket_ methods on your socket class and simply delegate to them. + """ + def __init__(self) -> None: + pass + + def __del__(self) -> None: + pass + + def gethostbyname(self, name: str) -> tuple[int, int, int, int]: + return (127, 0, 0, 1) + + def socket_socket(self) -> PINT_Socket: + return PINT_Socket() + + def socket_close(self, socket: PINT_Socket) -> None: + pass + + def socket_bind(self, socket: PINT_Socket, ip: tuple[int, int, int, int], port: int) -> bool: + return True + + def socket_listen(self, socket: PINT_Socket, backlog: int) -> bool: + return True + + def socket_accept(self, socket: PINT_Socket, socket2: PINT_Socket, ip: tuple[int, int, int, int], port: int) -> bool: + return True + + def socket_connect(self, socket: PINT_Socket, ip: tuple[int, int, int, int], port) -> bool: + return True + + def socket_send(self, socket: PINT_Socket, buf: bytearray) -> int: + return 0 + + def socket_recv(self, socket: PINT_Socket, buf: bytearray) -> int: + """Buf is provided as a mutable bytearray, you must write into it.""" + return 0 + + def socket_sendto(self, socket: PINT_Socket, buf: bytearray, ip, port) -> int: + return 0 + + def socket_recvfrom(self, socket: PINT_Socket, buf: bytearray, ip, port) -> int: + """Buf is provided as a mutable bytearray, you must write into it.""" + return 0 + + def socket_setsockopt(self, socket: PINT_Socket, level: int, opt: int, val: bytearray) -> bool: + return True + + def socket_settimeout(self, socket: PINT_Socket, timeout_ms: int) -> bool: + return True + + def socket_ioctl(self, socket: PINT_Socket, request: int, arg: int) -> bool: + return True + +``` \ No newline at end of file diff --git a/micropython/modules/pint/micropython.cmake b/micropython/modules/pint/micropython.cmake new file mode 100644 index 00000000..7e3382dd --- /dev/null +++ b/micropython/modules/pint/micropython.cmake @@ -0,0 +1,18 @@ +set(MOD_NAME pint) +string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER) +add_library(usermod_${MOD_NAME} INTERFACE) + +target_sources(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp +) + +target_include_directories(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +target_compile_definitions(usermod_${MOD_NAME} INTERFACE + MODULE_PINT_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) \ No newline at end of file diff --git a/micropython/modules/pint/pint.c b/micropython/modules/pint/pint.c new file mode 100644 index 00000000..42805ce8 --- /dev/null +++ b/micropython/modules/pint/pint.c @@ -0,0 +1,52 @@ +#include "pint.h" + +MP_DEFINE_CONST_FUN_OBJ_1(network_pint__del__obj, network_pint__del__); + +static const mod_network_nic_protocol_t mod_network_nic_protocol_pint = { + .gethostbyname = network_pint_gethostbyname, + .deinit = network_pint_deinit, + .socket = network_pint_socket_socket, + .close = network_pint_socket_close, + .bind = network_pint_socket_bind, + .listen = network_pint_socket_listen, + .accept = network_pint_socket_accept, + .connect = network_pint_socket_connect, + .send = network_pint_socket_send, + .recv = network_pint_socket_recv, + .sendto = network_pint_socket_sendto, + .recvfrom = network_pint_socket_recvfrom, + .setsockopt = network_pint_socket_setsockopt, + .settimeout = network_pint_socket_settimeout, + .ioctl = network_pint_socket_ioctl, +}; + +static const mp_rom_map_elem_t pint_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&network_pint__del__obj) }, +}; + +static MP_DEFINE_CONST_DICT(pint_locals_dict, pint_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + mod_network_nic_type_pint, + MP_QSTR_pint, + MP_TYPE_FLAG_NONE, + make_new, network_pint_make_new, + locals_dict, &pint_locals_dict, + protocol, &mod_network_nic_protocol_pint +); + +#ifdef NETWORK_PINT_MODULE +static const mp_map_elem_t pint_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pint) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PINT), (mp_obj_t)&mod_network_nic_type_pint }, +}; + +static MP_DEFINE_CONST_DICT(mp_module_pint_globals, pint_globals_table); + +const mp_obj_module_t pint_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_pint_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_pint, pint_user_cmodule); +#endif \ No newline at end of file diff --git a/micropython/modules/pint/pint.cpp b/micropython/modules/pint/pint.cpp new file mode 100644 index 00000000..348efcdb --- /dev/null +++ b/micropython/modules/pint/pint.cpp @@ -0,0 +1,366 @@ +#include +#include +#include "micropython/modules/util.hpp" + +//#define debug_printf(...) mp_printf(&mp_plat_print, "PINT: " __VA_ARGS__) +#define debug_printf(...) (void)0 + +extern "C" { +#include "pint.h" +#include "py/runtime.h" +#include "py/builtin.h" +#include "py/mperrno.h" +#include "extmod/modnetwork.h" + +typedef struct _pint_obj_t { + mp_obj_base_t base; + mp_obj_t __del__[2]; + mp_obj_t gethostbyname[2]; + mp_obj_t socket_socket[2]; + mp_obj_t socket_close[2]; + mp_obj_t socket_bind[2]; + mp_obj_t socket_listen[2]; + mp_obj_t socket_accept[2]; + mp_obj_t socket_connect[2]; + mp_obj_t socket_send[2]; + mp_obj_t socket_recv[2]; + mp_obj_t socket_sendto[2]; + mp_obj_t socket_recvfrom[2]; + mp_obj_t socket_setsockopt[2]; + mp_obj_t socket_settimeout[2]; + mp_obj_t socket_ioctl[2]; +} pint_obj_t; + +void bind_method(mp_obj_t impl, qstr name, mp_obj_t *dest, bool required=true) { + if(required) { + mp_load_method(impl, name, dest); + } else { + mp_load_method_maybe(impl, name, dest); + if(dest[0] == MP_OBJ_NULL) debug_printf("missing %s\n", qstr_str(name)); + } +} + +mp_obj_t call_method(mp_obj_t *method, uint8_t count=0, ...) { + mp_obj_t kwargs[10]; + + kwargs[0] = method[0]; + kwargs[1] = method[1]; + + va_list args; + + va_start(args, count); + + for(auto i = 0u; i < count; i++) { + kwargs[i + 2] = va_arg(args, mp_obj_t); + } + + va_end(args); + + return mp_call_method_n_kw(count, 0, kwargs); +} + +mp_obj_t network_pint__del__(mp_obj_t nic_in) { + pint_obj_t *nic = (pint_obj_t *)MP_OBJ_TO_PTR(nic_in); + call_method(nic->__del__); + return mp_const_none; +} + +mp_obj_t network_pint_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + _pint_obj_t *nic = nullptr; + + enum { + ARG_impl + }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_impl, MP_ARG_OBJ}, + }; + + // Parse args. + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + nic = m_new_obj_with_finaliser(_pint_obj_t); + nic->base.type = &mod_network_nic_type_pint; + + mp_obj_t impl = args[ARG_impl].u_obj; + + // Grab each method, this stores the method pointer and self in an mp_obj_t[2] for dispatch + bind_method(impl, MP_QSTR___del__, nic->__del__); + bind_method(impl, MP_QSTR_gethostbyname, nic->gethostbyname); + bind_method(impl, MP_QSTR_socket_socket, nic->socket_socket); + bind_method(impl, MP_QSTR_socket_close, nic->socket_close); + bind_method(impl, MP_QSTR_socket_bind, nic->socket_bind); + bind_method(impl, MP_QSTR_socket_listen, nic->socket_listen); + bind_method(impl, MP_QSTR_socket_accept, nic->socket_accept); + bind_method(impl, MP_QSTR_socket_connect, nic->socket_connect); + bind_method(impl, MP_QSTR_socket_send, nic->socket_send); + bind_method(impl, MP_QSTR_socket_recv, nic->socket_recv); + bind_method(impl, MP_QSTR_socket_sendto, nic->socket_sendto); + bind_method(impl, MP_QSTR_socket_recvfrom, nic->socket_recvfrom); + bind_method(impl, MP_QSTR_socket_setsockopt, nic->socket_setsockopt); + bind_method(impl, MP_QSTR_socket_settimeout, nic->socket_settimeout); + bind_method(impl, MP_QSTR_socket_ioctl, nic->socket_ioctl); + + // Register with network module + mod_network_register_nic(MP_OBJ_FROM_PTR(nic)); + + return MP_OBJ_FROM_PTR(nic); +} + +int network_pint_gethostbyname(mp_obj_t nic_in, const char *name, mp_uint_t len, uint8_t *out_ip) { + debug_printf("gethostbyname(%s)\n", name); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(nic_in); + + mp_obj_t mp_name = mp_obj_new_str(name, len); + mp_obj_t result = call_method(nic->gethostbyname, 1, mp_name); + + if (result != mp_const_none) { + if(mp_obj_is_exact_type(result, &mp_type_tuple)) { + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR2(result, mp_obj_tuple_t); + out_ip[0] = mp_obj_get_int(tuple->items[0]); + out_ip[1] = mp_obj_get_int(tuple->items[1]); + out_ip[2] = mp_obj_get_int(tuple->items[2]); + out_ip[3] = mp_obj_get_int(tuple->items[3]); + return 0; + } + } + + return -1; +} + +void network_pint_deinit(void) { + // TODO: ???? +} + +int network_pint_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { + debug_printf("socket_socket(%d %d %d)\n", socket->domain, socket->type, socket->proto); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t result = call_method(nic->socket_socket); + if (result != mp_const_none) { + socket->_private = (void *)result; + *_errno = 0; + return 0; + } + + *_errno = MP_EINVAL; + return -1; +} + +void network_pint_socket_close(mod_network_socket_obj_t *socket) { + debug_printf("socket_close(%d)\n", socket->fileno); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + call_method(nic->socket_close, 1, (mp_obj_t)socket->_private); +}; + +mp_obj_t ip_to_tuple(byte *ip) { + mp_obj_t _ip_tuple[4]; + _ip_tuple[0] = mp_obj_new_int(ip[0]); + _ip_tuple[1] = mp_obj_new_int(ip[1]); + _ip_tuple[2] = mp_obj_new_int(ip[2]); + _ip_tuple[3] = mp_obj_new_int(ip[3]); + return mp_obj_new_tuple(4, _ip_tuple); +} + +int network_pint_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { + debug_printf("socket_bind(%d, %d)\n", socket->fileno, port); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _port = mp_obj_new_int(port); + mp_obj_t _ip = ip_to_tuple(ip); + + mp_obj_t result = call_method(nic->socket_bind, 3, (mp_obj_t)socket->_private, _ip, _port); + if (result == mp_const_true) { + *_errno = 0; + return 0; + } + + *_errno = MP_EINVAL; + return -1; +}; + +int network_pint_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) { + debug_printf("socket_listen(%d, %d)\n", socket->fileno, backlog); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _backlog = mp_obj_new_int(backlog); + + mp_obj_t result = call_method(nic->socket_listen, 3, (mp_obj_t)socket->_private, _backlog); + if (result == mp_const_true) { + *_errno = 0; + return 0; + } + + *_errno = MP_EINVAL; + return -1; +}; + +int network_pint_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) { + debug_printf("socket_accept(%d)\n", socket->fileno); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _port = mp_obj_new_int(*port); + mp_obj_t _ip = ip_to_tuple(ip); + + mp_obj_t result = call_method(nic->socket_accept, 3, (mp_obj_t)socket->_private, (mp_obj_t)socket2->_private, _ip, _port); + if (result == mp_const_true) { + *_errno = 0; + return 0; + } + + *_errno = MP_EINVAL; + return -1; +}; + +int network_pint_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { + debug_printf("socket_connect(%d)\n", socket->fileno); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _port = mp_obj_new_int(port); + mp_obj_t _ip = ip_to_tuple(ip); + + mp_obj_t result = call_method(nic->socket_connect, 3, (mp_obj_t)socket->_private, _ip, _port); + if (result == mp_const_true) { + *_errno = 0; + return 0; + } + + *_errno = MP_EINVAL; + return -1; +}; + +mp_uint_t network_pint_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { + debug_printf("socket_send(%d, -, %d)\n", socket->fileno, len); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _buf = mp_obj_new_bytearray(len, buf); + + mp_obj_t result = call_method(nic->socket_send, 2, (mp_obj_t)socket->_private, _buf); + if (result != mp_const_none) { + *_errno = 0; + return mp_obj_get_int(result); + } + + *_errno = MP_EINVAL; + return 0; +}; + +mp_uint_t network_pint_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { + debug_printf("socket_recv(%d, -, %d)\n", socket->fileno, len); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _buf = mp_obj_new_bytearray_by_ref(len, buf); + + mp_obj_t result = call_method(nic->socket_recv, 2, (mp_obj_t)socket->_private, _buf); + if (result != mp_const_none) { + *_errno = 0; + return mp_obj_get_int(result); + } + + *_errno = MP_EINVAL; + return 0; +}; + +mp_uint_t network_pint_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { + debug_printf("socket_sendto(%d)\n", socket->fileno); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _buf = mp_obj_new_bytearray(len, buf); + mp_obj_t _port = mp_obj_new_int(port); + mp_obj_t _ip = ip_to_tuple(ip); + + mp_obj_t result = call_method(nic->socket_sendto, 4, (mp_obj_t)socket->_private, _buf, _ip, _port); + if (result != mp_const_none) { + *_errno = 0; + return mp_obj_get_int(result); + } + + *_errno = MP_EINVAL; + return 0; +}; + +mp_uint_t network_pint_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { + debug_printf("socket_recvfrom(%d)\n", socket->fileno); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _buf = mp_obj_new_bytearray_by_ref(len, buf); + mp_obj_t _port = mp_obj_new_int(*port); + mp_obj_t _ip = ip_to_tuple(ip); + + mp_obj_t result = call_method(nic->socket_recvfrom, 4, (mp_obj_t)socket->_private, _buf, _ip, _port); + if (result != mp_const_none) { + *_errno = 0; + return mp_obj_get_int(result); + } + + *_errno = MP_EINVAL; + return 0; +}; + +int network_pint_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { + debug_printf("socket_setsockopt(%d, %d)\n", socket->fileno, opt); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _optval = mp_obj_new_bytearray(optlen, optval); + mp_obj_t _optkey = mp_obj_new_int(opt); + mp_obj_t _optlvl = mp_obj_new_int(level); + + mp_obj_t result = call_method(nic->socket_setsockopt, 4, (mp_obj_t)socket->_private, _optlvl, _optkey, _optval); + if (result == mp_const_true) { + *_errno = 0; + return 0; + } + + *_errno = MP_EINVAL; + return -1; +}; + +int network_pint_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) { + debug_printf("socket_settimeout(%d, %d)\n", socket->fileno, timeout_ms); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _timeout_ms = mp_obj_new_int(timeout_ms); + + mp_obj_t result = call_method(nic->socket_settimeout, 2, (mp_obj_t)socket->_private, _timeout_ms); + if (result == mp_const_true) { + *_errno = 0; + return 0; + } + + *_errno = MP_EINVAL; + return -1; +}; + +int network_pint_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { + debug_printf("socket_ioctl(%d, %d, %d)\n", socket->fileno, request, arg); + + _pint_obj_t *nic = (_pint_obj_t *)MP_OBJ_TO_PTR(socket->nic); + + mp_obj_t _request = mp_obj_new_int(request); + mp_obj_t _arg = mp_obj_new_int(arg); + + mp_obj_t result = call_method(nic->socket_ioctl, 3, (mp_obj_t)socket->_private, _request, _arg); + if (result == mp_const_true) { + *_errno = 0; + return 0; + } + *_errno = MP_EINVAL; + return -1; +}; + +} \ No newline at end of file diff --git a/micropython/modules/pint/pint.h b/micropython/modules/pint/pint.h new file mode 100644 index 00000000..a2c1029f --- /dev/null +++ b/micropython/modules/pint/pint.h @@ -0,0 +1,26 @@ +// Include MicroPython API. +#include "py/runtime.h" +#include "py/objstr.h" + +#include "extmod/modnetwork.h" + +extern const mp_obj_type_t mod_network_nic_type_pint; + +extern mp_obj_t network_pint_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +extern mp_obj_t network_pint__del__(mp_obj_t self_in); + +extern int network_pint_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip); +extern void network_pint_deinit(void); +extern int network_pint_socket_socket(mod_network_socket_obj_t *socket, int *_errno); +extern void network_pint_socket_close(mod_network_socket_obj_t *socket); +extern int network_pint_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); +extern int network_pint_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno); +extern int network_pint_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno); +extern int network_pint_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); +extern mp_uint_t network_pint_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno); +extern mp_uint_t network_pint_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno); +extern mp_uint_t network_pint_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); +extern mp_uint_t network_pint_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); +extern int network_pint_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); +extern int network_pint_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); +extern int network_pint_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno);