Initial version

This commit is contained in:
Sandeep Mistry
2018-06-28 12:55:29 +02:00
parent 763916f80a
commit 48ebd39cfd
34 changed files with 4216 additions and 10 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
build/

5
Makefile Normal file
View File

@@ -0,0 +1,5 @@
PROJECT_NAME := mkrwifi1010-fw
EXTRA_COMPONENT_DIRS := $(PWD)/arduino
include $(IDF_PATH)/make/project.mk

31
README.md Normal file
View File

@@ -0,0 +1,31 @@
# MKR WiFi 1010: NINA-W102 firmware
This firmware uses [Espressif's IDF](https://github.com/espressif/esp-idf)
## Building
1. [Download the ESP32 toolchain](http://esp-idf.readthedocs.io/en/v3.0/get-started/index.html#setup-toolchain)
1. Extract it and add it to your `PATH`: `export PATH=$PATH:<path/to/toolchain>/bin`
1. Clone **v3.0** of the IDF: `git clone --branch v3.0 --recursive https://github.com/espressif/esp-idf.git`
1. Set the `IDF_PATH` environment variable: `export IDF_PATH=<path/to/idf>`
1. Run `make` to build the firmware (in the directory of this read me)
1. Load the `WiFi1010FirmwareUpdater` example sketch on to the board
1. Use `esptool` to flash the compiled firmware
## License
Copyright (c) 2018 Arduino AG. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

3
arduino/component.mk Normal file
View File

@@ -0,0 +1,3 @@
COMPONENT_ADD_INCLUDEDIRS := cores/esp32 libraries/SPIS/src libraries/WiFi/src
COMPONENT_SRCDIRS := cores/esp32 libraries/SPIS/src libraries/WiFi/src

View File

@@ -0,0 +1,52 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ARDUINO_H
#define ARDUINO_H
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
// system functions
void init(void);
// sketch
void setup(void);
void loop(void);
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
#include "WMath.h"
#endif
#include "delay.h"
#include "wiring_digital.h"
#include "wiring_analog.h"
#endif // ARDUINO_H

View File

@@ -0,0 +1,74 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <driver/gpio.h>
#include "wiring_digital.h"
#include "WInterrupts.h"
static voidFuncPtr callbacksInt[GPIO_NUM_MAX] = { NULL };
void IRAM_ATTR gpioInterruptHandler(void* arg)
{
uint32_t pin = (uint32_t)arg;
if (callbacksInt[pin]) {
callbacksInt[pin]();
}
}
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
{
callbacksInt[pin] = callback;
switch (mode) {
case LOW:
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_LOW_LEVEL);
gpio_wakeup_enable((gpio_num_t)pin, GPIO_INTR_LOW_LEVEL);
break;
case HIGH:
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_HIGH_LEVEL);
gpio_wakeup_enable((gpio_num_t)pin, GPIO_INTR_HIGH_LEVEL);
break;
case CHANGE:
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_ANYEDGE);
break;
case FALLING:
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_NEGEDGE);
break;
case RISING:
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_POSEDGE);
break;
default:
gpio_set_intr_type((gpio_num_t)pin, GPIO_INTR_DISABLE);
break;
}
gpio_install_isr_service(ESP_INTR_FLAG_LEVEL3);
gpio_isr_handler_add((gpio_num_t)pin, gpioInterruptHandler, (void*)pin);
gpio_intr_enable((gpio_num_t)pin);
}

View File

@@ -0,0 +1,43 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _WIRING_INTERRUPTS_
#define _WIRING_INTERRUPTS_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// #define LOW 0
// #define HIGH 1
#define CHANGE 2
#define FALLING 3
#define RISING 4
typedef void (*voidFuncPtr)(void);
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,33 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
extern "C" {
#include <esp_system.h>
}
#include "WMath.h"
extern long random(long howbig)
{
if(howbig == 0) {
return 0;
}
return esp_random() % howbig;
}

View File

@@ -0,0 +1,33 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _WIRING_MATH_
#define _WIRING_MATH_
#ifdef __cplusplus
extern "C" {
#endif
extern long random(long);
#ifdef __cplusplus
}
#endif
#endif /* _WIRING_MATH_ */

View File

@@ -0,0 +1,33 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "delay.h"
unsigned long millis()
{
return xTaskGetTickCount() * portTICK_PERIOD_MS;
}
void delay(uint32_t ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}

View File

@@ -0,0 +1,37 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DELAY_H
#define DELAY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
extern unsigned long millis();
extern void delay(uint32_t ms);
#ifdef __cplusplus
}
#endif
#endif // DELAY_H

View File

@@ -0,0 +1,40 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#define ARDUINO_MAIN
#include "Arduino.h"
void arduino_main(void*) {
init();
setup();
while (1) {
loop();
}
}
extern "C" {
void app_main() {
xTaskCreatePinnedToCore(arduino_main, "arduino", 8192, NULL, 1, NULL, 1);
}
}

View File

@@ -0,0 +1,26 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <nvs_flash.h>
#include "Arduino.h"
void init() {
nvs_flash_init();
}

View File

@@ -0,0 +1,45 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <driver/ledc.h>
#include "wiring_analog.h"
void analogWrite(uint32_t pin, uint32_t value)
{
periph_module_enable(PERIPH_LEDC_MODULE);
ledc_timer_config_t timerConf = {
.bit_num = LEDC_TIMER_10_BIT,
.freq_hz = 1000,
.speed_mode = LEDC_HIGH_SPEED_MODE,
.timer_num = (pin / 7),
};
ledc_timer_config(&timerConf);
ledc_channel_config_t ledc_conf = {
.channel = (pin % 7),
.duty = (value << 2),
.gpio_num = pin,
.intr_type = LEDC_INTR_DISABLE,
.speed_mode = LEDC_HIGH_SPEED_MODE,
.timer_sel = (pin / 7)
};
ledc_channel_config(&ledc_conf);
}

View File

@@ -0,0 +1,35 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIRING_ANALOG_H
#define WIRING_ANALOG_H
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void analogWrite(uint32_t pin, uint32_t value);
#ifdef __cplusplus
}
#endif
#endif // WIRING_ANALOG_H

View File

@@ -0,0 +1,44 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <driver/gpio.h>
#include "wiring_digital.h"
void pinMode(uint32_t pin, uint32_t mode)
{
switch (mode) {
case INPUT:
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_INPUT);
gpio_set_pull_mode((gpio_num_t)pin, GPIO_FLOATING);
break;
case OUTPUT:
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_OUTPUT);
gpio_set_pull_mode((gpio_num_t)pin, GPIO_FLOATING);
break;
}
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], PIN_FUNC_GPIO);
}
void digitalWrite(uint32_t pin, uint32_t val)
{
gpio_set_level((gpio_num_t)pin, val);
}

View File

@@ -0,0 +1,43 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIRING_DIGITAL_H
#define WIRING_DIGITAL_H
#include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LOW 0x00
#define HIGH 0x01
#define INPUT 0x00
#define OUTPUT 0x01
extern void pinMode(uint32_t pin, uint32_t mode);
extern void digitalWrite(uint32_t pin, uint32_t val);
#ifdef __cplusplus
}
#endif
#endif // WIRING_DIGITAL_H

View File

