drivers/ninaw10: Update driver to support firmware 1.5.0.
* Firmware 1.5.0 introduces a new BSD-like sockets ABI, which improves the integration with MicroPython.
This commit is contained in:
parent
875caca504
commit
be83bdf9ec
|
@ -97,7 +97,7 @@ int nina_bsp_read_irq(void) {
|
|||
int nina_bsp_spi_slave_select(uint32_t timeout) {
|
||||
// Wait for ACK to go low.
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); mp_hal_pin_read(MICROPY_HW_NINA_ACK) == 1; mp_hal_delay_ms(1)) {
|
||||
if ((mp_hal_ticks_ms() - start) >= timeout) {
|
||||
if (timeout && ((mp_hal_ticks_ms() - start) >= timeout)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,8 +60,7 @@
|
|||
#define NINA_ARGS(...) (nina_args_t []) {__VA_ARGS__}
|
||||
#define NINA_VALS(...) (nina_vals_t []) {__VA_ARGS__}
|
||||
|
||||
#define NINA_SSELECT_TIMEOUT (10000)
|
||||
#define NINA_RESPONSE_TIMEOUT (1000)
|
||||
#define NINA_SSELECT_TIMEOUT (1000)
|
||||
#define NINA_CONNECT_TIMEOUT (10000)
|
||||
|
||||
#if NINA_DEBUG
|
||||
|
@ -130,18 +129,24 @@ typedef enum {
|
|||
NINA_CMD_GET_MAC_ADDR = 0x22,
|
||||
|
||||
// Sockets commands.
|
||||
NINA_CMD_SOCKET_OPEN = 0x3F,
|
||||
NINA_CMD_SOCKET_CLOSE = 0x2E,
|
||||
NINA_CMD_SOCKET_CONNECT = 0x2D,
|
||||
NINA_CMD_SOCKET_AVAIL = 0x2B,
|
||||
NINA_CMD_SOCKET_BIND = 0x28,
|
||||
NINA_CMD_SOCKET_STATE = 0x2F,
|
||||
NINA_CMD_SOCKET_REMOTE_ADDR = 0x3A,
|
||||
|
||||
// TCP commands
|
||||
NINA_CMD_TCP_SEND = 0x44,
|
||||
NINA_CMD_TCP_RECV = 0x45,
|
||||
NINA_CMD_TCP_ACK = 0x2A,
|
||||
NINA_CMD_SOCKET_SOCKET = 0x70,
|
||||
NINA_CMD_SOCKET_CLOSE = 0x71,
|
||||
NINA_CMD_SOCKET_ERRNO = 0x72,
|
||||
NINA_CMD_SOCKET_BIND = 0x73,
|
||||
NINA_CMD_SOCKET_LISTEN = 0x74,
|
||||
NINA_CMD_SOCKET_ACCEPT = 0x75,
|
||||
NINA_CMD_SOCKET_CONNECT = 0x76,
|
||||
NINA_CMD_SOCKET_SEND = 0x77,
|
||||
NINA_CMD_SOCKET_RECV = 0x78,
|
||||
NINA_CMD_SOCKET_SENDTO = 0x79,
|
||||
NINA_CMD_SOCKET_RECVFROM = 0x7A,
|
||||
NINA_CMD_SOCKET_IOCTL = 0x7B,
|
||||
NINA_CMD_SOCKET_POLL = 0x7C,
|
||||
NINA_CMD_SOCKET_SETSOCKOPT = 0x7D,
|
||||
NINA_CMD_SOCKET_GETSOCKOPT = 0x7E,
|
||||
NINA_CMD_SOCKET_GETPEERNAME = 0x7F,
|
||||
|
||||
// UDP commands.
|
||||
NINA_CMD_UDP_SEND = 0x46,
|
||||
|
@ -201,28 +206,15 @@ static uint8_t nina_bsp_spi_read_byte(void) {
|
|||
return byte;
|
||||
}
|
||||
|
||||
static int nina_wait_for_cmd(uint8_t cmd, uint32_t timeout) {
|
||||
uint8_t buf = 0;
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
|
||||
buf = nina_bsp_spi_read_byte();
|
||||
if (buf == CMD_ERROR || buf == cmd
|
||||
|| ((mp_hal_ticks_ms() - start) >= timeout)) {
|
||||
break;
|
||||
}
|
||||
mp_hal_delay_ms(1);
|
||||
}
|
||||
|
||||
return (buf == cmd) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int nina_send_command(uint32_t cmd, uint32_t nargs, uint32_t width, nina_args_t *args) {
|
||||
int ret = -1;
|
||||
uint32_t length = 4; // 3 bytes header + 1 end byte
|
||||
|
||||
debug_printf("nina_send_command (cmd 0x%x nargs %d width %d): ", cmd, nargs, width);
|
||||
|
||||
nina_bsp_spi_slave_deselect();
|
||||
if (nina_bsp_spi_slave_select(NINA_SSELECT_TIMEOUT) != 0) {
|
||||
return -1;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
// Send command header.
|
||||
|
@ -265,29 +257,31 @@ error_out:
|
|||
|
||||
static int nina_read_response(uint32_t cmd, uint32_t nvals, uint32_t width, nina_vals_t *vals) {
|
||||
int ret = -1;
|
||||
uint32_t length = 3; // 3 bytes response header
|
||||
uint8_t header[3] = {0, 0, 0};
|
||||
|
||||
debug_printf("nina_read_response(cmd 0x%x nvals %d width %d): ", cmd, nvals, width);
|
||||
|
||||
// Read reply
|
||||
if (nina_bsp_spi_slave_select(NINA_SSELECT_TIMEOUT) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Wait for CMD_START
|
||||
if (nina_wait_for_cmd(CMD_START, NINA_RESPONSE_TIMEOUT) != 0) {
|
||||
nina_bsp_spi_slave_deselect();
|
||||
if (nina_bsp_spi_slave_select(0) != 0) {
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
// Should return CMD + REPLY flag.
|
||||
if (nina_bsp_spi_read_byte() != (cmd | CMD_REPLY)) {
|
||||
if (nina_bsp_spi_transfer(NULL, header, sizeof(header)) != 0
|
||||
|| header[1] != (cmd | CMD_REPLY)) {
|
||||
// Read padding.
|
||||
uint8_t header_padding = nina_bsp_spi_read_byte();
|
||||
(void)header_padding;
|
||||
debug_printf("nina_read_response() hdr 0x%x 0x%x 0x%x 0x%x\n",
|
||||
header[0], header[1], header[2], header_padding);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
// Sanity check the number of returned values.
|
||||
// NOTE: This is to handle the special case for the scan command.
|
||||
uint32_t rvals = nina_bsp_spi_read_byte();
|
||||
if (nvals > rvals) {
|
||||
nvals = rvals;
|
||||
if (nvals > header[2]) {
|
||||
nvals = header[2];
|
||||
}
|
||||
|
||||
// Read return value(s).
|
||||
|
@ -310,9 +304,12 @@ static int nina_read_response(uint32_t cmd, uint32_t nvals, uint32_t width, nina
|
|||
|
||||
// Set the size.
|
||||
*(vals[i].size) = bytes;
|
||||
length += bytes + width;
|
||||
}
|
||||
|
||||
if (nina_bsp_spi_read_byte() != CMD_END) {
|
||||
// Read CMD_END and padding.
|
||||
uint8_t rspbuf_end[4];
|
||||
if (nina_bsp_spi_transfer(NULL, rspbuf_end, ((length + 1) % 4) + 1) != 0 || rspbuf_end[0] != CMD_END) {
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
@ -337,7 +334,6 @@ static int nina_send_command_read_ack(uint32_t cmd, uint32_t nargs, uint32_t wid
|
|||
|
||||
static int nina_send_command_read_vals(uint32_t cmd, uint32_t nargs,
|
||||
uint32_t argsw, nina_args_t *args, uint32_t nvals, uint32_t valsw, nina_vals_t *vals) {
|
||||
|
||||
if (nina_send_command(cmd, nargs, argsw, args) != 0 ||
|
||||
nina_read_response(cmd, nvals, valsw, vals) != 0) {
|
||||
return -1;
|
||||
|
@ -367,16 +363,6 @@ static int nina_connection_status() {
|
|||
return nina_send_command_read_ack(NINA_CMD_CONN_STATUS, 0, ARG_8BITS, NULL);
|
||||
}
|
||||
|
||||
static int nina_socket_status(uint8_t fd) {
|
||||
return nina_send_command_read_ack(NINA_CMD_SOCKET_STATE,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)));
|
||||
}
|
||||
|
||||
static int nina_server_socket_status(uint8_t fd) {
|
||||
return nina_send_command_read_ack(NINA_CMD_SOCKET_STATE & 0xF9,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)));
|
||||
}
|
||||
|
||||
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
|
||||
uint8_t status = NINA_STATUS_CONNECT_FAILED;
|
||||
|
||||
|
@ -476,10 +462,6 @@ int nina_connected_sta(uint32_t *sta_ip) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int nina_wait_for_sta(uint32_t *sta_ip, uint32_t timeout) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
|
||||
int nina_ifconfig(nina_ifconfig_t *ifconfig, bool set) {
|
||||
uint16_t ip_len = NINA_IPV4_ADDR_LEN;
|
||||
uint16_t sub_len = NINA_IPV4_ADDR_LEN;
|
||||
|
@ -724,257 +706,213 @@ int nina_ioctl(uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_socket(uint8_t type) {
|
||||
int nina_socket_socket(uint8_t type, uint8_t proto) {
|
||||
uint16_t size = 1;
|
||||
uint8_t sock = 0;
|
||||
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_OPEN,
|
||||
0, ARG_8BITS, NULL,
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_SOCKET,
|
||||
2, ARG_8BITS, NINA_ARGS(ARG_BYTE(type), ARG_BYTE(proto)),
|
||||
1, ARG_8BITS, NINA_VALS({&size, &sock})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return sock;
|
||||
return (sock == NO_SOCKET_AVAIL) ? -1 : sock;
|
||||
}
|
||||
|
||||
int nina_socket_close(int fd) {
|
||||
if (fd > 0 && fd < 255) {
|
||||
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CLOSE,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd))) != SPI_ACK) {
|
||||
return -1;
|
||||
}
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
|
||||
if (nina_socket_status(fd) == SOCKET_STATE_CLOSED) {
|
||||
break;
|
||||
}
|
||||
if ((mp_hal_ticks_ms() - start) >= 5000) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CLOSE,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd))) != SPI_ACK) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port, int type) {
|
||||
if (nina_send_command_read_ack(NINA_CMD_SOCKET_BIND,
|
||||
3, ARG_8BITS,
|
||||
NINA_ARGS(
|
||||
ARG_SHORT(__REVSH(port)),
|
||||
ARG_BYTE(fd),
|
||||
ARG_BYTE(type))) != SPI_ACK) {
|
||||
int nina_socket_errno(int *_errno) {
|
||||
uint16_t size = 1;
|
||||
*_errno = 0;
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_ERRNO,
|
||||
0, ARG_8BITS, NULL,
|
||||
1, ARG_8BITS, NINA_VALS({&size, _errno})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Only TCP sockets' states should be checked.
|
||||
if (type == NINA_SOCKET_TYPE_TCP &&
|
||||
nina_server_socket_status(fd) != SOCKET_STATE_LISTEN) {
|
||||
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port) {
|
||||
if (nina_send_command_read_ack(NINA_CMD_SOCKET_BIND,
|
||||
2, ARG_8BITS,
|
||||
NINA_ARGS(
|
||||
ARG_BYTE(fd),
|
||||
ARG_SHORT(__REVSH(port)))) != SPI_ACK) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_listen(int fd, uint32_t backlog) {
|
||||
return 0; // No listen ?
|
||||
}
|
||||
|
||||
int nina_socket_avail(int fd, int type, uint16_t *data) {
|
||||
uint16_t size = 2;
|
||||
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_AVAIL,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
|
||||
1, ARG_8BITS, NINA_VALS({&size, data})) != 0) {
|
||||
if (nina_send_command_read_ack(NINA_CMD_SOCKET_LISTEN,
|
||||
2, ARG_8BITS,
|
||||
NINA_ARGS(
|
||||
ARG_BYTE(fd),
|
||||
ARG_BYTE(backlog))) != SPI_ACK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// For TCP sockets in listen state, return 0 if there's no accepted socket.
|
||||
if (*data == NO_SOCKET_AVAIL && type == NINA_SOCKET_TYPE_TCP
|
||||
&& nina_server_socket_status(fd) == SOCKET_STATE_LISTEN) {
|
||||
*data = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out, int32_t timeout) {
|
||||
uint16_t sock = 0;
|
||||
|
||||
if (nina_server_socket_status(fd) != SOCKET_STATE_LISTEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
|
||||
if (nina_socket_avail(fd, NINA_SOCKET_TYPE_TCP, &sock) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (sock != 0) {
|
||||
break;
|
||||
}
|
||||
if (timeout == 0 || (timeout > 0 && (mp_hal_ticks_ms() - start) >= timeout)) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out) {
|
||||
uint16_t fd_len = 1;
|
||||
uint16_t port_len = 2;
|
||||
uint16_t ip_len = NINA_IPV4_ADDR_LEN;
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_REMOTE_ADDR,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(sock)),
|
||||
2, ARG_8BITS, NINA_VALS({&ip_len, ip}, {&port_len, port})) != 0) {
|
||||
*fd_out = 0;
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_ACCEPT,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
|
||||
3, ARG_8BITS, NINA_VALS({&fd_len, fd_out}, {&ip_len, ip}, {&port_len, port})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
*fd_out = sock;
|
||||
*port = __REVSH(*port);
|
||||
return 0;
|
||||
return (*fd_out == NO_SOCKET_AVAIL) ? -1 : 0;
|
||||
}
|
||||
|
||||
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port, int32_t timeout) {
|
||||
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port) {
|
||||
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CONNECT,
|
||||
4, ARG_8BITS,
|
||||
3, ARG_8BITS,
|
||||
NINA_ARGS(
|
||||
ARG_WORD((*(uint32_t *)ip)),
|
||||
ARG_SHORT(__REVSH(port)),
|
||||
ARG_BYTE(fd),
|
||||
ARG_BYTE(NINA_SOCKET_TYPE_TCP))) != SPI_ACK) {
|
||||
ARG_WORD((*(uint32_t *)ip)),
|
||||
ARG_SHORT(__REVSH(port)))) != SPI_ACK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
|
||||
int state = nina_socket_status(fd);
|
||||
if (state == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (state == SOCKET_STATE_ESTABLISHED) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout == 0 || (timeout > 0 && (mp_hal_ticks_ms() - start) >= timeout)) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len, int32_t timeout) {
|
||||
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len) {
|
||||
uint16_t size = 2;
|
||||
uint16_t bytes = 0;
|
||||
|
||||
if (nina_socket_status(fd) != SOCKET_STATE_ESTABLISHED) {
|
||||
return -MP_ENOTCONN;
|
||||
}
|
||||
|
||||
if (nina_send_command_read_vals(NINA_CMD_TCP_SEND,
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_SEND,
|
||||
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), {len, buf}),
|
||||
1, ARG_8BITS, NINA_VALS({&size, &bytes})) != 0 || bytes <= 0) {
|
||||
1, ARG_8BITS, NINA_VALS({&size, &bytes})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
|
||||
int resp = nina_send_command_read_ack(NINA_CMD_TCP_ACK,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)));
|
||||
// Only args sizes (not args themselves) are reversed in read_response().
|
||||
bytes = __REVSH(bytes);
|
||||
|
||||
if (resp == -1) {
|
||||
if (bytes == 0) {
|
||||
int _errno = 0;
|
||||
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (resp == SPI_ACK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout == 0 || (timeout > 0 && (mp_hal_ticks_ms() - start) >= timeout)) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
mp_hal_delay_ms(1);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len, int32_t timeout) {
|
||||
uint16_t bytes = 0;
|
||||
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len) {
|
||||
uint16_t bytes = len;
|
||||
|
||||
if (nina_socket_status(fd) != SOCKET_STATE_ESTABLISHED) {
|
||||
return -MP_ENOTCONN;
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_RECV,
|
||||
2, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd), ARG_SHORT(bytes)),
|
||||
1, ARG_16BITS, NINA_VALS({&bytes, buf})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); bytes == 0; mp_hal_delay_ms(1)) {
|
||||
bytes = len;
|
||||
if (nina_send_command_read_vals(NINA_CMD_TCP_RECV,
|
||||
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), ARG_SHORT(bytes)),
|
||||
1, ARG_16BITS, NINA_VALS({&bytes, buf})) != 0) {
|
||||
if (bytes == 0) {
|
||||
int _errno = 0;
|
||||
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bytes != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout == 0 || (timeout > 0 && (mp_hal_ticks_ms() - start) >= timeout)) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// Check from the upper layer if the socket is bound, if not then auto-bind it first.
|
||||
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port, int32_t timeout) {
|
||||
// TODO do we need to split the packet somewhere?
|
||||
if (nina_send_command_read_ack(NINA_CMD_SOCKET_CONNECT,
|
||||
4, ARG_8BITS,
|
||||
NINA_ARGS(
|
||||
ARG_WORD((*(uint32_t *)ip)),
|
||||
ARG_SHORT(__REVSH(port)),
|
||||
ARG_BYTE(fd),
|
||||
ARG_BYTE(NINA_SOCKET_TYPE_UDP))) != SPI_ACK) {
|
||||
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port) {
|
||||
uint16_t size = 2;
|
||||
uint16_t bytes = 0;
|
||||
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_SENDTO,
|
||||
4, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), ARG_WORD((*(uint32_t *)ip)), ARG_SHORT(__REVSH(port)), {len, buf}),
|
||||
1, ARG_8BITS, NINA_VALS({&size, &bytes})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Buffer length and socket number are passed as 16bits.
|
||||
if (nina_send_command_read_ack(NINA_CMD_UDP_SEND,
|
||||
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), {len, buf})) != SPI_ACK) {
|
||||
return -1;
|
||||
// Only args sizes (not args themselves) are reversed in read_response().
|
||||
bytes = __REVSH(bytes);
|
||||
|
||||
if (bytes == 0) {
|
||||
int _errno = 0;
|
||||
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nina_send_command_read_ack(NINA_CMD_UDP_ACK,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd))) != SPI_ACK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// Check from the upper layer if the socket is bound, if not then auto-bind it first.
|
||||
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port, int32_t timeout) {
|
||||
uint16_t bytes = 0;
|
||||
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port) {
|
||||
uint16_t bytes = len;
|
||||
uint16_t port_len = 2;
|
||||
uint16_t ip_len = NINA_IPV4_ADDR_LEN;
|
||||
|
||||
for (mp_uint_t start = mp_hal_ticks_ms(); bytes == 0; mp_hal_delay_ms(1)) {
|
||||
bytes = len;
|
||||
if (nina_send_command_read_vals(NINA_CMD_UDP_RECV,
|
||||
2, ARG_16BITS, NINA_ARGS(ARG_BYTE(fd), ARG_SHORT(bytes)),
|
||||
1, ARG_16BITS, NINA_VALS({&bytes, buf})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bytes != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout == 0 || (timeout > 0 && (mp_hal_ticks_ms() - start) >= timeout)) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_REMOTE_ADDR,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
|
||||
2, ARG_8BITS, NINA_VALS({&ip_len, ip}, {&port_len, port})) != 0) {
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_RECVFROM,
|
||||
2, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd), ARG_SHORT(bytes)),
|
||||
3, ARG_16BITS, NINA_VALS({&ip_len, ip}, {&port_len, port}, {&bytes, buf})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bytes == 0) {
|
||||
int _errno = 0;
|
||||
if (nina_socket_errno(&_errno) != 0 || _errno != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint32_t optlen) {
|
||||
return -1;
|
||||
int nina_socket_ioctl(int fd, uint32_t cmd, void *argval, uint32_t arglen) {
|
||||
uint16_t len = arglen;
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_IOCTL,
|
||||
3, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd), ARG_WORD(cmd), {len, argval}),
|
||||
1, ARG_8BITS, NINA_VALS({&len, argval})) != 0 || arglen == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_poll(int fd, uint8_t *flags) {
|
||||
uint16_t flags_len = 1;
|
||||
if (nina_send_command_read_vals(NINA_CMD_SOCKET_POLL,
|
||||
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
|
||||
1, ARG_8BITS, NINA_VALS({&flags_len, flags})) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (*flags & 0x80) {
|
||||
// lwip_select() failed.
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t optname, const void *optval, uint16_t optlen) {
|
||||
if (nina_send_command_read_ack(
|
||||
NINA_CMD_SOCKET_SETSOCKOPT,
|
||||
3, ARG_8BITS,
|
||||
NINA_ARGS(ARG_BYTE(fd), ARG_WORD(optname), {optlen, optval})) != SPI_ACK) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nina_socket_getsockopt(int fd, uint32_t level, uint32_t optname, void *optval, uint16_t optlen) {
|
||||
if (nina_send_command_read_vals(
|
||||
NINA_CMD_SOCKET_GETSOCKOPT,
|
||||
3, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd), ARG_WORD(optname), ARG_BYTE(optlen)),
|
||||
1, ARG_8BITS, NINA_VALS({&optlen, optval})) != 0 || optlen == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_NINAW10
|
||||
|
|
|
@ -38,9 +38,9 @@
|
|||
#define NINA_MAX_NETWORK_LIST (10)
|
||||
#define NINA_MAX_SOCKET (10)
|
||||
|
||||
#define NINA_FW_VER_MAJOR (1)
|
||||
#define NINA_FW_VER_MINOR (4)
|
||||
#define NINA_FW_VER_PATCH (8)
|
||||
#define NINA_FW_VER_MIN_MAJOR (1)
|
||||
#define NINA_FW_VER_MIN_MINOR (5)
|
||||
#define NINA_FW_VER_MIN_PATCH (0)
|
||||
|
||||
#define NINA_FW_VER_MAJOR_OFFS (0)
|
||||
#define NINA_FW_VER_MINOR_OFFS (2)
|
||||
|
@ -54,11 +54,9 @@ typedef enum {
|
|||
} nina_security_t;
|
||||
|
||||
typedef enum {
|
||||
NINA_SOCKET_TYPE_TCP = 0,
|
||||
NINA_SOCKET_TYPE_UDP,
|
||||
NINA_SOCKET_TYPE_TLS,
|
||||
NINA_SOCKET_TYPE_UDP_MULTICAST,
|
||||
NINA_SOCKET_TYPE_TLS_BEARSSL
|
||||
NINA_SOCKET_TYPE_TCP = 1,
|
||||
NINA_SOCKET_TYPE_UDP = 2,
|
||||
NINA_SOCKET_TYPE_RAW = 3,
|
||||
} nina_socket_type_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -92,7 +90,6 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
|
|||
int nina_disconnect(void);
|
||||
int nina_isconnected(void);
|
||||
int nina_connected_sta(uint32_t *sta_ip);
|
||||
int nina_wait_for_sta(uint32_t *sta_ip, uint32_t timeout);
|
||||
int nina_ifconfig(nina_ifconfig_t *ifconfig, bool set);
|
||||
int nina_netinfo(nina_netinfo_t *netinfo);
|
||||
int nina_scan(nina_scan_callback_t scan_callback, void *arg, uint32_t timeout);
|
||||
|
@ -101,17 +98,20 @@ int nina_fw_version(uint8_t *fw_ver);
|
|||
int nina_set_hostname(const char *name);
|
||||
int nina_gethostbyname(const char *name, uint8_t *out_ip);
|
||||
int nina_ioctl(uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface);
|
||||
int nina_socket_socket(uint8_t type);
|
||||
int nina_socket_socket(uint8_t type, uint8_t proto);
|
||||
int nina_socket_close(int fd);
|
||||
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port, int type);
|
||||
int nina_socket_errno(int *_errno);
|
||||
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port);
|
||||
int nina_socket_listen(int fd, uint32_t backlog);
|
||||
int nina_socket_avail(int fd, int type, uint16_t *data);
|
||||
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out, int32_t timeout);
|
||||
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port, int32_t timeout);
|
||||
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len, int32_t timeout);
|
||||
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len, int32_t timeout);
|
||||
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port, int32_t timeout);
|
||||
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port, int32_t timeout);
|
||||
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint32_t optlen);
|
||||
|
||||
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out);
|
||||
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port);
|
||||
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len);
|
||||
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len);
|
||||
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port);
|
||||
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port);
|
||||
int nina_socket_ioctl(int fd, uint32_t cmd, void *argval, uint32_t arglen);
|
||||
int nina_socket_poll(int fd, uint8_t *flags);
|
||||
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint16_t optlen);
|
||||
int nina_socket_getsockopt(int fd, uint32_t level, uint32_t opt, void *optval, uint16_t optlen);
|
||||
int nina_socket_getpeername(int fd, uint8_t *ip, uint16_t *port);
|
||||
#endif // MICROPY_INCLUDED_DRIVERS_NINAW10_NINA_WIFI_DRV_H
|
||||
|
|
|
@ -53,8 +53,24 @@ typedef struct _nina_obj_t {
|
|||
} nina_obj_t;
|
||||
|
||||
// For auto-binding UDP sockets
|
||||
#define BIND_PORT_RANGE_MIN (65000)
|
||||
#define BIND_PORT_RANGE_MAX (65535)
|
||||
#define BIND_PORT_RANGE_MIN (65000)
|
||||
#define BIND_PORT_RANGE_MAX (65535)
|
||||
|
||||
#define SOCKET_IOCTL_FIONREAD (0x4004667F)
|
||||
#define SOCKET_IOCTL_FIONBIO (0x8004667E)
|
||||
|
||||
#define SOCKET_POLL_RD (0x01)
|
||||
#define SOCKET_POLL_WR (0x02)
|
||||
#define SOCKET_POLL_ERR (0x04)
|
||||
|
||||
#define SO_ACCEPTCONN (0x0002)
|
||||
#define SO_ERROR (0x1007)
|
||||
#define SO_TYPE (0x1008)
|
||||
#define SO_NO_CHECK (0x100a)
|
||||
|
||||
#define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS)
|
||||
|
||||
#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
|
||||
|
||||
static uint16_t bind_port = BIND_PORT_RANGE_MIN;
|
||||
const mod_network_nic_type_t mod_network_nic_type_nina;
|
||||
|
@ -85,22 +101,26 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
|
|||
MP_ERROR_TEXT("Failed to initialize Nina-W10 module, error: %d\n"), error);
|
||||
}
|
||||
// check firmware version
|
||||
uint8_t fw_ver[NINA_FW_VER_LEN];
|
||||
if (nina_fw_version(fw_ver) != 0) {
|
||||
uint8_t semver[NINA_FW_VER_LEN];
|
||||
if (nina_fw_version(semver) != 0) {
|
||||
nina_deinit();
|
||||
mp_raise_msg_varg(&mp_type_OSError,
|
||||
MP_ERROR_TEXT("Failed to read firmware version, error: %d\n"), error);
|
||||
}
|
||||
// Check fw version matches the driver.
|
||||
if ((fw_ver[NINA_FW_VER_MAJOR_OFFS] - 48) != NINA_FW_VER_MAJOR ||
|
||||
(fw_ver[NINA_FW_VER_MINOR_OFFS] - 48) != NINA_FW_VER_MINOR ||
|
||||
(fw_ver[NINA_FW_VER_PATCH_OFFS] - 48) != NINA_FW_VER_PATCH) {
|
||||
mp_printf(&mp_plat_print,
|
||||
"Warning: firmware version mismatch, expected %d.%d.%d found: %d.%d.%d\n",
|
||||
NINA_FW_VER_MAJOR, NINA_FW_VER_MINOR, NINA_FW_VER_PATCH,
|
||||
fw_ver[NINA_FW_VER_MAJOR_OFFS] - 48,
|
||||
fw_ver[NINA_FW_VER_MINOR_OFFS] - 48,
|
||||
fw_ver[NINA_FW_VER_PATCH_OFFS] - 48);
|
||||
// Check the minimum supported firmware version.
|
||||
uint32_t fwmin = (NINA_FW_VER_MIN_MAJOR * 100) +
|
||||
(NINA_FW_VER_MIN_MINOR * 10) +
|
||||
(NINA_FW_VER_MIN_PATCH * 1);
|
||||
|
||||
uint32_t fwver = (semver[NINA_FW_VER_MAJOR_OFFS] - 48) * 100 +
|
||||
(semver[NINA_FW_VER_MINOR_OFFS] - 48) * 10 +
|
||||
(semver[NINA_FW_VER_PATCH_OFFS] - 48) * 1;
|
||||
|
||||
if (fwver < fwmin) {
|
||||
mp_raise_msg_varg(&mp_type_OSError,
|
||||
MP_ERROR_TEXT("Firmware version mismatch. Minimum supported firmware is v%d.%d.%d found v%d.%d.%d\n"),
|
||||
NINA_FW_VER_MIN_MAJOR, NINA_FW_VER_MIN_MINOR, NINA_FW_VER_MIN_PATCH, semver[NINA_FW_VER_MAJOR_OFFS] - 48,
|
||||
semver[NINA_FW_VER_MINOR_OFFS] - 48, semver[NINA_FW_VER_PATCH_OFFS] - 48);
|
||||
}
|
||||
} else {
|
||||
nina_deinit();
|
||||
|
@ -318,6 +338,7 @@ STATIC mp_obj_t network_ninaw10_status(size_t n_args, const mp_obj_t *args) {
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_ninaw10_status_obj, 1, 2, network_ninaw10_status);
|
||||
|
||||
STATIC mp_obj_t network_ninaw10_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t buf_in) {
|
||||
debug_printf("ioctl(%d)\n", mp_obj_get_int(cmd_in));
|
||||
nina_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t buf;
|
||||
mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ | MP_BUFFER_WRITE);
|
||||
|
@ -327,45 +348,79 @@ STATIC mp_obj_t network_ninaw10_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(network_ninaw10_ioctl_obj, network_ninaw10_ioctl);
|
||||
|
||||
STATIC int network_ninaw10_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
|
||||
debug_printf("gethostbyname(%s)\n", name);
|
||||
return nina_gethostbyname(name, out_ip);
|
||||
}
|
||||
|
||||
STATIC int network_ninaw10_socket_poll(mod_network_socket_obj_t *socket, uint32_t rwf, int *_errno) {
|
||||
uint8_t flags = 0;
|
||||
debug_printf("socket_polling_rw(%d, %d)\n", socket->fileno, rwf);
|
||||
if (socket->timeout == 0) {
|
||||
// Non-blocking socket, next socket function will return EAGAIN
|
||||
return 0;
|
||||
}
|
||||
mp_uint_t start = mp_hal_ticks_ms();
|
||||
while (!(flags & rwf)) {
|
||||
if (nina_socket_poll(socket->fileno, &flags) < 0 || (flags & SOCKET_POLL_ERR)) {
|
||||
nina_socket_errno(_errno);
|
||||
debug_printf("socket_poll() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
if (!(flags & rwf) && socket->timeout != -1 &&
|
||||
mp_hal_ticks_ms() - start > socket->timeout) {
|
||||
*_errno = MP_ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int network_ninaw10_socket_setblocking(mod_network_socket_obj_t *socket, bool blocking, int *_errno) {
|
||||
uint32_t nonblocking = !blocking;
|
||||
// set socket in non-blocking mode
|
||||
if (nina_socket_ioctl(socket->fileno, SOCKET_IOCTL_FIONBIO, &nonblocking, sizeof(nonblocking)) < 0) {
|
||||
nina_socket_errno(_errno);
|
||||
nina_socket_close(socket->fileno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int network_ninaw10_socket_listening(mod_network_socket_obj_t *socket, int *_errno) {
|
||||
int listening = 0;
|
||||
if (nina_socket_getsockopt(socket->fileno, MOD_NETWORK_SOL_SOCKET,
|
||||
SO_ACCEPTCONN, &listening, sizeof(listening)) < 0) {
|
||||
nina_socket_errno(_errno);
|
||||
debug_printf("socket_getsockopt() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
return listening;
|
||||
}
|
||||
|
||||
STATIC int network_ninaw10_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
|
||||
uint8_t type;
|
||||
debug_printf("socket_socket(%d %d %d)\n", socket->domain, socket->type, socket->proto);
|
||||
|
||||
if (socket->domain != MOD_NETWORK_AF_INET) {
|
||||
*_errno = MP_EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (socket->type) {
|
||||
case MOD_NETWORK_SOCK_STREAM:
|
||||
type = NINA_SOCKET_TYPE_TCP;
|
||||
break;
|
||||
|
||||
case MOD_NETWORK_SOCK_DGRAM:
|
||||
type = NINA_SOCKET_TYPE_UDP;
|
||||
break;
|
||||
|
||||
default:
|
||||
*_errno = MP_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// open socket
|
||||
int fd = nina_socket_socket(type);
|
||||
int fd = nina_socket_socket(socket->type, socket->proto);
|
||||
if (fd < 0) {
|
||||
*_errno = fd;
|
||||
nina_socket_errno(_errno);
|
||||
debug_printf("socket_socket() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set socket state
|
||||
socket->fileno = fd;
|
||||
socket->bound = false;
|
||||
return 0;
|
||||
return network_ninaw10_socket_setblocking(socket, false, _errno);
|
||||
}
|
||||
|
||||
STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
|
||||
debug_printf("socket_close(%d)\n", socket->fileno);
|
||||
if (socket->fileno >= 0) {
|
||||
nina_socket_close(socket->fileno);
|
||||
socket->fileno = -1; // Mark socket FD as invalid
|
||||
|
@ -373,6 +428,7 @@ STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
|
|||
}
|
||||
|
||||
STATIC int network_ninaw10_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);
|
||||
uint8_t type;
|
||||
switch (socket->type) {
|
||||
case MOD_NETWORK_SOCK_STREAM:
|
||||
|
@ -388,10 +444,11 @@ STATIC int network_ninaw10_socket_bind(mod_network_socket_obj_t *socket, byte *i
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ret = nina_socket_bind(socket->fileno, ip, port, type);
|
||||
int ret = nina_socket_bind(socket->fileno, ip, port);
|
||||
if (ret < 0) {
|
||||
*_errno = ret;
|
||||
nina_socket_errno(_errno);
|
||||
network_ninaw10_socket_close(socket);
|
||||
debug_printf("socket_bind(%d, %d) -> errno: %d\n", socket->fileno, port, *_errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -401,10 +458,12 @@ STATIC int network_ninaw10_socket_bind(mod_network_socket_obj_t *socket, byte *i
|
|||
}
|
||||
|
||||
STATIC int network_ninaw10_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) {
|
||||
debug_printf("socket_listen(%d, %d)\n", socket->fileno, backlog);
|
||||
int ret = nina_socket_listen(socket->fileno, backlog);
|
||||
if (ret < 0) {
|
||||
*_errno = ret;
|
||||
nina_socket_errno(_errno);
|
||||
network_ninaw10_socket_close(socket);
|
||||
debug_printf("socket_listen() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -412,73 +471,109 @@ STATIC int network_ninaw10_socket_listen(mod_network_socket_obj_t *socket, mp_in
|
|||
|
||||
STATIC int network_ninaw10_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);
|
||||
|
||||
if (network_ninaw10_socket_poll(socket, SOCKET_POLL_RD, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*port = 0;
|
||||
int fd = 0;
|
||||
// Call accept.
|
||||
int ret = nina_socket_accept(socket->fileno, ip, (uint16_t *)port, &fd, socket->timeout);
|
||||
int ret = nina_socket_accept(socket->fileno, ip, (uint16_t *)port, &fd);
|
||||
if (ret < 0) {
|
||||
*_errno = -ret;
|
||||
// Close socket if not a timeout error.
|
||||
if (*_errno != MP_ETIMEDOUT) {
|
||||
nina_socket_errno(_errno);
|
||||
// Close socket if not a nonblocking error.
|
||||
if (!is_nonblocking_error(*_errno)) {
|
||||
network_ninaw10_socket_close(socket);
|
||||
}
|
||||
debug_printf("socket_accept() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set socket state
|
||||
socket2->fileno = fd;
|
||||
socket2->bound = false;
|
||||
return 0;
|
||||
return network_ninaw10_socket_setblocking(socket2, false, _errno);
|
||||
}
|
||||
|
||||
STATIC int network_ninaw10_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
|
||||
int ret = nina_socket_connect(socket->fileno, ip, port, socket->timeout);
|
||||
debug_printf("socket_connect(%d)\n", socket->fileno);
|
||||
|
||||
int ret = nina_socket_connect(socket->fileno, ip, port);
|
||||
if (ret < 0) {
|
||||
*_errno = -ret;
|
||||
// Close socket if not a timeout error.
|
||||
if (*_errno != MP_ETIMEDOUT) {
|
||||
nina_socket_errno(_errno);
|
||||
debug_printf("socket_connect() -> errno %d\n", *_errno);
|
||||
|
||||
// Close socket if not a nonblocking error.
|
||||
if (!is_nonblocking_error(*_errno)) {
|
||||
network_ninaw10_socket_close(socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Poll for write.
|
||||
if (socket->timeout == 0 ||
|
||||
network_ninaw10_socket_poll(socket, SOCKET_POLL_WR, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t network_ninaw10_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
|
||||
int ret = nina_socket_send(socket->fileno, buf, len, socket->timeout);
|
||||
debug_printf("socket_send(%d, %d)\n", socket->fileno, len);
|
||||
|
||||
if (network_ninaw10_socket_poll(socket, SOCKET_POLL_WR, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = nina_socket_send(socket->fileno, buf, len);
|
||||
if (ret < 0) {
|
||||
*_errno = -ret;
|
||||
// Close socket if not a timeout error.
|
||||
if (*_errno != MP_ETIMEDOUT) {
|
||||
nina_socket_errno(_errno);
|
||||
// Close socket if not a nonblocking error.
|
||||
if (!is_nonblocking_error(*_errno)) {
|
||||
network_ninaw10_socket_close(socket);
|
||||
}
|
||||
debug_printf("socket_send() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t network_ninaw10_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
|
||||
int ret = 0;
|
||||
if (socket->type == MOD_NETWORK_SOCK_DGRAM) {
|
||||
byte ip[4];
|
||||
uint16_t port;
|
||||
ret = nina_socket_recvfrom(socket->fileno, buf, len, ip, &port, socket->timeout);
|
||||
} else {
|
||||
ret = nina_socket_recv(socket->fileno, buf, len, socket->timeout);
|
||||
debug_printf("socket_recv(%d)\n", socket->fileno);
|
||||
// check if socket in listening state.
|
||||
if (network_ninaw10_socket_listening(socket, _errno) == 1) {
|
||||
*_errno = MP_ENOTCONN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (network_ninaw10_socket_poll(socket, SOCKET_POLL_RD, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = nina_socket_recv(socket->fileno, buf, len);
|
||||
if (ret < 0) {
|
||||
*_errno = -ret;
|
||||
// Close socket if not a timeout error.
|
||||
if (*_errno != MP_ETIMEDOUT) {
|
||||
nina_socket_errno(_errno);
|
||||
if (*_errno == MP_ENOTCONN) {
|
||||
*_errno = 0;
|
||||
return 0;
|
||||
}
|
||||
// Close socket if not a nonblocking error.
|
||||
if (!is_nonblocking_error(*_errno)) {
|
||||
network_ninaw10_socket_close(socket);
|
||||
}
|
||||
debug_printf("socket_recv() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t network_ninaw10_socket_auto_bind(mod_network_socket_obj_t *socket, int *_errno) {
|
||||
if (socket->bound == false) {
|
||||
debug_printf("socket_autobind(%d)\n", socket->fileno);
|
||||
if (socket->bound == false && socket->type != MOD_NETWORK_SOCK_RAW) {
|
||||
if (network_ninaw10_socket_bind(socket, NULL, bind_port, _errno) != 0) {
|
||||
nina_socket_errno(_errno);
|
||||
debug_printf("socket_bind() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
bind_port++;
|
||||
|
@ -489,16 +584,21 @@ STATIC mp_uint_t network_ninaw10_socket_auto_bind(mod_network_socket_obj_t *sock
|
|||
|
||||
STATIC mp_uint_t network_ninaw10_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);
|
||||
// Auto-bind the socket first if the socket is unbound.
|
||||
if (network_ninaw10_socket_auto_bind(socket, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = nina_socket_sendto(socket->fileno, buf, len, ip, port, socket->timeout);
|
||||
if (network_ninaw10_socket_poll(socket, SOCKET_POLL_WR, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = nina_socket_sendto(socket->fileno, buf, len, ip, port);
|
||||
if (ret < 0) {
|
||||
*_errno = -ret;
|
||||
// Close socket if not a timeout error.
|
||||
if (*_errno != MP_ETIMEDOUT) {
|
||||
nina_socket_errno(_errno);
|
||||
// Close socket if not a nonblocking error.
|
||||
if (!is_nonblocking_error(*_errno)) {
|
||||
network_ninaw10_socket_close(socket);
|
||||
}
|
||||
return -1;
|
||||
|
@ -508,24 +608,25 @@ STATIC mp_uint_t network_ninaw10_socket_sendto(mod_network_socket_obj_t *socket,
|
|||
|
||||
STATIC mp_uint_t network_ninaw10_socket_recvfrom(mod_network_socket_obj_t *socket,
|
||||
byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
||||
int ret = 0;
|
||||
if (socket->type == MOD_NETWORK_SOCK_STREAM) {
|
||||
*port = 0;
|
||||
*((uint32_t *)ip) = 0;
|
||||
ret = nina_socket_recv(socket->fileno, buf, len, socket->timeout);
|
||||
} else {
|
||||
// Auto-bind the socket first if the socket is unbound.
|
||||
if (network_ninaw10_socket_auto_bind(socket, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = nina_socket_recvfrom(socket->fileno, buf, len, ip, (uint16_t *)port, socket->timeout);
|
||||
debug_printf("socket_recvfrom(%d)\n", socket->fileno);
|
||||
// Auto-bind the socket first if the socket is unbound.
|
||||
if (network_ninaw10_socket_auto_bind(socket, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (network_ninaw10_socket_poll(socket, SOCKET_POLL_RD, _errno) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*port = 0;
|
||||
int ret = nina_socket_recvfrom(socket->fileno, buf, len, ip, (uint16_t *)port);
|
||||
if (ret < 0) {
|
||||
*_errno = -ret;
|
||||
// Close socket if not a timeout error.
|
||||
if (*_errno != MP_ETIMEDOUT) {
|
||||
nina_socket_errno(_errno);
|
||||
// Close socket if not a nonblocking error.
|
||||
if (!is_nonblocking_error(*_errno)) {
|
||||
network_ninaw10_socket_close(socket);
|
||||
}
|
||||
debug_printf("socket_recvfrom() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
|
@ -533,53 +634,60 @@ STATIC mp_uint_t network_ninaw10_socket_recvfrom(mod_network_socket_obj_t *socke
|
|||
|
||||
STATIC int network_ninaw10_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);
|
||||
int ret = nina_socket_setsockopt(socket->fileno, level, opt, optval, optlen);
|
||||
if (ret < 0) {
|
||||
*_errno = ret;
|
||||
nina_socket_errno(_errno);
|
||||
network_ninaw10_socket_close(socket);
|
||||
debug_printf("socket_setsockopt() -> errno %d\n", *_errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int network_ninaw10_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);
|
||||
#if 0
|
||||
if (timeout_ms == 0 || timeout_ms == UINT32_MAX) {
|
||||
// blocking/nonblocking mode
|
||||
uint32_t nonblocking = (timeout_ms == 0);
|
||||
ret |= nina_socket_ioctl(socket->fileno, SOCKET_IOCTL_FIONBIO, &nonblocking, sizeof(nonblocking));
|
||||
} else {
|
||||
// timeout provided
|
||||
uint32_t tv[2] = {
|
||||
(timeout_ms / 1000),
|
||||
(timeout_ms % 1000) * 1000,
|
||||
};
|
||||
ret |= nina_socket_setsockopt(socket->fileno, MOD_NETWORK_SOL_SOCKET, MOD_NETWORK_SO_SNDTIMEO, tv, sizeof(tv));
|
||||
ret |= nina_socket_setsockopt(socket->fileno, MOD_NETWORK_SOL_SOCKET, MOD_NETWORK_SO_RCVTIMEO, tv, sizeof(tv));
|
||||
}
|
||||
if (ret < 0) {
|
||||
nina_socket_errno(_errno);
|
||||
debug_printf("socket_settimeout() -> errno %d\n", *_errno);
|
||||
}
|
||||
#endif
|
||||
socket->timeout = timeout_ms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int network_ninaw10_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
|
||||
mp_uint_t ret = 0;
|
||||
uint8_t type;
|
||||
|
||||
switch (socket->type) {
|
||||
case MOD_NETWORK_SOCK_STREAM:
|
||||
type = NINA_SOCKET_TYPE_TCP;
|
||||
break;
|
||||
|
||||
case MOD_NETWORK_SOCK_DGRAM:
|
||||
type = NINA_SOCKET_TYPE_UDP;
|
||||
break;
|
||||
|
||||
default:
|
||||
*_errno = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
debug_printf("socket_ioctl(%d, %d)\n", socket->fileno, request);
|
||||
if (request == MP_STREAM_POLL) {
|
||||
if (arg & MP_STREAM_POLL_RD) {
|
||||
uint16_t avail = 0;
|
||||
if (nina_socket_avail(socket->fileno, type, &avail) != 0) {
|
||||
*_errno = MP_EIO;
|
||||
ret = MP_STREAM_ERROR;
|
||||
} else if (avail) {
|
||||
// Readable or accepted socket ready.
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
uint8_t flags = 0;
|
||||
if (nina_socket_poll(socket->fileno, &flags) < 0) {
|
||||
nina_socket_errno(_errno);
|
||||
ret = MP_STREAM_ERROR;
|
||||
debug_printf("socket_ioctl() -> errno %d\n", *_errno);
|
||||
}
|
||||
if (arg & MP_STREAM_POLL_WR) {
|
||||
if ((arg & MP_STREAM_POLL_RD) && (flags & SOCKET_POLL_RD)) {
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
if ((arg & MP_STREAM_POLL_WR) && (flags & SOCKET_POLL_WR)) {
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
} else {
|
||||
// NOTE: FIONREAD and FIONBIO are supported as well.
|
||||
*_errno = MP_EINVAL;
|
||||
ret = MP_STREAM_ERROR;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue