From 47514767bc08eb3b200fbfb78fdede3b1e42d521 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Wed, 16 Nov 2022 18:26:57 +0000 Subject: [PATCH] feat: Test IOTish things --- CMakeLists.txt | 44 ++++-- README.md | 1 + config_iot.h | 61 ++++++++ iot.cpp | 310 +++++++++++++++++++++++++++++++++++++ iot.h | 52 +++++++ lwipopts.h | 42 +++++ lwipopts_examples_common.h | 90 +++++++++++ main.cpp | 16 +- mbedtls_config.h | 67 ++++++++ mbedtls_util.c | 22 +++ 10 files changed, 694 insertions(+), 11 deletions(-) create mode 100644 config_iot.h create mode 100644 iot.cpp create mode 100644 iot.h create mode 100644 lwipopts.h create mode 100644 lwipopts_examples_common.h create mode 100644 mbedtls_config.h create mode 100644 mbedtls_util.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 964f31d..8148fed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,10 +27,15 @@ add_compile_options(-Wall -Wno-maybe-uninitialized ) -# Add your source files -add_executable(${NAME} - main.cpp ledcontrol.cpp ledcontrol.h util.h config.h encoder.cpp encoder.h -) +if ((PICO_CYW43_SUPPORTED) AND (TARGET pico_cyw43_arch)) + add_executable(${NAME} + main.cpp ledcontrol.cpp ledcontrol.h util.h config.h encoder.cpp encoder.h iot.cpp iot.h config_iot.h mbedtls_util.c + ) +else() + add_executable(${NAME} + main.cpp ledcontrol.cpp ledcontrol.h util.h config.h encoder.cpp encoder.h + ) +endif() # Include required libraries # This assumes `pimoroni-pico` is stored alongside your project @@ -49,12 +54,33 @@ target_link_libraries(${NAME} pico_bootsel_via_double_reset ) -if (PICO_CYW43_SUPPORTED) # set by BOARD=pico-w - if (TARGET pico_cyw43_arch) - target_link_libraries(${NAME} - pico_cyw43_arch_none # we need Wifi to access the GPIO, but we don't need anything else - ) +if ((PICO_CYW43_SUPPORTED) AND (TARGET pico_cyw43_arch)) # set by BOARD=pico-w + set(WIFI_SSID "${WIFI_SSID}" CACHE INTERNAL "WiFi SSID") + set(WIFI_PASSWORD "${WIFI_PASSWORD}" CACHE INTERNAL "WiFi password") + + if ("${WIFI_SSID}" STREQUAL "") + message(FATAL_ERROR "Skipping build as WIFI_SSID is not defined") + elseif ("${WIFI_PASSWORD}" STREQUAL "") + message(FATAL_ERROR "Skipping build as WIFI_PASSWORD is not defined") endif() + + target_compile_definitions(${NAME} PRIVATE + WIFI_SSID=\"${WIFI_SSID}\" + WIFI_PASSWORD=\"${WIFI_PASSWORD}\" + ) + + target_include_directories(${NAME} PRIVATE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts + ) + + target_link_libraries(${NAME} +# pico_cyw43_arch_lwip_poll + pico_cyw43_arch_lwip_threadsafe_background + pico_lwip_mbedtls + pico_mbedtls + pico_lwip_mqtt + ) endif() pico_enable_stdio_usb(${NAME} 1) diff --git a/README.md b/README.md index 40546bc..16bef25 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ And the Pico SDK: ``` git clone https://github.com/raspberrypi/pico-sdk cd pico-sdk +git checkout develop # Switch to develop branch git submodule update --init export PICO_SDK_PATH=`pwd` cd ../ diff --git a/config_iot.h b/config_iot.h new file mode 100644 index 0000000..b22ad96 --- /dev/null +++ b/config_iot.h @@ -0,0 +1,61 @@ +#ifndef CONFIG_IOT_H +#define CONFIG_IOT_H + +// Set this if you want to connect to MQTT securely +#define MQTT_TLS + +// MQTT server host name or ip address +#define MQTT_SERVER_HOST "test.mosquitto.org" + +// MQTT ports +#ifdef MQTT_TLS +#define MQTT_SERVER_PORT 8883 +#else +#define MQTT_SERVER_PORT 1883 +#endif + +// Enable this if you don't want certificate verification but still want to connect with TLS +//#define MQTT_TLS_INSECURE + +//#define MQTT_SERVER_HOST "91.121.93.94" +// add contents of https://test.mosquitto.org/ssl/mosquitto.org.crt here +#define MQTT_TLS_CERT "-----BEGIN CERTIFICATE-----\n" \ +"MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL\n" \ +"BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG\n" \ +"A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU\n" \ +"BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv\n" \ +"by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE\n" \ +"BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES\n" \ +"MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp\n" \ +"dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ\n" \ +"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg\n" \ +"UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW\n" \ +"Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA\n" \ +"s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH\n" \ +"3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo\n" \ +"E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT\n" \ +"MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV\n" \ +"6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n" \ +"BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC\n" \ +"6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf\n" \ +"+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK\n" \ +"sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839\n" \ +"LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE\n" \ +"m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=\n" \ +"-----END CERTIFICATE-----\n"; + +// Enable and configure these if you want client side certificates +/* +#define MQTT_TLS_KEY \ +"-----BEGIN RSA PRIVATE KEY-----\n" \ +"-----END RSA PRIVATE KEY-----"; +#define MQTT_TLS_CA \ +"-----BEGIN CERTIFICATE-----\n" \ +"-----END CERTIFICATE-----"; +*/ + +#define MQTT_CLIENT_ID "PicoW Ledcontrol" +//#define MQTT_CLIENT_USER "" +//#define MQTT_CLIENT_PASS "" + +#endif \ No newline at end of file diff --git a/iot.cpp b/iot.cpp new file mode 100644 index 0000000..08212a7 --- /dev/null +++ b/iot.cpp @@ -0,0 +1,310 @@ +#include "iot.h" +#include +#include +#include +#include "config_iot.h" + +#ifdef MQTT_TLS +#ifdef MQTT_TLS_CERT +const char *cert = MQTT_TLS_CERT; +#endif +#ifdef MQTT_TLS_CA +const char *ca = MQTT_TLS_CA; +#endif +#ifdef MQTT_TLS_KEY +const char *key = MQTT_TLS_KEY; +#endif +#endif + +IOT::IOT(): +_loop_cb(NULL) { +} + +int IOT::init(const char *ssid, const char *password, uint32_t authmode, void (*loop_cb)()) { + _loop_cb = loop_cb; + + cyw43_arch_enable_sta_mode(); + + printf("[wifi] connecting...\n"); + if (cyw43_arch_wifi_connect_timeout_ms(ssid, password, authmode, 30000)) { + printf("[wifi] failed to connect\n"); + return -1; + } + + printf("[wifi] connected\n"); + + mqtt_run_test(MQTT_SERVER_HOST, MQTT_SERVER_PORT); + return 0; +} + +void IOT::poll_wifi(uint32_t min_sleep_ms) { +// if (min_sleep_ms < 1) min_sleep_ms = 1; + + uint32_t start_time = to_ms_since_boot(get_absolute_time()); + uint32_t last_time; + do { +#if PICO_CYW43_ARCH_POLL + cyw43_arch_poll(); + sleep_ms(1); +#endif + if (_loop_cb != NULL) (*_loop_cb)(); + last_time = to_ms_since_boot(get_absolute_time()); + } while(start_time + min_sleep_ms > last_time); +} + +void IOT::_dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { + printf("[dns] found! %s\n", ip4addr_ntoa(ipaddr)); + auto ip = (ip_addr_t*)callback_arg; + *ip = *ipaddr; +} + +// run_dns_lookup tries to resolve the given host and set it to addr +int IOT::run_dns_lookup(const char *host, ip_addr_t *addr) { + addr->addr = 0; + printf("[dns] looking up %s\n", host); + + cyw43_arch_lwip_begin(); + err_t err = dns_gethostbyname(host, addr, _iot_dns_found_cb, addr); + cyw43_arch_lwip_end(); + + if (err == ERR_ARG) { + printf("[dns] failed to start query\n"); + return -1; + } + + if (err == ERR_OK) { + printf("[dns] no lookup needed\n"); + // addr was already written to from the cache, nothing to do + return 0; + } + + while (addr->addr == 0) poll_wifi(); + return 0; +} + +void IOT::mqtt_disconnect_and_free(mqtt_wrapper_t *state) { + if (!state->mqtt_client) return; + + mqtt_disconnect(state->mqtt_client); + mqtt_client_free(state->mqtt_client); + state->mqtt_client = NULL; +} + +int IOT::mqtt_fresh_state(const char *mqtt_host, uint16_t mqtt_port, mqtt_wrapper_t *state) { + // clean up previous state + mqtt_disconnect_and_free(state); + + state->mqtt_client = mqtt_client_new(); + if (state->mqtt_client == NULL) { + printf("[mqtt] failed to create client\n"); + return -1; + } + + ip_addr_t host_addr; + if (run_dns_lookup(mqtt_host, &host_addr)) { + printf("[dns] failed to resolve host\n"); + return -1; + } + printf("[dns] resolved addr to %s.\n", ip4addr_ntoa(&host_addr)); + + state->mqtt_client = mqtt_client_new(); + if (state->mqtt_client == NULL) { + printf("[mqtt] failed to create client\n"); + return -2; + } + + int res = mqtt_connect(host_addr, mqtt_port, state); + if (res != 0) { + printf("[mqtt] failed to connect: %d\n", res); + return -3; + } + + return 0; +} + +int IOT::mqtt_run_test(const char *mqtt_host, uint16_t mqtt_port) { + mqtt_wrapper_t *state = new mqtt_wrapper_t(); + state->mqtt_client = NULL; + state->reconnect = 0; + state->received = 0; + state->receiving = 0; + state->counter = 0; + int res = mqtt_fresh_state(mqtt_host, mqtt_port, state); + if (res != 0) { + printf("[mqtt] failed to init: %d\n", res); + return res; + } + +#if PICO_CYW43_ARCH_POLL + const uint32_t max_wait = 5000; + + u32_t notReady = max_wait; +#endif + + while (true) { + poll_wifi(); +#if PICO_CYW43_ARCH_POLL + if (!notReady--) { +#else + { +#endif +#if PICO_CYW43_ARCH_POLL + notReady = max_wait; +#endif + + cyw43_arch_lwip_begin(); + bool connected = mqtt_client_is_connected(state->mqtt_client); + cyw43_arch_lwip_end(); + if (!connected) { + printf(","); + continue; + } + + printf("[mqtt] connected\n"); + state->receiving = 1; + err_t err = mqtt_test_publish(state); + if (err != ERR_OK) { + printf("[mqtt] failed to publish, will retry: %d\n", err); + continue; + } + printf("[mqtt] published %d\n", state->counter); + state->counter++; + poll_wifi(5000); + + int res = mqtt_fresh_state(mqtt_host, mqtt_port, state); + if (res != 0) { + printf("[mqtt] failed to reinit: %d\n", res); + return res; + } + } + } // while + + return 0; +} + +int IOT::mqtt_connect(ip_addr_t host_addr, uint16_t host_port, mqtt_wrapper_t *state) { + struct mqtt_connect_client_info_t ci; + err_t err; + + memset(&ci, 0, sizeof(ci)); + + ci.client_id = MQTT_CLIENT_ID; +#ifdef MQTT_CLIENT_USER + ci.client_user = MQTT_CLIENT_USER; +#else + ci.client_user = NULL; +#endif +#ifdef MQTT_CLIENT_PASS + ci.client_pass = MQTT_CLIENT_PASS; +#else + ci.client_pass = NULL; +#endif + ci.keep_alive = 0; + ci.will_topic = NULL; + ci.will_msg = NULL; + ci.will_retain = 0; + +#ifdef MQTT_TLS + struct altcp_tls_config *tls_config; + +#ifdef MQTT_TLS_INSECURE + printf("[mqtt] Setting up TLS insecure mode...\n"); + tls_config = altcp_tls_create_config_client(NULL, 0); +#elif defined(MQTT_TLS_CERT) && defined(MQTT_TLS_KEY) && defined(MQTT_TLS_CA) + printf("[mqtt] Setting up TLS with 2wayauth...\n"); + tls_config = altcp_tls_create_config_client_2wayauth( + (const u8_t *)ca, 1 + strlen(ca), + (const u8_t *)key, 1 + strlen(key), + (const u8_t *)"", 0, + (const u8_t *)cert, 1 + strlen(cert) + ); +#elif defined(MQTT_TLS_CERT) + printf("[mqtt] Setting up TLS with cert...\n"); + tls_config = altcp_tls_create_config_client((const u8_t *) cert, 1 + strlen(cert)); +#else + #error "MQTT_TLS set but no TLS config. Please edit config_iot.h" +#endif // MQTT_TLS_INSECURE + + if (tls_config == NULL) { + // check error code shown with `strerror`, eg. `strerror -8576` + printf("\n[mqtt] Failed to initialize TLS config\n"); + return -1; + } + +// mbedtls_ssl_set_hostname(altcp_tls_context((struct altcp_pcb *)conn), MQTT_SERVER_HOST); + + ci.tls_config = tls_config; +#endif // MQTT_TLS + + cyw43_arch_lwip_begin(); + err = mqtt_client_connect(state->mqtt_client, &host_addr, host_port, _iot_mqtt_connection_cb, state, &ci); + // memp_malloc: out of memory in pool TCP_PCB + cyw43_arch_lwip_end(); + if (err != ERR_OK) { + printf("[mqtt] mqtt_client_connect returned error: %d\n", err); + return -2; + } + + printf("[mqtt] mqtt_client_connect successful.\n"); + return 0; +} + +err_t IOT::mqtt_test_publish(mqtt_wrapper_t *state) +{ + char buffer[128]; + +#ifdef MQTT_TLS +#ifdef MQTT_TLS_INSECURE +#define TLS_STR "TLS insecure" +#else +#define TLS_STR "TLS" +#endif +#else +#define TLS_STR "" +#endif + + sprintf(buffer, "hello from picow %s %d / %d %s", MQTT_CLIENT_ID, state->received, state->counter, TLS_STR); + + err_t err; + u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ + u8_t retain = 0; + cyw43_arch_lwip_begin(); + err = mqtt_publish(state->mqtt_client, "pico_w/test", buffer, strlen(buffer), qos, retain, _iot_mqtt_pub_request_cb, &state); + cyw43_arch_lwip_end(); + return err; +} + +void IOT::_mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) { +// mqtt_wrapper_t *state = (mqtt_wrapper_t*)arg; + if (status != 0) { + printf("[mqtt] connection failed (callback): %d\n", status); + return; + } + printf("[mqtt] connected (callback)\n"); +} + +void IOT::_mqtt_pub_request_cb(void *arg, err_t err) { + mqtt_wrapper_t *state = (mqtt_wrapper_t*)arg; + if (err == ERR_OK) { + printf("[mqtt] (cb) publish successful\n"); + } else { + printf("[mqtt] (cb) publish failed: %d\n", err); + } + state->receiving=0; + state->received++; +} + +IOT iot; + +// callback "bindings" to homemade static methods +static void _iot_dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { + iot._dns_found_cb(name, ipaddr, callback_arg); +} + +static void _iot_mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) { + iot._mqtt_connection_cb(client, arg, status); +} + +static void _iot_mqtt_pub_request_cb(void *arg, err_t err) { + iot._mqtt_pub_request_cb(arg, err); +} diff --git a/iot.h b/iot.h new file mode 100644 index 0000000..d9fc2d0 --- /dev/null +++ b/iot.h @@ -0,0 +1,52 @@ +#ifndef IOT_H +#define IOT_H + +#include +#include +#include "pico/stdlib.h" +#include "pico/cyw43_arch.h" +#include "hardware/structs/rosc.h" +#include "lwip/pbuf.h" +#include "lwip/altcp_tcp.h" +#include "lwip/altcp_tls.h" +#include "lwip/dns.h" +#include "lwip/apps/mqtt.h" + +class IOT { + private: + typedef struct { + mqtt_client_t *mqtt_client; + u8_t receiving; + u32_t received; + u32_t counter; + u32_t reconnect; + } mqtt_wrapper_t; + + void (*_loop_cb)(); + + void poll_wifi(uint32_t min_sleep_ms = 100); + int run_dns_lookup(const char *host, ip_addr_t *addr); + int mqtt_connect(ip_addr_t host_addr, uint16_t host_port, mqtt_wrapper_t *state); + void mqtt_disconnect_and_free(mqtt_wrapper_t *state); + err_t mqtt_test_publish(mqtt_wrapper_t *state); + int mqtt_fresh_state(const char *mqtt_host, uint16_t mqtt_port, mqtt_wrapper_t *state); + + public: + IOT(); + int init(const char *ssid, const char *password, uint32_t authmode, void (*loop_cb)()); + int mqtt_run_test(const char *mqtt_host, uint16_t mqtt_port); + + // callbacks + void _dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg); + void _mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); + void _mqtt_pub_request_cb(void *arg, err_t err); + +}; + +extern IOT iot; + +static void _iot_dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg); +static void _iot_mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); +static void _iot_mqtt_pub_request_cb(void *arg, err_t err); + +#endif //IOT_H diff --git a/lwipopts.h b/lwipopts.h new file mode 100644 index 0000000..86da86a --- /dev/null +++ b/lwipopts.h @@ -0,0 +1,42 @@ +#ifndef _LWIPOPTS_H +#define _LWIPOPTS_H + +#include "lwipopts_examples_common.h" + +/* TCP WND must be at least 16 kb to match TLS record size + or you will get a warning "altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!" */ +#undef TCP_WND +#define TCP_WND 16384 + +#undef MEM_SIZE +#define MEM_SIZE 32768 + + +#define LWIP_ALTCP 1 +#define LWIP_ALTCP_TLS 1 +#define LWIP_ALTCP_TLS_MBEDTLS 1 + +#define LWIP_DEBUG 1 +#define ALTCP_MBEDTLS_DEBUG LWIP_DBG_ON + +#undef MEM_DEBUG +#undef MEMP_DEBUG +#define MEM_DEBUG LWIP_DBG_ON +#define MEMP_DEBUG LWIP_DBG_ON + +#undef MEM_STATS +#define MEM_STATS 1 + +#undef SYS_STATS +#define SYS_STATS 1 + +#undef MEMP_STATS +#define MEMP_STATS 1 + +#define MEM_OVERFLOW_CHECK 1 +#define MEMP_OVERFLOW_CHECK 1 + +// this is the important bit. 8 is arbitrary. +#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + 8) + +#endif diff --git a/lwipopts_examples_common.h b/lwipopts_examples_common.h new file mode 100644 index 0000000..217cb13 --- /dev/null +++ b/lwipopts_examples_common.h @@ -0,0 +1,90 @@ +#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H +#define _LWIPOPTS_EXAMPLE_COMMONH_H + + +// Common settings used in most of the pico_w examples +// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) + +// allow override in some examples +#ifndef NO_SYS +#define NO_SYS 1 +#endif +// allow override in some examples +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 0 +#endif +#if PICO_CYW43_ARCH_POLL +#define MEM_LIBC_MALLOC 1 +#else +// MEM_LIBC_MALLOC is incompatible with non polling versions +#define MEM_LIBC_MALLOC 0 +#endif +#define MEM_ALIGNMENT 4 +#define MEM_SIZE 4000 +#define MEMP_NUM_TCP_SEG 32 +#define MEMP_NUM_ARP_QUEUE 10 +#define PBUF_POOL_SIZE 24 +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_ICMP 1 +#define LWIP_RAW 1 +#define TCP_WND (8 * TCP_MSS) +#define TCP_MSS 1460 +#define TCP_SND_BUF (8 * TCP_MSS) +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETCONN 0 +#define MEM_STATS 0 +#define SYS_STATS 0 +#define MEMP_STATS 0 +#define LINK_STATS 0 +// #define ETH_PAD_SIZE 2 +#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_DHCP 1 +#define LWIP_IPV4 1 +#define LWIP_TCP 1 +#define LWIP_UDP 1 +#define LWIP_DNS 1 +#define LWIP_TCP_KEEPALIVE 1 +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#define DHCP_DOES_ARP_CHECK 0 +#define LWIP_DHCP_DOES_ACD_CHECK 0 + +#ifndef NDEBUG +#define LWIP_DEBUG 1 +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 +#endif + +#define ETHARP_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_OFF +#define PBUF_DEBUG LWIP_DBG_OFF +#define API_LIB_DEBUG LWIP_DBG_OFF +#define API_MSG_DEBUG LWIP_DBG_OFF +#define SOCKETS_DEBUG LWIP_DBG_OFF +#define ICMP_DEBUG LWIP_DBG_OFF +#define INET_DEBUG LWIP_DBG_OFF +#define IP_DEBUG LWIP_DBG_OFF +#define IP_REASS_DEBUG LWIP_DBG_OFF +#define RAW_DEBUG LWIP_DBG_OFF +#define MEM_DEBUG LWIP_DBG_OFF +#define MEMP_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_OFF +#define TCP_DEBUG LWIP_DBG_OFF +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#define TCP_WND_DEBUG LWIP_DBG_OFF +#define TCP_FR_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF +#define UDP_DEBUG LWIP_DBG_OFF +#define TCPIP_DEBUG LWIP_DBG_OFF +#define PPP_DEBUG LWIP_DBG_OFF +#define SLIP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_OFF + +#endif /* __LWIPOPTS_H__ */ diff --git a/main.cpp b/main.cpp index 2bf3977..1e09103 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ #include "pico/stdlib.h" #ifdef RASPBERRYPI_PICO_W #include "pico/cyw43_arch.h" +#include "iot.h" #endif #include "ledcontrol.h" @@ -16,16 +17,21 @@ void board_led(bool val) { #endif } +void wifi_looper() { + printf("."); + sleep_ms(500); +} + int main() { stdio_init_all(); #ifdef RASPBERRYPI_PICO_W if (cyw43_arch_init()) { - printf("WiFi init failed"); + printf("WiFi init failed\n"); return -1; } #endif - if (false) +// if (false) { board_led(true); while (!stdio_usb_connected()) sleep_ms(100); @@ -33,6 +39,12 @@ int main() { board_led(false); } +#ifdef RASPBERRYPI_PICO_W + auto val = iot.init(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, wifi_looper); + printf("iot returned: %d\n", val); + while(true) sleep_ms(1000); +#endif + auto leds = ledcontrol::LEDControl(); leds.init(&encoder); diff --git a/mbedtls_config.h b/mbedtls_config.h new file mode 100644 index 0000000..2e87d49 --- /dev/null +++ b/mbedtls_config.h @@ -0,0 +1,67 @@ +/* Workaround for some mbedtls source files using INT_MAX without including limits.h */ +#include + +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_ENTROPY_HARDWARE_ALT + +#define MBEDTLS_SSL_OUT_CONTENT_LEN 2048 + +#define MBEDTLS_ALLOW_PRIVATE_ACCESS +#define MBEDTLS_HAVE_TIME + +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_SHA256_SMALLER +#define MBEDTLS_SSL_SERVER_NAME_INDICATION +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS5_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C + +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA224_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C +#define MBEDTLS_AES_FEWER_TABLES + +/* TLS 1.2 */ +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define MBEDTLS_GCM_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ASN1_WRITE_C + +// these were added for ledcontrol +#define MBEDTLS_BASE64_C +#define MBEDTLS_PEM_PARSE_C diff --git a/mbedtls_util.c b/mbedtls_util.c new file mode 100644 index 0000000..aa3f235 --- /dev/null +++ b/mbedtls_util.c @@ -0,0 +1,22 @@ +#include "hardware/structs/rosc.h" +#include "pico/stdlib.h" + +/* cribbed from https://github.com/peterharperuk/pico-examples/tree/add_mbedtls_example */ +/* Function to feed mbedtls entropy. May be better to move it to pico-sdk */ +int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) { + /* Code borrowed from pico_lwip_random_byte(), which is static, so we cannot call it directly */ + static uint8_t byte; + + for(size_t p=0; prandombit) ^ (byte & 0x80u ? 0x35u : 0); + // delay a little because the random bit is a little slow + busy_wait_at_least_cycles(30); + } + output[p] = byte; + } + + *olen = len; + return 0; +}