@@ -0,0 +1,116 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <driver/gpio.h>
#include <driver/spi_slave.h>
#include "wiring_digital.h"
#include "WInterrupts.h"
#include "SPIS.h"
SPISClass::SPISClass(spi_host_device_t hostDevice, int dmaChannel, int mosiPin, int misoPin, int sclkPin, int csPin, int readyPin) :
_hostDevice(hostDevice),
_dmaChannel(dmaChannel),
_mosiPin(mosiPin),
_misoPin(misoPin),
_sclkPin(sclkPin),
_csPin(csPin),
_readyPin(readyPin)
{
}
int SPISClass::begin()
{
spi_bus_config_t busCfg;
spi_slave_interface_config_t slvCfg;
pinMode(_readyPin, OUTPUT);
digitalWrite(_readyPin, HIGH);
_readySemaphore = xSemaphoreCreateCounting(1, 0);
attachInterrupt(_csPin, onChipSelect, FALLING);
memset(&busCfg, 0x00, sizeof(busCfg));
busCfg.mosi_io_num = _mosiPin;
busCfg.miso_io_num = _misoPin;
busCfg.sclk_io_num = _sclkPin;
memset(&slvCfg, 0x00, sizeof(slvCfg));
slvCfg.mode = 0;
slvCfg.spics_io_num = _csPin;
slvCfg.queue_size = 1;
slvCfg.flags = 0;
slvCfg.post_setup_cb = SPISClass::onSetupComplete;
slvCfg.post_trans_cb = NULL;
gpio_set_pull_mode((gpio_num_t)_mosiPin, GPIO_FLOATING);
gpio_set_pull_mode((gpio_num_t)_sclkPin, GPIO_PULLDOWN_ONLY);
gpio_set_pull_mode((gpio_num_t)_csPin, GPIO_PULLUP_ONLY);
spi_slave_initialize(_hostDevice, &busCfg, &slvCfg, _dmaChannel);
return 1;
}
int SPISClass::transfer(uint8_t out[], uint8_t in[], size_t len)
{
spi_slave_transaction_t slvTrans;
spi_slave_transaction_t* slvRetTrans;
memset(&slvTrans, 0x00, sizeof(slvTrans));
slvTrans.length = len * 8;
slvTrans.trans_len = 0;
slvTrans.tx_buffer = out;
slvTrans.rx_buffer = in;
spi_slave_queue_trans(_hostDevice, &slvTrans, portMAX_DELAY);
xSemaphoreTake(_readySemaphore, portMAX_DELAY);
digitalWrite(_readyPin, LOW);
spi_slave_get_trans_result(_hostDevice, &slvRetTrans, portMAX_DELAY);
digitalWrite(_readyPin, HIGH);
return (slvTrans.trans_len / 8);
}
void SPISClass::onChipSelect()
{
SPIS.handleOnChipSelect();
}
void SPISClass::handleOnChipSelect()
{
digitalWrite(_readyPin, HIGH);
}
void SPISClass::onSetupComplete(spi_slave_transaction_t*)
{
SPIS.handleSetupComplete();
}
void SPISClass::handleSetupComplete()
{
xSemaphoreGiveFromISR(_readySemaphore, NULL);
}
SPISClass SPIS(VSPI_HOST, 1, 12, 23, 18, 5, 33);

View File

@@ -0,0 +1,58 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SPIS_H
#define SPIS_H
#include <driver/spi_common.h>
#include <driver/spi_slave.h>
class SPISClass {
public:
SPISClass(spi_host_device_t hostDevice, int dmaChannel, int mosiPin, int misoPin, int sclkPin, int csPin, int readyPin);
int begin();
int transfer(uint8_t out[], uint8_t in[], size_t len);
private:
static void onChipSelect();
void handleOnChipSelect();
static void onSetupComplete(spi_slave_transaction_t*);
void handleSetupComplete();
private:
spi_host_device_t _hostDevice;
int _dmaChannel;
int _mosiPin;
int _misoPin;
int _sclkPin;
int _csPin;
int _readyPin;
intr_handle_t _csIntrHandle;
SemaphoreHandle_t _readySemaphore;
};
extern SPISClass SPIS;
#endif

View File

