mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Enable RP2 networking and add NINA-W10 driver and modules.
This commit is contained in:
parent
ff52402ca9
commit
a08a666a52
92
src/drivers/ninaw10/include/nina.h
Normal file
92
src/drivers/ninaw10/include/nina.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the OpenMV project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||||
|
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||||
|
*
|
||||||
|
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||||
|
*
|
||||||
|
* NINA-W10 driver.
|
||||||
|
*/
|
||||||
|
#ifndef __NINA_H__
|
||||||
|
#define __NINA_H__
|
||||||
|
#define NINA_FW_VER_LEN (6)
|
||||||
|
#define NINA_IPV4_ADDR_LEN (4)
|
||||||
|
#define NINA_MAC_ADDR_LEN (6)
|
||||||
|
#define NINA_MAX_SSID_LEN (32)
|
||||||
|
#define NINA_MAX_WEP_LEN (13)
|
||||||
|
#define NINA_MAX_WPA_LEN (63)
|
||||||
|
#define NINA_MAX_NETWORK_LIST (10)
|
||||||
|
#define NINA_MAX_SOCKET (10)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NINA_SEC_INVALID = 0,
|
||||||
|
NINA_SEC_OPEN,
|
||||||
|
NINA_SEC_WPA_PSK,
|
||||||
|
NINA_SEC_WEP
|
||||||
|
} 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_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NINA_ERROR_IO = -1,
|
||||||
|
NINA_ERROR_TIMEOUT = -2,
|
||||||
|
} nina_error_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ip_addr[NINA_IPV4_ADDR_LEN];
|
||||||
|
uint8_t subnet_addr[NINA_IPV4_ADDR_LEN];
|
||||||
|
uint8_t gateway_addr[NINA_IPV4_ADDR_LEN];
|
||||||
|
uint8_t dns_addr[NINA_IPV4_ADDR_LEN];
|
||||||
|
} nina_ifconfig_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int8_t rssi;
|
||||||
|
uint8_t security;
|
||||||
|
uint8_t channel;
|
||||||
|
uint8_t bssid[NINA_MAC_ADDR_LEN];
|
||||||
|
char ssid[NINA_MAX_SSID_LEN];
|
||||||
|
} nina_scan_result_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int8_t rssi;
|
||||||
|
uint8_t security;
|
||||||
|
char ssid[NINA_MAX_SSID_LEN];
|
||||||
|
uint8_t bssid[NINA_MAC_ADDR_LEN];
|
||||||
|
} nina_netinfo_t;
|
||||||
|
|
||||||
|
typedef int (*nina_scan_callback_t) (nina_scan_result_t *, void *);
|
||||||
|
|
||||||
|
int nina_init();
|
||||||
|
int nina_deinit();
|
||||||
|
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel);
|
||||||
|
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel);
|
||||||
|
int nina_disconnect();
|
||||||
|
int nina_isconnected();
|
||||||
|
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);
|
||||||
|
int nina_get_rssi();
|
||||||
|
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_socket_socket(uint8_t type);
|
||||||
|
int nina_socket_close(int fd);
|
||||||
|
int nina_socket_bind(int fd, uint8_t *ip, uint16_t port, int type);
|
||||||
|
int nina_socket_listen(int fd, uint32_t backlog);
|
||||||
|
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out, uint32_t timeout);
|
||||||
|
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port, uint32_t timeout);
|
||||||
|
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len, uint32_t timeout);
|
||||||
|
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len, uint32_t timeout);
|
||||||
|
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port, uint32_t timeout);
|
||||||
|
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port, uint32_t timeout);
|
||||||
|
int nina_socket_setsockopt(int fd, uint32_t level, uint32_t opt, const void *optval, uint32_t optlen);
|
||||||
|
#endif //define __NINA_H__
|
||||||
18
src/drivers/ninaw10/include/nina_bsp.h
Normal file
18
src/drivers/ninaw10/include/nina_bsp.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the OpenMV project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||||
|
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||||
|
*
|
||||||
|
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||||
|
*
|
||||||
|
* NINA-W10 driver BSP.
|
||||||
|
*/
|
||||||
|
#ifndef __NINA_BSP_H__
|
||||||
|
#define __NINA_BSP_H__
|
||||||
|
int nina_bsp_init();
|
||||||
|
int nina_bsp_reset();
|
||||||
|
int nina_bsp_spi_slave_select(uint32_t timeout);
|
||||||
|
int nina_bsp_spi_slave_deselect();
|
||||||
|
int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size);
|
||||||
|
#endif //define __NINA_BSP_H__
|
||||||
806
src/drivers/ninaw10/src/nina.c
Normal file
806
src/drivers/ninaw10/src/nina.c
Normal file
@ -0,0 +1,806 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the OpenMV project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||||
|
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||||
|
*
|
||||||
|
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||||
|
*
|
||||||
|
* NINA-W10 driver.
|
||||||
|
*/
|
||||||
|
#if MICROPY_PY_NINAW10
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "nina.h"
|
||||||
|
#include "nina_bsp.h"
|
||||||
|
|
||||||
|
#define DATA_FLAG (0x40)
|
||||||
|
|
||||||
|
#define SPI_ACK (1)
|
||||||
|
#define SPI_ERR (0xFF)
|
||||||
|
|
||||||
|
#define NO_SOCKET_AVAIL (255)
|
||||||
|
|
||||||
|
#define CMD_START (0xE0)
|
||||||
|
#define CMD_END (0xEE)
|
||||||
|
#define CMD_ERROR (0xEF)
|
||||||
|
#define CMD_REPLY (1<<7)
|
||||||
|
|
||||||
|
#define ARG_8BITS (1)
|
||||||
|
#define ARG_16BITS (2)
|
||||||
|
|
||||||
|
#define ARG_STR(x) {strlen(x), (const void *) x}
|
||||||
|
#define ARG_BYTE(x) {1, (uint8_t [1]){x}}
|
||||||
|
#define ARG_SHORT(x) {2, (uint16_t [1]){x}}
|
||||||
|
#define ARG_WORD(x) {4, (uint32_t [1]){x}}
|
||||||
|
|
||||||
|
#define NINA_ARGS(...) (nina_args_t []){__VA_ARGS__}
|
||||||
|
#define NINA_VALS(...) (nina_vals_t []){__VA_ARGS__}
|
||||||
|
|
||||||
|
#define NINA_SSELECT_TIMEOUT (10000)
|
||||||
|
#define NINA_RESP_TIMEOUT (1000)
|
||||||
|
#define NINA_CONNECT_TIMEOUT (1000)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t size;
|
||||||
|
const void *data;
|
||||||
|
} nina_args_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t *size;
|
||||||
|
void *data;
|
||||||
|
} nina_vals_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SET_NET_CMD = 0x10,
|
||||||
|
SET_PASSPHRASE_CMD = 0x11,
|
||||||
|
SET_KEY_CMD = 0x12,
|
||||||
|
//TEST_CMD = 0x13,
|
||||||
|
SET_IP_CONFIG_CMD = 0x14,
|
||||||
|
SET_DNS_CONFIG_CMD = 0x15,
|
||||||
|
SET_HOSTNAME_CMD = 0x16,
|
||||||
|
SET_POWER_MODE_CMD = 0x17,
|
||||||
|
SET_AP_NET_CMD = 0x18,
|
||||||
|
SET_AP_PASSPHRASE_CMD = 0x19,
|
||||||
|
SET_DEBUG_CMD = 0x1A,
|
||||||
|
GET_TEMPERATURE_CMD = 0x1B,
|
||||||
|
GET_REASON_CODE_CMD = 0x1F,
|
||||||
|
|
||||||
|
GET_CONN_STATUS_CMD = 0x20,
|
||||||
|
GET_IPADDR_CMD = 0x21,
|
||||||
|
GET_MACADDR_CMD = 0x22,
|
||||||
|
GET_CURR_SSID_CMD = 0x23,
|
||||||
|
GET_CURR_BSSID_CMD = 0x24,
|
||||||
|
GET_CURR_RSSI_CMD = 0x25,
|
||||||
|
GET_CURR_ENCT_CMD = 0x26,
|
||||||
|
SCAN_NETWORKS = 0x27,
|
||||||
|
START_SERVER_TCP_CMD = 0x28,
|
||||||
|
GET_STATE_TCP_CMD = 0x29,
|
||||||
|
DATA_SENT_TCP_CMD = 0x2A,
|
||||||
|
AVAIL_DATA_TCP_CMD = 0x2B,
|
||||||
|
GET_DATA_TCP_CMD = 0x2C,
|
||||||
|
START_CLIENT_TCP_CMD = 0x2D,
|
||||||
|
STOP_CLIENT_TCP_CMD = 0x2E,
|
||||||
|
GET_CLIENT_STATE_TCP_CMD= 0x2F,
|
||||||
|
DISCONNECT_CMD = 0x30,
|
||||||
|
//GET_IDX_SSID_CMD = 0x31,
|
||||||
|
GET_IDX_RSSI_CMD = 0x32,
|
||||||
|
GET_IDX_ENCT_CMD = 0x33,
|
||||||
|
REQ_HOST_BY_NAME_CMD = 0x34,
|
||||||
|
GET_HOST_BY_NAME_CMD = 0x35,
|
||||||
|
START_SCAN_NETWORKS = 0x36,
|
||||||
|
GET_FW_VERSION_CMD = 0x37,
|
||||||
|
//GET_TEST_CMD = 0x38,
|
||||||
|
SEND_DATA_UDP_CMD = 0x39,
|
||||||
|
GET_REMOTE_DATA_CMD = 0x3A,
|
||||||
|
GET_TIME_CMD = 0x3B,
|
||||||
|
GET_IDX_BSSID_CMD = 0x3C,
|
||||||
|
GET_IDX_CHANNEL_CMD = 0x3D,
|
||||||
|
PING_CMD = 0x3E,
|
||||||
|
GET_SOCKET_CMD = 0x3F,
|
||||||
|
|
||||||
|
// All command with DATA_FLAG 0x40 send a 16bit Len
|
||||||
|
SET_ENT_CMD = 0x40,
|
||||||
|
SEND_DATA_TCP_CMD = 0x44,
|
||||||
|
GET_DATABUF_TCP_CMD = 0x45,
|
||||||
|
INSERT_DATABUF_CMD = 0x46,
|
||||||
|
|
||||||
|
// regular format commands
|
||||||
|
SET_PIN_MODE = 0x50,
|
||||||
|
SET_DIGITAL_WRITE = 0x51,
|
||||||
|
SET_ANALOG_WRITE = 0x52,
|
||||||
|
GET_DIGITAL_READ = 0x53,
|
||||||
|
GET_ANALOG_READ = 0x54,
|
||||||
|
|
||||||
|
// regular format commands
|
||||||
|
CMD_WRITE_FILE = 0x60,
|
||||||
|
CMD_READ_FILE = 0x61,
|
||||||
|
CMD_DELETE_FILE = 0x62,
|
||||||
|
CMD_EXISTS_FILE = 0x63,
|
||||||
|
CMD_DOWNLOAD_FILE = 0x64,
|
||||||
|
CMD_APPLY_OTA_COMMAND = 0x65,
|
||||||
|
CMD_RENAME_FILE = 0x66,
|
||||||
|
CMD_DOWNLOAD_OTA = 0x67,
|
||||||
|
} nina_cmd_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WL_NO_SHIELD = 255,
|
||||||
|
WL_NO_MODULE = WL_NO_SHIELD,
|
||||||
|
WL_IDLE_STATUS = 0,
|
||||||
|
WL_NO_SSID_AVAIL,
|
||||||
|
WL_SCAN_COMPLETED,
|
||||||
|
WL_CONNECTED,
|
||||||
|
WL_CONNECT_FAILED,
|
||||||
|
WL_CONNECTION_LOST,
|
||||||
|
WL_DISCONNECTED,
|
||||||
|
WL_AP_LISTENING,
|
||||||
|
WL_AP_CONNECTED,
|
||||||
|
WL_AP_FAILED
|
||||||
|
} nina_wl_status_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SOCKET_STATE_CLOSED = 0,
|
||||||
|
SOCKET_STATE_LISTEN,
|
||||||
|
SOCKET_STATE_SYN_SENT,
|
||||||
|
SOCKET_STATE_SYN_RCVD,
|
||||||
|
SOCKET_STATE_ESTABLISHED,
|
||||||
|
SOCKET_STATE_FIN_WAIT_1,
|
||||||
|
SOCKET_STATE_FIN_WAIT_2,
|
||||||
|
SOCKET_STATE_CLOSE_WAIT,
|
||||||
|
SOCKET_STATE_CLOSING,
|
||||||
|
SOCKET_STATE_LAST_ACK,
|
||||||
|
SOCKET_STATE_TIME_WAIT
|
||||||
|
} nina_sock_state_t;
|
||||||
|
|
||||||
|
static uint8_t nina_bsp_spi_read_byte()
|
||||||
|
{
|
||||||
|
uint8_t byte = 0;
|
||||||
|
nina_bsp_spi_transfer(NULL, &byte, 1);
|
||||||
|
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
|
||||||
|
|
||||||
|
if (nina_bsp_spi_slave_select(NINA_SSELECT_TIMEOUT) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send command header.
|
||||||
|
uint8_t cmdbuf_hdr[3] = {CMD_START, cmd, nargs};
|
||||||
|
if (nina_bsp_spi_transfer(cmdbuf_hdr, NULL, sizeof(cmdbuf_hdr)) != 0) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send command arg(s).
|
||||||
|
for (uint32_t i=0; i<nargs; i++) {
|
||||||
|
// Send arg length.
|
||||||
|
if (nina_bsp_spi_transfer((uint8_t *) &args[i].size, NULL, width) != 0) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send arg value.
|
||||||
|
if (nina_bsp_spi_transfer(args[i].data, NULL, args[i].size) != 0) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
length += args[i].size + width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send END byte + padding to multiple of 4.
|
||||||
|
uint8_t cmdbuf_end[4] = {CMD_END, 0xFF, 0xFF, 0xFF};
|
||||||
|
if (nina_bsp_spi_transfer(cmdbuf_end, NULL, 1 + (length % 4)) != 0) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All good
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
error_out:
|
||||||
|
nina_bsp_spi_slave_deselect();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nina_read_response(uint32_t cmd, uint32_t nvals, uint32_t width, nina_vals_t *vals)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
// 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_RESP_TIMEOUT) != 0) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should return CMD + REPLY flag.
|
||||||
|
if (nina_bsp_spi_read_byte() != (cmd | CMD_REPLY)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read return value(s).
|
||||||
|
for (uint32_t i=0; i<nvals; i++) {
|
||||||
|
// Read return value size.
|
||||||
|
uint32_t bytes = nina_bsp_spi_read_byte();
|
||||||
|
if (width == ARG_16BITS) {
|
||||||
|
bytes = (bytes << 8) | nina_bsp_spi_read_byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the val fits the buffer.
|
||||||
|
if (*(vals[i].size) < bytes) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the returned value.
|
||||||
|
if (nina_bsp_spi_transfer(NULL, vals[i].data, bytes) != 0) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the size.
|
||||||
|
*(vals[i].size) = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_bsp_spi_read_byte() != CMD_END) {
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All good
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
error_out:
|
||||||
|
nina_bsp_spi_slave_deselect();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nina_send_command_read_ack(uint32_t cmd, uint32_t nargs, uint32_t width, nina_args_t *args)
|
||||||
|
{
|
||||||
|
uint32_t size = 1;
|
||||||
|
uint8_t rval = SPI_ERR;
|
||||||
|
if (nina_send_command(cmd, nargs, width, args) != 0 ||
|
||||||
|
nina_read_response(cmd, 1, width, NINA_VALS({&size, &rval})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_init()
|
||||||
|
{
|
||||||
|
// Initialize the BSP.
|
||||||
|
nina_bsp_init();
|
||||||
|
|
||||||
|
// check firmware version
|
||||||
|
uint8_t fw_ver[NINA_FW_VER_LEN];
|
||||||
|
if (nina_fw_version(fw_ver) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// TODO check fw version matches the driver.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nina_connection_status()
|
||||||
|
{
|
||||||
|
return nina_send_command_read_ack(GET_CONN_STATUS_CMD, 0, ARG_8BITS, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel)
|
||||||
|
{
|
||||||
|
uint8_t status = WL_CONNECT_FAILED;
|
||||||
|
|
||||||
|
if (key == NULL && security != NINA_SEC_OPEN) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (security) {
|
||||||
|
case NINA_SEC_OPEN:
|
||||||
|
if (nina_send_command_read_ack(SET_NET_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_STR(ssid))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NINA_SEC_WEP:
|
||||||
|
if (nina_send_command_read_ack(SET_PASSPHRASE_CMD,
|
||||||
|
2, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_STR(key))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NINA_SEC_WPA_PSK:
|
||||||
|
if (nina_send_command_read_ack(SET_KEY_CMD,
|
||||||
|
3, ARG_8BITS, NINA_ARGS(ARG_STR(ssid), ARG_BYTE(0), ARG_STR(key))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(100)) {
|
||||||
|
status = nina_connection_status();
|
||||||
|
|
||||||
|
if (status != WL_IDLE_STATUS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mp_hal_ticks_ms() - start) >= NINA_CONNECT_TIMEOUT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (status == WL_CONNECTED) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_disconnect()
|
||||||
|
{
|
||||||
|
if (nina_send_command_read_ack(DISCONNECT_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_isconnected()
|
||||||
|
{
|
||||||
|
int status = nina_connection_status();
|
||||||
|
if (status == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (status == WL_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_connected_sta(uint32_t *sta_ip)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_wait_for_sta(uint32_t *sta_ip, uint32_t timeout)
|
||||||
|
{
|
||||||
|
return NINA_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_ifconfig(nina_ifconfig_t *ifconfig, bool set)
|
||||||
|
{
|
||||||
|
uint32_t ip_len = NINA_IPV4_ADDR_LEN;
|
||||||
|
uint32_t sub_len = NINA_IPV4_ADDR_LEN;
|
||||||
|
uint32_t gw_len = NINA_IPV4_ADDR_LEN;
|
||||||
|
uint32_t dns_len = NINA_IPV4_ADDR_LEN;
|
||||||
|
|
||||||
|
if (set) {
|
||||||
|
if (nina_send_command_read_ack(SET_IP_CONFIG_CMD,
|
||||||
|
4, ARG_8BITS,
|
||||||
|
NINA_ARGS(
|
||||||
|
ARG_BYTE(3), // Valid number of args.
|
||||||
|
{ip_len, ifconfig->ip_addr},
|
||||||
|
{gw_len, ifconfig->gateway_addr},
|
||||||
|
{sub_len, ifconfig->subnet_addr})) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_ack(SET_DNS_CONFIG_CMD,
|
||||||
|
3, ARG_8BITS,
|
||||||
|
NINA_ARGS(
|
||||||
|
ARG_BYTE(1), // Valid number of args.
|
||||||
|
{dns_len, ifconfig->dns_addr},
|
||||||
|
{dns_len, ifconfig->dns_addr})) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (nina_send_command_read_vals(GET_IPADDR_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
|
||||||
|
3, ARG_8BITS,
|
||||||
|
NINA_VALS(
|
||||||
|
{&ip_len, ifconfig->ip_addr},
|
||||||
|
{&gw_len, ifconfig->gateway_addr},
|
||||||
|
{&sub_len, ifconfig->subnet_addr})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// No command to get DNS ?
|
||||||
|
memcpy(ifconfig->dns_addr, ifconfig->gateway_addr, NINA_IPV4_ADDR_LEN);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_netinfo(nina_netinfo_t *netinfo)
|
||||||
|
{
|
||||||
|
uint32_t rssi_len = 4;
|
||||||
|
uint32_t sec_len = 1;
|
||||||
|
uint32_t ssid_len = NINA_MAX_SSID_LEN;
|
||||||
|
uint32_t bssid_len = NINA_MAC_ADDR_LEN;
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_CURR_RSSI_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&rssi_len, &netinfo->rssi})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_CURR_ENCT_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&sec_len, &netinfo->security})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_CURR_SSID_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&ssid_len, &netinfo->ssid})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_CURR_BSSID_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&bssid_len, &netinfo->bssid})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_scan(nina_scan_callback_t scan_callback, void *arg, uint32_t timeout)
|
||||||
|
{
|
||||||
|
uint32_t sizes[NINA_MAX_NETWORK_LIST];
|
||||||
|
char ssids[NINA_MAX_NETWORK_LIST][NINA_MAX_SSID_LEN];
|
||||||
|
nina_vals_t vals[NINA_MAX_NETWORK_LIST];
|
||||||
|
|
||||||
|
// Initialize the values list.
|
||||||
|
for (int i=0; i< NINA_MAX_NETWORK_LIST; i++) {
|
||||||
|
sizes[i] = NINA_MAX_SSID_LEN - 1;
|
||||||
|
memset(ssids[i], 0, NINA_MAX_SSID_LEN);
|
||||||
|
vals[i].size = &sizes[i];
|
||||||
|
vals[i].data = ssids[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_ack(START_SCAN_NETWORKS,
|
||||||
|
0, ARG_8BITS, NULL) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
|
||||||
|
if (nina_send_command_read_vals(SCAN_NETWORKS,
|
||||||
|
0, ARG_8BITS, NULL,
|
||||||
|
NINA_MAX_NETWORK_LIST, ARG_8BITS, vals) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssids[0][0] != 0) {
|
||||||
|
// Found at least 1 network.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mp_hal_ticks_ms() - start) >= timeout) {
|
||||||
|
// Timeout, no networks.
|
||||||
|
return NINA_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_hal_delay_ms(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<NINA_MAX_NETWORK_LIST; i++) {
|
||||||
|
uint32_t rssi_len = 4;
|
||||||
|
uint32_t sec_len = 1;
|
||||||
|
uint32_t chan_len = 1;
|
||||||
|
uint32_t bssid_len = NINA_MAC_ADDR_LEN;
|
||||||
|
nina_scan_result_t scan_result;
|
||||||
|
|
||||||
|
if (ssids[i][0] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set AP SSID
|
||||||
|
strncpy(scan_result.ssid, ssids[i], NINA_MAX_SSID_LEN);
|
||||||
|
|
||||||
|
// Read AP RSSI
|
||||||
|
if (nina_send_command_read_vals(GET_IDX_RSSI_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&rssi_len, &scan_result.rssi})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read AP encryption type
|
||||||
|
if (nina_send_command_read_vals(GET_IDX_ENCT_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&sec_len, &scan_result.security})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read AP channel
|
||||||
|
if (nina_send_command_read_vals(GET_IDX_CHANNEL_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&chan_len, &scan_result.channel})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read AP bssid
|
||||||
|
if (nina_send_command_read_vals(GET_IDX_BSSID_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(i)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&bssid_len, scan_result.bssid})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
scan_callback(&scan_result, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_get_rssi()
|
||||||
|
{
|
||||||
|
uint32_t size = 4;
|
||||||
|
uint32_t rssi = 0;
|
||||||
|
if (nina_send_command_read_vals(GET_CURR_RSSI_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(0xFF)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&size, &rssi})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_fw_version(uint8_t *fw_ver)
|
||||||
|
{
|
||||||
|
uint32_t size = NINA_FW_VER_LEN;
|
||||||
|
if (nina_send_command_read_vals(GET_FW_VERSION_CMD,
|
||||||
|
0, ARG_8BITS, NULL,
|
||||||
|
1, ARG_8BITS, NINA_VALS({&size, fw_ver})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_set_hostname(const char *hostname)
|
||||||
|
{
|
||||||
|
if (nina_send_command_read_ack(SET_HOSTNAME_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_STR(hostname))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_gethostbyname(const char *name, uint8_t *out_ip)
|
||||||
|
{
|
||||||
|
uint32_t size = 4;
|
||||||
|
|
||||||
|
if (nina_send_command_read_ack(REQ_HOST_BY_NAME_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_STR(name))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_HOST_BY_NAME_CMD,
|
||||||
|
0, ARG_8BITS, NULL,
|
||||||
|
1, ARG_8BITS, NINA_VALS({&size, out_ip})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_socket_socket(uint8_t type)
|
||||||
|
{
|
||||||
|
uint32_t size = 1;
|
||||||
|
uint8_t sock = 0;
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_SOCKET_CMD,
|
||||||
|
0, ARG_8BITS, NULL,
|
||||||
|
1, ARG_8BITS, NINA_VALS({&size, &sock})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_socket_close(int fd)
|
||||||
|
{
|
||||||
|
if (nina_send_command_read_ack(STOP_CLIENT_TCP_CMD,
|
||||||
|
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(START_SERVER_TCP_CMD,
|
||||||
|
3, ARG_8BITS,
|
||||||
|
NINA_ARGS(
|
||||||
|
ARG_SHORT(port),
|
||||||
|
ARG_BYTE(fd),
|
||||||
|
ARG_BYTE(type))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_socket_listen(int fd, uint32_t backlog)
|
||||||
|
{
|
||||||
|
return 0; // No listen ?
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_socket_accept(int fd, uint8_t *ip, uint16_t *port, int *fd_out, uint32_t timeout)
|
||||||
|
{
|
||||||
|
uint32_t size = 2;
|
||||||
|
uint16_t sock = 0;
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(AVAIL_DATA_TCP_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&size, &sock})) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock != NO_SOCKET_AVAIL) {
|
||||||
|
*fd_out = sock;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NINA_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_socket_connect(int fd, uint8_t *ip, uint16_t port, uint32_t timeout)
|
||||||
|
{
|
||||||
|
if (nina_send_command_read_ack(START_CLIENT_TCP_CMD,
|
||||||
|
4, ARG_8BITS,
|
||||||
|
NINA_ARGS(
|
||||||
|
ARG_WORD((*(uint32_t*)ip)),
|
||||||
|
ARG_SHORT(port),
|
||||||
|
ARG_BYTE(fd),
|
||||||
|
ARG_BYTE(NINA_SOCKET_TYPE_TCP))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(100)) {
|
||||||
|
int state = nina_send_command_read_ack(
|
||||||
|
GET_CLIENT_STATE_TCP_CMD, 1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)));
|
||||||
|
|
||||||
|
if (state == SOCKET_STATE_ESTABLISHED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == -1 || (mp_hal_ticks_ms() - start) >= timeout) {
|
||||||
|
return NINA_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_socket_send(int fd, const uint8_t *buf, uint32_t len, uint32_t timeout)
|
||||||
|
{
|
||||||
|
uint32_t size = 2;
|
||||||
|
uint16_t bytes = 0;
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(SEND_DATA_TCP_CMD,
|
||||||
|
2, ARG_16BITS, NINA_ARGS(ARG_SHORT(fd), {len, buf}),
|
||||||
|
1, ARG_8BITS, NINA_VALS({&size, &bytes})) != 0 || bytes <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mp_uint_t start = mp_hal_ticks_ms(); ;) {
|
||||||
|
int resp = nina_send_command_read_ack(DATA_SENT_TCP_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_SHORT(fd)));
|
||||||
|
|
||||||
|
if (resp == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp == SPI_ACK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mp_hal_ticks_ms() - start) >= timeout) {
|
||||||
|
return NINA_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
mp_hal_delay_ms(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_socket_recv(int fd, uint8_t *buf, uint32_t len, uint32_t timeout)
|
||||||
|
{
|
||||||
|
uint32_t size = 2;
|
||||||
|
uint16_t bytes = 0;
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_DATABUF_TCP_CMD,
|
||||||
|
2, ARG_16BITS, NINA_ARGS(ARG_SHORT(fd), {len, buf}),
|
||||||
|
1, ARG_16BITS, NINA_VALS({&size, &bytes})) != 0 || bytes <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check from the upper layer if the socket is bound, if not then auto-bind it 32768->60999 first.
|
||||||
|
int nina_socket_sendto(int fd, const uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port, uint32_t timeout)
|
||||||
|
{
|
||||||
|
// TODO do we need to split the packet somewhere?
|
||||||
|
if (nina_send_command_read_ack(START_CLIENT_TCP_CMD,
|
||||||
|
4, ARG_8BITS,
|
||||||
|
NINA_ARGS(
|
||||||
|
ARG_WORD((*(uint32_t*)ip)),
|
||||||
|
ARG_SHORT(port),
|
||||||
|
ARG_BYTE(fd),
|
||||||
|
ARG_BYTE(NINA_SOCKET_TYPE_UDP))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer length and socket number are passed as 16bits.
|
||||||
|
if (nina_send_command_read_ack(INSERT_DATABUF_CMD,
|
||||||
|
2, ARG_16BITS, NINA_ARGS(ARG_SHORT(fd), {len, buf})) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_ack(SEND_DATA_UDP_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd))) != SPI_ACK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check from the upper layer if the socket is bound, if not then auto-bind it 32768->60999 first.
|
||||||
|
int nina_socket_recvfrom(int fd, uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t *port, uint32_t timeout)
|
||||||
|
{
|
||||||
|
uint32_t size = 2;
|
||||||
|
uint16_t bytes = 0;
|
||||||
|
|
||||||
|
uint32_t ip_len = NINA_IPV4_ADDR_LEN;
|
||||||
|
uint32_t port_len = 2;
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_DATABUF_TCP_CMD,
|
||||||
|
2, ARG_16BITS, NINA_ARGS(ARG_SHORT(fd), {len, buf}),
|
||||||
|
1, ARG_16BITS, NINA_VALS({&size, &bytes})) != 0 || bytes <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nina_send_command_read_vals(GET_REMOTE_DATA_CMD,
|
||||||
|
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(fd)),
|
||||||
|
2, ARG_8BITS, NINA_VALS({&ip_len, ip}, {&port_len, port})) != 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;
|
||||||
|
}
|
||||||
|
#endif //MICROPY_PY_NINAW10
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 0cfe9fd8d402669af8a4345fd6006cbdc7114a69
|
Subproject commit 5ede9f316bbcd4f462337633e1720e490acd6c96
|
||||||
@ -1,8 +1,7 @@
|
|||||||
set(MICROPY_PY_SENSOR 1)
|
set(MICROPY_PY_SENSOR 1)
|
||||||
set(MICROPY_PY_ULAB 1)
|
set(MICROPY_PY_ULAB 1)
|
||||||
|
set(MICROPY_PY_NINAW10 1)
|
||||||
set(MICROPY_PY_WINC1500 0)
|
set(MICROPY_PY_WINC1500 0)
|
||||||
set(MICROPY_PY_LWIP 0)
|
|
||||||
set(MICROPY_PY_NETWORK_CYW43 0)
|
|
||||||
set(MICROPY_PY_BLUETOOTH 0)
|
set(MICROPY_PY_BLUETOOTH 0)
|
||||||
set(MICROPY_BLUETOOTH_NIMBLE 0)
|
set(MICROPY_BLUETOOTH_NIMBLE 0)
|
||||||
set(MICROPY_PY_AUDIO 1)
|
set(MICROPY_PY_AUDIO 1)
|
||||||
|
|||||||
@ -124,24 +124,29 @@ extern unsigned char *OMV_UNIQUE_ID_ADDR;
|
|||||||
#define I2C1_SDA_PIN (6)
|
#define I2C1_SDA_PIN (6)
|
||||||
#define I2C1_SPEED (CAMBUS_SPEED_FULL)
|
#define I2C1_SPEED (CAMBUS_SPEED_FULL)
|
||||||
|
|
||||||
|
// LCD config.
|
||||||
#define LCD_SPI (spi0)
|
#define LCD_SPI (spi0)
|
||||||
|
#define LCD_CS_PIN (5)
|
||||||
#define LCD_MOSI_PIN (7)
|
#define LCD_MOSI_PIN (7)
|
||||||
#define LCD_SCLK_PIN (6)
|
#define LCD_SCLK_PIN (6)
|
||||||
|
|
||||||
#define LCD_RST_PIN (4)
|
#define LCD_RST_PIN (4)
|
||||||
#define LCD_RST_PIN_WRITE(bit) gpio_put(LCD_RST_PIN, bit);
|
|
||||||
|
|
||||||
#define LCD_RS_PIN (0)
|
#define LCD_RS_PIN (0)
|
||||||
#define LCD_RS_PIN_WRITE(bit) gpio_put(LCD_RS_PIN, bit);
|
|
||||||
|
|
||||||
#define LCD_CS_PIN (5)
|
// WiFi/NINA config.
|
||||||
#define LCD_CS_PIN_WRITE(bit) gpio_put(LCD_CS_PIN, bit);
|
#define WIFI_SPI (spi1)
|
||||||
|
#define WIFI_CS_PIN (9)
|
||||||
|
#define WIFI_MOSI_PIN (11)
|
||||||
|
#define WIFI_MISO_PIN (8)
|
||||||
|
#define WIFI_SCLK_PIN (14)
|
||||||
|
#define WIFI_RST_PIN (3)
|
||||||
|
#define WIFI_GPIO0_PIN (2)
|
||||||
|
#define WIFI_ACK_PIN (10)
|
||||||
|
|
||||||
// AUDIO config.
|
// AUDIO config.
|
||||||
#define PDM_PIO (pio1)
|
#define PDM_PIO (pio1)
|
||||||
#define PDM_SM (0)
|
#define PDM_SM (0)
|
||||||
#define PDM_DMA (1)
|
#define PDM_DMA (1)
|
||||||
#define PDM_DMA_IRQ (DMA_IRQ_1)
|
#define PDM_DMA_IRQ (DMA_IRQ_1)
|
||||||
#define PDM_DMA_CHANNEL (0)
|
#define PDM_DMA_CHANNEL (0)
|
||||||
|
|
||||||
#define PDM_CLK_PIN (23)
|
#define PDM_CLK_PIN (23)
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
set(MICROPY_PY_SENSOR 1)
|
set(MICROPY_PY_SENSOR 1)
|
||||||
set(MICROPY_PY_ULAB 1)
|
set(MICROPY_PY_ULAB 1)
|
||||||
|
set(MICROPY_PY_NINAW10 0)
|
||||||
set(MICROPY_PY_WINC1500 0)
|
set(MICROPY_PY_WINC1500 0)
|
||||||
set(MICROPY_PY_LWIP 0)
|
|
||||||
set(MICROPY_PY_NETWORK_CYW43 0)
|
|
||||||
set(MICROPY_PY_BLUETOOTH 0)
|
set(MICROPY_PY_BLUETOOTH 0)
|
||||||
set(MICROPY_BLUETOOTH_NIMBLE 0)
|
set(MICROPY_BLUETOOTH_NIMBLE 0)
|
||||||
set(MICROPY_PY_AUDIO 0)
|
set(MICROPY_PY_AUDIO 0)
|
||||||
|
|||||||
@ -125,17 +125,21 @@ extern unsigned char *OMV_UNIQUE_ID_ADDR;
|
|||||||
#define I2C1_SPEED (CAMBUS_SPEED_FULL)
|
#define I2C1_SPEED (CAMBUS_SPEED_FULL)
|
||||||
|
|
||||||
#define LCD_SPI (spi0)
|
#define LCD_SPI (spi0)
|
||||||
|
#define LCD_CS_PIN (17)
|
||||||
#define LCD_MOSI_PIN (19)
|
#define LCD_MOSI_PIN (19)
|
||||||
#define LCD_SCLK_PIN (18)
|
#define LCD_SCLK_PIN (18)
|
||||||
|
|
||||||
#define LCD_RST_PIN (20)
|
#define LCD_RST_PIN (20)
|
||||||
#define LCD_RST_PIN_WRITE(bit) gpio_put(LCD_RST_PIN, bit);
|
|
||||||
|
|
||||||
#define LCD_RS_PIN (21)
|
#define LCD_RS_PIN (21)
|
||||||
#define LCD_RS_PIN_WRITE(bit) gpio_put(LCD_RS_PIN, bit);
|
|
||||||
|
|
||||||
#define LCD_CS_PIN (17)
|
// WiFi/NINA config.
|
||||||
#define LCD_CS_PIN_WRITE(bit) gpio_put(LCD_CS_PIN, bit);
|
//#define WIFI_SPI (spi1)
|
||||||
|
//#define WIFI_CS_PIN (15)
|
||||||
|
//#define WIFI_MOSI_PIN (16)
|
||||||
|
//#define WIFI_MISO_PIN (17)
|
||||||
|
//#define WIFI_SCLK_PIN (18)
|
||||||
|
//#define WIFI_RST_PIN (19)
|
||||||
|
//#define WIFI_GPIO0_PIN (20)
|
||||||
|
//#define WIFI_ACK_PIN (21)
|
||||||
|
|
||||||
// AUDIO config.
|
// AUDIO config.
|
||||||
//#define PDM_PIO (pio1)
|
//#define PDM_PIO (pio1)
|
||||||
|
|||||||
537
src/omv/ports/rp2/modules/py_nina.c
Normal file
537
src/omv/ports/rp2/modules/py_nina.c
Normal file
@ -0,0 +1,537 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the OpenMV project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||||
|
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||||
|
*
|
||||||
|
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||||
|
*
|
||||||
|
* NINA-W10 Python module.
|
||||||
|
*/
|
||||||
|
#if MICROPY_PY_NINAW10
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "py/nlr.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
|
#include "py/objtuple.h"
|
||||||
|
#include "py/objlist.h"
|
||||||
|
#include "py/stream.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "mperrno.h"
|
||||||
|
#include "lib/netutils/netutils.h"
|
||||||
|
#include "modnetwork.h"
|
||||||
|
|
||||||
|
#include "nina.h"
|
||||||
|
|
||||||
|
typedef struct _nina_obj_t {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
} nina_obj_t;
|
||||||
|
|
||||||
|
static const nina_obj_t nina_obj = {{(mp_obj_type_t*) &mod_network_nic_type_nina}};
|
||||||
|
|
||||||
|
// Initialise the module using the given SPI bus and pins and return a nina object.
|
||||||
|
static mp_obj_t py_nina_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args)
|
||||||
|
{
|
||||||
|
// Init Nina module
|
||||||
|
int error = nina_init();
|
||||||
|
if (error != 0) {
|
||||||
|
mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("Failed to initialize Nina-W10 module: %d\n"), error);
|
||||||
|
}
|
||||||
|
return (mp_obj_t)&nina_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// method connect(ssid, key=None, *, security=WPA2, bssid=None)
|
||||||
|
static mp_obj_t py_nina_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
|
||||||
|
{
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||||
|
{ MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||||
|
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NINA_SEC_WPA_PSK} },
|
||||||
|
};
|
||||||
|
|
||||||
|
// parse args
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
// get ssid
|
||||||
|
const char *ssid = mp_obj_str_get_str(args[0].u_obj);
|
||||||
|
|
||||||
|
if (strlen(ssid) == 0) {
|
||||||
|
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SSID can't be empty!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get key and sec
|
||||||
|
const char *key = NULL;
|
||||||
|
mp_uint_t security = NINA_SEC_OPEN;
|
||||||
|
|
||||||
|
if (args[1].u_obj != mp_const_none) {
|
||||||
|
key = mp_obj_str_get_str(args[1].u_obj);
|
||||||
|
security = args[2].u_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (security != NINA_SEC_OPEN && strlen(key) == 0) {
|
||||||
|
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Key can't be empty!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect to AP
|
||||||
|
if (nina_connect(ssid, security, key, 0) != 0) {
|
||||||
|
mp_raise_msg_varg(&mp_type_OSError,
|
||||||
|
MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"), ssid, security, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// method start_ap(ssid, key=None, security=OPEN)
|
||||||
|
static mp_obj_t py_nina_start_ap(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
|
||||||
|
{
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_ssid, MP_ARG_REQUIRED| MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||||
|
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||||
|
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NINA_SEC_OPEN } },
|
||||||
|
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
||||||
|
};
|
||||||
|
|
||||||
|
// parse args
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
// get ssid
|
||||||
|
const char *ssid = mp_obj_str_get_str(args[0].u_obj);
|
||||||
|
|
||||||
|
// get key and security
|
||||||
|
const char *key = NULL;
|
||||||
|
mp_uint_t security = args[2].u_int;
|
||||||
|
|
||||||
|
if (security != NINA_SEC_OPEN && security != NINA_SEC_WEP) {
|
||||||
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "AP mode supports WEP security only."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (security == NINA_SEC_WEP && args[1].u_obj == MP_OBJ_NULL) {
|
||||||
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Missing WEP key!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (security != NINA_SEC_OPEN) {
|
||||||
|
key = mp_obj_str_get_str(args[1].u_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get channel
|
||||||
|
mp_uint_t channel = args[3].u_int;
|
||||||
|
|
||||||
|
// Initialize WiFi in AP mode.
|
||||||
|
if (nina_start_ap(ssid, security, key, channel) != 0) {
|
||||||
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "failed to start in AP mode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("AP mode started. You can connect to %s.\r\n", ssid);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_disconnect(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
nina_disconnect();
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_isconnected(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
return mp_obj_new_bool(nina_isconnected());
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_connected_sta(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
uint32_t sta_ip = 0;
|
||||||
|
mp_obj_t sta_list = mp_obj_new_list(0, NULL);
|
||||||
|
|
||||||
|
if (nina_connected_sta(&sta_ip) == 0) {
|
||||||
|
mp_obj_list_append(sta_list, netutils_format_inet_addr(
|
||||||
|
(uint8_t*)&sta_ip, 0, NETUTILS_BIG));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sta_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_wait_for_sta(mp_obj_t self_in, mp_obj_t timeout_in)
|
||||||
|
{
|
||||||
|
uint32_t sta_ip;
|
||||||
|
// get timeout
|
||||||
|
mp_obj_t sta_list = mp_obj_new_list(0, NULL);
|
||||||
|
mp_uint_t timeout = mp_obj_get_int(timeout_in);
|
||||||
|
|
||||||
|
if (nina_wait_for_sta(&sta_ip, timeout) == 0) {
|
||||||
|
mp_obj_list_append(sta_list, netutils_format_inet_addr(
|
||||||
|
(uint8_t*)&sta_ip, 0, NETUTILS_BIG));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sta_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_ifconfig(size_t n_args, const mp_obj_t *args)
|
||||||
|
{
|
||||||
|
nina_ifconfig_t ifconfig;
|
||||||
|
if (n_args == 1) {
|
||||||
|
// get ifconfig info
|
||||||
|
nina_ifconfig(&ifconfig, false);
|
||||||
|
mp_obj_t tuple[4] = {
|
||||||
|
netutils_format_ipv4_addr(ifconfig.ip_addr, NETUTILS_BIG),
|
||||||
|
netutils_format_ipv4_addr(ifconfig.subnet_addr, NETUTILS_BIG),
|
||||||
|
netutils_format_ipv4_addr(ifconfig.gateway_addr, NETUTILS_BIG),
|
||||||
|
netutils_format_ipv4_addr(ifconfig.dns_addr, NETUTILS_BIG),
|
||||||
|
};
|
||||||
|
return mp_obj_new_tuple(4, tuple);
|
||||||
|
} else {
|
||||||
|
// set ifconfig info
|
||||||
|
mp_obj_t *items;
|
||||||
|
mp_obj_get_array_fixed_n(args[1], 4, &items);
|
||||||
|
netutils_parse_ipv4_addr(items[0], ifconfig.ip_addr, NETUTILS_BIG);
|
||||||
|
netutils_parse_ipv4_addr(items[1], ifconfig.subnet_addr, NETUTILS_BIG);
|
||||||
|
netutils_parse_ipv4_addr(items[2], ifconfig.gateway_addr, NETUTILS_BIG);
|
||||||
|
netutils_parse_ipv4_addr(items[3], ifconfig.dns_addr, NETUTILS_BIG);
|
||||||
|
nina_ifconfig(&ifconfig, true);
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_netinfo(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
nina_netinfo_t netinfo;
|
||||||
|
nina_netinfo(&netinfo);
|
||||||
|
|
||||||
|
// Format MAC address
|
||||||
|
VSTR_FIXED(bssid_vstr, 18);
|
||||||
|
vstr_printf(&bssid_vstr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
netinfo.bssid[0], netinfo.bssid[1], netinfo.bssid[2],
|
||||||
|
netinfo.bssid[3], netinfo.bssid[4], netinfo.bssid[5]);
|
||||||
|
|
||||||
|
// Add connection info
|
||||||
|
mp_obj_t tuple[4] = {
|
||||||
|
mp_obj_new_int(netinfo.rssi),
|
||||||
|
mp_obj_new_int(netinfo.security),
|
||||||
|
mp_obj_new_str(netinfo.ssid, strlen(netinfo.ssid)),
|
||||||
|
mp_obj_new_str(bssid_vstr.buf, bssid_vstr.len),
|
||||||
|
};
|
||||||
|
return mp_obj_new_tuple(4, tuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nina_scan_callback(nina_scan_result_t *scan_result, void *arg)
|
||||||
|
{
|
||||||
|
mp_obj_t scan_list = (mp_obj_t) arg;
|
||||||
|
|
||||||
|
// Format MAC address
|
||||||
|
VSTR_FIXED(bssid_vstr, 18);
|
||||||
|
vstr_printf(&bssid_vstr, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||||
|
scan_result->bssid[0], scan_result->bssid[1], scan_result->bssid[2],
|
||||||
|
scan_result->bssid[3], scan_result->bssid[4], scan_result->bssid[5]);
|
||||||
|
|
||||||
|
mp_obj_t ap[5] = {
|
||||||
|
mp_obj_new_int(scan_result->channel),
|
||||||
|
mp_obj_new_int(scan_result->rssi),
|
||||||
|
mp_obj_new_int(scan_result->security),
|
||||||
|
mp_obj_new_str(bssid_vstr.buf, bssid_vstr.len),
|
||||||
|
mp_obj_new_str(scan_result->ssid, strlen(scan_result->ssid)),
|
||||||
|
};
|
||||||
|
|
||||||
|
mp_obj_list_append(scan_list, mp_obj_new_tuple(MP_ARRAY_SIZE(ap), ap));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_scan(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
mp_obj_t scan_list;
|
||||||
|
scan_list = mp_obj_new_list(0, NULL);
|
||||||
|
nina_scan(nina_scan_callback, scan_list, 10000);
|
||||||
|
return scan_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_get_rssi(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
return mp_obj_new_int(nina_get_rssi());
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_obj_t py_nina_fw_version(mp_obj_t self_in)
|
||||||
|
{
|
||||||
|
uint8_t fwver[NINA_FW_VER_LEN];
|
||||||
|
nina_fw_version(fwver);
|
||||||
|
|
||||||
|
// We don't know how the fw version looks like, assume ints.
|
||||||
|
mp_obj_tuple_t *t_fwver = mp_obj_new_tuple(NINA_FW_VER_LEN, NULL);
|
||||||
|
for (int i=0; i<NINA_FW_VER_LEN; i++) {
|
||||||
|
t_fwver->items[i] = mp_obj_new_int(fwver[i]);
|
||||||
|
}
|
||||||
|
return t_fwver;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip)
|
||||||
|
{
|
||||||
|
return nina_gethostbyname(name, out_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_socket_socket(mod_network_socket_obj_t *socket, int *_errno)
|
||||||
|
{
|
||||||
|
uint8_t type;
|
||||||
|
|
||||||
|
if (socket->u_param.domain != MOD_NETWORK_AF_INET) {
|
||||||
|
*_errno = MP_EAFNOSUPPORT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (socket->u_param.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);
|
||||||
|
if (fd < 0) {
|
||||||
|
*_errno = fd;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store state of this socket
|
||||||
|
socket->fd = fd;
|
||||||
|
socket->timeout = 0; // blocking
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void py_nina_socket_close(mod_network_socket_obj_t *socket)
|
||||||
|
{
|
||||||
|
if (socket->fd >= 0) {
|
||||||
|
nina_socket_close(socket->fd);
|
||||||
|
socket->fd = -1; // Mark socket FD as invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno)
|
||||||
|
{
|
||||||
|
uint8_t type;
|
||||||
|
switch (socket->u_param.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = nina_socket_bind(socket->fd, ip, port, type);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno)
|
||||||
|
{
|
||||||
|
int ret = nina_socket_listen(socket->fd, backlog);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_socket_accept(mod_network_socket_obj_t *socket,
|
||||||
|
mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno)
|
||||||
|
{
|
||||||
|
int fd = 0;
|
||||||
|
// Call accept.
|
||||||
|
int ret = nina_socket_accept(socket->fd, ip, (uint16_t*) port, &fd, socket->timeout);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default socket timeout.
|
||||||
|
socket2->fd = fd;
|
||||||
|
socket2->timeout = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno)
|
||||||
|
{
|
||||||
|
int ret = nina_socket_connect(socket->fd, ip, port, socket->timeout);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_uint_t py_nina_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno)
|
||||||
|
{
|
||||||
|
int ret = nina_socket_send(socket->fd, buf, len, socket->timeout);
|
||||||
|
if (ret == NINA_ERROR_TIMEOUT) {
|
||||||
|
// The socket is Not closed on timeout when calling functions that accept a timeout.
|
||||||
|
*_errno = MP_ETIMEDOUT;
|
||||||
|
return 0;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
// Close the socket on any other errors.
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_uint_t py_nina_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno)
|
||||||
|
{
|
||||||
|
int ret = nina_socket_recv(socket->fd, buf, len, socket->timeout);
|
||||||
|
if (ret == NINA_ERROR_TIMEOUT) {
|
||||||
|
// The socket is Not closed on timeout when calling functions that accept a timeout.
|
||||||
|
*_errno = MP_ETIMEDOUT;
|
||||||
|
return 0;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
// Close the socket on any other errors.
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_uint_t py_nina_socket_sendto(mod_network_socket_obj_t *socket,
|
||||||
|
const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno)
|
||||||
|
{
|
||||||
|
int ret = nina_socket_sendto(socket->fd, buf, len, ip, port, socket->timeout);
|
||||||
|
if (ret == NINA_ERROR_TIMEOUT) {
|
||||||
|
// The socket is Not closed on timeout when calling functions that accept a timeout.
|
||||||
|
*_errno = MP_ETIMEDOUT;
|
||||||
|
return 0;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mp_uint_t py_nina_socket_recvfrom(mod_network_socket_obj_t *socket,
|
||||||
|
byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno)
|
||||||
|
{
|
||||||
|
int ret = nina_socket_recvfrom(socket->fd, buf, len, ip, (uint16_t *) port, socket->timeout);
|
||||||
|
if (ret == NINA_ERROR_TIMEOUT) {
|
||||||
|
// The socket is Not closed on timeout when calling functions that accept a timeout.
|
||||||
|
*_errno = MP_ETIMEDOUT;
|
||||||
|
return 0;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
// Close the socket on any other errors.
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_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)
|
||||||
|
{
|
||||||
|
int ret = nina_socket_setsockopt(socket->fd, level, opt, optval, optlen);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
py_nina_socket_close(socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno)
|
||||||
|
{
|
||||||
|
if (timeout_ms == UINT32_MAX) {
|
||||||
|
// no timeout is given, set the socket to blocking mode.
|
||||||
|
timeout_ms = 0;
|
||||||
|
} else if (timeout_ms == 0) {
|
||||||
|
// non-blocking mode, set the timeout to a small number other than zero.
|
||||||
|
timeout_ms = 10;
|
||||||
|
} // otherwise, timeout is provided.
|
||||||
|
|
||||||
|
socket->timeout = timeout_ms;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int py_nina_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno)
|
||||||
|
{
|
||||||
|
*_errno = MP_EIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_KW(py_nina_connect_obj, 1, py_nina_connect);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_KW(py_nina_start_ap_obj,1, py_nina_start_ap);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(py_nina_disconnect_obj, py_nina_disconnect);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(py_nina_isconnected_obj, py_nina_isconnected);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(py_nina_connected_sta_obj, py_nina_connected_sta);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_2(py_nina_wait_for_sta_obj, py_nina_wait_for_sta);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(py_nina_ifconfig_obj, 1, 2, py_nina_ifconfig);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(py_nina_netinfo_obj, py_nina_netinfo);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(py_nina_scan_obj, py_nina_scan);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(py_nina_get_rssi_obj, py_nina_get_rssi);
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_1(py_nina_fw_version_obj, py_nina_fw_version);
|
||||||
|
|
||||||
|
static const mp_map_elem_t nina_locals_dict_table[] = {
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&py_nina_connect_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_start_ap), (mp_obj_t)&py_nina_start_ap_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&py_nina_disconnect_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&py_nina_isconnected_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_connected_sta), (mp_obj_t)&py_nina_connected_sta_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_wait_for_sta), (mp_obj_t)&py_nina_wait_for_sta_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&py_nina_ifconfig_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_netinfo), (mp_obj_t)&py_nina_netinfo_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&py_nina_scan_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_rssi), (mp_obj_t)&py_nina_get_rssi_obj },
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_fw_version), (mp_obj_t)&py_nina_fw_version_obj },
|
||||||
|
// Network is not secured.
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_OPEN), MP_OBJ_NEW_SMALL_INT(NINA_SEC_OPEN) },
|
||||||
|
// Security type WEP (40 or 104).
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(NINA_SEC_WEP) },
|
||||||
|
// Network secured with WPA/WPA2 personal(PSK).
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA_PSK), MP_OBJ_NEW_SMALL_INT(NINA_SEC_WPA_PSK) },
|
||||||
|
};
|
||||||
|
|
||||||
|
static MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
|
||||||
|
|
||||||
|
const mod_network_nic_type_t mod_network_nic_type_nina = {
|
||||||
|
.base = {
|
||||||
|
{ &mp_type_type },
|
||||||
|
.name = MP_QSTR_nina,
|
||||||
|
.make_new = py_nina_make_new,
|
||||||
|
.locals_dict = (mp_obj_t)&nina_locals_dict,
|
||||||
|
},
|
||||||
|
.gethostbyname = py_nina_gethostbyname,
|
||||||
|
.socket = py_nina_socket_socket,
|
||||||
|
.close = py_nina_socket_close,
|
||||||
|
.bind = py_nina_socket_bind,
|
||||||
|
.listen = py_nina_socket_listen,
|
||||||
|
.accept = py_nina_socket_accept,
|
||||||
|
.connect = py_nina_socket_connect,
|
||||||
|
.send = py_nina_socket_send,
|
||||||
|
.recv = py_nina_socket_recv,
|
||||||
|
.sendto = py_nina_socket_sendto,
|
||||||
|
.recvfrom = py_nina_socket_recvfrom,
|
||||||
|
.setsockopt = py_nina_socket_setsockopt,
|
||||||
|
.settimeout = py_nina_socket_settimeout,
|
||||||
|
.ioctl = py_nina_socket_ioctl,
|
||||||
|
};
|
||||||
|
#endif // MICROPY_PY_NINAW10
|
||||||
102
src/omv/ports/rp2/nina_bsp.c
Normal file
102
src/omv/ports/rp2/nina_bsp.c
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the OpenMV project.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||||
|
* Copyright (c) 2013-2021 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||||
|
*
|
||||||
|
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||||
|
*
|
||||||
|
* NINA-W10 driver BSP implementation.
|
||||||
|
*/
|
||||||
|
#if MICROPY_PY_NINAW10
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "py/mphal.h"
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/spi.h"
|
||||||
|
#include "omv_boardconfig.h"
|
||||||
|
|
||||||
|
#include "nina.h"
|
||||||
|
#include "nina_bsp.h"
|
||||||
|
|
||||||
|
int nina_bsp_init()
|
||||||
|
{
|
||||||
|
gpio_init(WIFI_CS_PIN);
|
||||||
|
gpio_set_dir(WIFI_CS_PIN, GPIO_OUT);
|
||||||
|
|
||||||
|
gpio_init(WIFI_ACK_PIN);
|
||||||
|
gpio_set_dir(WIFI_ACK_PIN, GPIO_IN);
|
||||||
|
|
||||||
|
gpio_init(WIFI_RST_PIN);
|
||||||
|
gpio_set_dir(WIFI_RST_PIN, GPIO_OUT);
|
||||||
|
|
||||||
|
gpio_init(WIFI_GPIO0_PIN);
|
||||||
|
gpio_set_dir(WIFI_GPIO0_PIN, GPIO_OUT);
|
||||||
|
|
||||||
|
gpio_put(WIFI_GPIO0_PIN, 1);
|
||||||
|
gpio_put(WIFI_CS_PIN, 1);
|
||||||
|
|
||||||
|
gpio_put(WIFI_RST_PIN, 0);
|
||||||
|
mp_hal_delay_ms(10);
|
||||||
|
gpio_put(WIFI_RST_PIN, 1);
|
||||||
|
mp_hal_delay_ms(750);
|
||||||
|
|
||||||
|
gpio_put(WIFI_GPIO0_PIN, 0);
|
||||||
|
|
||||||
|
spi_init(WIFI_SPI, 8 * 1000 * 1000);
|
||||||
|
|
||||||
|
gpio_set_function(WIFI_SCLK_PIN, GPIO_FUNC_SPI);
|
||||||
|
gpio_set_function(WIFI_MOSI_PIN, GPIO_FUNC_SPI);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_bsp_reset()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_bsp_spi_slave_select(uint32_t timeout)
|
||||||
|
{
|
||||||
|
// Wait for ACK to go low.
|
||||||
|
for (mp_uint_t start = mp_hal_ticks_ms(); gpio_get(WIFI_ACK_PIN) != 0; mp_hal_delay_ms(1)) {
|
||||||
|
if ((mp_hal_ticks_ms() - start) >= timeout) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chip select.
|
||||||
|
gpio_put(WIFI_CS_PIN, 0);
|
||||||
|
|
||||||
|
// Wait for ACK to go high.
|
||||||
|
for (mp_uint_t start = mp_hal_ticks_ms(); gpio_get(WIFI_ACK_PIN) == 0; mp_hal_delay_ms(1)) {
|
||||||
|
if ((mp_hal_ticks_ms() - start) >= 100) {
|
||||||
|
gpio_put(WIFI_CS_PIN, 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_bsp_spi_slave_deselect()
|
||||||
|
{
|
||||||
|
gpio_put(WIFI_CS_PIN, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size)
|
||||||
|
{
|
||||||
|
gpio_put(WIFI_CS_PIN, 0);
|
||||||
|
if (tx_buf && rx_buf) {
|
||||||
|
spi_write_read_blocking(WIFI_SPI, tx_buf, rx_buf, size);
|
||||||
|
} else if (tx_buf) {
|
||||||
|
spi_write_blocking(WIFI_SPI, tx_buf, size);
|
||||||
|
} else if (rx_buf) {
|
||||||
|
spi_read_blocking(WIFI_SPI, 0x00, rx_buf, size);
|
||||||
|
}
|
||||||
|
gpio_put(WIFI_CS_PIN, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif //MICROPY_PY_NINAW10
|
||||||
@ -14,6 +14,7 @@ set(CMSIS_DIR hal/cmsis)
|
|||||||
set(LEPTON_DIR drivers/lepton)
|
set(LEPTON_DIR drivers/lepton)
|
||||||
set(LSM6DS3_DIR drivers/lsm6ds3)
|
set(LSM6DS3_DIR drivers/lsm6ds3)
|
||||||
set(WINC1500_DIR drivers/winc1500)
|
set(WINC1500_DIR drivers/winc1500)
|
||||||
|
set(NINAW10_DIR drivers/ninaw10)
|
||||||
set(MLX90621_DIR drivers/mlx90621)
|
set(MLX90621_DIR drivers/mlx90621)
|
||||||
set(MLX90640_DIR drivers/mlx90640)
|
set(MLX90640_DIR drivers/mlx90640)
|
||||||
set(MLX90641_DIR drivers/mlx90641)
|
set(MLX90641_DIR drivers/mlx90641)
|
||||||
@ -77,6 +78,7 @@ target_include_directories(${MICROPY_TARGET} PRIVATE
|
|||||||
${TOP_DIR}/${LEPTON_DIR}/include/
|
${TOP_DIR}/${LEPTON_DIR}/include/
|
||||||
${TOP_DIR}/${LSM6DS3_DIR}/include/
|
${TOP_DIR}/${LSM6DS3_DIR}/include/
|
||||||
${TOP_DIR}/${WINC1500_DIR}/include/
|
${TOP_DIR}/${WINC1500_DIR}/include/
|
||||||
|
${TOP_DIR}/${NINAW10}/include/
|
||||||
${TOP_DIR}/${MLX90621_DIR}/include/
|
${TOP_DIR}/${MLX90621_DIR}/include/
|
||||||
${TOP_DIR}/${MLX90640_DIR}/include/
|
${TOP_DIR}/${MLX90640_DIR}/include/
|
||||||
${TOP_DIR}/${MLX90641_DIR}/include/
|
${TOP_DIR}/${MLX90641_DIR}/include/
|
||||||
@ -251,6 +253,26 @@ if(MICROPY_PY_ULAB)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(MICROPY_PY_NINAW10)
|
||||||
|
target_include_directories(${MICROPY_TARGET} PRIVATE
|
||||||
|
${TOP_DIR}/${NINAW10_DIR}/include/
|
||||||
|
)
|
||||||
|
|
||||||
|
set(NINA_SOURCES
|
||||||
|
${TOP_DIR}/${NINAW10_DIR}/src/nina.c
|
||||||
|
${TOP_DIR}/${OMV_DIR}/ports/${PORT}/nina_bsp.c
|
||||||
|
${TOP_DIR}/${OMV_DIR}/ports/${PORT}/modules/py_nina.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_sources(${MICROPY_TARGET} PRIVATE ${NINA_SOURCES})
|
||||||
|
|
||||||
|
target_compile_definitions(${MICROPY_TARGET} PRIVATE
|
||||||
|
MICROPY_PY_USOCKET=1
|
||||||
|
MICROPY_PY_NETWORK=1
|
||||||
|
MICROPY_PY_NINAW10=1
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_command(TARGET ${MICROPY_TARGET}
|
add_custom_command(TARGET ${MICROPY_TARGET}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${BIN_DIR}
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${BIN_DIR}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user