Experimental: PINT module bindings.

P.I.N.T

Python Implementation of Network Transports.
Phil Howard 2024-03-11 23:21:03 +00:00
rodzic 32c10482d9
commit 1687719212
12 zmienionych plików z 635 dodań i 0 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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"
}

Wyświetl plik

@ -0,0 +1,5 @@
include("$(PORT_DIR)/boards/manifest.py")
require("bundle-networking")
include("../manifest_pico.py")

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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
1 GP0 GPIO0
2 GP1 GPIO1
3 GP2 GPIO2
4 GP3 GPIO3
5 GP4 GPIO4
6 GP5 GPIO5
7 GP6 GPIO6
8 GP7 GPIO7
9 GP8 GPIO8
10 GP9 GPIO9
11 GP10 GPIO10
12 GP11 GPIO11
13 GP12 GPIO12
14 GP13 GPIO13
15 GP14 GPIO14
16 GP15 GPIO15
17 GP16 GPIO16
18 GP17 GPIO17
19 GP18 GPIO18
20 GP19 GPIO19
21 GP20 GPIO20
22 GP21 GPIO21
23 GP22 GPIO22
24 GP25 GPIO25
25 GP26 GPIO26
26 GP27 GPIO27
27 GP28 GPIO28
28 LED GPIO25

Wyświetl plik

@ -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)

Wyświetl plik

@ -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
```

Wyświetl plik

@ -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})

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,366 @@
#include <cstdio>
#include <stdarg.h>
#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;
};
}

Wyświetl plik

@ -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);