@@ -0,0 +1,674 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <time.h>
#include <esp_wifi.h>
#include <tcpip_adapter.h>
#include <apps/sntp/sntp.h>
#include <lwip/dns.h>
#include <lwip/netdb.h>
#include <lwip/raw.h>
#include <lwip/icmp.h>
#include <lwip/sockets.h>
#include <lwip/ip_addr.h>
#include <lwip/inet_chksum.h>
#include "WiFi.h"
WiFiClass::WiFiClass() :
_initialized(false),
_status(WL_NO_SHIELD),
_interface(ESP_IF_WIFI_STA),
_onReceiveCallback(NULL)
{
_eventGroup = xEventGroupCreate();
memset(&_apRecord, 0x00, sizeof(_apRecord));
memset(&_ipInfo, 0x00, sizeof(_ipInfo));
}
uint8_t WiFiClass::status()
{
if (!_initialized) {
_initialized = true;
init();
}
return _status;
}
int WiFiClass::hostByName(const char* hostname, /*IPAddress*/uint32_t& result)
{
result = 0xffffffff;
struct hostent* hostEntry = lwip_gethostbyname(hostname);
if (hostEntry == NULL) {
return 0;
}
memcpy(&result, hostEntry->h_addr_list[0], sizeof(result));
return 1;
}
int WiFiClass::ping(/*IPAddress*/uint32_t host, uint8_t ttl)
{
uint32_t timeout = 5000;
int s = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP);
struct timeval timeoutVal;
timeoutVal.tv_sec = (timeout / 1000);
timeoutVal.tv_usec = (timeout % 1000) * 1000;
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeoutVal, sizeof(timeoutVal));
setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
struct __attribute__((__packed__)) {
struct icmp_echo_hdr header;
uint8_t data[32];
} request;
ICMPH_TYPE_SET(&request.header, ICMP_ECHO);
ICMPH_CODE_SET(&request.header, 0);
request.header.chksum = 0;
request.header.id = 0xAFAF;
request.header.seqno = random(0xffff);
for (size_t i = 0; i < sizeof(request.data); i++) {
request.data[i] = i;
}
request.header.chksum = inet_chksum(&request, sizeof(request));
ip_addr_t addr;
addr.type = IPADDR_TYPE_V4;
addr.u_addr.ip4.addr = host;
// IP_ADDR4(&addr, ip[0], ip[1], ip[2], ip[3]);
struct sockaddr_in to;
struct sockaddr_in from;
to.sin_len = sizeof(to);
to.sin_family = AF_INET;
inet_addr_from_ipaddr(&to.sin_addr, ip_2_ip4(&addr));
sendto(s, &request, sizeof(request), 0, (struct sockaddr*)&to, sizeof(to));
unsigned long sendTime = millis();
unsigned long recvTime = 0;
do {
socklen_t fromlen = sizeof(from);
struct __attribute__((__packed__)) {
struct ip_hdr ipHeader;
struct icmp_echo_hdr header;
} response;
int rxSize = recvfrom(s, &response, sizeof(response), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen);
if (rxSize == -1) {
// time out
break;
}
if (rxSize < sizeof(response)) {
// too short
continue;
}
if (from.sin_family != AF_INET) {
// not IPv4
continue;
}
if ((response.header.id == request.header.id) && (response.header.seqno == request.header.seqno)) {
recvTime = millis();
}
} while (recvTime == 0);
close(s);
if (recvTime == 0) {
return -1;
} else {
return (recvTime - sendTime);
}
}
uint8_t WiFiClass::begin(const char* ssid)
{
return begin(ssid, "");
}
uint8_t WiFiClass::begin(const char* ssid, uint8_t key_idx, const char* key)
{
return begin(ssid, key);
}
uint8_t WiFiClass::begin(const char* ssid, const char* key)
{
wifi_config_t wifiConfig;
memset(&wifiConfig, 0x00, sizeof(wifiConfig));
strncpy((char*)wifiConfig.sta.ssid, ssid, sizeof(wifiConfig.sta.ssid));
strncpy((char*)wifiConfig.sta.password, key, sizeof(wifiConfig.sta.password));
_status = WL_NO_SSID_AVAIL;
_interface = ESP_IF_WIFI_STA;
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_start();
xEventGroupWaitBits(_eventGroup, BIT0, false, true, portMAX_DELAY);
if (esp_wifi_set_config(ESP_IF_WIFI_STA, &wifiConfig) != ESP_OK) {
_status = WL_CONNECT_FAILED;
}
esp_wifi_connect();
return _status;
}
uint8_t WiFiClass::beginAP(const char *ssid, uint8_t channel)
{
wifi_config_t wifiConfig;
memset(&wifiConfig, 0x00, sizeof(wifiConfig));
strncpy((char*)wifiConfig.ap.ssid, ssid, sizeof(wifiConfig.sta.ssid));
wifiConfig.ap.channel = 0;
wifiConfig.ap.authmode = WIFI_AUTH_OPEN;
wifiConfig.ap.max_connection = 4;
_status = WL_NO_SSID_AVAIL;
_interface = ESP_IF_WIFI_AP;
esp_wifi_stop();
esp_wifi_set_mode(WIFI_MODE_AP);
if (esp_wifi_set_config(ESP_IF_WIFI_AP, &wifiConfig) != ESP_OK) {
_status = WL_AP_FAILED;
}
esp_wifi_start();
xEventGroupWaitBits(_eventGroup, BIT1, false, true, portMAX_DELAY);
return _status;
}
uint8_t WiFiClass::beginAP(const char *ssid, uint8_t key_idx, const char* key, uint8_t channel)
{
wifi_config_t wifiConfig;
memset(&wifiConfig, 0x00, sizeof(wifiConfig));
strncpy((char*)wifiConfig.ap.ssid, ssid, sizeof(wifiConfig.sta.ssid));
strncpy((char*)wifiConfig.ap.password, key, sizeof(wifiConfig.sta.password));
wifiConfig.ap.channel = 0;
wifiConfig.ap.authmode = WIFI_AUTH_WEP;
wifiConfig.ap.max_connection = 4;
_status = WL_NO_SSID_AVAIL;
_interface = ESP_IF_WIFI_AP;
esp_wifi_stop();
esp_wifi_set_mode(WIFI_MODE_AP);
if (esp_wifi_set_config(ESP_IF_WIFI_AP, &wifiConfig) != ESP_OK) {
_status = WL_AP_FAILED;
}
esp_wifi_start();
xEventGroupWaitBits(_eventGroup, BIT1, false, true, portMAX_DELAY);
return _status;
}
uint8_t WiFiClass::beginAP(const char *ssid, const char* key, uint8_t channel)
{
wifi_config_t wifiConfig;
memset(&wifiConfig, 0x00, sizeof(wifiConfig));
strncpy((char*)wifiConfig.ap.ssid, ssid, sizeof(wifiConfig.sta.ssid));
strncpy((char*)wifiConfig.ap.password, key, sizeof(wifiConfig.sta.password));
wifiConfig.ap.channel = 0;
wifiConfig.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
wifiConfig.ap.max_connection = 4;
_status = WL_NO_SSID_AVAIL;
_interface = ESP_IF_WIFI_AP;
esp_wifi_stop();
esp_wifi_set_mode(WIFI_MODE_AP);
if (esp_wifi_set_config(ESP_IF_WIFI_AP, &wifiConfig) != ESP_OK) {
_status = WL_AP_FAILED;
}
esp_wifi_start();
xEventGroupWaitBits(_eventGroup, BIT1, false, true, portMAX_DELAY);
return _status;
}
void WiFiClass::config(/*IPAddress*/uint32_t local_ip, /*IPAddress*/uint32_t gateway, /*IPAddress*/uint32_t subnet)
{
dns_clear_servers(true);
_ipInfo.ip.addr = local_ip;
_ipInfo.gw.addr = gateway;
_ipInfo.netmask.addr = subnet;
tcpip_adapter_set_ip_info(_interface == ESP_IF_WIFI_AP ? TCPIP_ADAPTER_IF_AP : TCPIP_ADAPTER_IF_STA, &_ipInfo);
}
void WiFiClass::setDNS(/*IPAddress*/uint32_t dns_server1, /*IPAddress*/uint32_t dns_server2)
{
ip_addr_t d;
d.type = IPADDR_TYPE_V4;
if (dns_server1) {
d.u_addr.ip4.addr = static_cast<uint32_t>(dns_server1);
dns_setserver(0, &d);
}
if (dns_server2) {
d.u_addr.ip4.addr = static_cast<uint32_t>(dns_server2);
dns_setserver(1, &d);
}
}
void WiFiClass::hostname(const char* name)
{
tcpip_adapter_set_hostname(_interface == ESP_IF_WIFI_AP ? TCPIP_ADAPTER_IF_AP : TCPIP_ADAPTER_IF_STA, name);
}
void WiFiClass::disconnect()
{
esp_wifi_disconnect();
esp_wifi_stop();
}
void WiFiClass::end()
{
esp_wifi_stop();
}
uint8_t* WiFiClass::macAddress(uint8_t* mac)
{
uint8_t macTemp[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
esp_wifi_get_mac(_interface, macTemp);
mac[0] = macTemp[5];
mac[1] = macTemp[4];
mac[2] = macTemp[3];
mac[3] = macTemp[2];
mac[4] = macTemp[1];
mac[5] = macTemp[0];
return mac;
}
uint32_t WiFiClass::localIP()
{
return _ipInfo.ip.addr;
}
uint32_t WiFiClass::subnetMask()
{
return _ipInfo.netmask.addr;
}
uint32_t WiFiClass::gatewayIP()
{
return _ipInfo.gw.addr;
}
char* WiFiClass::SSID()
{
return (char*)_apRecord.ssid;
}
int32_t WiFiClass::RSSI()
{
if (_interface == ESP_IF_WIFI_AP) {
return 0;
} else {
esp_wifi_sta_get_ap_info(&_apRecord);
return _apRecord.rssi;
}
}
uint8_t WiFiClass::encryptionType()
{
uint8_t encryptionType = _apRecord.authmode;
if (encryptionType == WIFI_AUTH_OPEN) {
encryptionType = 7;
} else if (encryptionType == WIFI_AUTH_WEP) {
encryptionType = 5;
} else if (encryptionType == WIFI_AUTH_WPA_PSK) {
encryptionType = 2;
} else if (encryptionType == WIFI_AUTH_WPA2_PSK || encryptionType == WIFI_AUTH_WPA_WPA2_PSK) {
encryptionType = 4;
} else {
// unknown?
encryptionType = 255;
}
return encryptionType;
}
uint8_t* WiFiClass::BSSID(uint8_t* bssid)
{
if (_interface == ESP_IF_WIFI_AP) {
return macAddress(bssid);
} else {
bssid[0] = _apRecord.bssid[5];
bssid[1] = _apRecord.bssid[4];
bssid[2] = _apRecord.bssid[3];
bssid[3] = _apRecord.bssid[2];
bssid[4] = _apRecord.bssid[1];
bssid[5] = _apRecord.bssid[0];
return bssid;
}
}
int8_t WiFiClass::scanNetworks()
{
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_start();
xEventGroupWaitBits(_eventGroup, BIT0, false, true, portMAX_DELAY);
wifi_scan_config_t config;
config.ssid = 0;
config.bssid = 0;
config.channel = 0;
config.show_hidden = false;
config.scan_type = WIFI_SCAN_TYPE_ACTIVE;
config.scan_time.active.min = 100;
config.scan_time.active.max = 300;
xEventGroupClearBits(_eventGroup, BIT2);
if (esp_wifi_scan_start(&config, false) != ESP_OK) {
_status = WL_NO_SSID_AVAIL;
return 0;
}
xEventGroupWaitBits(_eventGroup, BIT2, false, true, portMAX_DELAY);
uint16_t numNetworks;
esp_wifi_scan_get_ap_num(&numNetworks);
if (numNetworks > MAX_SCAN_RESULTS) {
numNetworks = MAX_SCAN_RESULTS;
}
esp_wifi_scan_get_ap_records(&numNetworks, _scanResults);
_status = WL_SCAN_COMPLETED;
return numNetworks;
}
char* WiFiClass::SSID(uint8_t pos)
{
return (char*)_scanResults[pos].ssid;
}
int32_t WiFiClass::RSSI(uint8_t pos)
{
return _scanResults[pos].rssi;
}
uint8_t WiFiClass::encryptionType(uint8_t pos)
{
uint8_t encryptionType = _scanResults[pos].authmode;
if (encryptionType == WIFI_AUTH_OPEN) {
encryptionType = 7;
} else if (encryptionType == WIFI_AUTH_WEP) {
encryptionType = 5;
} else if (encryptionType == WIFI_AUTH_WPA_PSK) {
encryptionType = 2;
} else if (encryptionType == WIFI_AUTH_WPA2_PSK || encryptionType == WIFI_AUTH_WPA_WPA2_PSK) {
encryptionType = 4;
} else {
// unknown?
encryptionType = 255;
}
return encryptionType;
}
uint8_t* WiFiClass::BSSID(uint8_t pos, uint8_t* bssid)
{
const uint8_t* tempBssid = _scanResults[pos].bssid;
bssid[0] = tempBssid[5];
bssid[1] = tempBssid[4];
bssid[2] = tempBssid[3];
bssid[3] = tempBssid[2];
bssid[4] = tempBssid[1];
bssid[5] = tempBssid[0];
return bssid;
}
uint8_t WiFiClass::channel(uint8_t pos)
{
return _scanResults[pos].primary;
}
unsigned long WiFiClass::getTime()
{
time_t now;
time(&now);
if (now < 946684800) {
return 0;
}
return now;
}
void WiFiClass::lowPowerMode()
{
esp_wifi_set_ps(WIFI_PS_MODEM);
}
void WiFiClass::noLowPowerMode()
{
esp_wifi_set_ps(WIFI_PS_NONE);
}
void WiFiClass::onReceive(void(*callback)(void))
{
_onReceiveCallback = callback;
}
err_t WiFiClass::staNetifInputHandler(struct pbuf* p, struct netif* inp)
{
return WiFi.handleStaNetifInput(p, inp);
}
err_t WiFiClass::apNetifInputHandler(struct pbuf* p, struct netif* inp)
{
return WiFi.handleApNetifInput(p, inp);
}
err_t WiFiClass::handleStaNetifInput(struct pbuf* p, struct netif* inp)
{
err_t result = _staNetifInput(p, inp);
if (_onReceiveCallback) {
_onReceiveCallback();
}
return result;
}
err_t WiFiClass::handleApNetifInput(struct pbuf* p, struct netif* inp)
{
err_t result = _apNetifInput(p, inp);
if (_onReceiveCallback) {
_onReceiveCallback();
}
return result;
}
void WiFiClass::init()
{
tcpip_adapter_init();
esp_event_loop_init(WiFiClass::systemEventHandler, this);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_storage(WIFI_STORAGE_RAM);
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, (char*)"0.pool.ntp.org");
sntp_setservername(1, (char*)"1.pool.ntp.org");
sntp_setservername(2, (char*)"2.pool.ntp.org");
sntp_init();
_status = WL_IDLE_STATUS;
}
esp_err_t WiFiClass::systemEventHandler(void* ctx, system_event_t* event)
{
((WiFiClass*)ctx)->handleSystemEvent(event);
return ESP_OK;
}
void WiFiClass::handleSystemEvent(system_event_t* event)
{
switch (event->event_id) {
case SYSTEM_EVENT_SCAN_DONE:
xEventGroupSetBits(_eventGroup, BIT2);
break;
case SYSTEM_EVENT_STA_START: {
struct netif* staNetif;
if (tcpip_adapter_get_netif(TCPIP_ADAPTER_IF_STA, (void**)&staNetif) == ESP_OK) {
if (staNetif->input != WiFiClass::staNetifInputHandler) {
_staNetifInput = staNetif->input;
staNetif->input = WiFiClass::staNetifInputHandler;
}
}
xEventGroupSetBits(_eventGroup, BIT0);
break;
}
case SYSTEM_EVENT_STA_STOP:
xEventGroupClearBits(_eventGroup, BIT0);
break;
case SYSTEM_EVENT_STA_CONNECTED:
esp_wifi_sta_get_ap_info(&_apRecord);
break;
case SYSTEM_EVENT_STA_GOT_IP:
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &_ipInfo);
_status = WL_CONNECTED;
break;
case SYSTEM_EVENT_STA_DISCONNECTED: {
uint8_t reason = event->event_info.disconnected.reason;
memset(&_apRecord, 0x00, sizeof(_apRecord));
if (reason == 201/*NO_AP_FOUND*/ || reason == 202/*AUTH_FAIL*/ || reason == 203/*ASSOC_FAIL*/) {
_status = WL_CONNECT_FAILED;
} else {
_status = WL_DISCONNECTED;
}
break;
}
case SYSTEM_EVENT_STA_LOST_IP:
memset(&_ipInfo, 0x00, sizeof(_ipInfo));
_status = WL_CONNECTION_LOST;
break;
case SYSTEM_EVENT_AP_START: {
struct netif* apNetif;
if (tcpip_adapter_get_netif(TCPIP_ADAPTER_IF_AP, (void**)&apNetif) == ESP_OK) {
if (apNetif->input != WiFiClass::apNetifInputHandler) {
_apNetifInput = apNetif->input;
apNetif->input = WiFiClass::apNetifInputHandler;
}
}
wifi_config_t config;
esp_wifi_get_config(ESP_IF_WIFI_AP, &config);
memcpy(_apRecord.ssid, config.ap.ssid, sizeof(config.ap.ssid));
_apRecord.authmode = config.ap.authmode;
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &_ipInfo);
_status = WL_AP_LISTENING;
xEventGroupSetBits(_eventGroup, BIT1);
break;
}
case SYSTEM_EVENT_AP_STOP:
_status = WL_IDLE_STATUS;
memset(&_apRecord, 0x00, sizeof(_apRecord));
memset(&_ipInfo, 0x00, sizeof(_ipInfo));
xEventGroupClearBits(_eventGroup, BIT1);
break;
case SYSTEM_EVENT_AP_STACONNECTED:
_status = WL_AP_CONNECTED;
break;
case SYSTEM_EVENT_AP_STADISCONNECTED:
wifi_sta_list_t staList;
esp_wifi_ap_get_sta_list(&staList);
if (staList.num == 0) {
_status = WL_AP_LISTENING;
}
break;
default:
break;
}
}
WiFiClass WiFi;

View File

@@ -0,0 +1,129 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIFI_H
#define WIFI_H
#include <esp_event_loop.h>
#include <freertos/FreeRTOS.h>
#include <freertos/event_groups.h>
#include <lwip/netif.h>
#include <Arduino.h>
typedef enum {
WL_NO_SHIELD = 255,
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,
} wl_status_t;
#define MAX_SCAN_RESULTS 10
class WiFiClass
{
public:
WiFiClass();
uint8_t begin(const char* ssid);
uint8_t begin(const char* ssid, uint8_t key_idx, const char* key);
uint8_t begin(const char* ssid, const char* key);
uint8_t beginAP(const char *ssid, uint8_t channel);
uint8_t beginAP(const char *ssid, uint8_t key_idx, const char* key, uint8_t channel);
uint8_t beginAP(const char *ssid, const char* key, uint8_t channel);
void config(/*IPAddress*/uint32_t local_ip, /*IPAddress*/uint32_t gateway, /*IPAddress*/uint32_t subnet);
void setDNS(/*IPAddress*/uint32_t dns_server1, /*IPAddress*/uint32_t dns_server2);
void hostname(const char* name);
void disconnect();
void end();
uint8_t* macAddress(uint8_t* mac);
uint32_t localIP();
uint32_t subnetMask();
uint32_t gatewayIP();
char* SSID();
int32_t RSSI();
uint8_t encryptionType();
uint8_t* BSSID(uint8_t* bssid);
int8_t scanNetworks();
char* SSID(uint8_t pos);
int32_t RSSI(uint8_t pos);
uint8_t encryptionType(uint8_t pos);
uint8_t* BSSID(uint8_t pos, uint8_t* bssid);
uint8_t channel(uint8_t pos);
uint8_t status();
int hostByName(const char* hostname, /*IPAddress*/uint32_t& result);
int ping(/*IPAddress*/uint32_t host, uint8_t ttl);
unsigned long getTime();
void lowPowerMode();
void noLowPowerMode();
void onReceive(void(*)(void));
private:
void init();
static esp_err_t systemEventHandler(void* ctx, system_event_t* event);
void handleSystemEvent(system_event_t* event);
static err_t staNetifInputHandler(struct pbuf* p, struct netif* inp);
static err_t apNetifInputHandler(struct pbuf* p, struct netif* inp);
err_t handleStaNetifInput(struct pbuf* p, struct netif* inp);
err_t handleApNetifInput(struct pbuf* p, struct netif* inp);
private:
bool _initialized;
volatile uint8_t _status;
EventGroupHandle_t _eventGroup;
esp_interface_t _interface;
wifi_ap_record_t _scanResults[MAX_SCAN_RESULTS];
wifi_ap_record_t _apRecord;
tcpip_adapter_ip_info_t _ipInfo;
netif_input_fn _staNetifInput;
netif_input_fn _apNetifInput;
void (*_onReceiveCallback)(void);
};
extern WiFiClass WiFi;
#endif // WIFI_H

View File

@@ -0,0 +1,215 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include <string.h>
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#include "WiFiClient.h"
WiFiClient::WiFiClient() :
WiFiClient(-1)
{
}
WiFiClient::WiFiClient(int socket) :
_socket(socket)
{
}
int WiFiClient::connect(const char* host, uint16_t port)
{
struct hostent* server = gethostbyname(host);
if (server == NULL) {
return 0;
}
return connect(server->h_addr, port);
}
int WiFiClient::connect(/*IPAddress*/uint32_t ip, uint16_t port)
{
_socket = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (_socket < 0) {
_socket = -1;
return 0;
}
struct sockaddr_in addr;
memset(&addr, 0x00, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = (uint32_t)ip;
addr.sin_port = htons(port);
if (lwip_connect_r(_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
lwip_close_r(_socket);
_socket = -1;
return 0;
}
int nonBlocking = 1;
lwip_ioctl_r(_socket, FIONBIO, &nonBlocking);
return 1;
}
size_t WiFiClient::write(uint8_t b)
{
return write(&b, 1);
}
size_t WiFiClient::write(const uint8_t *buf, size_t size)
{
if (_socket == -1) {
return 0;
}
int result = lwip_send_r(_socket, (void*)buf, size, MSG_DONTWAIT);
if (result < 0) {
lwip_close_r(_socket);
_socket = -1;
return 0;
}
return result;
}
int WiFiClient::available()
{
if (_socket == -1) {
return 0;
}
int result = 0;
if (lwip_ioctl_r(_socket, FIONREAD, &result) < 0) {
lwip_close_r(_socket);
_socket = -1;
return 0;
}
return result;
}
int WiFiClient::read()
{
uint8_t b;
if (read(&b, sizeof(b)) == -1) {
return -1;
}
return b;
}
int WiFiClient::read(uint8_t* buf, size_t size)
{
if (!available()) {
return -1;
}
int result = lwip_recv_r(_socket, buf, size, MSG_DONTWAIT);
if (result <= 0 && errno != EWOULDBLOCK) {
lwip_close_r(_socket);
_socket = -1;
return 0;
}
if (result == 0) {
result = -1;
}
return result;
}
int WiFiClient::peek()
{
uint8_t b;
if (recv(_socket, &b, sizeof(b), MSG_PEEK | MSG_DONTWAIT) <= 0) {
if (errno != EWOULDBLOCK) {
lwip_close_r(_socket);
_socket = -1;
}
return -1;
}
return b;
}
void WiFiClient::flush()
{
}
void WiFiClient::stop()
{
if (_socket != -1) {
lwip_close_r(_socket);
_socket = -1;
}
}
uint8_t WiFiClient::connected()
{
if (_socket != -1) {
// use peek to update socket state
peek();
}
return (_socket != -1);
}
WiFiClient::operator bool()
{
return (_socket != -1);
}
bool WiFiClient::operator==(const WiFiClient &other) const
{
return (_socket == other._socket);
}
/*IPAddress*/uint32_t WiFiClient::remoteIP()
{
struct sockaddr_storage addr;
socklen_t len = sizeof(addr);
getpeername(_socket, (struct sockaddr*)&addr, &len);
return ((struct sockaddr_in *)&addr)->sin_addr.s_addr;
}
uint16_t WiFiClient::remotePort()
{
struct sockaddr_storage addr;
socklen_t len = sizeof(addr);
getpeername(_socket, (struct sockaddr*)&addr, &len);
return ntohs(((struct sockaddr_in *)&addr)->sin_port);
}

View File

@@ -0,0 +1,64 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIFICLIENT_H
#define WIFICLIENT_H
#include <Arduino.h>
// #include <Client.h>
// #include <IPAddress.h>
class WiFiServer;
class WiFiClient /*: public Client*/ {
public:
WiFiClient();
uint8_t status();
virtual int connect(/*IPAddress*/uint32_t ip, uint16_t port);
virtual int connect(const char* host, uint16_t port);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int available();
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
virtual operator bool();
bool operator==(const WiFiClient &other) const;
virtual /*IPAddress*/uint32_t remoteIP();
virtual uint16_t remotePort();
// using Print::write;
protected:
friend class WiFiServer;
WiFiClient(int socket);
private:
int _socket;
};
#endif // WIFICLIENT_H

View File

@@ -0,0 +1,554 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#include "WiFiSSLClient.h"
class __Guard {
public:
__Guard(SemaphoreHandle_t handle) {
_handle = handle;
xSemaphoreTakeRecursive(_handle, portMAX_DELAY);
}
~__Guard() {
xSemaphoreGiveRecursive(_handle);
}
private:
SemaphoreHandle_t _handle;
};
#define synchronized __Guard __guard(_mbedMutex);
WiFiSSLClient::WiFiSSLClient() :
_connected(false),
_peek(-1)
{
_netContext.fd = -1;
_mbedMutex = xSemaphoreCreateRecursiveMutex();
}
int WiFiSSLClient::connect(const char* host, uint16_t port)
{
synchronized {
_netContext.fd = -1;
_connected = false;
mbedtls_ssl_init(&_sslContext);
mbedtls_ctr_drbg_init(&_ctrDrbgContext);
mbedtls_ssl_config_init(&_sslConfig);
mbedtls_entropy_init(&_entropyContext);
mbedtls_x509_crt_init(&_caCrt);
mbedtls_net_init(&_netContext);
if (mbedtls_ctr_drbg_seed(&_ctrDrbgContext, mbedtls_entropy_func, &_entropyContext, NULL, 0) != 0) {
stop();
return 0;
}
if (mbedtls_ssl_config_defaults(&_sslConfig, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
stop();
return 0;
}
mbedtls_ssl_conf_authmode(&_sslConfig, MBEDTLS_SSL_VERIFY_REQUIRED);
if (mbedtls_x509_crt_parse(&_caCrt, (const unsigned char *)ROOT_CAs, strlen(ROOT_CAs) + 1) != 0) {
stop();
return 0;
}
mbedtls_ssl_conf_ca_chain(&_sslConfig, &_caCrt, NULL);
mbedtls_ssl_conf_rng(&_sslConfig, mbedtls_ctr_drbg_random, &_ctrDrbgContext);
if (mbedtls_ssl_setup(&_sslContext, &_sslConfig) != 0) {
stop();
return 0;
}
char portStr[6];
itoa(port, portStr, 10);
if (mbedtls_net_connect(&_netContext, host, portStr, MBEDTLS_NET_PROTO_TCP) != 0) {
stop();
return 0;
}
mbedtls_ssl_set_bio(&_sslContext, &_netContext, mbedtls_net_send, mbedtls_net_recv, NULL);
int result;
do {
result = mbedtls_ssl_handshake(&_sslContext);
} while (result == MBEDTLS_ERR_SSL_WANT_READ || result == MBEDTLS_ERR_SSL_WANT_WRITE);
if (result != 0) {
stop();
return 0;
}
mbedtls_net_set_nonblock(&_netContext);
_connected = true;
return 1;
}
}
int WiFiSSLClient::connect(/*IPAddress*/uint32_t ip, uint16_t port)
{
char ipStr[16];
sprintf(ipStr, "%d.%d.%d.%d", ((ip & 0xff000000) >> 24), ((ip & 0x00ff0000) >> 16), ((ip & 0x0000ff00) >> 8), ((ip & 0x000000ff) >> 0)/*ip[0], ip[1], ip[2], ip[3]*/);
return connect(ipStr, port);
}
size_t WiFiSSLClient::write(uint8_t b)
{
return write(&b, 1);
}
size_t WiFiSSLClient::write(const uint8_t *buf, size_t size)
{
synchronized {
int written = mbedtls_ssl_write(&_sslContext, buf, size);
if (written < 0) {
written = 0;
}
return written;
}
}
int WiFiSSLClient::available()
{
synchronized {
int result = mbedtls_ssl_read(&_sslContext, NULL, 0);
int n = mbedtls_ssl_get_bytes_avail(&_sslContext);
if (n == 0 && result != 0 && result != MBEDTLS_ERR_SSL_WANT_READ) {
stop();
}
return n;
}
}
int WiFiSSLClient::read()
{
uint8_t b;
if (_peek != -1) {
b = _peek;
_peek = -1;
} else if (read(&b, sizeof(b)) == -1) {
return -1;
}
return b;
}
int WiFiSSLClient::read(uint8_t* buf, size_t size)
{
synchronized {
if (!available()) {
return -1;
}
int result = mbedtls_ssl_read(&_sslContext, buf, size);
if (result < 0) {
if (result != MBEDTLS_ERR_SSL_WANT_READ && result != MBEDTLS_ERR_SSL_WANT_WRITE) {
stop();
}
return -1;
}
return result;
}
}
int WiFiSSLClient::peek()
{
if (_peek == -1) {
_peek = read();
}
return _peek;
}
void WiFiSSLClient::flush()
{
}
void WiFiSSLClient::stop()
{
synchronized {
if (_netContext.fd > 0) {
mbedtls_ssl_session_reset(&_sslContext);
mbedtls_net_free(&_netContext);
mbedtls_x509_crt_free(&_caCrt);
mbedtls_entropy_free(&_entropyContext);
mbedtls_ssl_config_free(&_sslConfig);
mbedtls_ctr_drbg_free(&_ctrDrbgContext);
mbedtls_ssl_free(&_sslContext);
}
_connected = false;
_netContext.fd = -1;
}
}
uint8_t WiFiSSLClient::connected()
{
synchronized {
if (!_connected) {
return 0;
}
if (available()) {
return 1;
}
return 1;
}
}
WiFiSSLClient::operator bool()
{
return ((_netContext.fd != -1) && _connected);
}
/*IPAddress*/uint32_t WiFiSSLClient::remoteIP()
{
struct sockaddr_storage addr;
socklen_t len = sizeof(addr);
getpeername(_netContext.fd, (struct sockaddr*)&addr, &len);
return ((struct sockaddr_in *)&addr)->sin_addr.s_addr;
}
uint16_t WiFiSSLClient::remotePort()
{
struct sockaddr_storage addr;
socklen_t len = sizeof(addr);
getpeername(_netContext.fd, (struct sockaddr*)&addr, &len);
return ntohs(((struct sockaddr_in *)&addr)->sin_port);
}
const char* WiFiSSLClient::ROOT_CAs =
"-----BEGIN CERTIFICATE-----\n"
"MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU\n"
"MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs\n"
"IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290\n"
"MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux\n"
"FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h\n"
"bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v\n"
"dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt\n"
"H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9\n"
"uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX\n"
"mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX\n"
"a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN\n"
"E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0\n"
"WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD\n"
"VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0\n"
"Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU\n"
"cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx\n"
"IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN\n"
"AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH\n"
"YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5\n"
"6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC\n"
"Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX\n"
"c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a\n"
"mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\n"
"RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\n"
"VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\n"
"DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\n"
"ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\n"
"VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\n"
"mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\n"
"IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\n"
"mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n"
"XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\n"
"dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\n"
"jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\n"
"BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\n"
"DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\n"
"9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n"
"jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\n"
"Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\n"
"ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n"
"R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB\n"
"hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n"
"A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV\n"
"BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5\n"
"MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT\n"
"EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR\n"
"Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh\n"
"dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR\n"
"6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X\n"
"pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC\n"
"9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV\n"
"/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf\n"
"Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z\n"
"+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w\n"
"qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah\n"
"SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC\n"
"u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf\n"
"Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq\n"
"crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E\n"
"FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB\n"
"/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl\n"
"wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM\n"
"4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV\n"
"2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna\n"
"FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ\n"
"CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK\n"
"boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke\n"
"jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL\n"
"S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb\n"
"QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl\n"
"0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB\n"
"NVOFBkpdn627G190\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n"
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n"
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n"
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n"
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n"
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n"
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n"
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n"
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n"
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n"
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n"
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n"
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n"
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n"
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n"
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs\n"
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
"d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\n"
"ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL\n"
"MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\n"
"LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug\n"
"RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm\n"
"+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW\n"
"PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\n"
"xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB\n"
"Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3\n"
"hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg\n"
"EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF\n"
"MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA\n"
"FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec\n"
"nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z\n"
"eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF\n"
"hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\n"
"Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe\n"
"vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n"
"+OkuE6N36B9K\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC\n"
"VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0\n"
"Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW\n"
"KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl\n"
"cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw\n"
"NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw\n"
"NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy\n"
"ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV\n"
"BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ\n"
"KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo\n"
"Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4\n"
"4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9\n"
"KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI\n"
"rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi\n"
"94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB\n"
"sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi\n"
"gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo\n"
"kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE\n"
"vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA\n"
"A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t\n"
"O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua\n"
"AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP\n"
"9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/\n"
"eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m\n"
"0vdXcDazv/wor3ElhVsT/h5/WrQ8\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV\n"
"UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy\n"
"dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1\n"
"MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx\n"
"dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B\n"
"AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f\n"
"BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A\n"
"cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC\n"
"AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ\n"
"MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm\n"
"aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw\n"
"ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj\n"
"IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF\n"
"MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA\n"
"A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y\n"
"7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh\n"
"1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n"
"MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\n"
"YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG\n"
"EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg\n"
"R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9\n"
"9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq\n"
"fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv\n"
"iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU\n"
"1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+\n"
"bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW\n"
"MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA\n"
"ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l\n"
"uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn\n"
"Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS\n"
"tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF\n"
"PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un\n"
"hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV\n"
"5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB\n"
"mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT\n"
"MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s\n"
"eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv\n"
"cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ\n"
"BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg\n"
"MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0\n"
"BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg\n"
"LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz\n"
"+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm\n"
"hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn\n"
"5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W\n"
"JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL\n"
"DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC\n"
"huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw\n"
"HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB\n"
"AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB\n"
"zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN\n"
"kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD\n"
"AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH\n"
"SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G\n"
"spki4cErx5z481+oghLrGREt\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G\n"
"A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp\n"
"Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1\n"
"MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG\n"
"A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\n"
"hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL\n"
"v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8\n"
"eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq\n"
"tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd\n"
"C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa\n"
"zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB\n"
"mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH\n"
"V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n\n"
"bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG\n"
"3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs\n"
"J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO\n"
"291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS\n"
"ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd\n"
"AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7\n"
"TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx\n"
"EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT\n"
"EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp\n"
"ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz\n"
"NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH\n"
"EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE\n"
"AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw\n"
"DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD\n"
"E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH\n"
"/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy\n"
"DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh\n"
"GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR\n"
"tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA\n"
"AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE\n"
"FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX\n"
"WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu\n"
"9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr\n"
"gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo\n"
"2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO\n"
"LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI\n"
"4uJEvlz36hz1\n"
"-----END CERTIFICATE-----\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n"
"yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\n"
"ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\n"
"U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\n"
"ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\n"
"aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL\n"
"MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW\n"
"ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln\n"
"biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp\n"
"U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y\n"
"aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1\n"
"nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex\n"
"t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz\n"
"SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG\n"
"BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+\n"
"rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/\n"
"NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E\n"
"BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH\n"
"BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy\n"
"aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv\n"
"MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE\n"
"p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y\n"
"5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK\n"
"WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ\n"
"4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N\n"
"hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq\n"
"-----END CERTIFICATE-----\n";

View File

@@ -0,0 +1,73 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIFISSLCLIENT_H
#define WIFISSLCLIENT_H
#include <mbedtls/net.h>
#include <mbedtls/ssl.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/error.h>
#include <Arduino.h>
// #include <Client.h>
// #include <IPAddress.h>
class WiFiSSLClient /*: public Client*/ {
public:
WiFiSSLClient();
uint8_t status();
virtual int connect(/*IPAddress*/uint32_t ip, uint16_t port);
virtual int connect(const char* host, uint16_t port);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
virtual int available();
virtual int read();
virtual int read(uint8_t *buf, size_t size);
virtual int peek();
virtual void flush();
virtual void stop();
virtual uint8_t connected();
virtual operator bool();
// using Print::write;
virtual /*IPAddress*/uint32_t remoteIP();
virtual uint16_t remotePort();
private:
static const char* ROOT_CAs;
mbedtls_entropy_context _entropyContext;
mbedtls_ctr_drbg_context _ctrDrbgContext;
mbedtls_ssl_context _sslContext;
mbedtls_ssl_config _sslConfig;
mbedtls_net_context _netContext;
mbedtls_x509_crt _caCrt;
bool _connected;
int _peek;
SemaphoreHandle_t _mbedMutex;
};
#endif /* WIFISSLCLIENT_H */

View File

@@ -0,0 +1,142 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include <string.h>
#include <lwip/sockets.h>
#include "WiFiClient.h"
#include "WiFiServer.h"
WiFiServer::WiFiServer() :
WiFiServer(0)
{
}
WiFiServer::WiFiServer(uint16_t port) :
_port(port),
_socket(-1)
{
for (int i = 0; i < CONFIG_LWIP_MAX_SOCKETS; i++) {
_spawnedSockets[i] = -1;
}
}
void WiFiServer::begin()
{
_socket = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (_socket < 0) {
return;
}
struct sockaddr_in addr;
memset(&addr, 0x00, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = (uint32_t)0;
addr.sin_port = htons(_port);
if (lwip_bind(_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
lwip_close_r(_socket);
_socket = -1;
return;
}
if (lwip_listen(_socket, 1) < 0) {
lwip_close_r(_socket);
_socket = -1;
return;
}
int nonBlocking = 1;
lwip_ioctl_r(_socket, FIONBIO, &nonBlocking);
return;
}
WiFiClient WiFiServer::available(uint8_t* status)
{
int result = lwip_accept(_socket, NULL, 0);
if (status) {
*status = (result != -1);
}
if (result != -1) {
// store the connected socket
for (int i = 0; i < CONFIG_LWIP_MAX_SOCKETS; i++) {
if (_spawnedSockets[i] == -1) {
_spawnedSockets[i] = result;
break;
}
}
}
result = -1;
// find an existing socket with data
for (int i = 0; i < CONFIG_LWIP_MAX_SOCKETS; i++) {
if (_spawnedSockets[i] != -1) {
WiFiClient c(_spawnedSockets[i]);
if (!c.connected()) {
// socket not connected, clear from book keeping
_spawnedSockets[i] = -1;
} else if (c.available()) {
result = _spawnedSockets[i];
break;
}
}
}
return WiFiClient(result);
}
uint8_t WiFiServer::status() {
// Deprecated.
return 0;
}
size_t WiFiServer::write(uint8_t b)
{
return write(&b, 1);
}
size_t WiFiServer::write(const uint8_t *buffer, size_t size)
{
size_t written = 0;
for (int i = 0; i < CONFIG_LWIP_MAX_SOCKETS; i++) {
if (_spawnedSockets[i] != -1) {
WiFiClient c(_spawnedSockets[i]);
written += c.write(buffer, size);
}
}
return written;
}
WiFiServer::operator bool()
{
return (_port != 0 && _socket != -1);
}

View File

@@ -0,0 +1,50 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIFISERVER_H
#define WIFISERVER_H
#include <sdkconfig.h>
#include <Arduino.h>
// #include <Server.h>
class WiFiClient;
class WiFiServer /*: public Server*/ {
public:
WiFiServer();
WiFiServer(uint16_t);
WiFiClient available(uint8_t* status = NULL);
void begin();
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
uint8_t status();
// using Print::write;
virtual operator bool();
private:
uint16_t _port;
int _socket;
int _spawnedSockets[CONFIG_LWIP_MAX_SOCKETS];
};
#endif // WIFISERVER_H

View File

@@ -0,0 +1,218 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include <string.h>
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#include "WiFiUdp.h"
WiFiUDP::WiFiUDP() :
_socket(-1),
_remoteIp(0),
_remotePort(0),
_rcvIndex(0),
_rcvSize(0),
_sndSize(0)
{
}
uint8_t WiFiUDP::begin(uint16_t port)
{
_socket = lwip_socket(AF_INET, SOCK_DGRAM, 0);
if (_socket < 0) {
return 0;
}
struct sockaddr_in addr;
memset(&addr, 0x00, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = (uint32_t)0;
addr.sin_port = htons(port);
if (lwip_bind(_socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
lwip_close_r(_socket);
_socket = -1;
return 0;
}
int nonBlocking = 1;
lwip_ioctl_r(_socket, FIONBIO, &nonBlocking);
return 1;
}
uint8_t WiFiUDP::beginMulticast(/*IPAddress*/uint32_t ip, uint16_t port)
{
if (!begin(port)) {
return 0;
}
struct ip_mreq multi;
multi.imr_multiaddr.s_addr = (uint32_t)ip;
multi.imr_interface.s_addr = (uint32_t)0;
lwip_setsockopt_r(_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multi, sizeof(multi));
return 1;
}
/* return number of bytes available in the current packet,
will return zero if parsePacket hasn't been called yet */
int WiFiUDP::available()
{
return (_rcvSize - _rcvIndex);
}
/* Release any resources being used by this WiFiUDP instance */
void WiFiUDP::stop()
{
lwip_close_r(_socket);
_socket = -1;
}
int WiFiUDP::beginPacket(const char *host, uint16_t port)
{
struct hostent* server = gethostbyname(host);
if (server == NULL) {
return 0;
}
return beginPacket(server->h_addr, port);
}
int WiFiUDP::beginPacket(/*IPAddress*/uint32_t ip, uint16_t port)
{
_remoteIp = ip;
_remotePort = port;
_sndSize = 0;
return 1;
}
int WiFiUDP::endPacket()
{
struct sockaddr_in addr;
memset(&addr, 0x00, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = _remoteIp;
addr.sin_port = htons(_remotePort);
if (lwip_sendto(_socket, _sndBuffer, _sndSize, 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
return 0;
}
return 1;
}
size_t WiFiUDP::write(uint8_t byte)
{
return write(&byte, 1);
}
size_t WiFiUDP::write(const uint8_t *buffer, size_t size)
{
size_t written = size;
if ((_sndSize + size) > sizeof(_sndBuffer)) {
written = sizeof(_sndBuffer) - _sndSize;
}
memcpy(&_sndBuffer[_sndSize], buffer, size);
_sndSize += written;
return written;
}
int WiFiUDP::parsePacket()
{
struct sockaddr_in addr;
socklen_t addrLen = sizeof(addr);
_rcvIndex = 0;
_rcvSize = 0;
int result = lwip_recvfrom_r(_socket, _rcvBuffer, sizeof(_rcvBuffer), MSG_DONTWAIT, (struct sockaddr*)&addr, &addrLen);
if (result <= 0) {
return 0;
}
_rcvSize = result;
_remoteIp = addr.sin_addr.s_addr;
_remotePort = ntohs(addr.sin_port);
return result;
}
int WiFiUDP::read()
{
uint8_t b;
if (read(&b, sizeof(b)) < 1) {
return -1;
}
return b;
}
int WiFiUDP::read(unsigned char* buf, size_t size)
{
if (available() < (int)size) {
size = available();
}
memcpy(buf, &_rcvBuffer[_rcvIndex], size);
_rcvIndex += size;
return size;
}
int WiFiUDP::peek()
{
if (!available()) {
return -1;
}
return _rcvBuffer[_rcvIndex];
}
void WiFiUDP::flush()
{
}
/*IPAddress*/uint32_t WiFiUDP::remoteIP()
{
return _remoteIp;
}
uint16_t WiFiUDP::remotePort()
{
return _remotePort;
}

View File

@@ -0,0 +1,66 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef WIFIUDP_H
#define WIFIUDP_H
// #include <Udp.h>
class WiFiUDP /*: public UDP*/ {
public:
WiFiUDP();
virtual uint8_t begin(uint16_t);
virtual uint8_t beginMulticast(/*IPAddress*/uint32_t, uint16_t);
virtual void stop();
virtual int beginPacket(/*IPAddress*/uint32_t ip, uint16_t port);
virtual int beginPacket(const char *host, uint16_t port);
virtual int endPacket();
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buffer, size_t size);
// using Print::write;
virtual int parsePacket();
virtual int available();
virtual int read();
virtual int read(unsigned char* buffer, size_t len);
virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); };
virtual int peek();
virtual void flush();
virtual /*IPAddress*/ uint32_t remoteIP();
virtual uint16_t remotePort();
virtual operator bool() { return _socket != -1; }
private:
int _socket;
uint32_t _remoteIp;
uint16_t _remotePort;
uint8_t _rcvBuffer[1500];
uint16_t _rcvIndex;
uint16_t _rcvSize;
uint8_t _sndBuffer[1500];
uint16_t _sndSize;
};
#endif // WIFIUDP_H

1104
main/CommandHandler.cpp Normal file

File diff suppressed because it is too large Load Diff

45
main/CommandHandler.h Normal file
View File

@@ -0,0 +1,45 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef COMMAND_HANDLER_H
#define COMMAND_HANDLER_H
#include <stdint.h>
class CommandHandlerClass {
public:
CommandHandlerClass();
void begin();
int handle(const uint8_t command[], uint8_t response[]);
private:
static void gpio0Updater(void*);
void updateGpio0Pin();
static void onWiFiReceive();
void handleWiFiReceive();
private:
SemaphoreHandle_t _updateGpio0PinSemaphore;
};
extern CommandHandlerClass CommandHandler;
#endif

0
main/component.mk Normal file
View File

121
main/sketch.ino.cpp Normal file
View File

@@ -0,0 +1,121 @@
/*
This file is part of the MKR WiFi 1010 firmware.
Copyright (C) 2018 Arduino AG (http://www.arduino.cc/)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <rom/uart.h>
extern "C" {
#include <driver/periph_ctrl.h>
}
#include <Arduino.h>
#include <SPIS.h>
#include <WiFi.h>
#include "CommandHandler.h"
#define SPI_BUFFER_LEN SPI_MAX_DMA_LEN
int debug = 0;
uint8_t* commandBuffer;
uint8_t* responseBuffer;
void dumpBuffer(const char* label, uint8_t data[], int length) {
ets_printf("%s: ", label);
for (int i = 0; i < length; i++) {
ets_printf("%02x", data[i]);
}
ets_printf("\r\n");
}
void setDebug(int d) {
debug = d;
if (debug) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[1], 0);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[3], 0);
const char* default_uart_dev = "/dev/uart/0";
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
uart_div_modify(CONFIG_CONSOLE_UART_NUM, (APB_CLK_FREQ << 4) / 115200);
// uartAttach();
ets_install_uart_printf();
uart_tx_switch(CONFIG_CONSOLE_UART_NUM);
} else {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[1], PIN_FUNC_GPIO);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[3], PIN_FUNC_GPIO);
_GLOBAL_REENT->_stdin = (FILE*) &__sf_fake_stdin;
_GLOBAL_REENT->_stdout = (FILE*) &__sf_fake_stdout;
_GLOBAL_REENT->_stderr = (FILE*) &__sf_fake_stderr;
ets_install_putc1(NULL);
ets_install_putc2(NULL);
}
}
void setup() {
setDebug(debug);
// put SWD and SWCLK pins connected to SAMD as inputs
pinMode(15, INPUT);
pinMode(21, INPUT);
SPIS.begin();
if (WiFi.status() == WL_NO_SHIELD) {
while (1); // no shield
}
commandBuffer = (uint8_t*)heap_caps_malloc(SPI_BUFFER_LEN, MALLOC_CAP_DMA);
responseBuffer = (uint8_t*)heap_caps_malloc(SPI_BUFFER_LEN, MALLOC_CAP_DMA);
CommandHandler.begin();
}
void loop() {
// wait for a command
memset(commandBuffer, 0x00, SPI_BUFFER_LEN);
int commandLength = SPIS.transfer(NULL, commandBuffer, SPI_BUFFER_LEN);
if (commandLength == 0) {
return;
}
if (debug) {
dumpBuffer("COMMAND", commandBuffer, commandLength);
}
// process
memset(responseBuffer, 0x00, SPI_BUFFER_LEN);
int responseLength = CommandHandler.handle(commandBuffer, responseBuffer);
SPIS.transfer(responseBuffer, NULL, responseLength);
if (debug) {
dumpBuffer("RESPONSE", responseBuffer, responseLength);
}
}

View File

@@ -13,13 +13,13 @@ CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y
#
# Bootloader config
#
CONFIG_LOG_BOOTLOADER_LEVEL_NONE=
CONFIG_LOG_BOOTLOADER_LEVEL_NONE=y
CONFIG_LOG_BOOTLOADER_LEVEL_ERROR=
CONFIG_LOG_BOOTLOADER_LEVEL_WARN=
CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
CONFIG_LOG_BOOTLOADER_LEVEL_INFO=
CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=
CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE=
CONFIG_LOG_BOOTLOADER_LEVEL=3
CONFIG_LOG_BOOTLOADER_LEVEL=0
CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V=
CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y
@@ -127,10 +127,10 @@ CONFIG_BT_RESERVE_DRAM=0
#
# ESP32-specific
#
CONFIG_ESP32_DEFAULT_CPU_FREQ_80=
CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_160=
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=80
CONFIG_MEMMAP_SMP=y
CONFIG_SPIRAM_SUPPORT=
CONFIG_MEMMAP_TRACEMEM=
@@ -156,11 +156,10 @@ CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF=
CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=
CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y
CONFIG_NEWLIB_NANO_FORMAT=
CONFIG_CONSOLE_UART_DEFAULT=y
CONFIG_CONSOLE_UART_DEFAULT=
CONFIG_CONSOLE_UART_CUSTOM=
CONFIG_CONSOLE_UART_NONE=
CONFIG_CONSOLE_UART_NONE=y
CONFIG_CONSOLE_UART_NUM=0
CONFIG_CONSOLE_UART_BAUDRATE=115200
CONFIG_ULP_COPROC_ENABLED=
CONFIG_ULP_COPROC_RESERVE_MEM=0
CONFIG_ESP32_PANIC_PRINT_HALT=
@@ -341,7 +340,7 @@ CONFIG_L2_TO_L3_COPY=
CONFIG_LWIP_MAX_SOCKETS=10
CONFIG_LWIP_SO_REUSE=y
CONFIG_LWIP_SO_REUSE_RXTOALL=y
CONFIG_LWIP_SO_RCVBUF=
CONFIG_LWIP_SO_RCVBUF=y
CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
CONFIG_LWIP_IP_FRAG=
CONFIG_LWIP_IP_REASSEMBLY=